diff --git a/.gitignore b/.gitignore index 921e230..5e94d01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -SOURCES/DJM-GPG-KEY.gpg -SOURCES/openssh-8.0p1.tar.gz -SOURCES/pam_ssh_agent_auth-0.10.3.tar.bz2 +gpgkey-736060BA.gpg +openssh-9.8p1.tar.gz diff --git a/.openssh.metadata b/.openssh.metadata deleted file mode 100644 index ee9c622..0000000 --- a/.openssh.metadata +++ /dev/null @@ -1,3 +0,0 @@ -bed7240bb17840b451b8f8457791c33456814d93 SOURCES/DJM-GPG-KEY.gpg -756dbb99193f9541c9206a667eaa27b0fa184a4f SOURCES/openssh-8.0p1.tar.gz -a4482a050fdad1d012427e45799564136708cf6b SOURCES/pam_ssh_agent_auth-0.10.3.tar.bz2 diff --git a/SOURCES/openssh-4.3p2-askpass-grab-info.patch b/SOURCES/openssh-4.3p2-askpass-grab-info.patch deleted file mode 100644 index e9a0b0d..0000000 --- a/SOURCES/openssh-4.3p2-askpass-grab-info.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.grab-info openssh-7.4p1/contrib/gnome-ssh-askpass2.c ---- openssh-7.4p1/contrib/gnome-ssh-askpass2.c.grab-info 2016-12-23 13:31:22.645213115 +0100 -+++ openssh-7.4p1/contrib/gnome-ssh-askpass2.c 2016-12-23 13:31:40.997216691 +0100 -@@ -65,9 +65,12 @@ report_failed_grab (GtkWidget *parent_wi - err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, -- "Could not grab %s. " -- "A malicious client may be eavesdropping " -- "on your session.", what); -+ "SSH password dialog could not grab the %s input.\n" -+ "This might be caused by application such as screensaver, " -+ "however it could also mean that someone may be eavesdropping " -+ "on your session.\n" -+ "Either close the application which grabs the %s or " -+ "log out and log in again to prevent this from happening.", what, what); - gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); - - gtk_dialog_run(GTK_DIALOG(err)); diff --git a/SOURCES/openssh-5.1p1-askpass-progress.patch b/SOURCES/openssh-5.1p1-askpass-progress.patch deleted file mode 100644 index 6601fbf..0000000 --- a/SOURCES/openssh-5.1p1-askpass-progress.patch +++ /dev/null @@ -1,81 +0,0 @@ -diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contrib/gnome-ssh-askpass2.c ---- openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/contrib/gnome-ssh-askpass2.c 2016-12-23 13:31:16.545211926 +0100 -@@ -53,6 +53,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -81,13 +82,24 @@ ok_dialog(GtkWidget *entry, gpointer dia - gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - } - -+static void -+move_progress(GtkWidget *entry, gpointer progress) -+{ -+ gdouble step; -+ g_return_if_fail(GTK_IS_PROGRESS_BAR(progress)); -+ -+ step = g_random_double_range(0.03, 0.1); -+ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress), step); -+ gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress)); -+} -+ - static int - passphrase_dialog(char *message) - { - const char *failed; - char *passphrase, *local; - int result, grab_tries, grab_server, grab_pointer; -- GtkWidget *parent_window, *dialog, *entry; -+ GtkWidget *parent_window, *dialog, *entry, *progress, *hbox; - GdkGrabStatus status; - - grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); -@@ -104,14 +116,32 @@ passphrase_dialog(char *message) - "%s", - message); - -+ hbox = gtk_hbox_new(FALSE, 0); -+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, -+ FALSE, 0); -+ gtk_widget_show(hbox); -+ - entry = gtk_entry_new(); - gtk_box_pack_start( -- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry, -- FALSE, FALSE, 0); -+ GTK_BOX(hbox), entry, -+ TRUE, FALSE, 0); -+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 2); - gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); - gtk_widget_grab_focus(entry); - gtk_widget_show(entry); - -+ hbox = gtk_hbox_new(FALSE, 0); -+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, -+ FALSE, 8); -+ gtk_widget_show(hbox); -+ -+ progress = gtk_progress_bar_new(); -+ -+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "Passphrase length hidden intentionally"); -+ gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE, -+ TRUE, 5); -+ gtk_widget_show(progress); -+ - gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH"); - gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); - gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); -@@ -120,6 +150,8 @@ passphrase_dialog(char *message) - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - g_signal_connect(G_OBJECT(entry), "activate", - G_CALLBACK(ok_dialog), dialog); -+ g_signal_connect(G_OBJECT(entry), "changed", -+ G_CALLBACK(move_progress), progress); - - gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); - diff --git a/SOURCES/openssh-6.3p1-ctr-evp-fast.patch b/SOURCES/openssh-6.3p1-ctr-evp-fast.patch deleted file mode 100644 index ddcb7f1..0000000 --- a/SOURCES/openssh-6.3p1-ctr-evp-fast.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff -up openssh-5.9p1/cipher-ctr.c.ctr-evp openssh-5.9p1/cipher-ctr.c ---- openssh-5.9p1/cipher-ctr.c.ctr-evp 2012-01-11 09:24:06.000000000 +0100 -+++ openssh-5.9p1/cipher-ctr.c 2012-01-11 15:54:04.675956600 +0100 -@@ -38,7 +38,7 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, in - - struct ssh_aes_ctr_ctx - { -- AES_KEY aes_ctx; -+ EVP_CIPHER_CTX ecbctx; - u_char aes_counter[AES_BLOCK_SIZE]; - }; - -@@ -63,21 +63,42 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char - { - struct ssh_aes_ctr_ctx *c; - size_t n = 0; -- u_char buf[AES_BLOCK_SIZE]; -+ u_char ctrbuf[AES_BLOCK_SIZE*256]; -+ u_char buf[AES_BLOCK_SIZE*256]; - - if (len == 0) - return (1); - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) - return (0); - -- while ((len--) > 0) { -+ for (; len > 0; len -= sizeof(u_int)) { -+ u_int r,a,b; -+ - if (n == 0) { -- AES_encrypt(c->aes_counter, buf, &c->aes_ctx); -- ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); -+ int outl, i, buflen; -+ -+ buflen = MIN(len, sizeof(ctrbuf)); -+ -+ for(i = 0; i < buflen; i += AES_BLOCK_SIZE) { -+ memcpy(&ctrbuf[i], c->aes_counter, AES_BLOCK_SIZE); -+ ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); -+ } -+ -+ EVP_EncryptUpdate(&c->ecbctx, buf, &outl, -+ ctrbuf, buflen); - } -- *(dest++) = *(src++) ^ buf[n]; -- n = (n + 1) % AES_BLOCK_SIZE; -+ -+ memcpy(&a, src, sizeof(a)); -+ memcpy(&b, &buf[n], sizeof(b)); -+ r = a ^ b; -+ memcpy(dest, &r, sizeof(r)); -+ src += sizeof(a); -+ dest += sizeof(r); -+ -+ n = (n + sizeof(b)) % sizeof(buf); - } -+ memset(ctrbuf, '\0', sizeof(ctrbuf)); -+ memset(buf, '\0', sizeof(buf)); - return (1); - } - -@@ -91,9 +112,28 @@ ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, co - c = xmalloc(sizeof(*c)); - EVP_CIPHER_CTX_set_app_data(ctx, c); - } -- if (key != NULL) -- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, -- &c->aes_ctx); -+ -+ EVP_CIPHER_CTX_init(&c->ecbctx); -+ -+ if (key != NULL) { -+ const EVP_CIPHER *cipher; -+ switch(EVP_CIPHER_CTX_key_length(ctx)*8) { -+ case 128: -+ cipher = EVP_aes_128_ecb(); -+ break; -+ case 192: -+ cipher = EVP_aes_192_ecb(); -+ break; -+ case 256: -+ cipher = EVP_aes_256_ecb(); -+ break; -+ default: -+ fatal("ssh_aes_ctr_init: wrong aes key length"); -+ } -+ if(!EVP_EncryptInit_ex(&c->ecbctx, cipher, NULL, key, NULL)) -+ fatal("ssh_aes_ctr_init: cannot initialize aes encryption"); -+ EVP_CIPHER_CTX_set_padding(&c->ecbctx, 0); -+ } - if (iv != NULL) - memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); - return (1); -@@ -105,6 +145,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) - struct ssh_aes_ctr_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { -+ EVP_CIPHER_CTX_cleanup(&c->ecbctx); - memset(c, 0, sizeof(*c)); - free(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); diff --git a/SOURCES/openssh-6.6p1-ctr-cavstest.patch b/SOURCES/openssh-6.6p1-ctr-cavstest.patch deleted file mode 100644 index e906b70..0000000 --- a/SOURCES/openssh-6.6p1-ctr-cavstest.patch +++ /dev/null @@ -1,257 +0,0 @@ -diff -up openssh-6.8p1/Makefile.in.ctr-cavs openssh-6.8p1/Makefile.in ---- openssh-6.8p1/Makefile.in.ctr-cavs 2015-03-18 11:22:05.493289018 +0100 -+++ openssh-6.8p1/Makefile.in 2015-03-18 11:22:44.504196316 +0100 -@@ -28,6 +28,7 @@ SSH_KEYSIGN=$(libexecdir)/ssh-keysign - SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper - SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper - SSH_KEYCAT=$(libexecdir)/ssh-keycat -+CTR_CAVSTEST=$(libexecdir)/ctr-cavstest - SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper - PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ -@@ -66,7 +67,7 @@ EXEEXT=@EXEEXT@ - MKDIR_P=@MKDIR_P@ - INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ - --TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) -+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) - - XMSS_OBJS=\ - ssh-xmss.o \ -@@ -194,6 +195,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l - ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o - $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS) - -+ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o -+ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) -+ - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) - -@@ -326,6 +330,7 @@ install-files: - $(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ - fi - $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT) -+ $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) - $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c ---- openssh-6.8p1/ctr-cavstest.c.ctr-cavs 2015-03-18 11:22:05.521288952 +0100 -+++ openssh-6.8p1/ctr-cavstest.c 2015-03-18 11:22:05.521288952 +0100 -@@ -0,0 +1,215 @@ -+/* -+ * -+ * invocation (all of the following are equal): -+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 -+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 --iv 00000000000000000000000000000000 -+ * echo -n a6deca405eef2e8e4609abf3c3ccf4a6 | ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt -+ */ -+ -+#include "includes.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "xmalloc.h" -+#include "log.h" -+#include "ssherr.h" -+#include "cipher.h" -+ -+/* compatibility with old or broken OpenSSL versions */ -+#include "openbsd-compat/openssl-compat.h" -+ -+void usage(void) { -+ fprintf(stderr, "Usage: ctr-cavstest --algo \n" -+ " --key --mode \n" -+ " [--iv ] --data \n\n" -+ "Hexadecimal output is printed to stdout.\n" -+ "Hexadecimal input data can be alternatively read from stdin.\n"); -+ exit(1); -+} -+ -+void *fromhex(char *hex, size_t *len) -+{ -+ unsigned char *bin; -+ char *p; -+ size_t n = 0; -+ int shift = 4; -+ unsigned char out = 0; -+ unsigned char *optr; -+ -+ bin = xmalloc(strlen(hex)/2); -+ optr = bin; -+ -+ for (p = hex; *p != '\0'; ++p) { -+ unsigned char c; -+ -+ c = *p; -+ if (isspace(c)) -+ continue; -+ -+ if (c >= '0' && c <= '9') { -+ c = c - '0'; -+ } else if (c >= 'A' && c <= 'F') { -+ c = c - 'A' + 10; -+ } else if (c >= 'a' && c <= 'f') { -+ c = c - 'a' + 10; -+ } else { -+ /* truncate on nonhex cipher */ -+ break; -+ } -+ -+ out |= c << shift; -+ shift = (shift + 4) % 8; -+ -+ if (shift) { -+ *(optr++) = out; -+ out = 0; -+ ++n; -+ } -+ } -+ -+ *len = n; -+ return bin; -+} -+ -+#define READ_CHUNK 4096 -+#define MAX_READ_SIZE 1024*1024*100 -+char *read_stdin(void) -+{ -+ char *buf; -+ size_t n, total = 0; -+ -+ buf = xmalloc(READ_CHUNK); -+ -+ do { -+ n = fread(buf + total, 1, READ_CHUNK, stdin); -+ if (n < READ_CHUNK) /* terminate on short read */ -+ break; -+ -+ total += n; -+ buf = xreallocarray(buf, total + READ_CHUNK, 1); -+ } while(total < MAX_READ_SIZE); -+ return buf; -+} -+ -+int main (int argc, char *argv[]) -+{ -+ -+ const struct sshcipher *c; -+ struct sshcipher_ctx *cc; -+ char *algo = "aes128-ctr"; -+ char *hexkey = NULL; -+ char *hexiv = "00000000000000000000000000000000"; -+ char *hexdata = NULL; -+ char *p; -+ int i, r; -+ int encrypt = 1; -+ void *key; -+ size_t keylen; -+ void *iv; -+ size_t ivlen; -+ void *data; -+ size_t datalen; -+ void *outdata; -+ -+ for (i = 1; i < argc; ++i) { -+ if (strcmp(argv[i], "--algo") == 0) { -+ algo = argv[++i]; -+ } else if (strcmp(argv[i], "--key") == 0) { -+ hexkey = argv[++i]; -+ } else if (strcmp(argv[i], "--mode") == 0) { -+ ++i; -+ if (argv[i] == NULL) { -+ usage(); -+ } -+ if (strncmp(argv[i], "enc", 3) == 0) { -+ encrypt = 1; -+ } else if (strncmp(argv[i], "dec", 3) == 0) { -+ encrypt = 0; -+ } else { -+ usage(); -+ } -+ } else if (strcmp(argv[i], "--iv") == 0) { -+ hexiv = argv[++i]; -+ } else if (strcmp(argv[i], "--data") == 0) { -+ hexdata = argv[++i]; -+ } -+ } -+ -+ if (hexkey == NULL || algo == NULL) { -+ usage(); -+ } -+ -+ OpenSSL_add_all_algorithms(); -+ -+ c = cipher_by_name(algo); -+ if (c == NULL) { -+ fprintf(stderr, "Error: unknown algorithm\n"); -+ return 2; -+ } -+ -+ if (hexdata == NULL) { -+ hexdata = read_stdin(); -+ } else { -+ hexdata = xstrdup(hexdata); -+ } -+ -+ key = fromhex(hexkey, &keylen); -+ -+ if (keylen != 16 && keylen != 24 && keylen == 32) { -+ fprintf(stderr, "Error: unsupported key length\n"); -+ return 2; -+ } -+ -+ iv = fromhex(hexiv, &ivlen); -+ -+ if (ivlen != 16) { -+ fprintf(stderr, "Error: unsupported iv length\n"); -+ return 2; -+ } -+ -+ data = fromhex(hexdata, &datalen); -+ -+ if (data == NULL || datalen == 0) { -+ fprintf(stderr, "Error: no data to encrypt/decrypt\n"); -+ return 2; -+ } -+ -+ if ((r = cipher_init(&cc, c, key, keylen, iv, ivlen, encrypt)) != 0) { -+ fprintf(stderr, "Error: cipher_init failed: %s\n", ssh_err(r)); -+ return 2; -+ } -+ -+ free(key); -+ free(iv); -+ -+ outdata = malloc(datalen); -+ if(outdata == NULL) { -+ fprintf(stderr, "Error: memory allocation failure\n"); -+ return 2; -+ } -+ -+ if ((r = cipher_crypt(cc, 0, outdata, data, datalen, 0, 0)) != 0) { -+ fprintf(stderr, "Error: cipher_crypt failed: %s\n", ssh_err(r)); -+ return 2; -+ } -+ -+ free(data); -+ -+ cipher_free(cc); -+ -+ for (p = outdata; datalen > 0; ++p, --datalen) { -+ printf("%02X", (unsigned char)*p); -+ } -+ -+ free(outdata); -+ -+ printf("\n"); -+ return 0; -+} -+ diff --git a/SOURCES/openssh-6.6p1-keyperm.patch b/SOURCES/openssh-6.6p1-keyperm.patch deleted file mode 100644 index fbe33b0..0000000 --- a/SOURCES/openssh-6.6p1-keyperm.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/authfile.c b/authfile.c -index e93d867..4fc5b3d 100644 ---- a/authfile.c -+++ b/authfile.c -@@ -32,6 +32,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -207,6 +208,13 @@ sshkey_perm_ok(int fd, const char *filename) - #ifdef HAVE_CYGWIN - if (check_ntsec(filename)) - #endif -+ if (st.st_mode & 040) { -+ struct group *gr; -+ -+ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid)) -+ st.st_mode &= ~040; -+ } -+ - if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); diff --git a/SOURCES/openssh-6.7p1-coverity.patch b/SOURCES/openssh-6.7p1-coverity.patch deleted file mode 100644 index d24c4a2..0000000 --- a/SOURCES/openssh-6.7p1-coverity.patch +++ /dev/null @@ -1,177 +0,0 @@ -diff -up openssh-8.0p1/channels.c.coverity openssh-8.0p1/channels.c ---- openssh-8.0p1/channels.c.coverity 2021-06-21 10:59:17.297473319 +0200 -+++ openssh-8.0p1/channels.c 2021-06-21 11:11:32.467290400 +0200 -@@ -341,15 +341,15 @@ channel_register_fds(struct ssh *ssh, Ch - * restore their blocking state on exit to avoid interfering - * with other programs that follow. - */ -- if (rfd != -1 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) { -+ if (rfd >= 0 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) { - c->restore_block |= CHANNEL_RESTORE_RFD; - set_nonblock(rfd); - } -- if (wfd != -1 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) { -+ if (wfd >= 0 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) { - c->restore_block |= CHANNEL_RESTORE_WFD; - set_nonblock(wfd); - } -- if (efd != -1 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) { -+ if (efd >= 0 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) { - c->restore_block |= CHANNEL_RESTORE_EFD; - set_nonblock(efd); - } -diff -up openssh-8.0p1/monitor.c.coverity openssh-8.0p1/monitor.c ---- openssh-8.0p1/monitor.c.coverity 2021-06-21 10:59:17.282473202 +0200 -+++ openssh-8.0p1/monitor.c 2021-06-21 10:59:17.297473319 +0200 -@@ -401,7 +401,7 @@ monitor_child_preauth(struct ssh *ssh, s - mm_get_keystate(ssh, pmonitor); - - /* Drain any buffered messages from the child */ -- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) -+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) - ; - - if (pmonitor->m_recvfd >= 0) -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("%s: cannot allocate fds for pty", __func__); -- 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 -@@ -58,7 +58,7 @@ bindresvport_sa(int sd, struct sockaddr - struct sockaddr_in6 *in6; - u_int16_t *portp; - u_int16_t port; -- socklen_t salen; -+ socklen_t salen = sizeof(struct sockaddr_storage); - int i; - - if (sa == NULL) { -diff -up openssh-7.4p1/scp.c.coverity openssh-7.4p1/scp.c ---- openssh-7.4p1/scp.c.coverity 2016-12-23 16:40:26.856788681 +0100 -+++ openssh-7.4p1/scp.c 2016-12-23 16:40:26.901788691 +0100 -@@ -157,7 +157,7 @@ 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 (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 -@@ -1547,7 +1547,7 @@ process_server_config_line(ServerOptions - fatal("%s line %d: Missing subsystem name.", - filename, linenum); - if (!*activep) { -- arg = strdelim(&cp); -+ /*arg =*/ (void) strdelim(&cp); - break; - } - for (i = 0; i < options->num_subsystems; i++) -@@ -1638,8 +1638,9 @@ process_server_config_line(ServerOptions - if (*activep && *charptr == NULL) { - *charptr = tilde_expand_filename(arg, getuid()); - /* increase optional counter */ -- if (intptr != NULL) -- *intptr = *intptr + 1; -+ /* DEAD CODE intptr is still NULL ;) -+ if (intptr != NULL) -+ *intptr = *intptr + 1; */ - } - break; - -diff -up openssh-7.4p1/serverloop.c.coverity openssh-7.4p1/serverloop.c ---- openssh-7.4p1/serverloop.c.coverity 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/serverloop.c 2016-12-23 16:40:26.902788691 +0100 -@@ -125,13 +125,13 @@ notify_setup(void) - static void - notify_parent(void) - { -- if (notify_pipe[1] != -1) -+ if (notify_pipe[1] >= 0) - (void)write(notify_pipe[1], "", 1); - } - static void - notify_prepare(fd_set *readset) - { -- if (notify_pipe[0] != -1) -+ if (notify_pipe[0] >= 0) - FD_SET(notify_pipe[0], readset); - } - static void -@@ -139,8 +139,8 @@ notify_done(fd_set *readset) - { - char c; - -- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) -- while (read(notify_pipe[0], &c, 1) != -1) -+ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) -+ while (read(notify_pipe[0], &c, 1) >= 0) - debug2("%s: reading", __func__); - } - -@@ -518,7 +518,7 @@ server_request_tun(void) - debug("%s: invalid tun", __func__); - goto done; - } -- if (auth_opts->force_tun_device != -1) { -+ if (auth_opts->force_tun_device >= 0) { - if (tun != SSH_TUNID_ANY && - auth_opts->force_tun_device != (int)tun) - goto done; -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 -@@ -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-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 -@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt) - - privsep_preauth_child(ssh); - setproctitle("%s", "[net]"); -- if (box != NULL) -+ if (box != NULL) { - ssh_sandbox_child(box); -+ free(box); -+ } - - return 0; - } -@@ -1386,6 +1388,9 @@ server_accept_loop(int *sock_in, int *so - explicit_bzero(rnd, sizeof(rnd)); - } - } -+ -+ if (fdset != NULL) -+ free(fdset); - } - - /* diff --git a/SOURCES/openssh-6.7p1-kdf-cavs.patch b/SOURCES/openssh-6.7p1-kdf-cavs.patch deleted file mode 100644 index 549cde4..0000000 --- a/SOURCES/openssh-6.7p1-kdf-cavs.patch +++ /dev/null @@ -1,618 +0,0 @@ -diff -up openssh-6.8p1/Makefile.in.kdf-cavs openssh-6.8p1/Makefile.in ---- openssh-6.8p1/Makefile.in.kdf-cavs 2015-03-18 11:23:46.346049359 +0100 -+++ openssh-6.8p1/Makefile.in 2015-03-18 11:24:20.395968445 +0100 -@@ -29,6 +29,7 @@ SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-h - SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper - SSH_KEYCAT=$(libexecdir)/ssh-keycat - CTR_CAVSTEST=$(libexecdir)/ctr-cavstest -+SSH_CAVS=$(libexecdir)/ssh-cavs - SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper - PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ -@@ -67,7 +68,7 @@ EXEEXT=@EXEEXT@ - MKDIR_P=@MKDIR_P@ - INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ - --TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) -+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) ssh-cavs$(EXEEXT) - - XMSS_OBJS=\ - ssh-xmss.o \ -@@ -198,6 +199,9 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHD - ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o - $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) - -+ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-cavs.o -+ $(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) - -@@ -331,6 +335,8 @@ install-files: - fi - $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(EXEEXT) -+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-cavs$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-cavs$(EXEEXT) -+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-cavs_driver.pl $(DESTDIR)$(libexecdir)/ssh-cavs_driver.pl - $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) - $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c ---- openssh-6.8p1/ssh-cavs.c.kdf-cavs 2015-03-18 11:23:46.348049354 +0100 -+++ openssh-6.8p1/ssh-cavs.c 2015-03-18 11:23:46.348049354 +0100 -@@ -0,0 +1,387 @@ -+/* -+ * Copyright (C) 2015, Stephan Mueller -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, and the entire permission notice in its entirety, -+ * including the disclaimer of warranties. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The name of the author may not be used to endorse or promote -+ * products derived from this software without specific prior -+ * written permission. -+ * -+ * ALTERNATIVELY, this product may be distributed under the terms of -+ * the GNU General Public License, in which case the provisions of the GPL2 -+ * are required INSTEAD OF the above restrictions. (This clause is -+ * necessary due to a potential bad interaction between the GPL and -+ * the restrictions contained in a BSD-style copyright.) -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF -+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ */ -+ -+#include "includes.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "xmalloc.h" -+#include "sshbuf.h" -+#include "sshkey.h" -+#include "cipher.h" -+#include "kex.h" -+#include "packet.h" -+#include "digest.h" -+ -+static int bin_char(unsigned char hex) -+{ -+ if (48 <= hex && 57 >= hex) -+ return (hex - 48); -+ if (65 <= hex && 70 >= hex) -+ return (hex - 55); -+ if (97 <= hex && 102 >= hex) -+ return (hex - 87); -+ return 0; -+} -+ -+/* -+ * Convert hex representation into binary string -+ * @hex input buffer with hex representation -+ * @hexlen length of hex -+ * @bin output buffer with binary data -+ * @binlen length of already allocated bin buffer (should be at least -+ * half of hexlen -- if not, only a fraction of hexlen is converted) -+ */ -+static void hex2bin(const char *hex, size_t hexlen, -+ unsigned char *bin, size_t binlen) -+{ -+ size_t i = 0; -+ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen; -+ -+ for (i = 0; i < chars; i++) { -+ bin[i] = bin_char(hex[(i*2)]) << 4; -+ bin[i] |= bin_char(hex[((i*2)+1)]); -+ } -+} -+ -+/* -+ * Allocate sufficient space for binary representation of hex -+ * and convert hex into bin -+ * -+ * Caller must free bin -+ * @hex input buffer with hex representation -+ * @hexlen length of hex -+ * @bin return value holding the pointer to the newly allocated buffer -+ * @binlen return value holding the allocated size of bin -+ * -+ * return: 0 on success, !0 otherwise -+ */ -+static int hex2bin_alloc(const char *hex, size_t hexlen, -+ unsigned char **bin, size_t *binlen) -+{ -+ unsigned char *out = NULL; -+ size_t outlen = 0; -+ -+ if (!hexlen) -+ return -EINVAL; -+ -+ outlen = (hexlen + 1) / 2; -+ -+ out = calloc(1, outlen); -+ if (!out) -+ return -errno; -+ -+ hex2bin(hex, hexlen, out, outlen); -+ *bin = out; -+ *binlen = outlen; -+ return 0; -+} -+ -+static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7', -+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; -+static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7', -+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; -+static char hex_char(unsigned int bin, int u) -+{ -+ if (bin < sizeof(hex_char_map_l)) -+ return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin]; -+ return 'X'; -+} -+ -+/* -+ * Convert binary string into hex representation -+ * @bin input buffer with binary data -+ * @binlen length of bin -+ * @hex output buffer to store hex data -+ * @hexlen length of already allocated hex buffer (should be at least -+ * twice binlen -- if not, only a fraction of binlen is converted) -+ * @u case of hex characters (0=>lower case, 1=>upper case) -+ */ -+static void bin2hex(const unsigned char *bin, size_t binlen, -+ char *hex, size_t hexlen, int u) -+{ -+ size_t i = 0; -+ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen; -+ -+ for (i = 0; i < chars; i++) { -+ hex[(i*2)] = hex_char((bin[i] >> 4), u); -+ hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u); -+ } -+} -+ -+struct kdf_cavs { -+ unsigned char *K; -+ size_t Klen; -+ unsigned char *H; -+ size_t Hlen; -+ unsigned char *session_id; -+ size_t session_id_len; -+ -+ unsigned int iv_len; -+ unsigned int ek_len; -+ unsigned int ik_len; -+}; -+ -+static int sshkdf_cavs(struct kdf_cavs *test) -+{ -+ int ret = 0; -+ struct kex kex; -+ struct sshbuf *Kb = NULL; -+ BIGNUM *Kbn = NULL; -+ int mode = 0; -+ struct newkeys *ctoskeys; -+ struct newkeys *stockeys; -+ struct ssh *ssh = NULL; -+ -+#define HEXOUTLEN 500 -+ char hex[HEXOUTLEN]; -+ -+ memset(&kex, 0, sizeof(struct kex)); -+ -+ Kbn = BN_new(); -+ BN_bin2bn(test->K, test->Klen, Kbn); -+ if (!Kbn) { -+ printf("cannot convert K into bignum\n"); -+ ret = 1; -+ goto out; -+ } -+ Kb = sshbuf_new(); -+ if (!Kb) { -+ printf("cannot convert K into sshbuf\n"); -+ ret = 1; -+ goto out; -+ } -+ sshbuf_put_bignum2(Kb, Kbn); -+ -+ kex.session_id = test->session_id; -+ kex.session_id_len = test->session_id_len; -+ -+ /* setup kex */ -+ -+ /* select the right hash based on struct ssh_digest digests */ -+ switch (test->ik_len) { -+ case 20: -+ kex.hash_alg = SSH_DIGEST_SHA1; -+ break; -+ case 32: -+ kex.hash_alg = SSH_DIGEST_SHA256; -+ break; -+ case 48: -+ kex.hash_alg = SSH_DIGEST_SHA384; -+ break; -+ case 64: -+ kex.hash_alg = SSH_DIGEST_SHA512; -+ break; -+ default: -+ printf("Wrong hash type %u\n", test->ik_len); -+ ret = 1; -+ goto out; -+ } -+ -+ /* implement choose_enc */ -+ for (mode = 0; mode < 2; mode++) { -+ kex.newkeys[mode] = calloc(1, sizeof(struct newkeys)); -+ if (!kex.newkeys[mode]) { -+ printf("allocation of newkeys failed\n"); -+ ret = 1; -+ goto out; -+ } -+ kex.newkeys[mode]->enc.iv_len = test->iv_len; -+ kex.newkeys[mode]->enc.key_len = test->ek_len; -+ kex.newkeys[mode]->enc.block_size = (test->iv_len == 64) ? 8 : 16; -+ kex.newkeys[mode]->mac.key_len = test->ik_len; -+ } -+ -+ /* implement kex_choose_conf */ -+ kex.we_need = kex.newkeys[0]->enc.key_len; -+ if (kex.we_need < kex.newkeys[0]->enc.block_size) -+ kex.we_need = kex.newkeys[0]->enc.block_size; -+ if (kex.we_need < kex.newkeys[0]->enc.iv_len) -+ kex.we_need = kex.newkeys[0]->enc.iv_len; -+ if (kex.we_need < kex.newkeys[0]->mac.key_len) -+ kex.we_need = kex.newkeys[0]->mac.key_len; -+ -+ /* MODE_OUT (1) -> server to client -+ * MODE_IN (0) -> client to server */ -+ kex.server = 1; -+ -+ /* do it */ -+ if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL){ -+ printf("Allocation error\n"); -+ goto out; -+ } -+ ssh->kex = &kex; -+ kex_derive_keys(ssh, test->H, test->Hlen, Kb); -+ -+ ctoskeys = kex.newkeys[0]; -+ stockeys = kex.newkeys[1]; -+ -+ /* get data */ -+ memset(hex, 0, HEXOUTLEN); -+ bin2hex(ctoskeys->enc.iv, (size_t)ctoskeys->enc.iv_len, -+ hex, HEXOUTLEN, 0); -+ printf("Initial IV (client to server) = %s\n", hex); -+ memset(hex, 0, HEXOUTLEN); -+ bin2hex(stockeys->enc.iv, (size_t)stockeys->enc.iv_len, -+ hex, HEXOUTLEN, 0); -+ printf("Initial IV (server to client) = %s\n", hex); -+ -+ memset(hex, 0, HEXOUTLEN); -+ bin2hex(ctoskeys->enc.key, (size_t)ctoskeys->enc.key_len, -+ hex, HEXOUTLEN, 0); -+ printf("Encryption key (client to server) = %s\n", hex); -+ memset(hex, 0, HEXOUTLEN); -+ bin2hex(stockeys->enc.key, (size_t)stockeys->enc.key_len, -+ hex, HEXOUTLEN, 0); -+ printf("Encryption key (server to client) = %s\n", hex); -+ -+ memset(hex, 0, HEXOUTLEN); -+ bin2hex(ctoskeys->mac.key, (size_t)ctoskeys->mac.key_len, -+ hex, HEXOUTLEN, 0); -+ printf("Integrity key (client to server) = %s\n", hex); -+ memset(hex, 0, HEXOUTLEN); -+ bin2hex(stockeys->mac.key, (size_t)stockeys->mac.key_len, -+ hex, HEXOUTLEN, 0); -+ printf("Integrity key (server to client) = %s\n", hex); -+ -+out: -+ if (Kbn) -+ BN_free(Kbn); -+ if (Kb) -+ sshbuf_free(Kb); -+ if (ssh) -+ ssh_packet_close(ssh); -+ return ret; -+} -+ -+static void usage(void) -+{ -+ fprintf(stderr, "\nOpenSSH KDF CAVS Test\n\n"); -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, "\t-K\tShared secret string\n"); -+ fprintf(stderr, "\t-H\tHash string\n"); -+ fprintf(stderr, "\t-s\tSession ID string\n"); -+ fprintf(stderr, "\t-i\tIV length to be generated\n"); -+ fprintf(stderr, "\t-e\tEncryption key length to be generated\n"); -+ fprintf(stderr, "\t-m\tMAC key length to be generated\n"); -+} -+ -+/* -+ * Test command example: -+ * ./ssh-cavs -K 0055d50f2d163cc07cd8a93cc7c3430c30ce786b572c01ad29fec7597000cf8618d664e2ec3dcbc8bb7a1a7eb7ef67f61cdaf291625da879186ac0a5cb27af571b59612d6a6e0627344d846271959fda61c78354aa498773d59762f8ca2d0215ec590d8633de921f920d41e47b3de6ab9a3d0869e1c826d0e4adebf8e3fb646a15dea20a410b44e969f4b791ed6a67f13f1b74234004d5fa5e87eff7abc32d49bbdf44d7b0107e8f10609233b7e2b7eff74a4daf25641de7553975dac6ac1e5117df6f6dbaa1c263d23a6c3e5a3d7d49ae8a828c1e333ac3f85fbbf57b5c1a45be45e43a7be1a4707eac779b8285522d1f531fe23f890fd38a004339932b93eda4 -H d3ab91a850febb417a25d892ec48ed5952c7a5de -s d3ab91a850febb417a25d892ec48ed5952c7a5de -i 8 -e 24 -m 20 -+ * -+ * Initial IV (client to server) = 4bb320d1679dfd3a -+ * Initial IV (server to client) = 43dea6fdf263a308 -+ * Encryption key (client to server) = 13048cc600b9d3cf9095aa6cf8e2ff9cf1c54ca0520c89ed -+ * Encryption key (server to client) = 1e483c5134e901aa11fc4e0a524e7ec7b75556148a222bb0 -+ * Integrity key (client to server) = ecef63a092b0dcc585bdc757e01b2740af57d640 -+ * Integrity key (server to client) = 7424b05f3c44a72b4ebd281fb71f9cbe7b64d479 -+ */ -+int main(int argc, char *argv[]) -+{ -+ struct kdf_cavs test; -+ int ret = 1; -+ int opt = 0; -+ -+ memset(&test, 0, sizeof(struct kdf_cavs)); -+ while((opt = getopt(argc, argv, "K:H:s:i:e:m:")) != -1) -+ { -+ size_t len = 0; -+ switch(opt) -+ { -+ /* -+ * CAVS K is MPINT -+ * we want a hex (i.e. the caller must ensure the -+ * following transformations already happened): -+ * 1. cut off first four bytes -+ * 2. if most significant bit of value is -+ * 1, prepend 0 byte -+ */ -+ case 'K': -+ len = strlen(optarg); -+ ret = hex2bin_alloc(optarg, len, -+ &test.K, &test.Klen); -+ if (ret) -+ goto out; -+ break; -+ case 'H': -+ len = strlen(optarg); -+ ret = hex2bin_alloc(optarg, len, -+ &test.H, &test.Hlen); -+ if (ret) -+ goto out; -+ break; -+ case 's': -+ len = strlen(optarg); -+ ret = hex2bin_alloc(optarg, len, -+ &test.session_id, -+ &test.session_id_len); -+ if (ret) -+ goto out; -+ break; -+ case 'i': -+ test.iv_len = strtoul(optarg, NULL, 10); -+ break; -+ case 'e': -+ test.ek_len = strtoul(optarg, NULL, 10); -+ break; -+ case 'm': -+ test.ik_len = strtoul(optarg, NULL, 10); -+ break; -+ default: -+ usage(); -+ goto out; -+ } -+ } -+ -+ ret = sshkdf_cavs(&test); -+ -+out: -+ if (test.session_id) -+ free(test.session_id); -+ if (test.K) -+ free(test.K); -+ if (test.H) -+ free(test.H); -+ return ret; -+ -+} -diff -up openssh-6.8p1/ssh-cavs_driver.pl.kdf-cavs openssh-6.8p1/ssh-cavs_driver.pl ---- openssh-6.8p1/ssh-cavs_driver.pl.kdf-cavs 2015-03-18 11:23:46.348049354 +0100 -+++ openssh-6.8p1/ssh-cavs_driver.pl 2015-03-18 11:23:46.348049354 +0100 -@@ -0,0 +1,184 @@ -+#!/usr/bin/env perl -+# -+# CAVS test driver for OpenSSH -+# -+# Copyright (C) 2015, Stephan Mueller -+# -+# Permission is hereby granted, free of charge, to any person obtaining a copy -+# of this software and associated documentation files (the "Software"), to deal -+# in the Software without restriction, including without limitation the rights -+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+# copies of the Software, and to permit persons to whom the Software is -+# furnished to do so, subject to the following conditions: -+# -+# The above copyright notice and this permission notice shall be included in -+# all copies or substantial portions of the Software. -+# -+# NO WARRANTY -+# -+# BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -+# FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -+# OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -+# PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -+# OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -+# TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -+# PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -+# REPAIR OR CORRECTION. -+# -+# IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -+# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -+# REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -+# INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -+# OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -+# TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -+# YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -+# PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -+# POSSIBILITY OF SUCH DAMAGES. -+# -+use strict; -+use warnings; -+use IPC::Open2; -+ -+# Executing a program by feeding STDIN and retrieving -+# STDOUT -+# $1: data string to be piped to the app on STDIN -+# rest: program and args -+# returns: STDOUT of program as string -+sub pipe_through_program($@) { -+ my $in = shift; -+ my @args = @_; -+ -+ my ($CO, $CI); -+ my $pid = open2($CO, $CI, @args); -+ -+ my $out = ""; -+ my $len = length($in); -+ my $first = 1; -+ while (1) { -+ my $rin = ""; -+ my $win = ""; -+ # Output of prog is FD that we read -+ vec($rin,fileno($CO),1) = 1; -+ # Input of prog is FD that we write -+ # check for $first is needed because we can have NULL input -+ # that is to be written to the app -+ if ( $len > 0 || $first) { -+ (vec($win,fileno($CI),1) = 1); -+ $first=0; -+ } -+ # Let us wait for 100ms -+ my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1); -+ if ( $wout ) { -+ my $written = syswrite($CI, $in, $len); -+ die "broken pipe" if !defined $written; -+ $len -= $written; -+ substr($in, 0, $written) = ""; -+ if ($len <= 0) { -+ close $CI or die "broken pipe: $!"; -+ } -+ } -+ if ( $rout ) { -+ my $tmp_out = ""; -+ my $bytes_read = sysread($CO, $tmp_out, 4096); -+ $out .= $tmp_out; -+ last if ($bytes_read == 0); -+ } -+ } -+ close $CO or die "broken pipe: $!"; -+ waitpid $pid, 0; -+ -+ return $out; -+} -+ -+# Parser of CAVS test vector file -+# $1: Test vector file -+# $2: Output file for test results -+# return: nothing -+sub parse($$) { -+ my $infile = shift; -+ my $outfile = shift; -+ -+ my $out = ""; -+ -+ my $K = ""; -+ my $H = ""; -+ my $session_id = ""; -+ my $ivlen = 0; -+ my $eklen = ""; -+ my $iklen = ""; -+ -+ open(IN, "<$infile"); -+ while() { -+ -+ my $line = $_; -+ chomp($line); -+ $line =~ s/\r//; -+ -+ if ($line =~ /\[SHA-1\]/) { -+ $iklen = 20; -+ } elsif ($line =~ /\[SHA-256\]/) { -+ $iklen = 32; -+ } elsif ($line =~ /\[SHA-384\]/) { -+ $iklen = 48; -+ } elsif ($line =~ /\[SHA-512\]/) { -+ $iklen = 64; -+ } elsif ($line =~ /^\[IV length\s*=\s*(.*)\]/) { -+ $ivlen = $1; -+ $ivlen = $ivlen / 8; -+ } elsif ($line =~ /^\[encryption key length\s*=\s*(.*)\]/) { -+ $eklen = $1; -+ $eklen = $eklen / 8; -+ } elsif ($line =~ /^K\s*=\s*(.*)/) { -+ $K = $1; -+ $K = substr($K, 8); -+ $K = "00" . $K; -+ } elsif ($line =~ /^H\s*=\s*(.*)/) { -+ $H = $1; -+ } elsif ($line =~ /^session_id\s*=\s*(.*)/) { -+ $session_id = $1; -+ } -+ $out .= $line . "\n"; -+ -+ if ($K ne "" && $H ne "" && $session_id ne "" && -+ $ivlen ne "" && $eklen ne "" && $iklen > 0) { -+ $out .= pipe_through_program("", "./ssh-cavs -H $H -K $K -s $session_id -i $ivlen -e $eklen -m $iklen"); -+ -+ $K = ""; -+ $H = ""; -+ $session_id = ""; -+ } -+ } -+ close IN; -+ $out =~ s/\n/\r\n/g; # make it a dos file -+ open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?"; -+ print OUT $out; -+ close OUT; -+} -+ -+############################################################ -+# -+# let us pretend to be C :-) -+sub main() { -+ -+ my $infile=$ARGV[0]; -+ die "Error: Test vector file $infile not found" if (! -f $infile); -+ -+ my $outfile = $infile; -+ # let us add .rsp regardless whether we could strip .req -+ $outfile =~ s/\.req$//; -+ $outfile .= ".rsp"; -+ if (-f $outfile) { -+ die "Output file $outfile could not be removed: $?" -+ unless unlink($outfile); -+ } -+ print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n"; -+ -+ # Do the job -+ parse($infile, $outfile); -+} -+ -+########################################### -+# Call it -+main(); -+1; diff --git a/SOURCES/openssh-6.7p1-ldap.patch b/SOURCES/openssh-6.7p1-ldap.patch deleted file mode 100644 index e5de1bb..0000000 --- a/SOURCES/openssh-6.7p1-ldap.patch +++ /dev/null @@ -1,2746 +0,0 @@ -diff -up openssh-6.8p1/HOWTO.ldap-keys.ldap openssh-6.8p1/HOWTO.ldap-keys ---- openssh-6.8p1/HOWTO.ldap-keys.ldap 2015-03-18 11:11:29.029801467 +0100 -+++ openssh-6.8p1/HOWTO.ldap-keys 2015-03-18 11:11:29.029801467 +0100 -@@ -0,0 +1,122 @@ -+ -+HOW TO START -+ -+1) configure LDAP server -+ * Use LDAP server documentation -+2) add appropriate LDAP schema -+ * For OpenLDAP or SunONE Use attached schema, otherwise you have to create it. -+ * LDAP user entry -+ User entry: -+ - attached to the 'ldapPublicKey' objectclass -+ - attached to the 'posixAccount' objectclass -+ - with a filled 'sshPublicKey' attribute -+3) insert users into LDAP -+ * Use LDAP Tree management tool as useful -+ * Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' which are defined in core.schema and the additionnal lpk.schema. -+ * Example: -+ dn: uid=captain,ou=commanders,dc=enterprise,dc=universe -+ objectclass: top -+ objectclass: person -+ objectclass: organizationalPerson -+ objectclass: posixAccount -+ objectclass: ldapPublicKey -+ description: Jonathan Archer -+ userPassword: Porthos -+ cn: onathan Archer -+ sn: onathan Archer -+ uid: captain -+ uidNumber: 1001 -+ gidNumber: 1001 -+ homeDirectory: /home/captain -+ sshPublicKey: ssh-rss AAAAB3.... =captain@universe -+ sshPublicKey: command="kill -9 1" ssh-rss AAAAM5... -+4) on the ssh side set in sshd_config -+ * Set up the backend -+ AuthorizedKeysCommand /usr/libexec/openssh/ssh-ldap-wrapper -+ AuthorizedKeysCommandUser -+ * Do not forget to set -+ PubkeyAuthentication yes -+ * Swith off unnecessary auth methods -+5) confugure ldap.conf -+ * Default ldap.conf is placed in /etc/ssh -+ * The configuration style is the same as other ldap based aplications -+6) if necessary edit ssh-ldap-wrapper -+ * There is a possibility to change ldap.conf location -+ * There are some debug options -+ * Example -+ /usr/libexec/openssh -s -f /etc/ldap.conf -w -d >> /tmp/ldapdebuglog.txt -+7) Configure SELinux boolean which allows ldap-helper to bind ldap server -+ Run this command -+ # setsebool -P authlogin_nsswitch_use_ldap on -+ -+HOW TO MIGRATE FROM LPK -+ -+1) goto HOW TO START 4) .... the ldap schema is the same -+ -+2) convert the group requests to the appropriate LDAP requests -+ -+HOW TO SOLVE PROBLEMS -+ -+1) use debug in sshd -+ * /usr/sbin/sshd -d -d -d -d -+2) use debug in ssh-ldap-helper -+ * ssh-ldap-helper -d -d -d -d -s -+3) use tcpdump ... other ldap client etc. -+ -+HOW TO CONFIGURE SSH FOR OTHER LDAP CONFIGURATION / SERVER /SCHEMA -+ -+You can adjust search format string in /etc/ldap.conf using -+ 1) SSH_Filter option to limit results for only specified users -+ (this appends search condition after original query) -+ 2) Search_Format option to define your own search string using expansion -+ characters %u for username, %c for objectclass and %f for above mentioned filter. -+ -+Example: -+Search_Format (&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%u)%f) -+ -+ADVANTAGES -+ -+1) Blocking an user account can be done directly from LDAP (if sshd is using PubkeyAuthentication + AuthorizedKeysCommand with ldap only). -+ -+DISADVANTAGES -+ -+1) LDAP must be well configured, getting the public key of some user is not a problem, but if anonymous LDAP -+ allows write to users dn, somebody could replace some user's public key by his own and impersonate some -+ of your users in all your server farm -- be VERY CAREFUL. -+2) With incomplete PKI the MITM attack when sshd is requesting the public key, could lead to a compromise of your servers allowing login -+ as the impersonated user. -+3) If LDAP server is down there may be no fallback on passwd auth. -+ -+MISC. -+ -+1) todo -+ * Possibility to reuse the ssh-ldap-helper. -+ * Tune the LDAP part to accept all possible LDAP configurations. -+ -+2) differences from original lpk -+ * No LDAP code in sshd. -+ * Support for various LDAP platforms and configurations. -+ * LDAP is configured in separate ldap.conf file. -+ -+3) docs/link -+ * http://pacsec.jp/core05/psj05-barisani-en.pdf -+ * http://fritz.potsdam.edu/projects/openssh-lpk/ -+ * http://fritz.potsdam.edu/projects/sshgate/ -+ * http://dev.inversepath.com/trac/openssh-lpk -+ * http://lam.sf.net/ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm ) -+ -+4) contributors/ideas/greets -+ - Eric AUGE -+ - Andrea Barisani -+ - Falk Siemonsmeier. -+ - Jacob Rief. -+ - Michael Durchgraf. -+ - frederic peters. -+ - Finlay dobbie. -+ - Stefan Fisher. -+ - Robin H. Johnson. -+ - Adrian Bridgett. -+ -+5) Author -+ Jan F. Chadima -+ -diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in ---- openssh-6.8p1/Makefile.in.ldap 2015-03-17 06:49:20.000000000 +0100 -+++ openssh-6.8p1/Makefile.in 2015-03-18 11:13:10.147561177 +0100 -@@ -25,6 +25,8 @@ SSH_PROGRAM=@bindir@/ssh - ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass - SFTP_SERVER=$(libexecdir)/sftp-server - SSH_KEYSIGN=$(libexecdir)/ssh-keysign -+SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper -+SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper - SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper - PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ -@@ -50,6 +50,7 @@ - CFLAGS=@CFLAGS@ - CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ - LIBS=@LIBS@ -+LDAPLIBS=@LDAPLIBS@ - K5LIBS=@K5LIBS@ - GSSLIBS=@GSSLIBS@ - SSHLIBS=@SSHLIBS@ -@@ -61,8 +63,9 @@ XAUTH_PATH=@XAUTH_PATH@ - EXEEXT=@EXEEXT@ - MANFMT=@MANFMT@ - MKDIR_P=@MKDIR_P@ -+INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ - --TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) -+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) - - XMSS_OBJS=\ - ssh-xmss.o \ -@@ -112,8 +115,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw - sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \ - sandbox-solaris.o uidswap.o - --MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out --MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 -+MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap-helper.8.out ssh-ldap.conf.5.out -+MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 ssh-ldap-helper.8 ssh-ldap.conf.5 - MANTYPE = @MANTYPE@ - - CONFIGFILES=sshd_config.out ssh_config.out moduli.out -@@ -184,6 +187,9 @@ ssh-keysign$(EXEEXT): $(LIBCOMPAT) libss - ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o - $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) - -+ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o -+ $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LDAPLIBS) -+ - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) - -@@ -311,6 +317,10 @@ install-files: - $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) - $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) -+ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ -+ $(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \ -+ $(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ -+ fi - $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) - $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -@@ -327,6 +337,10 @@ install-files: - $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 - $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 - $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 -+ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ -+ $(INSTALL) -m 644 ssh-ldap-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 ; \ -+ $(INSTALL) -m 644 ssh-ldap.conf.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh-ldap.conf.5 ; \ -+ fi - - install-sysconf: - $(MKDIR_P) $(DESTDIR)$(sysconfdir) -@@ -356,6 +370,13 @@ install-sysconf: - else \ - echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \ - fi -+ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ -+ if [ ! -f $(DESTDIR)$(sysconfdir)/ldap.conf ]; then \ -+ $(INSTALL) -m 644 ldap.conf $(DESTDIR)$(sysconfdir)/ldap.conf; \ -+ else \ -+ echo "$(DESTDIR)$(sysconfdir)/ldap.conf already exists, install will not overwrite"; \ -+ fi ; \ -+ fi - - host-key: ssh-keygen$(EXEEXT) - @if [ -z "$(DESTDIR)" ] ; then \ -@@ -419,6 +440,8 @@ uninstall: - -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) - -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) - -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) -+ -rm -f $(DESTDIR)$(SSH_LDAP_HELPER)$(EXEEXT) -+ -rm -f $(DESTDIR)$(SSH_LDAP_WRAPPER)$(EXEEXT) - -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 - -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 - -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 -@@ -430,6 +453,7 @@ uninstall: - -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 - -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 - -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 -+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 - - regress-prep: - $(MKDIR_P) `pwd`/regress/unittests/test_helper -diff -up openssh-6.8p1/configure.ac.ldap openssh-6.8p1/configure.ac ---- openssh-6.8p1/configure.ac.ldap 2015-03-17 06:49:20.000000000 +0100 -+++ openssh-6.8p1/configure.ac 2015-03-18 11:11:29.030801464 +0100 -@@ -1605,6 +1605,110 @@ if test "x$use_pie" != "xno"; then - fi - fi - -+# Check whether user wants LDAP support -+LDAP_MSG="no" -+INSTALL_SSH_LDAP_HELPER="" -+AC_ARG_WITH(ldap, -+ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)], -+ [ -+ if test "x$withval" != "xno" ; then -+ -+ INSTALL_SSH_LDAP_HELPER="yes" -+ CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED" -+ -+ if test "x$withval" != "xyes" ; then -+ CPPFLAGS="$CPPFLAGS -I${withval}/include" -+ LDFLAGS="$LDFLAGS -L${withval}/lib" -+ fi -+ -+ AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support]) -+ LDAP_MSG="yes" -+ -+ AC_CHECK_HEADERS(lber.h) -+ AC_CHECK_HEADERS(ldap.h, , AC_MSG_ERROR(could not locate )) -+ AC_CHECK_HEADERS(ldap_ssl.h) -+ -+ AC_ARG_WITH(ldap-lib, -+ [ --with-ldap-lib=type select ldap library [auto|netscape5|netscape4|netscape3|umich|openldap]]) -+ -+ if test -z "$with_ldap_lib"; then -+ with_ldap_lib=auto -+ fi -+ -+ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = umich -o $with_ldap_lib = openldap \); then -+ AC_CHECK_LIB(lber, main, LDAPLIBS="-llber $LDAPLIBS" found_ldap_lib=yes) -+ AC_CHECK_LIB(ldap, main, LDAPLIBS="-lldap $LDAPLIBS" found_ldap_lib=yes) -+ fi -+ -+ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape5 \); then -+ AC_CHECK_LIB(ldap50, main, LDAPLIBS="-lldap50 -lssldap50 -lssl3 -lnss3 -lnspr4 -lprldap50 -lplc4 -lplds4 $LDAPLIBS" found_ldap_lib=yes) -+ fi -+ -+ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape4 \); then -+ AC_CHECK_LIB(ldapssl41, main, LDAPLIBS="-lldapssl41 -lplc3 -lplds3 -lnspr3 $LDAPLIBS" found_ldap_lib=yes) -+ if test -z "$found_ldap_lib"; then -+ AC_CHECK_LIB(ldapssl40, main, LDAPLIBS="-lldapssl40 $LDAPLIBS" found_ldap_lib=yes) -+ fi -+ if test -z "$found_ldap_lib"; then -+ AC_CHECK_LIB(ldap41, main, LDAPLIBS="-lldap41 $LDAPLIBS" found_ldap_lib=yes) -+ fi -+ if test -z "$found_ldap_lib"; then -+ AC_CHECK_LIB(ldap40, main, LDAPLIBS="-lldap40 $LDAPLIBS" found_ldap_lib=yes) -+ fi -+ fi -+ -+ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape3 \); then -+ AC_CHECK_LIB(ldapssl30, main, LDAPLIBS="-lldapssl30 $LDAPLIBS" found_ldap_lib=yes) -+ fi -+ -+ if test -z "$found_ldap_lib"; then -+ AC_MSG_ERROR(could not locate a valid LDAP library) -+ fi -+ -+ saved_LIBS="$LIBS" -+ LIBS="$LIBS $LDAPLIBS" -+ AC_MSG_CHECKING([for working LDAP support]) -+ AC_TRY_COMPILE( -+ [#include -+ #include ], -+ [(void)ldap_init(0, 0);], -+ [AC_MSG_RESULT(yes)], -+ [ -+ AC_MSG_RESULT(no) -+ AC_MSG_ERROR([** Incomplete or missing ldap libraries **]) -+ ]) -+ AC_CHECK_FUNCS( \ -+ ldap_init \ -+ ldap_get_lderrno \ -+ ldap_set_lderrno \ -+ ldap_parse_result \ -+ ldap_memfree \ -+ ldap_controls_free \ -+ ldap_set_option \ -+ ldap_get_option \ -+ ldapssl_init \ -+ ldap_start_tls_s \ -+ ldap_pvt_tls_set_option \ -+ ldap_initialize \ -+ ) -+ AC_CHECK_FUNCS(ldap_set_rebind_proc, -+ AC_MSG_CHECKING([number arguments of ldap_set_rebind_proc]) -+ AC_TRY_COMPILE( -+ [#include -+ #include ], -+ [ldap_set_rebind_proc(0, 0, 0);], -+ [ac_cv_ldap_set_rebind_proc=3], -+ [ac_cv_ldap_set_rebind_proc=2]) -+ AC_MSG_RESULT($ac_cv_ldap_set_rebind_proc) -+ AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $ac_cv_ldap_set_rebind_proc, [number arguments of ldap_set_rebind_proc]) -+ ) -+ LIBS="$saved_LIBS" -+ fi -+ ] -+) -+AC_SUBST(INSTALL_SSH_LDAP_HELPER) -+AC_SUBST(LDAPLIBS) -+ - dnl Checks for library functions. Please keep in alphabetical order - AC_CHECK_FUNCS([ \ - Blowfish_initstate \ -@@ -5227,6 +5352,9 @@ - echo "Preprocessor flags: ${CPPFLAGS}" - echo " Linker flags: ${LDFLAGS}" - echo " Libraries: ${LIBS}" -+if test ! -z "${LDAPLIBS}"; then -+echo " +for ldap: ${LDAPLIBS}" -+fi - if test ! -z "${SSHDLIBS}"; then - echo " +for sshd: ${SSHDLIBS}" - fi -diff -up openssh-6.8p1/ldap-helper.c.ldap openssh-6.8p1/ldap-helper.c ---- openssh-6.8p1/ldap-helper.c.ldap 2015-03-18 11:11:29.030801464 +0100 -+++ openssh-6.8p1/ldap-helper.c 2015-03-18 11:11:29.030801464 +0100 -@@ -0,0 +1,151 @@ -+/* $OpenBSD: ssh-pka-ldap.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ -+/* -+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "ldapincludes.h" -+#include "log.h" -+#include "misc.h" -+#include "xmalloc.h" -+#include "ldapconf.h" -+#include "ldapbody.h" -+#include -+#include -+#include -+ -+static int config_debug = 0; -+int config_exclusive_config_file = 0; -+static char *config_file_name = "/etc/ssh/ldap.conf"; -+static char *config_single_user = NULL; -+static int config_verbose = SYSLOG_LEVEL_VERBOSE; -+int config_warning_config_file = 0; -+extern char *__progname; -+ -+static void -+usage(void) -+{ -+ fprintf(stderr, "usage: %s [options]\n", -+ __progname); -+ fprintf(stderr, "Options:\n"); -+ fprintf(stderr, " -d Output the log messages to stderr.\n"); -+ fprintf(stderr, " -e Check the config file for unknown commands.\n"); -+ fprintf(stderr, " -f file Use alternate config file (default is /etc/ssh/ldap.conf).\n"); -+ fprintf(stderr, " -s user Do not demonize, send the user's key to stdout.\n"); -+ fprintf(stderr, " -v Increase verbosity of the debug output (implies -d).\n"); -+ fprintf(stderr, " -w Warn on unknown commands in the config file.\n"); -+ exit(1); -+} -+ -+/* -+ * Main program for the ssh pka ldap agent. -+ */ -+ -+int -+main(int ac, char **av) -+{ -+ int opt; -+ FILE *outfile = NULL; -+ -+ __progname = ssh_get_progname(av[0]); -+ -+ log_init(__progname, SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); -+ -+ /* -+ * Initialize option structure to indicate that no values have been -+ * set. -+ */ -+ initialize_options(); -+ -+ /* Parse command-line arguments. */ -+ while ((opt = getopt(ac, av, "def:s:vw")) != -1) { -+ switch (opt) { -+ case 'd': -+ config_debug = 1; -+ break; -+ -+ case 'e': -+ config_exclusive_config_file = 1; -+ config_warning_config_file = 1; -+ break; -+ -+ case 'f': -+ config_file_name = optarg; -+ break; -+ -+ case 's': -+ config_single_user = optarg; -+ outfile = fdopen (dup (fileno (stdout)), "w"); -+ break; -+ -+ case 'v': -+ config_debug = 1; -+ if (config_verbose < SYSLOG_LEVEL_DEBUG3) -+ config_verbose++; -+ break; -+ -+ case 'w': -+ config_warning_config_file = 1; -+ break; -+ -+ case '?': -+ default: -+ usage(); -+ break; -+ } -+ } -+ -+ /* Initialize loging */ -+ log_init(__progname, config_verbose, SYSLOG_FACILITY_AUTH, config_debug); -+ -+ if (ac != optind) -+ fatal ("illegal extra parameter %s", av[1]); -+ -+ /* Ensure that fds 0 and 2 are open or directed to /dev/null */ -+ if (config_debug == 0) -+ sanitise_stdfd(); -+ -+ /* Read config file */ -+ read_config_file(config_file_name); -+ fill_default_options(); -+ if (config_verbose == SYSLOG_LEVEL_DEBUG3) { -+ debug3 ("=== Configuration ==="); -+ dump_config(); -+ debug3 ("=== *** ==="); -+ } -+ -+ ldap_checkconfig(); -+ ldap_do_connect(); -+ -+ if (config_single_user) { -+ process_user (config_single_user, outfile); -+ } else { -+ usage(); -+ fatal ("Not yet implemented"); -+/* TODO -+ * open unix socket a run the loop on it -+ */ -+ } -+ -+ ldap_do_close(); -+ return 0; -+} -diff -up openssh-6.8p1/ldap-helper.h.ldap openssh-6.8p1/ldap-helper.h ---- openssh-6.8p1/ldap-helper.h.ldap 2015-03-18 11:11:29.031801462 +0100 -+++ openssh-6.8p1/ldap-helper.h 2015-03-18 11:11:29.031801462 +0100 -@@ -0,0 +1,32 @@ -+/* $OpenBSD: ldap-helper.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ -+/* -+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef LDAP_HELPER_H -+#define LDAP_HELPER_H -+ -+extern int config_exclusive_config_file; -+extern int config_warning_config_file; -+ -+#endif /* LDAP_HELPER_H */ -diff -up openssh-6.8p1/ldap.conf.ldap openssh-6.8p1/ldap.conf ---- openssh-6.8p1/ldap.conf.ldap 2015-03-18 11:11:29.031801462 +0100 -+++ openssh-6.8p1/ldap.conf 2015-03-18 11:11:29.031801462 +0100 -@@ -0,0 +1,95 @@ -+# $Id: openssh-5.5p1-ldap.patch,v 1.3 2010/07/07 13:48:36 jfch2222 Exp $ -+# -+# This is the example configuration file for the OpenSSH -+# LDAP backend -+# -+# see ssh-ldap.conf(5) -+# -+ -+# URI with your LDAP server name. This allows to use -+# Unix Domain Sockets to connect to a local LDAP Server. -+#uri ldap://127.0.0.1/ -+#uri ldaps://127.0.0.1/ -+#uri ldapi://%2fvar%2frun%2fldapi_sock/ -+# Note: %2f encodes the '/' used as directory separator -+ -+# Another way to specify your LDAP server is to provide an -+# host name and the port of our LDAP server. Host name -+# must be resolvable without using LDAP. -+# Multiple hosts may be specified, each separated by a -+# space. How long nss_ldap takes to failover depends on -+# whether your LDAP client library supports configurable -+# network or connect timeouts (see bind_timelimit). -+#host 127.0.0.1 -+ -+# The port. -+# Optional: default is 389. -+#port 389 -+ -+# The distinguished name to bind to the server with. -+# Optional: default is to bind anonymously. -+#binddn cn=openssh_keys,dc=example,dc=org -+ -+# The credentials to bind with. -+# Optional: default is no credential. -+#bindpw TopSecret -+ -+# The distinguished name of the search base. -+#base dc=example,dc=org -+ -+# The LDAP version to use (defaults to 3 -+# if supported by client library) -+#ldap_version 3 -+ -+# The search scope. -+#scope sub -+#scope one -+#scope base -+ -+# Search timelimit -+#timelimit 30 -+ -+# Bind/connect timelimit -+#bind_timelimit 30 -+ -+# Reconnect policy: hard (default) will retry connecting to -+# the software with exponential backoff, soft will fail -+# immediately. -+#bind_policy hard -+ -+# SSL setup, may be implied by URI also. -+#ssl no -+#ssl on -+#ssl start_tls -+ -+# OpenLDAP SSL options -+# Require and verify server certificate (yes/no) -+# Default is to use libldap's default behavior, which can be configured in -+# /etc/openldap/ldap.conf using the TLS_REQCERT setting. The default for -+# OpenLDAP 2.0 and earlier is "no", for 2.1 and later is "yes". -+#tls_checkpeer hard -+ -+# CA certificates for server certificate verification -+# At least one of these are required if tls_checkpeer is "yes" -+#tls_cacertfile /etc/ssl/ca.cert -+#tls_cacertdir /etc/pki/tls/certs -+ -+# Seed the PRNG if /dev/urandom is not provided -+#tls_randfile /var/run/egd-pool -+ -+# SSL cipher suite -+# See man ciphers for syntax -+#tls_ciphers TLSv1 -+ -+# Client certificate and key -+# Use these, if your server requires client authentication. -+#tls_cert -+#tls_key -+ -+# OpenLDAP search_format -+# format used to search for users in LDAP directory using substitution -+# for %u for user name and %f for SSH_Filter option (optional, empty by default) -+#search_format (&(objectclass=%c)(objectclass=ldapPublicKey)(uid=%u)%f) -+ -+#AccountClass posixAccount -+ -diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c ---- openssh-6.8p1/ldapbody.c.ldap 2015-03-18 11:11:29.031801462 +0100 -+++ openssh-6.8p1/ldapbody.c 2015-03-18 11:11:29.031801462 +0100 -@@ -0,0 +1,499 @@ -+/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ -+/* -+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "ldapincludes.h" -+#include "log.h" -+#include "xmalloc.h" -+#include "ldapconf.h" -+#include "ldapmisc.h" -+#include "ldapbody.h" -+#include -+#include -+#include -+#include "misc.h" -+ -+#define LDAPSEARCH_FORMAT "(&(objectclass=%c)(objectclass=ldapPublicKey)(uid=%u)%f)" -+#define PUBKEYATTR "sshPublicKey" -+#define LDAP_LOGFILE "%s/ldap.%d" -+ -+static FILE *logfile = NULL; -+static LDAP *ld; -+ -+static char *attrs[] = { -+ PUBKEYATTR, -+ NULL -+}; -+ -+void -+ldap_checkconfig (void) -+{ -+#ifdef HAVE_LDAP_INITIALIZE -+ if (options.host == NULL && options.uri == NULL) -+#else -+ if (options.host == NULL) -+#endif -+ fatal ("missing \"host\" in config file"); -+} -+ -+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -+static int -+#if LDAP_API_VERSION > 3000 -+_rebind_proc (LDAP * ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params) -+#else -+_rebind_proc (LDAP * ld, LDAP_CONST char *url, int request, ber_int_t msgid) -+#endif -+{ -+ struct timeval timeout; -+ int rc; -+#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) -+ LDAPMessage *result; -+#endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */ -+ -+ debug2 ("Doing LDAP rebind to %s", options.binddn); -+ if (options.ssl == SSL_START_TLS) { -+ if ((rc = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) { -+ error ("ldap_starttls_s: %s", ldap_err2string (rc)); -+ return LDAP_OPERATIONS_ERROR; -+ } -+ } -+ -+#if !defined(HAVE_LDAP_PARSE_RESULT) || !defined(HAVE_LDAP_CONTROLS_FREE) -+ return ldap_simple_bind_s (ld, options.binddn, options.bindpw); -+#else -+ if (ldap_simple_bind(ld, options.binddn, options.bindpw) < 0) -+ fatal ("ldap_simple_bind %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); -+ -+ timeout.tv_sec = options.bind_timelimit; -+ timeout.tv_usec = 0; -+ result = NULL; -+ if ((rc = ldap_result (ld, msgid, 0, &timeout, &result)) < 1) { -+ error ("ldap_result %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); -+ ldap_msgfree (result); -+ return LDAP_OPERATIONS_ERROR; -+ } -+ debug3 ("LDAP rebind to %s succesfull", options.binddn); -+ return rc; -+#endif -+} -+#else -+ -+static int -+_rebind_proc (LDAP * ld, char **whop, char **credp, int *methodp, int freeit) -+{ -+ if (freeit) -+ return LDAP_SUCCESS; -+ -+ *whop = strdup (options.binddn); -+ *credp = strdup (options.bindpw); -+ *methodp = LDAP_AUTH_SIMPLE; -+ debug2 ("Doing LDAP rebind for %s", *whop); -+ return LDAP_SUCCESS; -+} -+#endif -+ -+void -+ldap_do_connect(void) -+{ -+ int rc, msgid, ld_errno = 0; -+ struct timeval timeout; -+#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) -+ int parserc; -+ LDAPMessage *result; -+ LDAPControl **controls; -+ int reconnect = 0; -+#endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */ -+ -+ debug ("LDAP do connect"); -+ -+retry: -+ if (reconnect) { -+ debug3 ("Reconnecting with ld_errno %d", ld_errno); -+ if (options.bind_policy == 0 || -+ (ld_errno != LDAP_SERVER_DOWN && ld_errno != LDAP_TIMEOUT) || -+ reconnect > 5) -+ fatal ("Cannot connect to LDAP server"); -+ -+ if (reconnect > 1) -+ sleep (reconnect - 1); -+ -+ if (ld != NULL) { -+ ldap_unbind (ld); -+ ld = NULL; -+ } -+ logit("reconnecting to LDAP server..."); -+ } -+ -+ if (ld == NULL) { -+ int rc; -+ struct timeval tv; -+ -+#ifdef HAVE_LDAP_SET_OPTION -+ if (options.debug > 0) { -+#ifdef LBER_OPT_LOG_PRINT_FILE -+ if (options.logdir) { -+ char *logfilename; -+ int logfilenamelen; -+ -+ logfilenamelen = strlen(LDAP_LOGFILE) -+ + strlen("000000") + strlen (options.logdir); -+ logfilename = xmalloc (logfilenamelen); -+ snprintf (logfilename, logfilenamelen, LDAP_LOGFILE, options.logdir, (int) getpid ()); -+ logfilename[logfilenamelen - 1] = 0; -+ if ((logfile = fopen (logfilename, "a")) == NULL) -+ fatal ("cannot append to %s: %s", logfilename, strerror (errno)); -+ debug3 ("LDAP debug into %s", logfilename); -+ free (logfilename); -+ ber_set_option (NULL, LBER_OPT_LOG_PRINT_FILE, logfile); -+ } -+#endif -+ if (options.debug) { -+#ifdef LBER_OPT_DEBUG_LEVEL -+ ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &options.debug); -+#endif /* LBER_OPT_DEBUG_LEVEL */ -+#ifdef LDAP_OPT_DEBUG_LEVEL -+ (void) ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &options.debug); -+#endif /* LDAP_OPT_DEBUG_LEVEL */ -+ debug3 ("Set LDAP debug to %d", options.debug); -+ } -+ } -+#endif /* HAVE_LDAP_SET_OPTION */ -+ -+ ld = NULL; -+#ifdef HAVE_LDAPSSL_INIT -+ if (options.host != NULL) { -+ if (options.ssl_on == SSL_LDAPS) { -+ if ((rc = ldapssl_client_init (options.sslpath, NULL)) != LDAP_SUCCESS) -+ fatal ("ldapssl_client_init %s", ldap_err2string (rc)); -+ debug3 ("LDAPssl client init"); -+ } -+ -+ if (options.ssl_on != SSL_OFF) { -+ if ((ld = ldapssl_init (options.host, options.port, 1)) == NULL) -+ fatal ("ldapssl_init failed"); -+ debug3 ("LDAPssl init"); -+ } -+ } -+#endif /* HAVE_LDAPSSL_INIT */ -+ -+ /* continue with opening */ -+ if (ld == NULL) { -+#if defined (HAVE_LDAP_START_TLS_S) || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) -+ /* Some global TLS-specific options need to be set before we create our -+ * session context, so we set them here. */ -+ -+#ifdef LDAP_OPT_X_TLS_RANDOM_FILE -+ /* rand file */ -+ if (options.tls_randfile != NULL) { -+ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE, -+ options.tls_randfile)) != LDAP_SUCCESS) -+ fatal ("ldap_set_option(LDAP_OPT_X_TLS_RANDOM_FILE): %s", -+ ldap_err2string (rc)); -+ debug3 ("Set TLS random file %s", options.tls_randfile); -+ } -+#endif /* LDAP_OPT_X_TLS_RANDOM_FILE */ -+ -+ /* ca cert file */ -+ if (options.tls_cacertfile != NULL) { -+ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, -+ options.tls_cacertfile)) != LDAP_SUCCESS) -+ error ("ldap_set_option(LDAP_OPT_X_TLS_CACERTFILE): %s", -+ ldap_err2string (rc)); -+ debug3 ("Set TLS CA cert file %s ", options.tls_cacertfile); -+ } -+ -+ /* ca cert directory */ -+ if (options.tls_cacertdir != NULL) { -+ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, -+ options.tls_cacertdir)) != LDAP_SUCCESS) -+ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR): %s", -+ ldap_err2string (rc)); -+ debug3 ("Set TLS CA cert dir %s ", options.tls_cacertdir); -+ } -+ -+ /* require cert? */ -+ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, -+ &options.tls_checkpeer)) != LDAP_SUCCESS) -+ fatal ("ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT): %s", -+ ldap_err2string (rc)); -+ debug3 ("Set TLS check peer to %d ", options.tls_checkpeer); -+ -+ /* set cipher suite, certificate and private key: */ -+ if (options.tls_ciphers != NULL) { -+ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, -+ options.tls_ciphers)) != LDAP_SUCCESS) -+ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CIPHER_SUITE): %s", -+ ldap_err2string (rc)); -+ debug3 ("Set TLS ciphers to %s ", options.tls_ciphers); -+ } -+ -+ /* cert file */ -+ if (options.tls_cert != NULL) { -+ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE, -+ options.tls_cert)) != LDAP_SUCCESS) -+ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CERTFILE): %s", -+ ldap_err2string (rc)); -+ debug3 ("Set TLS cert file %s ", options.tls_cert); -+ } -+ -+ /* key file */ -+ if (options.tls_key != NULL) { -+ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE, -+ options.tls_key)) != LDAP_SUCCESS) -+ fatal ("ldap_set_option(LDAP_OPT_X_TLS_KEYFILE): %s", -+ ldap_err2string (rc)); -+ debug3 ("Set TLS key file %s ", options.tls_key); -+ } -+#endif -+#ifdef HAVE_LDAP_INITIALIZE -+ if (options.uri != NULL) { -+ if ((rc = ldap_initialize (&ld, options.uri)) != LDAP_SUCCESS) -+ fatal ("ldap_initialize %s", ldap_err2string (rc)); -+ debug3 ("LDAP initialize %s", options.uri); -+ } -+ } -+#endif /* HAVE_LDAP_INTITIALIZE */ -+ -+ /* continue with opening */ -+ if ((ld == NULL) && (options.host != NULL)) { -+#ifdef HAVE_LDAP_INIT -+ if ((ld = ldap_init (options.host, options.port)) == NULL) -+ fatal ("ldap_init failed"); -+ debug3 ("LDAP init %s:%d", options.host, options.port); -+#else -+ if ((ld = ldap_open (options.host, options.port)) == NULL) -+ fatal ("ldap_open failed"); -+ debug3 ("LDAP open %s:%d", options.host, options.port); -+#endif /* HAVE_LDAP_INIT */ -+ } -+ -+ if (ld == NULL) -+ fatal ("no way to open ldap"); -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS) -+ if (options.ssl == SSL_LDAPS) { -+ if ((rc = ldap_set_option (ld, LDAP_OPT_X_TLS, &options.tls_checkpeer)) != LDAP_SUCCESS) -+ fatal ("ldap_set_option(LDAP_OPT_X_TLS) %s", ldap_err2string (rc)); -+ debug3 ("LDAP set LDAP_OPT_X_TLS_%d", options.tls_checkpeer); -+ } -+#endif /* LDAP_OPT_X_TLS */ -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_PROTOCOL_VERSION) -+ (void) ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, -+ &options.ldap_version); -+#else -+ ld->ld_version = options.ldap_version; -+#endif -+ debug3 ("LDAP set version to %d", options.ldap_version); -+ -+#if LDAP_SET_REBIND_PROC_ARGS == 3 -+ ldap_set_rebind_proc (ld, _rebind_proc, NULL); -+#elif LDAP_SET_REBIND_PROC_ARGS == 2 -+ ldap_set_rebind_proc (ld, _rebind_proc); -+#else -+#warning unknown LDAP_SET_REBIND_PROC_ARGS -+#endif -+ debug3 ("LDAP set rebind proc"); -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_DEREF) -+ (void) ldap_set_option (ld, LDAP_OPT_DEREF, &options.deref); -+#else -+ ld->ld_deref = options.deref; -+#endif -+ debug3 ("LDAP set deref to %d", options.deref); -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_TIMELIMIT) -+ (void) ldap_set_option (ld, LDAP_OPT_TIMELIMIT, -+ &options.timelimit); -+#else -+ ld->ld_timelimit = options.timelimit; -+#endif -+ debug3 ("LDAP set timelimit to %d", options.timelimit); -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_X_OPT_CONNECT_TIMEOUT) -+ /* -+ * This is a new option in the Netscape SDK which sets -+ * the TCP connect timeout. For want of a better value, -+ * we use the bind_timelimit to control this. -+ */ -+ timeout = options.bind_timelimit * 1000; -+ (void) ldap_set_option (ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout); -+ debug3 ("LDAP set opt connect timeout to %d", timeout); -+#endif -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_NETWORK_TIMEOUT) -+ tv.tv_sec = options.bind_timelimit; -+ tv.tv_usec = 0; -+ (void) ldap_set_option (ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); -+ debug3 ("LDAP set opt network timeout to %ld.0", tv.tv_sec); -+#endif -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_REFERRALS) -+ (void) ldap_set_option (ld, LDAP_OPT_REFERRALS, -+ options.referrals ? LDAP_OPT_ON : LDAP_OPT_OFF); -+ debug3 ("LDAP set referrals to %d", options.referrals); -+#endif -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_RESTART) -+ (void) ldap_set_option (ld, LDAP_OPT_RESTART, -+ options.restart ? LDAP_OPT_ON : LDAP_OPT_OFF); -+ debug3 ("LDAP set restart to %d", options.restart); -+#endif -+ -+#ifdef HAVE_LDAP_START_TLS_S -+ if (options.ssl == SSL_START_TLS) { -+ int version; -+ -+ if (ldap_get_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version) -+ == LDAP_SUCCESS) { -+ if (version < LDAP_VERSION3) { -+ version = LDAP_VERSION3; -+ (void) ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, -+ &version); -+ debug3 ("LDAP set version to %d", version); -+ } -+ } -+ -+ if ((rc = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) -+ fatal ("ldap_starttls_s: %s", ldap_err2string (rc)); -+ debug3 ("LDAP start TLS"); -+ } -+#endif /* HAVE_LDAP_START_TLS_S */ -+ } -+ -+ if ((msgid = ldap_simple_bind (ld, options.binddn, -+ options.bindpw)) == -1) { -+ ld_errno = ldap_get_lderrno (ld, 0, 0); -+ -+ error ("ldap_simple_bind %s", ldap_err2string (ld_errno)); -+ reconnect++; -+ goto retry; -+ } -+ debug3 ("LDAP simple bind (%s)", options.binddn); -+ -+ timeout.tv_sec = options.bind_timelimit; -+ timeout.tv_usec = 0; -+ if ((rc = ldap_result (ld, msgid, 0, &timeout, &result)) < 1) { -+ ld_errno = ldap_get_lderrno (ld, 0, 0); -+ -+ error ("ldap_result %s", ldap_err2string (ld_errno)); -+ reconnect++; -+ goto retry; -+ } -+ debug3 ("LDAP result in time"); -+ -+#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) -+ controls = NULL; -+ if ((parserc = ldap_parse_result (ld, result, &rc, 0, 0, 0, &controls, 1)) != LDAP_SUCCESS) -+ fatal ("ldap_parse_result %s", ldap_err2string (parserc)); -+ debug3 ("LDAP parse result OK"); -+ -+ if (controls != NULL) { -+ ldap_controls_free (controls); -+ } -+#else -+ rc = ldap_result2error (session->ld, result, 1); -+#endif -+ if (rc != LDAP_SUCCESS) -+ fatal ("error trying to bind as user \"%s\" (%s)", -+ options.binddn, ldap_err2string (rc)); -+ -+ debug2 ("LDAP do connect OK"); -+} -+ -+void -+process_user (const char *user, FILE *output) -+{ -+ LDAPMessage *res, *e; -+ char *buffer, *format; -+ int rc, i; -+ struct timeval timeout; -+ -+ debug ("LDAP process user"); -+ -+ /* quick check for attempts to be evil */ -+ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || -+ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) { -+ logit ("illegal user name %s not processed", user); -+ return; -+ } -+ -+ /* build filter for LDAP request */ -+ format = LDAPSEARCH_FORMAT; -+ if (options.search_format != NULL) -+ format = options.search_format; -+ buffer = percent_expand(format, "c", options.account_class, "u", user, "f", options.ssh_filter, (char *)NULL); -+ -+ debug3 ("LDAP search scope = %d %s", options.scope, buffer); -+ -+ timeout.tv_sec = options.timelimit; -+ timeout.tv_usec = 0; -+ if ((rc = ldap_search_st(ld, options.base, options.scope, buffer, attrs, 0, &timeout, &res)) != LDAP_SUCCESS) { -+ error ("ldap_search_st(): %s", ldap_err2string (rc)); -+ free (buffer); -+ return; -+ } -+ -+ /* free */ -+ free (buffer); -+ -+ for (e = ldap_first_entry(ld, res); e != NULL; e = ldap_next_entry(ld, e)) { -+ int num; -+ struct berval **keys; -+ -+ keys = ldap_get_values_len(ld, e, PUBKEYATTR); -+ num = ldap_count_values_len(keys); -+ for (i = 0 ; i < num ; i++) { -+ char *cp; //, *options = NULL; -+ -+ for (cp = keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++); -+ if (!*cp || *cp == '\n' || *cp == '#') -+ continue; -+ -+ /* We have found the desired key. */ -+ fprintf (output, "%s\n", keys[i]->bv_val); -+ } -+ -+ ldap_value_free_len(keys); -+ } -+ -+ ldap_msgfree(res); -+ debug2 ("LDAP process user finished"); -+} -+ -+void -+ldap_do_close(void) -+{ -+ int rc; -+ -+ debug ("LDAP do close"); -+ if ((rc = ldap_unbind_ext(ld, NULL, NULL)) != LDAP_SUCCESS) -+ fatal ("ldap_unbind_ext: %s", -+ ldap_err2string (rc)); -+ -+ ld = NULL; -+ debug2 ("LDAP do close OK"); -+ return; -+} -+ -diff -up openssh-6.8p1/ldapbody.h.ldap openssh-6.8p1/ldapbody.h ---- openssh-6.8p1/ldapbody.h.ldap 2015-03-18 11:11:29.031801462 +0100 -+++ openssh-6.8p1/ldapbody.h 2015-03-18 11:11:29.031801462 +0100 -@@ -0,0 +1,37 @@ -+/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ -+/* -+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef LDAPBODY_H -+#define LDAPBODY_H -+ -+#include -+ -+void ldap_checkconfig(void); -+void ldap_do_connect(void); -+void process_user(const char *, FILE *); -+void ldap_do_close(void); -+ -+#endif /* LDAPBODY_H */ -+ -diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c ---- openssh-6.8p1/ldapconf.c.ldap 2015-03-18 11:11:29.032801460 +0100 -+++ openssh-6.8p1/ldapconf.c 2015-03-18 11:11:29.032801460 +0100 -@@ -0,0 +1,729 @@ -+/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ -+/* -+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "ldapincludes.h" -+#include "ldap-helper.h" -+#include "log.h" -+#include "misc.h" -+#include "xmalloc.h" -+#include "ldapconf.h" -+#include -+#include -+#include -+ -+/* Keyword tokens. */ -+ -+typedef enum { -+ lBadOption, -+ lHost, lURI, lBase, lBindDN, lBindPW, lRootBindDN, -+ lScope, lDeref, lPort, lTimeLimit, lBind_TimeLimit, -+ lLdap_Version, lBind_Policy, lSSLPath, lSSL, lReferrals, -+ lRestart, lTLS_CheckPeer, lTLS_CaCertFile, -+ lTLS_CaCertDir, lTLS_Ciphers, lTLS_Cert, lTLS_Key, -+ lTLS_RandFile, lLogDir, lDebug, lSSH_Filter, lSearch_Format, -+ lAccountClass, lDeprecated, lUnsupported -+} OpCodes; -+ -+/* Textual representations of the tokens. */ -+ -+static struct { -+ const char *name; -+ OpCodes opcode; -+} keywords[] = { -+ { "URI", lURI }, -+ { "Base", lBase }, -+ { "BindDN", lBindDN }, -+ { "BindPW", lBindPW }, -+ { "RootBindDN", lRootBindDN }, -+ { "Host", lHost }, -+ { "Port", lPort }, -+ { "Scope", lScope }, -+ { "Deref", lDeref }, -+ { "TimeLimit", lTimeLimit }, -+ { "TimeOut", lTimeLimit }, -+ { "Bind_Timelimit", lBind_TimeLimit }, -+ { "Network_TimeOut", lBind_TimeLimit }, -+/* -+ * Todo -+ * SIZELIMIT -+ */ -+ { "Ldap_Version", lLdap_Version }, -+ { "Version", lLdap_Version }, -+ { "Bind_Policy", lBind_Policy }, -+ { "SSLPath", lSSLPath }, -+ { "SSL", lSSL }, -+ { "Referrals", lReferrals }, -+ { "Restart", lRestart }, -+ { "TLS_CheckPeer", lTLS_CheckPeer }, -+ { "TLS_ReqCert", lTLS_CheckPeer }, -+ { "TLS_CaCertFile", lTLS_CaCertFile }, -+ { "TLS_CaCert", lTLS_CaCertFile }, -+ { "TLS_CaCertDir", lTLS_CaCertDir }, -+ { "TLS_Ciphers", lTLS_Ciphers }, -+ { "TLS_Cipher_Suite", lTLS_Ciphers }, -+ { "TLS_Cert", lTLS_Cert }, -+ { "TLS_Certificate", lTLS_Cert }, -+ { "TLS_Key", lTLS_Key }, -+ { "TLS_RandFile", lTLS_RandFile }, -+/* -+ * Todo -+ * TLS_CRLCHECK -+ * TLS_CRLFILE -+ */ -+ { "LogDir", lLogDir }, -+ { "Debug", lDebug }, -+ { "SSH_Filter", lSSH_Filter }, -+ { "search_format", lSearch_Format }, -+ { "AccountClass", lAccountClass }, -+ { NULL, lBadOption } -+}; -+ -+/* Configuration ptions. */ -+ -+Options options; -+ -+/* -+ * Returns the number of the token pointed to by cp or oBadOption. -+ */ -+ -+static OpCodes -+parse_token(const char *cp, const char *filename, int linenum) -+{ -+ u_int i; -+ -+ for (i = 0; keywords[i].name; i++) -+ if (strcasecmp(cp, keywords[i].name) == 0) -+ return keywords[i].opcode; -+ -+ if (config_warning_config_file) -+ logit("%s: line %d: Bad configuration option: %s", -+ filename, linenum, cp); -+ return lBadOption; -+} -+ -+/* Characters considered whitespace in strsep calls. */ -+#define WHITESPACE " \t\r\n" -+ -+/* return next token in configuration line */ -+static char * -+ldap_strdelim(char **s) -+{ -+ char *old; -+ int wspace = 0; -+ -+ if (*s == NULL) -+ return NULL; -+ -+ old = *s; -+ -+ *s = strpbrk(*s, WHITESPACE); -+ if (*s == NULL) -+ return (old); -+ -+ *s[0] = '\0'; -+ -+ /* Skip any extra whitespace after first token */ -+ *s += strspn(*s + 1, WHITESPACE) + 1; -+ if (*s[0] == '=' && !wspace) -+ *s += strspn(*s + 1, WHITESPACE) + 1; -+ -+ return (old); -+} -+ -+/* -+ * Processes a single option line as used in the configuration files. This -+ * only sets those values that have not already been set. -+ */ -+#define WHITESPACE " \t\r\n" -+ -+static int -+process_config_line(char *line, const char *filename, int linenum) -+{ -+ char *s, **charptr, **xstringptr, *endofnumber, *keyword, *arg; -+ char *rootbinddn = NULL; -+ int opcode, *intptr, value; -+ size_t len; -+ -+ /* Strip trailing whitespace */ -+ for (len = strlen(line) - 1; len > 0; len--) { -+ if (strchr(WHITESPACE, line[len]) == NULL) -+ break; -+ line[len] = '\0'; -+ } -+ -+ s = line; -+ /* Get the keyword. (Each line is supposed to begin with a keyword). */ -+ if ((keyword = ldap_strdelim(&s)) == NULL) -+ return 0; -+ /* Ignore leading whitespace. */ -+ if (*keyword == '\0') -+ keyword = ldap_strdelim(&s); -+ if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') -+ return 0; -+ -+ opcode = parse_token(keyword, filename, linenum); -+ -+ switch (opcode) { -+ case lBadOption: -+ /* don't panic, but count bad options */ -+ return -1; -+ /* NOTREACHED */ -+ -+ case lHost: -+ xstringptr = &options.host; -+parse_xstring: -+ if (!s || *s == '\0') -+ fatal("%s line %d: missing dn",filename,linenum); -+ if (*xstringptr == NULL) -+ *xstringptr = xstrdup(s); -+ return 0; -+ -+ case lURI: -+ xstringptr = &options.uri; -+ goto parse_xstring; -+ -+ case lBase: -+ xstringptr = &options.base; -+ goto parse_xstring; -+ -+ case lBindDN: -+ xstringptr = &options.binddn; -+ goto parse_xstring; -+ -+ case lBindPW: -+ charptr = &options.bindpw; -+parse_string: -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing argument.", filename, linenum); -+ if (*charptr == NULL) -+ *charptr = xstrdup(arg); -+ break; -+ -+ case lRootBindDN: -+ xstringptr = &rootbinddn; -+ goto parse_xstring; -+ -+ case lScope: -+ intptr = &options.scope; -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing sub/one/base argument.", filename, linenum); -+ value = 0; /* To avoid compiler warning... */ -+ if (strcasecmp (arg, "sub") == 0 || strcasecmp (arg, "subtree") == 0) -+ value = LDAP_SCOPE_SUBTREE; -+ else if (strcasecmp (arg, "one") == 0) -+ value = LDAP_SCOPE_ONELEVEL; -+ else if (strcasecmp (arg, "base") == 0) -+ value = LDAP_SCOPE_BASE; -+ else -+ fatal("%.200s line %d: Bad sub/one/base argument.", filename, linenum); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ -+ case lDeref: -+ intptr = &options.scope; -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing never/searching/finding/always argument.", filename, linenum); -+ value = 0; /* To avoid compiler warning... */ -+ if (!strcasecmp (arg, "never")) -+ value = LDAP_DEREF_NEVER; -+ else if (!strcasecmp (arg, "searching")) -+ value = LDAP_DEREF_SEARCHING; -+ else if (!strcasecmp (arg, "finding")) -+ value = LDAP_DEREF_FINDING; -+ else if (!strcasecmp (arg, "always")) -+ value = LDAP_DEREF_ALWAYS; -+ else -+ fatal("%.200s line %d: Bad never/searching/finding/always argument.", filename, linenum); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ -+ case lPort: -+ intptr = &options.port; -+parse_int: -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing argument.", filename, linenum); -+ if (arg[0] < '0' || arg[0] > '9') -+ fatal("%.200s line %d: Bad number.", filename, linenum); -+ -+ /* Octal, decimal, or hex format? */ -+ value = strtol(arg, &endofnumber, 0); -+ if (arg == endofnumber) -+ fatal("%.200s line %d: Bad number.", filename, linenum); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ -+ case lTimeLimit: -+ intptr = &options.timelimit; -+parse_time: -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing time value.", -+ filename, linenum); -+ if ((value = convtime(arg)) == -1) -+ fatal("%s line %d: invalid time value.", -+ filename, linenum); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ -+ case lBind_TimeLimit: -+ intptr = &options.bind_timelimit; -+ goto parse_time; -+ -+ case lLdap_Version: -+ intptr = &options.ldap_version; -+ goto parse_int; -+ -+ case lBind_Policy: -+ intptr = &options.bind_policy; -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing soft/hard argument.", filename, linenum); -+ value = 0; /* To avoid compiler warning... */ -+ if (strcasecmp(arg, "hard") == 0 || strcasecmp(arg, "hard_open") == 0 || strcasecmp(arg, "hard_init") == 0) -+ value = 1; -+ else if (strcasecmp(arg, "soft") == 0) -+ value = 0; -+ else -+ fatal("%.200s line %d: Bad soft/hard argument.", filename, linenum); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ -+ case lSSLPath: -+ charptr = &options.sslpath; -+ goto parse_string; -+ -+ case lSSL: -+ intptr = &options.ssl; -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing yes/no/start_tls argument.", filename, linenum); -+ value = 0; /* To avoid compiler warning... */ -+ if (strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0 || strcasecmp(arg, "on") == 0) -+ value = SSL_LDAPS; -+ else if (strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0 || strcasecmp(arg, "off") == 0) -+ value = SSL_OFF; -+ else if (!strcasecmp (arg, "start_tls")) -+ value = SSL_START_TLS; -+ else -+ fatal("%.200s line %d: Bad yes/no/start_tls argument.", filename, linenum); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ -+ case lReferrals: -+ intptr = &options.referrals; -+parse_flag: -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); -+ value = 0; /* To avoid compiler warning... */ -+ if (strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0 || strcasecmp(arg, "on") == 0) -+ value = 1; -+ else if (strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0 || strcasecmp(arg, "off") == 0) -+ value = 0; -+ else -+ fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ -+ case lRestart: -+ intptr = &options.restart; -+ goto parse_flag; -+ -+ case lTLS_CheckPeer: -+ intptr = &options.tls_checkpeer; -+ arg = ldap_strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing never/hard/demand/alow/try argument.", filename, linenum); -+ value = 0; /* To avoid compiler warning... */ -+ if (strcasecmp(arg, "never") == 0 || strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0 || strcasecmp(arg, "off") == 0) -+ value = LDAP_OPT_X_TLS_NEVER; -+ else if (strcasecmp(arg, "hard") == 0 || strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0 || strcasecmp(arg, "on") == 0) -+ value = LDAP_OPT_X_TLS_HARD; -+ else if (strcasecmp(arg, "demand") == 0) -+ value = LDAP_OPT_X_TLS_DEMAND; -+ else if (strcasecmp(arg, "allow") == 0) -+ value = LDAP_OPT_X_TLS_ALLOW; -+ else if (strcasecmp(arg, "try") == 0) -+ value = LDAP_OPT_X_TLS_TRY; -+ else -+ fatal("%.200s line %d: Bad never/hard/demand/alow/try argument.", filename, linenum); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ -+ case lTLS_CaCertFile: -+ charptr = &options.tls_cacertfile; -+ goto parse_string; -+ -+ case lTLS_CaCertDir: -+ charptr = &options.tls_cacertdir; -+ goto parse_string; -+ -+ case lTLS_Ciphers: -+ xstringptr = &options.tls_ciphers; -+ goto parse_xstring; -+ -+ case lTLS_Cert: -+ charptr = &options.tls_cert; -+ goto parse_string; -+ -+ case lTLS_Key: -+ charptr = &options.tls_key; -+ goto parse_string; -+ -+ case lTLS_RandFile: -+ charptr = &options.tls_randfile; -+ goto parse_string; -+ -+ case lLogDir: -+ charptr = &options.logdir; -+ goto parse_string; -+ -+ case lDebug: -+ intptr = &options.debug; -+ goto parse_int; -+ -+ case lSSH_Filter: -+ xstringptr = &options.ssh_filter; -+ goto parse_xstring; -+ -+ case lSearch_Format: -+ charptr = &options.search_format; -+ goto parse_string; -+ -+ case lAccountClass: -+ charptr = &options.account_class; -+ goto parse_string; -+ -+ case lDeprecated: -+ debug("%s line %d: Deprecated option \"%s\"", -+ filename, linenum, keyword); -+ return 0; -+ -+ case lUnsupported: -+ error("%s line %d: Unsupported option \"%s\"", -+ filename, linenum, keyword); -+ return 0; -+ -+ default: -+ fatal("process_config_line: Unimplemented opcode %d", opcode); -+ } -+ -+ /* Check that there is no garbage at end of line. */ -+ if ((arg = ldap_strdelim(&s)) != NULL && *arg != '\0') { -+ fatal("%.200s line %d: garbage at end of line; \"%.200s\".", -+ filename, linenum, arg); -+ } -+ return 0; -+} -+ -+/* -+ * Reads the config file and modifies the options accordingly. Options -+ * should already be initialized before this call. This never returns if -+ * there is an error. If the file does not exist, this returns 0. -+ */ -+ -+void -+read_config_file(const char *filename) -+{ -+ FILE *f; -+ char line[1024]; -+ int linenum; -+ int bad_options = 0; -+ struct stat sb; -+ -+ if ((f = fopen(filename, "r")) == NULL) -+ fatal("fopen %s: %s", filename, strerror(errno)); -+ -+ if (fstat(fileno(f), &sb) == -1) -+ fatal("fstat %s: %s", filename, strerror(errno)); -+ if (((sb.st_uid != 0 && sb.st_uid != getuid()) || -+ (sb.st_mode & 022) != 0)) -+ fatal("Bad owner or permissions on %s", filename); -+ -+ debug("Reading configuration data %.200s", filename); -+ -+ /* -+ * Mark that we are now processing the options. This flag is turned -+ * on/off by Host specifications. -+ */ -+ linenum = 0; -+ while (fgets(line, sizeof(line), f)) { -+ /* Update line number counter. */ -+ linenum++; -+ if (process_config_line(line, filename, linenum) != 0) -+ bad_options++; -+ } -+ fclose(f); -+ if ((bad_options > 0) && config_exclusive_config_file) -+ fatal("%s: terminating, %d bad configuration options", -+ filename, bad_options); -+} -+ -+/* -+ * Initializes options to special values that indicate that they have not yet -+ * been set. Read_config_file will only set options with this value. Options -+ * are processed in the following order: command line, user config file, -+ * system config file. Last, fill_default_options is called. -+ */ -+ -+void -+initialize_options(void) -+{ -+ memset(&options, 'X', sizeof(options)); -+ options.host = NULL; -+ options.uri = NULL; -+ options.base = NULL; -+ options.binddn = NULL; -+ options.bindpw = NULL; -+ options.scope = -1; -+ options.deref = -1; -+ options.port = -1; -+ options.timelimit = -1; -+ options.bind_timelimit = -1; -+ options.ldap_version = -1; -+ options.bind_policy = -1; -+ options.sslpath = NULL; -+ options.ssl = -1; -+ options.referrals = -1; -+ options.restart = -1; -+ options.tls_checkpeer = -1; -+ options.tls_cacertfile = NULL; -+ options.tls_cacertdir = NULL; -+ options.tls_ciphers = NULL; -+ options.tls_cert = NULL; -+ options.tls_key = NULL; -+ options.tls_randfile = NULL; -+ options.logdir = NULL; -+ options.debug = -1; -+ options.ssh_filter = NULL; -+ options.search_format = NULL; -+ options.account_class = NULL; -+} -+ -+/* -+ * Called after processing other sources of option data, this fills those -+ * options for which no value has been specified with their default values. -+ */ -+ -+void -+fill_default_options(void) -+{ -+ if (options.uri != NULL) { -+ LDAPURLDesc *ludp; -+ -+ if (ldap_url_parse(options.uri, &ludp) == LDAP_SUCCESS) { -+ if (options.ssl == -1) { -+ if (strcmp (ludp->lud_scheme, "ldap") == 0) -+ options.ssl = 2; -+ if (strcmp (ludp->lud_scheme, "ldapi") == 0) -+ options.ssl = 0; -+ else if (strcmp (ludp->lud_scheme, "ldaps") == 0) -+ options.ssl = 1; -+ } -+ if (options.host == NULL) -+ options.host = xstrdup (ludp->lud_host); -+ if (options.port == -1) -+ options.port = ludp->lud_port; -+ -+ ldap_free_urldesc (ludp); -+ } -+ } -+ if (options.ssl == -1) -+ options.ssl = SSL_START_TLS; -+ if (options.port == -1) -+ options.port = (options.ssl == 0) ? 389 : 636; -+ if (options.uri == NULL) { -+ int len; -+#define MAXURILEN 4096 -+ -+ options.uri = xmalloc (MAXURILEN); -+ len = snprintf (options.uri, MAXURILEN, "ldap%s://%s:%d", -+ (options.ssl == 0) ? "" : "s", options.host, options.port); -+ options.uri[MAXURILEN - 1] = 0; -+ options.uri = xreallocarray(options.uri, len + 1, 1); -+ } -+ if (options.binddn == NULL) -+ options.binddn = ""; -+ if (options.bindpw == NULL) -+ options.bindpw = ""; -+ if (options.scope == -1) -+ options.scope = LDAP_SCOPE_SUBTREE; -+ if (options.deref == -1) -+ options.deref = LDAP_DEREF_NEVER; -+ if (options.timelimit == -1) -+ options.timelimit = 10; -+ if (options.bind_timelimit == -1) -+ options.bind_timelimit = 10; -+ if (options.ldap_version == -1) -+ options.ldap_version = 3; -+ if (options.bind_policy == -1) -+ options.bind_policy = 1; -+ if (options.referrals == -1) -+ options.referrals = 1; -+ if (options.restart == -1) -+ options.restart = 1; -+ if (options.tls_checkpeer == -1) -+ options.tls_checkpeer = LDAP_OPT_X_TLS_HARD; -+ if (options.debug == -1) -+ options.debug = 0; -+ if (options.ssh_filter == NULL) -+ options.ssh_filter = ""; -+ if (options.account_class == NULL) -+ options.account_class = "posixAccount"; -+} -+ -+static const char * -+lookup_opcode_name(OpCodes code) -+{ -+ u_int i; -+ -+ for (i = 0; keywords[i].name != NULL; i++) -+ if (keywords[i].opcode == code) -+ return(keywords[i].name); -+ return "UNKNOWN"; -+} -+ -+static void -+dump_cfg_string(OpCodes code, const char *val) -+{ -+ if (val == NULL) -+ debug3("%s ", lookup_opcode_name(code)); -+ else -+ debug3("%s %s", lookup_opcode_name(code), val); -+} -+ -+static void -+dump_cfg_int(OpCodes code, int val) -+{ -+ if (val == -1) -+ debug3("%s ", lookup_opcode_name(code)); -+ else -+ debug3("%s %d", lookup_opcode_name(code), val); -+} -+ -+struct names { -+ int value; -+ char *name; -+}; -+ -+static void -+dump_cfg_namedint(OpCodes code, int val, struct names *names) -+{ -+ u_int i; -+ -+ if (val == -1) -+ debug3("%s ", lookup_opcode_name(code)); -+ else { -+ for (i = 0; names[i].value != -1; i++) -+ if (names[i].value == val) { -+ debug3("%s %s", lookup_opcode_name(code), names[i].name); -+ return; -+ } -+ debug3("%s unknown: %d", lookup_opcode_name(code), val); -+ } -+} -+ -+static struct names _yesnotls[] = { -+ { 0, "No" }, -+ { 1, "Yes" }, -+ { 2, "Start_TLS" }, -+ { -1, NULL }}; -+ -+static struct names _scope[] = { -+ { LDAP_SCOPE_BASE, "Base" }, -+ { LDAP_SCOPE_ONELEVEL, "One" }, -+ { LDAP_SCOPE_SUBTREE, "Sub"}, -+ { -1, NULL }}; -+ -+static struct names _deref[] = { -+ { LDAP_DEREF_NEVER, "Never" }, -+ { LDAP_DEREF_SEARCHING, "Searching" }, -+ { LDAP_DEREF_FINDING, "Finding" }, -+ { LDAP_DEREF_ALWAYS, "Always" }, -+ { -1, NULL }}; -+ -+static struct names _yesno[] = { -+ { 0, "No" }, -+ { 1, "Yes" }, -+ { -1, NULL }}; -+ -+static struct names _bindpolicy[] = { -+ { 0, "Soft" }, -+ { 1, "Hard" }, -+ { -1, NULL }}; -+ -+static struct names _checkpeer[] = { -+ { LDAP_OPT_X_TLS_NEVER, "Never" }, -+ { LDAP_OPT_X_TLS_HARD, "Hard" }, -+ { LDAP_OPT_X_TLS_DEMAND, "Demand" }, -+ { LDAP_OPT_X_TLS_ALLOW, "Allow" }, -+ { LDAP_OPT_X_TLS_TRY, "TRY" }, -+ { -1, NULL }}; -+ -+void -+dump_config(void) -+{ -+ dump_cfg_string(lURI, options.uri); -+ dump_cfg_string(lHost, options.host); -+ dump_cfg_int(lPort, options.port); -+ dump_cfg_namedint(lSSL, options.ssl, _yesnotls); -+ dump_cfg_int(lLdap_Version, options.ldap_version); -+ dump_cfg_int(lTimeLimit, options.timelimit); -+ dump_cfg_int(lBind_TimeLimit, options.bind_timelimit); -+ dump_cfg_string(lBase, options.base); -+ dump_cfg_string(lBindDN, options.binddn); -+ dump_cfg_string(lBindPW, options.bindpw); -+ dump_cfg_namedint(lScope, options.scope, _scope); -+ dump_cfg_namedint(lDeref, options.deref, _deref); -+ dump_cfg_namedint(lReferrals, options.referrals, _yesno); -+ dump_cfg_namedint(lRestart, options.restart, _yesno); -+ dump_cfg_namedint(lBind_Policy, options.bind_policy, _bindpolicy); -+ dump_cfg_string(lSSLPath, options.sslpath); -+ dump_cfg_namedint(lTLS_CheckPeer, options.tls_checkpeer, _checkpeer); -+ dump_cfg_string(lTLS_CaCertFile, options.tls_cacertfile); -+ dump_cfg_string(lTLS_CaCertDir, options.tls_cacertdir); -+ dump_cfg_string(lTLS_Ciphers, options.tls_ciphers); -+ dump_cfg_string(lTLS_Cert, options.tls_cert); -+ dump_cfg_string(lTLS_Key, options.tls_key); -+ dump_cfg_string(lTLS_RandFile, options.tls_randfile); -+ dump_cfg_string(lLogDir, options.logdir); -+ dump_cfg_int(lDebug, options.debug); -+ dump_cfg_string(lSSH_Filter, options.ssh_filter); -+ dump_cfg_string(lSearch_Format, options.search_format); -+ dump_cfg_string(lAccountClass, options.account_class); -+} -+ -diff -up openssh-6.8p1/ldapconf.h.ldap openssh-6.8p1/ldapconf.h ---- openssh-6.8p1/ldapconf.h.ldap 2015-03-18 11:11:29.032801460 +0100 -+++ openssh-6.8p1/ldapconf.h 2015-03-18 11:11:29.032801460 +0100 -@@ -0,0 +1,73 @@ -+/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ -+/* -+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef LDAPCONF_H -+#define LDAPCONF_H -+ -+#define SSL_OFF 0 -+#define SSL_LDAPS 1 -+#define SSL_START_TLS 2 -+ -+/* Data structure for representing option data. */ -+ -+typedef struct { -+ char *host; -+ char *uri; -+ char *base; -+ char *binddn; -+ char *bindpw; -+ int scope; -+ int deref; -+ int port; -+ int timelimit; -+ int bind_timelimit; -+ int ldap_version; -+ int bind_policy; -+ char *sslpath; -+ int ssl; -+ int referrals; -+ int restart; -+ int tls_checkpeer; -+ char *tls_cacertfile; -+ char *tls_cacertdir; -+ char *tls_ciphers; -+ char *tls_cert; -+ char *tls_key; -+ char *tls_randfile; -+ char *logdir; -+ int debug; -+ char *ssh_filter; -+ char *search_format; -+ char *account_class; -+} Options; -+ -+extern Options options; -+ -+void read_config_file(const char *); -+void initialize_options(void); -+void fill_default_options(void); -+void dump_config(void); -+ -+#endif /* LDAPCONF_H */ -diff -up openssh-6.8p1/ldapincludes.h.ldap openssh-6.8p1/ldapincludes.h ---- openssh-6.8p1/ldapincludes.h.ldap 2015-03-18 11:11:29.032801460 +0100 -+++ openssh-6.8p1/ldapincludes.h 2015-03-18 11:11:29.032801460 +0100 -@@ -0,0 +1,41 @@ -+/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ -+/* -+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef LDAPINCLUDES_H -+#define LDAPINCLUDES_H -+ -+#include "includes.h" -+ -+#ifdef HAVE_LBER_H -+#include -+#endif -+#ifdef HAVE_LDAP_H -+#include -+#endif -+#ifdef HAVE_LDAP_SSL_H -+#include -+#endif -+ -+#endif /* LDAPINCLUDES_H */ -diff -up openssh-6.8p1/ldapmisc.c.ldap openssh-6.8p1/ldapmisc.c ---- openssh-6.8p1/ldapmisc.c.ldap 2015-03-18 11:11:29.032801460 +0100 -+++ openssh-6.8p1/ldapmisc.c 2015-03-18 11:11:29.032801460 +0100 -@@ -0,0 +1,79 @@ -+ -+#include "ldapincludes.h" -+#include "ldapmisc.h" -+ -+#ifndef HAVE_LDAP_GET_LDERRNO -+int -+ldap_get_lderrno (LDAP * ld, char **m, char **s) -+{ -+#ifdef HAVE_LDAP_GET_OPTION -+ int rc; -+#endif -+ int lderrno; -+ -+#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) -+ if ((rc = ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, &lderrno)) != LDAP_SUCCESS) -+ return rc; -+#else -+ lderrno = ld->ld_errno; -+#endif -+ -+ if (s != NULL) { -+#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_STRING) -+ if ((rc = ldap_get_option (ld, LDAP_OPT_ERROR_STRING, s)) != LDAP_SUCCESS) -+ return rc; -+#else -+ *s = ld->ld_error; -+#endif -+ } -+ -+ if (m != NULL) { -+#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_MATCHED_DN) -+ if ((rc = ldap_get_option (ld, LDAP_OPT_MATCHED_DN, m)) != LDAP_SUCCESS) -+ return rc; -+#else -+ *m = ld->ld_matched; -+#endif -+ } -+ -+ return lderrno; -+} -+#endif -+ -+#ifndef HAVE_LDAP_SET_LDERRNO -+int -+ldap_set_lderrno (LDAP * ld, int lderrno, const char *m, const char *s) -+{ -+#ifdef HAVE_LDAP_SET_OPTION -+ int rc; -+#endif -+ -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) -+ if ((rc = ldap_set_option (ld, LDAP_OPT_ERROR_NUMBER, &lderrno)) != LDAP_SUCCESS) -+ return rc; -+#else -+ ld->ld_errno = lderrno; -+#endif -+ -+ if (s != NULL) { -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_ERROR_STRING) -+ if ((rc = ldap_set_option (ld, LDAP_OPT_ERROR_STRING, s)) != LDAP_SUCCESS) -+ return rc; -+#else -+ ld->ld_error = s; -+#endif -+ } -+ -+ if (m != NULL) { -+#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_MATCHED_DN) -+ if ((rc = ldap_set_option (ld, LDAP_OPT_MATCHED_DN, m)) != LDAP_SUCCESS) -+ return rc; -+#else -+ ld->ld_matched = m; -+#endif -+ } -+ -+ return LDAP_SUCCESS; -+} -+#endif -+ -diff -up openssh-6.8p1/ldapmisc.h.ldap openssh-6.8p1/ldapmisc.h ---- openssh-6.8p1/ldapmisc.h.ldap 2015-03-18 11:11:29.032801460 +0100 -+++ openssh-6.8p1/ldapmisc.h 2015-03-18 11:11:29.032801460 +0100 -@@ -0,0 +1,35 @@ -+/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ -+/* -+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef LDAPMISC_H -+#define LDAPMISC_H -+ -+#include "ldapincludes.h" -+ -+int ldap_get_lderrno (LDAP *, char **, char **); -+int ldap_set_lderrno (LDAP *, int, const char *, const char *); -+ -+#endif /* LDAPMISC_H */ -+ -diff -up openssh-6.8p1/openssh-lpk-openldap.schema.ldap openssh-6.8p1/openssh-lpk-openldap.schema ---- openssh-6.8p1/openssh-lpk-openldap.schema.ldap 2015-03-18 11:11:29.033801457 +0100 -+++ openssh-6.8p1/openssh-lpk-openldap.schema 2015-03-18 11:11:29.033801457 +0100 -@@ -0,0 +1,21 @@ -+# -+# LDAP Public Key Patch schema for use with openssh-ldappubkey -+# useful with PKA-LDAP also -+# -+# Author: Eric AUGE -+# -+# Based on the proposal of : Mark Ruijter -+# -+ -+ -+# octetString SYNTAX -+attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' -+ DESC 'MANDATORY: OpenSSH Public key' -+ EQUALITY octetStringMatch -+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) -+ -+# printableString SYNTAX yes|no -+objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY -+ DESC 'MANDATORY: OpenSSH LPK objectclass' -+ MUST ( sshPublicKey $ uid ) -+ ) -diff -up openssh-6.8p1/openssh-lpk-sun.schema.ldap openssh-6.8p1/openssh-lpk-sun.schema ---- openssh-6.8p1/openssh-lpk-sun.schema.ldap 2015-03-18 11:11:29.033801457 +0100 -+++ openssh-6.8p1/openssh-lpk-sun.schema 2015-03-18 11:11:29.033801457 +0100 -@@ -0,0 +1,23 @@ -+# -+# LDAP Public Key Patch schema for use with openssh-ldappubkey -+# useful with PKA-LDAP also -+# -+# Author: Eric AUGE -+# -+# Schema for Sun Directory Server. -+# Based on the original schema, modified by Stefan Fischer. -+# -+ -+dn: cn=schema -+ -+# octetString SYNTAX -+attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' -+ DESC 'MANDATORY: OpenSSH Public key' -+ EQUALITY octetStringMatch -+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) -+ -+# printableString SYNTAX yes|no -+objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY -+ DESC 'MANDATORY: OpenSSH LPK objectclass' -+ MUST ( sshPublicKey $ uid ) -+ ) -diff -up openssh-6.8p1/ssh-ldap-helper.8.ldap openssh-6.8p1/ssh-ldap-helper.8 ---- openssh-6.8p1/ssh-ldap-helper.8.ldap 2015-03-18 11:11:29.033801457 +0100 -+++ openssh-6.8p1/ssh-ldap-helper.8 2015-03-18 11:11:29.033801457 +0100 -@@ -0,0 +1,79 @@ -+.\" $OpenBSD: ssh-ldap-helper.8,v 1.1 2010/02/10 23:20:38 markus Exp $ -+.\" -+.\" Copyright (c) 2010 Jan F. Chadima. All rights reserved. -+.\" -+.\" Permission to use, copy, modify, and distribute this software for any -+.\" purpose with or without fee is hereby granted, provided that the above -+.\" copyright notice and this permission notice appear in all copies. -+.\" -+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+.\" -+.Dd $Mdocdate: April 29 2010 $ -+.Dt SSH-LDAP-HELPER 8 -+.Os -+.Sh NAME -+.Nm ssh-ldap-helper -+.Nd sshd helper program for ldap support -+.Sh SYNOPSIS -+.Nm ssh-ldap-helper -+.Op Fl devw -+.Op Fl f Ar file -+.Op Fl s Ar user -+.Sh DESCRIPTION -+.Nm -+is used by -+.Xr sshd 1 -+to access keys provided by an LDAP. -+.Nm -+is disabled by default and can only be enabled in the -+sshd configuration file -+.Pa /etc/ssh/sshd_config -+by setting -+.Cm AuthorizedKeysCommand -+to -+.Dq /usr/libexec/ssh-ldap-wrapper . -+.Pp -+.Nm -+is not intended to be invoked by the user, but from -+.Xr sshd 8 via -+.Xr ssh-ldap-wrapper . -+.Pp -+The options are as follows: -+.Bl -tag -width Ds -+.It Fl d -+Set the debug mode; -+.Nm -+prints all logs to stderr instead of syslog. -+.It Fl e -+Implies \-w; -+.Nm -+halts if it encounters an unknown item in the ldap.conf file. -+.It Fl f -+.Nm -+uses this file as the ldap configuration file instead of /etc/ssh/ldap.conf (default). -+.It Fl s -+.Nm -+prints out the user's keys to stdout and exits. -+.It Fl v -+Implies \-d; -+increases verbosity. -+.It Fl w -+.Nm -+writes warnings about unknown items in the ldap.conf configuration file. -+.El -+.Sh SEE ALSO -+.Xr sshd 8 , -+.Xr sshd_config 5 , -+.Xr ssh-ldap.conf 5 , -+.Sh HISTORY -+.Nm -+first appeared in -+OpenSSH 5.5 + PKA-LDAP . -+.Sh AUTHORS -+.An Jan F. Chadima Aq jchadima@redhat.com -diff -up openssh-6.8p1/ssh-ldap-wrapper.ldap openssh-6.8p1/ssh-ldap-wrapper ---- openssh-6.8p1/ssh-ldap-wrapper.ldap 2015-03-18 11:11:29.033801457 +0100 -+++ openssh-6.8p1/ssh-ldap-wrapper 2015-03-18 11:11:29.033801457 +0100 -@@ -0,0 +1,4 @@ -+#!/bin/sh -+ -+exec /usr/libexec/openssh/ssh-ldap-helper -s "$1" -+ -diff -up openssh-6.8p1/ssh-ldap.conf.5.ldap openssh-6.8p1/ssh-ldap.conf.5 ---- openssh-6.8p1/ssh-ldap.conf.5.ldap 2015-03-18 11:11:29.033801457 +0100 -+++ openssh-6.8p1/ssh-ldap.conf.5 2015-03-18 11:11:29.033801457 +0100 -@@ -0,0 +1,385 @@ -+.\" $OpenBSD: ssh-ldap.conf.5,v 1.1 2010/02/10 23:20:38 markus Exp $ -+.\" -+.\" Copyright (c) 2010 Jan F. Chadima. All rights reserved. -+.\" -+.\" Permission to use, copy, modify, and distribute this software for any -+.\" purpose with or without fee is hereby granted, provided that the above -+.\" copyright notice and this permission notice appear in all copies. -+.\" -+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+.\" -+.Dd $Mdocdate: may 12 2010 $ -+.Dt SSH-LDAP.CONF 5 -+.Os -+.Sh NAME -+.Nm ssh-ldap.conf -+.Nd configuration file for ssh-ldap-helper -+.Sh SYNOPSIS -+.Nm /etc/ssh/ldap.conf -+.Sh DESCRIPTION -+.Xr ssh-ldap-helper 8 -+reads configuration data from -+.Pa /etc/ssh/ldap.conf -+(or the file specified with -+.Fl f -+on the command line). -+The file contains keyword-argument pairs, one per line. -+Lines starting with -+.Ql # -+and empty lines are interpreted as comments. -+.Pp -+The value starts with the first non-blank character after -+the keyword's name, and terminates at the end of the line, -+or at the last sequence of blanks before the end of the line. -+Quoting values that contain blanks -+may be incorrect, as the quotes would become part of the value. -+The possible keywords and their meanings are as follows (note that -+keywords are case-insensitive, and arguments, on a case by case basis, may be case-sensitive). -+.Bl -tag -width Ds -+.It Cm URI -+The argument(s) are in the form -+.Pa ldap[si]://[name[:port]] -+and specify the URI(s) of an LDAP server(s) to which the -+.Xr ssh-ldap-helper 8 -+should connect. The URI scheme may be any of -+.Dq ldap , -+.Dq ldaps -+or -+.Dq ldapi , -+which refer to LDAP over TCP, LDAP over SSL (TLS) and LDAP -+over IPC (UNIX domain sockets), respectively. -+Each server's name can be specified as a -+domain-style name or an IP address literal. Optionally, the -+server's name can followed by a ':' and the port number the LDAP -+server is listening on. If no port number is provided, the default -+port for the scheme is used (389 for ldap://, 636 for ldaps://). -+For LDAP over IPC, name is the name of the socket, and no port -+is required, nor allowed; note that directory separators must be -+URL-encoded, like any other characters that are special to URLs; -+A space separated list of URIs may be provided. -+There is no default. -+.It Cm Base -+Specifies the default base Distinguished Name (DN) to use when performing ldap operations. -+The base must be specified as a DN in LDAP format. -+There is no default. -+.It Cm BindDN -+Specifies the default BIND DN to use when connecting to the ldap server. -+The bind DN must be specified as a Distinguished Name in LDAP format. -+There is no default. -+.It Cm BindPW -+Specifies the default password to use when connecting to the ldap server via -+.Cm BindDN . -+There is no default. -+.It Cm RootBindDN -+Intentionaly does nothing. Recognized for compatibility reasons. -+.It Cm Host -+The argument(s) specifies the name(s) of an LDAP server(s) to which the -+.Xr ssh-ldap-helper 8 -+should connect. Each server's name can be specified as a -+domain-style name or an IP address and optionally followed by a ':' and -+the port number the ldap server is listening on. A space-separated -+list of hosts may be provided. -+There is no default. -+.Cm Host -+is deprecated in favor of -+.Cm URI . -+.It Cm Port -+Specifies the default port used when connecting to LDAP servers(s). -+The port may be specified as a number. -+The default port is 389 for ldap:// or 636 for ldaps:// respectively. -+.Cm Port -+is deprecated in favor of -+.Cm URI . -+.It Cm Scope -+Specifies the starting point of an LDAP search and the depth from the base DN to which the search should descend. -+There are three options (values) that can be assigned to the -+.Cm Scope parameter: -+.Dq base , -+.Dq one -+and -+.Dq subtree . -+Alias for the subtree is -+.Dq sub . -+The value -+.Dq base -+is used to indicate searching only the entry at the base DN, resulting in only that entry being returned (keeping in mind that it also has to meet the search filter criteria!). -+The value -+.Dq one -+is used to indicate searching all entries one level under the base DN, but not including the base DN and not including any entries under that one level under the base DN. -+The value -+.Dq subtree -+is used to indicate searching of all entries at all levels under and including the specified base DN. -+The default is -+.Dq subtree . -+.It Cm Deref -+Specifies how alias dereferencing is done when performing a search. There are four -+possible values that can be assigned to the -+.Cm Deref -+parameter: -+.Dq never , -+.Dq searching , -+.Dq finding , -+and -+.Dq always . -+The value -+.Dq never -+means that the aliases are never dereferenced. -+The value -+.Dq searching -+means that the aliases are dereferenced in subordinates of the base object, but -+not in locating the base object of the search. -+The value -+.Dq finding -+means that the aliases are only dereferenced when locating the base object of the search. -+The value -+.Dq always -+means that the aliases are dereferenced both in searching and in locating the base object -+of the search. -+The default is -+.Dq never . -+.It Cm TimeLimit -+Specifies a time limit (in seconds) to use when performing searches. -+The number should be a non-negative integer. A -+.Cm TimeLimit -+of zero (0) specifies that the search time is unlimited. Please note that the server -+may still apply any server-side limit on the duration of a search operation. -+The default value is 10. -+.It Cm TimeOut -+Is an aliast to -+.Cm TimeLimit . -+.It Cm Bind_TimeLimit -+Specifies the timeout (in seconds) after which the poll(2)/select(2) -+following a connect(2) returns in case of no activity. -+The default value is 10. -+.It Cm Network_TimeOut -+Is an alias to -+.Cm Bind_TimeLimit . -+.It Cm Ldap_Version -+Specifies what version of the LDAP protocol should be used. -+The allowed values are 2 or 3. The default is 3. -+.It Cm Version -+Is an alias to -+.Cm Ldap_Version . -+.It Cm Bind_Policy -+Specifies the policy to use for reconnecting to an unavailable LDAP server. There are 2 available values: -+.Dq hard -+and -+.Dq soft. -+.Dq hard has 2 aliases -+.Dq hard_open -+and -+.Dq hard_init . -+The value -+.Dq hard -+means that reconects that the -+.Xr ssh-ldap-helper 8 -+tries to reconnect to the LDAP server 5 times before failure. There is exponential backoff before retrying. -+The value -+.Dq soft -+means that -+.Xr ssh-ldap-helper 8 -+fails immediately when it cannot connect to the LDAP seerver. -+The deault is -+.Dq hard . -+.It Cm SSLPath -+Specifies the path to the X.509 certificate database. -+There is no default. -+.It Cm SSL -+Specifies whether to use SSL/TLS or not. -+There are three allowed values: -+.Dq yes , -+.Dq no -+and -+.Dq start_tls -+Both -+.Dq true -+and -+.Dq on -+are the aliases for -+.Dq yes . -+.Dq false -+and -+.Dq off -+are the aliases for -+.Dq no . -+If -+.Dq start_tls -+is specified then StartTLS is used rather than raw LDAP over SSL. -+The default for ldap:// is -+.Dq start_tls , -+for ldaps:// -+.Dq yes -+and -+.Dq no -+for the ldapi:// . -+In case of host based configuration the default is -+.Dq start_tls . -+.It Cm Referrals -+Specifies if the client should automatically follow referrals returned -+by LDAP servers. -+The value can be or -+.Dq yes -+or -+.Dq no . -+.Dq true -+and -+.Dq on -+are the aliases for -+.Dq yes . -+.Dq false -+and -+.Dq off -+are the aliases for -+.Dq no . -+The default is yes. -+.It Cm Restart -+Specifies whether the LDAP client library should restart the select(2) system call when interrupted. -+The value can be or -+.Dq yes -+or -+.Dq no . -+.Dq true -+and -+.Dq on -+are the aliases for -+.Dq yes . -+.Dq false -+and -+.Dq off -+are the aliases for -+.Dq no . -+The default is yes. -+.It Cm TLS_CheckPeer -+Specifies what checks to perform on server certificates in a TLS session, -+if any. The value -+can be specified as one of the following keywords: -+.Dq never , -+.Dq hard , -+.Dq demand , -+.Dq allow -+and -+.Dq try . -+.Dq true , -+.Dq on -+and -+.Dq yes -+are aliases for -+.Dq hard . -+.Dq false , -+.Dq off -+and -+.Dq no -+are the aliases for -+.Dq never . -+The value -+.Dq never -+means that the client will not request or check any server certificate. -+The value -+.Dq allow -+means that the server certificate is requested. If no certificate is provided, -+the session proceeds normally. If a bad certificate is provided, it will -+be ignored and the session proceeds normally. -+The value -+.Dq try -+means that the server certificate is requested. If no certificate is provided, -+the session proceeds normally. If a bad certificate is provided, -+the session is immediately terminated. -+The value -+.Dq demand -+means that the server certificate is requested. If no -+certificate is provided, or a bad certificate is provided, the session -+is immediately terminated. -+The value -+.Dq hard -+is the same as -+.Dq demand . -+It requires an SSL connection. In the case of the plain conection the -+session is immediately terminated. -+The default is -+.Dq hard . -+.It Cm TLS_ReqCert -+Is an alias for -+.Cm TLS_CheckPeer . -+.It Cm TLS_CACertFile -+Specifies the file that contains certificates for all of the Certificate -+Authorities the client will recognize. -+There is no default. -+.It Cm TLS_CACert -+Is an alias for -+.Cm TLS_CACertFile . -+.It Cm TLS_CACertDIR -+Specifies the path of a directory that contains Certificate Authority -+certificates in separate individual files. The -+.Cm TLS_CACert -+is always used before -+.Cm TLS_CACertDir . -+The specified directory must be managed with the OpenSSL c_rehash utility. -+There is no default. -+.It Cm TLS_Ciphers -+Specifies acceptable cipher suite and preference order. -+The value should be a cipher specification for OpenSSL, -+e.g., -+.Dq HIGH:MEDIUM:+SSLv2 . -+The default is -+.Dq ALL . -+.It Cm TLS_Cipher_Suite -+Is an alias for -+.Cm TLS_Ciphers . -+.It Cm TLS_Cert -+Specifies the file that contains the client certificate. -+There is no default. -+.It Cm TLS_Certificate -+Is an alias for -+.Cm TLS_Cert . -+.It Cm TLS_Key -+Specifies the file that contains the private key that matches the certificate -+stored in the -+.Cm TLS_Cert -+file. Currently, the private key must not be protected with a password, so -+it is of critical importance that the key file is protected carefully. -+There is no default. -+.It Cm TLS_RandFile -+Specifies the file to obtain random bits from when /dev/[u]random is -+not available. Generally set to the name of the EGD/PRNGD socket. -+The environment variable RANDFILE can also be used to specify the filename. -+There is no default. -+.It Cm LogDir -+Specifies the directory used for logging by the LDAP client library. -+There is no default. -+.It Cm Debug -+Specifies the debug level used for logging by the LDAP client library. -+There is no default. -+.It Cm SSH_Filter -+Specifies the user filter applied on the LDAP search. -+The default is no filter. -+.It Cm AccountClass -+Specifies the LDAP class used to find user accounts. -+The default is posixAccount. -+.It Cm search_format -+Specifies the user format of search string in LDAP substituting %u for user name -+and %f for additional ssh filter -+.Cm SSH_Filter -+(optional). -+The default value is (&(objectclass=%c)(objectclass=ldapPublicKey)(uid=%u)%f) -+.El -+.Sh FILES -+.Bl -tag -width Ds -+.It Pa /etc/ssh/ldap.conf -+Ldap configuration file for -+.Xr ssh-ldap-helper 8 . -+.El -+.Sh "SEE ALSO" -+.Xr ldap.conf 5 , -+.Xr ssh-ldap-helper 8 -+.Sh HISTORY -+.Nm -+first appeared in -+OpenSSH 5.5 + PKA-LDAP . -+.Sh AUTHORS -+.An Jan F. Chadima Aq jchadima@redhat.com -diff --git a/openssh-lpk-openldap.ldif b/openssh-lpk-openldap.ldif -new file mode 100644 -index 0000000..9adf4b8 ---- /dev/null -+++ b/openssh-lpk-openldap.ldif -@@ -0,0 +1,19 @@ -+# -+# LDAP Public Key Patch schema for use with openssh-ldappubkey -+# useful with PKA-LDAP also -+# -+# Author: Eric AUGE -+# -+# LDIF for openLDAP Directory Server. -+# Based on the original schema, modified by Jakub Jelen. -+# -+ -+dn: cn=openssh-lpk,cn=schema,cn=config -+objectClass: olcSchemaConfig -+cn: openssh-lpk -+olcAttributeTypes: {0}( 1.3.6.1.4.1.24552.500.1.1.1.13 -+ NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' -+ EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) -+olcObjectClasses: {0}( 1.3.6.1.4.1.24552.500.1.1.2.0 -+ NAME 'ldapPublicKey' DESC 'MANDATORY: OpenSSH LPK objectclass' -+ SUP top AUXILIARY MUST ( sshPublicKey $ uid ) ) -diff --git a/openssh-lpk-sun.ldif b/openssh-lpk-sun.ldif -new file mode 100644 -index 0000000..9adf4b8 ---- /dev/null -+++ b/openssh-lpk-sun.ldif -@@ -0,0 +1,17 @@ -+# -+# LDAP Public Key Patch schema for use with openssh-ldappubkey -+# useful with PKA-LDAP also -+# -+# Author: Eric AUGE -+# -+# LDIF for Sun Directory Server. -+# Based on the original schema, modified by Jakub Jelen. -+# -+ -+dn: cn=schema -+attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 -+ NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' -+ EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) -+objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 -+ NAME 'ldapPublicKey' DESC 'MANDATORY: OpenSSH LPK objectclass' -+ SUP top AUXILIARY MUST ( sshPublicKey $ uid ) ) diff --git a/SOURCES/openssh-6.9p1-permit-root-login.patch b/SOURCES/openssh-6.9p1-permit-root-login.patch deleted file mode 100644 index 6b4c4da..0000000 --- a/SOURCES/openssh-6.9p1-permit-root-login.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up openssh-7.0p1/sshd_config.root-login openssh-7.0p1/sshd_config ---- openssh-7.0p1/sshd_config.root-login 2015-08-12 11:29:12.919269245 +0200 -+++ openssh-7.0p1/sshd_config 2015-08-12 11:31:03.653096466 +0200 -@@ -46,7 +46,7 @@ SyslogFacility AUTHPRIV - # Authentication: - - #LoginGraceTime 2m --#PermitRootLogin prohibit-password -+PermitRootLogin yes - #StrictModes yes - #MaxAuthTries 6 - #MaxSessions 10 diff --git a/SOURCES/openssh-7.4p1-systemd.patch b/SOURCES/openssh-7.4p1-systemd.patch deleted file mode 100644 index 4f9e58a..0000000 --- a/SOURCES/openssh-7.4p1-systemd.patch +++ /dev/null @@ -1,98 +0,0 @@ -commit 0e22b79bfde45a7cf7a2e51a68ec11c4285f3b31 -Author: Jakub Jelen -Date: Mon Nov 21 15:04:06 2016 +0100 - - systemd stuff - -diff --git a/configure.ac b/configure.ac -index 2ffc369..162ce92 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -4265,6 +4265,30 @@ AC_ARG_WITH([kerberos5], - AC_SUBST([GSSLIBS]) - AC_SUBST([K5LIBS]) - -+# Check whether user wants systemd support -+SYSTEMD_MSG="no" -+AC_ARG_WITH(systemd, -+ [ --with-systemd Enable systemd support], -+ [ if test "x$withval" != "xno" ; then -+ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) -+ if test "$PKGCONFIG" != "no"; then -+ AC_MSG_CHECKING([for libsystemd]) -+ if $PKGCONFIG --exists libsystemd; then -+ SYSTEMD_CFLAGS=`$PKGCONFIG --cflags libsystemd` -+ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd` -+ CPPFLAGS="$CPPFLAGS $SYSTEMD_CFLAGS" -+ SSHDLIBS="$SSHDLIBS $SYSTEMD_LIBS" -+ AC_MSG_RESULT([yes]) -+ AC_DEFINE(HAVE_SYSTEMD, 1, [Define if you want systemd support.]) -+ SYSTEMD_MSG="yes" -+ else -+ AC_MSG_RESULT([no]) -+ fi -+ fi -+ fi ] -+) -+ -+ - # Looking for programs, paths and files - - PRIVSEP_PATH=/var/empty -@@ -5097,6 +5121,7 @@ echo " libedit support: $LIBEDIT_MSG" - echo " Solaris process contract support: $SPC_MSG" - echo " Solaris project support: $SP_MSG" - echo " Solaris privilege support: $SPP_MSG" -+echo " systemd support: $SYSTEMD_MSG" - echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" - echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" - echo " BSD Auth support: $BSD_AUTH_MSG" -diff --git a/contrib/sshd.service b/contrib/sshd.service -new file mode 100644 -index 0000000..e0d4923 ---- /dev/null -+++ b/contrib/sshd.service -@@ -0,0 +1,16 @@ -+[Unit] -+Description=OpenSSH server daemon -+Documentation=man:sshd(8) man:sshd_config(5) -+After=network.target -+ -+[Service] -+Type=notify -+ExecStart=/usr/sbin/sshd -D $OPTIONS -+ExecReload=/bin/kill -HUP $MAINPID -+KillMode=process -+Restart=on-failure -+RestartPreventExitStatus=255 -+ -+[Install] -+WantedBy=multi-user.target -+ -diff --git a/sshd.c b/sshd.c -index 816611c..b8b9d13 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -85,6 +85,10 @@ - #include - #endif - -+#ifdef HAVE_SYSTEMD -+#include -+#endif -+ - #include "xmalloc.h" - #include "ssh.h" - #include "ssh2.h" -@@ -1888,6 +1892,11 @@ main(int ac, char **av) - } - } - -+#ifdef HAVE_SYSTEMD -+ /* Signal systemd that we are ready to accept connections */ -+ sd_notify(0, "READY=1"); -+#endif -+ - /* Accept a connection and return in a forked child */ - server_accept_loop(&sock_in, &sock_out, - &newsock, config_s); diff --git a/SOURCES/openssh-7.7p1-fips.patch b/SOURCES/openssh-7.7p1-fips.patch deleted file mode 100644 index 0cbd22f..0000000 --- a/SOURCES/openssh-7.7p1-fips.patch +++ /dev/null @@ -1,569 +0,0 @@ -diff -up openssh-7.9p1/cipher-ctr.c.fips openssh-7.9p1/cipher-ctr.c ---- openssh-7.9p1/cipher-ctr.c.fips 2019-03-11 17:06:37.519877082 +0100 -+++ openssh-7.9p1/cipher-ctr.c 2019-03-11 17:06:37.620878031 +0100 -@@ -179,7 +179,8 @@ evp_aes_128_ctr(void) - aes_ctr.do_cipher = ssh_aes_ctr; - #ifndef SSH_OLD_EVP - aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | -- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | -+ EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); - } -diff -up openssh-7.9p1/clientloop.c.fips openssh-7.9p1/clientloop.c ---- openssh-7.9p1/clientloop.c.fips 2019-03-11 17:06:37.523877120 +0100 -+++ openssh-7.9p1/clientloop.c 2019-03-11 17:06:37.620878031 +0100 -@@ -2014,7 +2014,8 @@ key_accepted_by_hostkeyalgs(const struct - { - const char *ktype = sshkey_ssh_name(key); - const char *hostkeyalgs = options.hostkeyalgorithms != NULL ? -- options.hostkeyalgorithms : KEX_DEFAULT_PK_ALG; -+ options.hostkeyalgorithms : (FIPS_mode() ? -+ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG); - - if (key == NULL || key->type == KEY_UNSPEC) - return 0; -diff -up openssh-7.9p1/dh.c.fips openssh-7.9p1/dh.c ---- openssh-7.9p1/dh.c.fips 2018-10-17 02:01:20.000000000 +0200 -+++ openssh-7.9p1/dh.c 2019-03-11 17:08:11.769763057 +0100 -@@ -152,6 +152,12 @@ choose_dh(int min, int wantbits, int max - int best, bestcount, which, linenum; - struct dhgroup dhg; - -+ if (FIPS_mode()) { -+ verbose("Using arbitrary primes is not allowed in FIPS mode." -+ " Falling back to known groups."); -+ return (dh_new_group_fallback(max)); -+ } -+ - if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) { - logit("WARNING: could not open %s (%s), using fixed modulus", - _PATH_DH_MODULI, strerror(errno)); -@@ -489,4 +495,38 @@ dh_estimate(int bits) - return 8192; - } - -+/* -+ * Compares the received DH parameters with known-good groups, -+ * which might be either from group14, group16 or group18. -+ */ -+int -+dh_is_known_group(const DH *dh) -+{ -+ const BIGNUM *p, *g; -+ const BIGNUM *known_p, *known_g; -+ DH *known = NULL; -+ int bits = 0, rv = 0; -+ -+ DH_get0_pqg(dh, &p, NULL, &g); -+ bits = BN_num_bits(p); -+ -+ if (bits <= 3072) { -+ known = dh_new_group14(); -+ } else if (bits <= 6144) { -+ known = dh_new_group16(); -+ } else { -+ known = dh_new_group18(); -+ } -+ -+ DH_get0_pqg(known, &known_p, NULL, &known_g); -+ -+ if (BN_cmp(g, known_g) == 0 && -+ BN_cmp(p, known_p) == 0) { -+ rv = 1; -+ } -+ -+ DH_free(known); -+ return rv; -+} -+ - #endif /* WITH_OPENSSL */ -diff -up openssh-7.9p1/dh.h.fips openssh-7.9p1/dh.h ---- openssh-7.9p1/dh.h.fips 2018-10-17 02:01:20.000000000 +0200 -+++ openssh-7.9p1/dh.h 2019-03-11 17:08:18.718828381 +0100 -@@ -43,6 +43,7 @@ DH *dh_new_group_fallback(int); - - int dh_gen_key(DH *, int); - int dh_pub_is_valid(const DH *, const BIGNUM *); -+int dh_is_known_group(const DH *); - - u_int dh_estimate(int); - -diff -up openssh-7.9p1/kex.c.fips openssh-7.9p1/kex.c ---- openssh-7.9p1/kex.c.fips 2019-03-11 17:06:37.614877975 +0100 -+++ openssh-7.9p1/kex.c 2019-03-11 17:06:37.621878041 +0100 -@@ -175,7 +196,10 @@ kex_names_valid(const char *names) - for ((p = strsep(&cp, ",")); p && *p != '\0'; - (p = strsep(&cp, ","))) { - if (kex_alg_by_name(p) == NULL) { -- error("Unsupported KEX algorithm \"%.100s\"", p); -+ if (FIPS_mode()) -+ error("\"%.100s\" is not allowed in FIPS mode", p); -+ else -+ error("Unsupported KEX algorithm \"%.100s\"", p); - free(s); - return 0; - } -diff -up openssh-7.9p1/kexgexc.c.fips openssh-7.9p1/kexgexc.c ---- openssh-7.9p1/kexgexc.c.fips 2018-10-17 02:01:20.000000000 +0200 -+++ openssh-7.9p1/kexgexc.c 2019-03-11 17:06:37.621878041 +0100 -@@ -28,6 +28,7 @@ - - #ifdef WITH_OPENSSL - -+#include - #include - - #include -@@ -118,6 +119,10 @@ input_kex_dh_gex_group(int type, u_int32 - r = SSH_ERR_ALLOC_FAIL; - goto out; - } -+ if (FIPS_mode() && dh_is_known_group(kex->dh) == 0) { -+ r = SSH_ERR_INVALID_ARGUMENT; -+ goto out; -+ } - p = g = NULL; /* belong to kex->dh now */ - - /* generate and send 'e', client DH public key */ -diff -up openssh-7.9p1/myproposal.h.fips openssh-7.9p1/myproposal.h ---- openssh-7.9p1/myproposal.h.fips 2018-10-17 02:01:20.000000000 +0200 -+++ openssh-7.9p1/myproposal.h 2019-03-11 17:06:37.621878041 +0100 -@@ -116,6 +116,16 @@ - "rsa-sha2-256," \ - "ssh-rsa" - -+#define KEX_FIPS_PK_ALG \ -+ HOSTKEY_ECDSA_CERT_METHODS \ -+ "rsa-sha2-512-cert-v01@openssh.com," \ -+ "rsa-sha2-256-cert-v01@openssh.com," \ -+ "ssh-rsa-cert-v01@openssh.com," \ -+ HOSTKEY_ECDSA_METHODS \ -+ "rsa-sha2-512," \ -+ "rsa-sha2-256," \ -+ "ssh-rsa" -+ - /* the actual algorithms */ - - #define KEX_SERVER_ENCRYPT \ -@@ -139,6 +147,38 @@ - - #define KEX_CLIENT_MAC KEX_SERVER_MAC - -+#define KEX_FIPS_ENCRYPT \ -+ "aes128-ctr,aes192-ctr,aes256-ctr," \ -+ "aes128-cbc,3des-cbc," \ -+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" \ -+ AESGCM_CIPHER_MODES -+#ifdef HAVE_EVP_SHA256 -+# define KEX_DEFAULT_KEX_FIPS \ -+ KEX_ECDH_METHODS \ -+ KEX_SHA2_METHODS \ -+ "diffie-hellman-group14-sha256" -+# define KEX_FIPS_MAC \ -+ "hmac-sha1," \ -+ "hmac-sha2-256," \ -+ "hmac-sha2-512," \ -+ "hmac-sha1-etm@openssh.com," \ -+ "hmac-sha2-256-etm@openssh.com," \ -+ "hmac-sha2-512-etm@openssh.com" -+#else -+# ifdef OPENSSL_HAS_NISTP521 -+# define KEX_DEFAULT_KEX_FIPS \ -+ "ecdh-sha2-nistp256," \ -+ "ecdh-sha2-nistp384," \ -+ "ecdh-sha2-nistp521" -+# else -+# define KEX_DEFAULT_KEX_FIPS \ -+ "ecdh-sha2-nistp256," \ -+ "ecdh-sha2-nistp384" -+# endif -+#define KEX_FIPS_MAC \ -+ "hmac-sha1" -+#endif -+ - /* Not a KEX value, but here so all the algorithm defaults are together */ - #define SSH_ALLOWED_CA_SIGALGS \ - "ecdsa-sha2-nistp256," \ -diff -up openssh-7.9p1/readconf.c.fips openssh-7.9p1/readconf.c ---- openssh-7.9p1/readconf.c.fips 2019-03-11 17:06:37.601877853 +0100 -+++ openssh-7.9p1/readconf.c 2019-03-11 17:06:37.622878050 +0100 -@@ -2178,18 +2178,19 @@ fill_default_options(Options * options) - all_kex = kex_alg_list(','); - all_key = sshkey_alg_list(0, 0, 1, ','); - all_sig = sshkey_alg_list(0, 1, 1, ','); --#define ASSEMBLE(what, defaults, all) \ -+#define ASSEMBLE(what, defaults, fips_defaults, all) \ - do { \ - if ((r = kex_assemble_names(&options->what, \ -- defaults, all)) != 0) \ -+ (FIPS_mode() ? fips_defaults : defaults), \ -+ all)) != 0) \ - fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \ - } while (0) -- ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, all_cipher); -- ASSEMBLE(macs, KEX_CLIENT_MAC, all_mac); -- ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, all_kex); -- ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key); -- ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key); -- ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig); -+ ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher); -+ ASSEMBLE(macs, KEX_CLIENT_MAC, KEX_FIPS_MAC, all_mac); -+ ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, KEX_DEFAULT_KEX_FIPS, all_kex); -+ ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); -+ ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); -+ ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, KEX_FIPS_PK_ALG, all_sig); - #undef ASSEMBLE - free(all_cipher); - free(all_mac); -diff -up openssh-7.9p1/sandbox-seccomp-filter.c.fips openssh-7.9p1/sandbox-seccomp-filter.c ---- openssh-7.9p1/sandbox-seccomp-filter.c.fips 2019-03-11 17:06:37.586877712 +0100 -+++ openssh-7.9p1/sandbox-seccomp-filter.c 2019-03-11 17:06:37.622878050 +0100 -@@ -137,6 +137,9 @@ static const struct sock_filter preauth_ - #ifdef __NR_open - SC_DENY(__NR_open, EACCES), - #endif -+#ifdef __NR_socket -+ SC_DENY(__NR_socket, EACCES), -+#endif - #ifdef __NR_openat - SC_DENY(__NR_openat, EACCES), - #endif -diff -up openssh-7.9p1/servconf.c.fips openssh-7.9p1/servconf.c ---- openssh-7.9p1/servconf.c.fips 2019-03-11 17:06:37.568877543 +0100 -+++ openssh-7.9p1/servconf.c 2019-03-11 17:06:37.622878050 +0100 -@@ -209,18 +209,19 @@ assemble_algorithms(ServerOptions *o) - all_kex = kex_alg_list(','); - all_key = sshkey_alg_list(0, 0, 1, ','); - all_sig = sshkey_alg_list(0, 1, 1, ','); --#define ASSEMBLE(what, defaults, all) \ -+#define ASSEMBLE(what, defaults, fips_defaults, all) \ - do { \ -- if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ -+ if ((r = kex_assemble_names(&o->what, (FIPS_mode() \ -+ ? fips_defaults : defaults), all)) != 0) \ - fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \ - } while (0) -- ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher); -- ASSEMBLE(macs, KEX_SERVER_MAC, all_mac); -- ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex); -- ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, all_key); -- ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key); -- ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key); -- ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig); -+ ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher); -+ ASSEMBLE(macs, KEX_SERVER_MAC, KEX_FIPS_MAC, all_mac); -+ ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, KEX_DEFAULT_KEX_FIPS, all_kex); -+ ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); -+ ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); -+ ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); -+ ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, KEX_FIPS_PK_ALG, all_sig); - #undef ASSEMBLE - free(all_cipher); - free(all_mac); -diff -up openssh-7.9p1/ssh.c.fips openssh-7.9p1/ssh.c ---- openssh-7.9p1/ssh.c.fips 2019-03-11 17:06:37.602877862 +0100 -+++ openssh-7.9p1/ssh.c 2019-03-11 17:06:37.623878060 +0100 -@@ -76,6 +76,7 @@ - #include - #include - #endif -+#include - #include "openbsd-compat/openssl-compat.h" - #include "openbsd-compat/sys-queue.h" - -@@ -1283,6 +1294,10 @@ main(int ac, char **av) - dump_client_config(&options, host); - exit(0); - } -+ -+ if (FIPS_mode()) { -+ debug("FIPS mode initialized"); -+ } - - if (muxclient_command != 0 && options.control_path == NULL) - fatal("No ControlPath specified for \"-O\" command"); -diff -up openssh-7.9p1/sshconnect2.c.fips openssh-7.9p1/sshconnect2.c ---- openssh-7.9p1/sshconnect2.c.fips 2019-03-11 17:06:37.580877655 +0100 -+++ openssh-7.9p1/sshconnect2.c 2019-03-11 17:06:37.623878060 +0100 -@@ -44,6 +44,8 @@ - #include - #endif - -+#include -+ - #include "openbsd-compat/sys-queue.h" - - #include "xmalloc.h" -@@ -148,7 +150,8 @@ order_hostkeyalgs(char *host, struct soc - * Otherwise, prefer the host key algorithms that match known keys - * while keeping the ordering of HostkeyAlgorithms as much as possible. - */ -- oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG); -+ oavail = avail = xstrdup((FIPS_mode() -+ ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG)); - maxlen = strlen(avail) + 1; - first = xmalloc(maxlen); - last = xmalloc(maxlen); -@@ -229,14 +232,16 @@ ssh_kex2(struct ssh *ssh, char *host, st - if (options.hostkeyalgorithms != NULL) { - all_key = sshkey_alg_list(0, 0, 1, ','); - if (kex_assemble_names(&options.hostkeyalgorithms, -- KEX_DEFAULT_PK_ALG, all_key) != 0) -+ (FIPS_mode() ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), -+ all_key) != 0) - fatal("%s: kex_assemble_namelist", __func__); - free(all_key); - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - compat_pkalg_proposal(options.hostkeyalgorithms); - } else { - /* Enforce default */ -- options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG); -+ options.hostkeyalgorithms = xstrdup((FIPS_mode() -+ ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG)); - /* Prefer algorithms that we already have keys for */ - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - compat_pkalg_proposal( -@@ -201,35 +201,40 @@ ssh_kex2(char *host, struct sockaddr *ho - - #if defined(GSSAPI) && defined(WITH_OPENSSL) - if (options.gss_keyex) { -- /* Add the GSSAPI mechanisms currently supported on this -- * client to the key exchange algorithm proposal */ -- orig = myproposal[PROPOSAL_KEX_ALGS]; -- -- if (options.gss_server_identity) { -- gss_host = xstrdup(options.gss_server_identity); -- } else if (options.gss_trust_dns) { -- gss_host = remote_hostname(ssh); -- /* Fall back to specified host if we are using proxy command -- * and can not use DNS on that socket */ -- if (strcmp(gss_host, "UNKNOWN") == 0) { -- gss_host = xstrdup(host); -- } -- } else { -- gss_host = xstrdup(host); -- } -- -- gss = ssh_gssapi_client_mechanisms(gss_host, -- options.gss_client_identity, options.gss_kex_algorithms); -- if (gss) { -- debug("Offering GSSAPI proposal: %s", gss); -- xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -- "%s,%s", gss, orig); -- -- /* If we've got GSSAPI algorithms, then we also support the -- * 'null' hostkey, as a last resort */ -- orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; -- xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], -- "%s,null", orig); -+ if (FIPS_mode()) { -+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); -+ options.gss_keyex = 0; -+ } else { -+ /* Add the GSSAPI mechanisms currently supported on this -+ * client to the key exchange algorithm proposal */ -+ orig = myproposal[PROPOSAL_KEX_ALGS]; -+ -+ if (options.gss_server_identity) { -+ gss_host = xstrdup(options.gss_server_identity); -+ } else if (options.gss_trust_dns) { -+ gss_host = remote_hostname(ssh); -+ /* Fall back to specified host if we are using proxy command -+ * and can not use DNS on that socket */ -+ if (strcmp(gss_host, "UNKNOWN") == 0) { -+ gss_host = xstrdup(host); -+ } -+ } else { -+ gss_host = xstrdup(host); -+ } -+ -+ gss = ssh_gssapi_client_mechanisms(gss_host, -+ options.gss_client_identity, options.gss_kex_algorithms); -+ if (gss) { -+ debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -+ "%s,%s", gss, orig); -+ -+ /* If we've got GSSAPI algorithms, then we also support the -+ * 'null' hostkey, as a last resort */ -+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; -+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "%s,null", orig); -+ } - } - } - #endif -diff -up openssh-7.9p1/sshd.c.fips openssh-7.9p1/sshd.c ---- openssh-7.9p1/sshd.c.fips 2019-03-11 17:06:37.617878003 +0100 -+++ openssh-7.9p1/sshd.c 2019-03-11 17:06:37.624878069 +0100 -@@ -66,6 +66,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -77,6 +78,7 @@ - #include - #include - #include -+#include - #include "openbsd-compat/openssl-compat.h" - #endif - -@@ -1581,6 +1584,7 @@ main(int ac, char **av) - #endif - __progname = ssh_get_progname(av[0]); - -+ OpenSSL_add_all_algorithms(); - /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ - saved_argc = ac; - rexec_argc = ac; -@@ -2036,6 +2051,10 @@ main(int ac, char **av) - /* Reinitialize the log (because of the fork above). */ - log_init(__progname, options.log_level, options.log_facility, log_stderr); - -+ if (FIPS_mode()) { -+ debug("FIPS mode initialized"); -+ } -+ - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ - if (chdir("/") == -1) -@@ -2412,10 +2431,14 @@ do_ssh2_kex(void) - if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) - orig = NULL; - -- if (options.gss_keyex) -- gss = ssh_gssapi_server_mechanisms(); -- else -- gss = NULL; -+ if (options.gss_keyex) { -+ if (FIPS_mode()) { -+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); -+ options.gss_keyex = 0; -+ } else { -+ gss = ssh_gssapi_server_mechanisms(); -+ } -+ } - - if (gss && orig) - xasprintf(&newstr, "%s,%s", gss, orig); -diff -up openssh-7.9p1/sshkey.c.fips openssh-7.9p1/sshkey.c ---- openssh-7.9p1/sshkey.c.fips 2019-03-11 17:06:37.617878003 +0100 -+++ openssh-7.9p1/sshkey.c 2019-03-11 17:06:37.624878069 +0100 -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - #endif - - #include "crypto_api.h" -@@ -57,6 +58,7 @@ - #include "sshkey.h" - #include "sshkey-xmss.h" - #include "match.h" -+#include "log.h" - - #include "xmss_fast.h" - -@@ -392,7 +394,8 @@ sshkey_calculate_signature(EVP_PKEY *pkey - { - EVP_MD_CTX *ctx = NULL; - u_char *sig = NULL; -- int ret, slen, len; -+ int ret, slen; -+ size_t len; - - if (sigp == NULL || lenp == NULL) { - return SSH_ERR_INVALID_ARGUMENT; -@@ -411,9 +414,10 @@ sshkey_calculate_signature(EVP_PKEY *pkey - ret = SSH_ERR_ALLOC_FAIL; - goto error; - } -- if (EVP_SignInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || -- EVP_SignUpdate(ctx, data, datalen) <= 0 || -- EVP_SignFinal(ctx, sig, &len, pkey) <= 0) { -+ if (EVP_DigestSignInit(ctx, NULL, ssh_digest_to_md(hash_alg), -+ NULL, pkey) != 1 || -+ EVP_DigestSignUpdate(ctx, data, datalen) != 1 || -+ EVP_DigestSignFinal(ctx, sig, &len) != 1) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto error; - } -@@ -440,12 +444,13 @@ sshkey_verify_signature(EVP_PKEY *pkey - if ((ctx = EVP_MD_CTX_new()) == NULL) { - return SSH_ERR_ALLOC_FAIL; - } -- if (EVP_VerifyInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || -- EVP_VerifyUpdate(ctx, data, datalen) <= 0) { -+ if (EVP_DigestVerifyInit(ctx, NULL, ssh_digest_to_md(hash_alg), -+ NULL, pkey) != 1 || -+ EVP_DigestVerifyUpdate(ctx, data, datalen) != 1) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto done; - } -- ret = EVP_VerifyFinal(ctx, sigbuf, siglen, pkey); -+ ret = EVP_DigestVerifyFinal(ctx, sigbuf, siglen); - switch (ret) { - case 1: - ret = 0; -@@ -1514,6 +1516,8 @@ rsa_generate_private_key(u_int bits, RSA - } - if (!BN_set_word(f4, RSA_F4) || - !RSA_generate_key_ex(private, bits, f4, NULL)) { -+ if (FIPS_mode()) -+ logit("%s: the key length might be unsupported by FIPS mode approved key generation method", __func__); - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -diff -up openssh-7.9p1/ssh-keygen.c.fips openssh-7.9p1/ssh-keygen.c ---- openssh-7.9p1/ssh-keygen.c.fips 2019-03-11 17:06:37.590877750 +0100 -+++ openssh-7.9p1/ssh-keygen.c 2019-03-11 17:06:37.625878079 +0100 -@@ -230,6 +230,12 @@ type_bits_valid(int type, const char *na - OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; - if (*bitsp > maxbits) - fatal("key bits exceeds maximum %d", maxbits); -+ if (FIPS_mode()) { -+ if (type == KEY_DSA) -+ fatal("DSA keys are not allowed in FIPS mode"); -+ if (type == KEY_ED25519) -+ fatal("ED25519 keys are not allowed in FIPS mode"); -+ } - switch (type) { - case KEY_DSA: - if (*bitsp != 1024) -@@ -1029,9 +1035,17 @@ do_gen_all_hostkeys(struct passwd *pw) - first = 1; - printf("%s: generating new host keys: ", __progname); - } -+ type = sshkey_type_from_name(key_types[i].key_type); -+ -+ /* Skip the keys that are not supported in FIPS mode */ -+ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) { -+ logit("Skipping %s key in FIPS mode", -+ key_types[i].key_type_display); -+ goto next; -+ } -+ - printf("%s ", key_types[i].key_type_display); - fflush(stdout); -- type = sshkey_type_from_name(key_types[i].key_type); - if ((fd = mkstemp(prv_tmp)) == -1) { - error("Could not save your public key in %s: %s", - prv_tmp, strerror(errno)); -diff -up openssh-8.0p1/sshd_config.xxx openssh-8.0p1/sshd_config ---- openssh-8.0p1/sshd_config.xxx 2023-10-30 13:01:59.150952364 +0100 -+++ openssh-8.0p1/sshd_config 2023-10-30 13:02:56.662231354 +0100 -@@ -21,6 +21,7 @@ - - HostKey /etc/ssh/ssh_host_rsa_key - HostKey /etc/ssh/ssh_host_ecdsa_key -+#In FIPS mode Ed25519 keys are not supported, please comment out the next line - HostKey /etc/ssh/ssh_host_ed25519_key - - # Ciphers and keying diff --git a/SOURCES/openssh-7.7p1-redhat.patch b/SOURCES/openssh-7.7p1-redhat.patch deleted file mode 100644 index 1c1d778..0000000 --- a/SOURCES/openssh-7.7p1-redhat.patch +++ /dev/null @@ -1,164 +0,0 @@ -diff -up openssh-7.7p1/ssh_config.redhat openssh-7.7p1/ssh_config ---- openssh-7.7p1/ssh_config.redhat 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/ssh_config 2018-07-03 10:44:06.522245125 +0200 -@@ -44,3 +44,8 @@ - # VisualHostKey no - # ProxyCommand ssh -q -W %h:%p gateway.example.com - # RekeyLimit 1G 1h -+# -+# This system is following system-wide crypto policy. -+# To modify the system-wide ssh configuration, create a *.conf file under -+# /etc/ssh/ssh_config.d/ which will be automatically included below -+Include /etc/ssh/ssh_config.d/*.conf -diff -up openssh-7.7p1/ssh_config_redhat.redhat openssh-7.7p1/ssh_config_redhat ---- openssh-7.7p1/ssh_config_redhat.redhat 2018-07-03 10:44:06.522245125 +0200 -+++ openssh-7.7p1/ssh_config_redhat 2018-07-03 10:44:06.522245125 +0200 -@@ -0,0 +1,21 @@ -+# The options here are in the "Match final block" to be applied as the last -+# options and could be potentially overwritten by the user configuration -+Match final all -+ # Follow system-wide Crypto Policy, if defined: -+ Include /etc/crypto-policies/back-ends/openssh.config -+ -+ GSSAPIAuthentication yes -+ -+# If this option is set to yes then remote X11 clients will have full access -+# to the original X11 display. As virtually no X11 client supports the untrusted -+# mode correctly we set this to yes. -+ ForwardX11Trusted yes -+ -+# Send locale-related environment variables -+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+ SendEnv XMODIFIERS -+ -+# Uncomment this if you want to use .local domain -+# Host *.local -+# CheckHostIP no -diff -up openssh-7.7p1/sshd_config.0.redhat openssh-7.7p1/sshd_config.0 ---- openssh-7.7p1/sshd_config.0.redhat 2018-04-02 07:39:27.000000000 +0200 -+++ openssh-7.7p1/sshd_config.0 2018-07-03 10:44:06.523245133 +0200 -@@ -872,9 +872,9 @@ DESCRIPTION - - SyslogFacility - Gives the facility code that is used when logging messages from -- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, -- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The -- default is AUTH. -+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV, -+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. -+ The default is AUTH. - - TCPKeepAlive - Specifies whether the system should send TCP keepalive messages -diff -up openssh-7.7p1/sshd_config.5.redhat openssh-7.7p1/sshd_config.5 ---- openssh-7.7p1/sshd_config.5.redhat 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/sshd_config.5 2018-07-03 10:44:06.523245133 +0200 -@@ -1461,7 +1461,7 @@ By default no subsystems are defined. - .It Cm SyslogFacility - Gives the facility code that is used when logging messages from - .Xr sshd 8 . --The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, -+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2, - LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. - The default is AUTH. - .It Cm TCPKeepAlive -diff -up openssh-7.7p1/sshd_config.redhat openssh-7.7p1/sshd_config ---- openssh-7.7p1/sshd_config.redhat 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/sshd_config 2018-07-03 10:45:16.950782466 +0200 -@@ -10,20 +10,31 @@ - # possible, but leave them commented. Uncommented options override the - # default value. - -+# If you want to change the port on a SELinux system, you have to tell -+# SELinux about this change. -+# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER -+# - #Port 22 - #AddressFamily any - #ListenAddress 0.0.0.0 - #ListenAddress :: - --#HostKey /etc/ssh/ssh_host_rsa_key --#HostKey /etc/ssh/ssh_host_ecdsa_key --#HostKey /etc/ssh/ssh_host_ed25519_key -+HostKey /etc/ssh/ssh_host_rsa_key -+HostKey /etc/ssh/ssh_host_ecdsa_key -+HostKey /etc/ssh/ssh_host_ed25519_key - - # Ciphers and keying - #RekeyLimit default none - -+# This system is following system-wide crypto policy. The changes to -+# crypto properties (Ciphers, MACs, ...) will not have any effect here. -+# They will be overridden by command-line options passed to the server -+# on command line. -+# Please, check manual pages for update-crypto-policies(8) and sshd_config(5). -+ - # Logging - #SyslogFacility AUTH -+SyslogFacility AUTHPRIV - #LogLevel INFO - - # Authentication: -@@ -56,9 +70,11 @@ AuthorizedKeysFile .ssh/authorized_keys - # To disable tunneled clear text passwords, change to no here! - #PasswordAuthentication yes - #PermitEmptyPasswords no -+PasswordAuthentication yes - - # Change to no to disable s/key passwords - #ChallengeResponseAuthentication yes -+ChallengeResponseAuthentication no - - # Kerberos options - #KerberosAuthentication no -@@ -67,8 +83,8 @@ AuthorizedKeysFile .ssh/authorized_keys - #KerberosGetAFSToken no - - # GSSAPI options --#GSSAPIAuthentication no --#GSSAPICleanupCredentials yes -+GSSAPIAuthentication yes -+GSSAPICleanupCredentials no - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -@@ -79,16 +95,20 @@ AuthorizedKeysFile .ssh/authorized_keys - # If you just want the PAM account and session checks to run without - # PAM authentication, then enable this but set PasswordAuthentication - # and ChallengeResponseAuthentication to 'no'. --#UsePAM no -+UsePAM yes - - #AllowAgentForwarding yes - #AllowTcpForwarding yes - #GatewayPorts no --#X11Forwarding no -+X11Forwarding yes - #X11DisplayOffset 10 - #X11UseLocalhost yes - #PermitTTY yes --#PrintMotd yes -+ -+# It is recommended to use pam_motd in /etc/pam.d/sshd instead of PrintMotd, -+# as it is more configurable and versatile than the built-in version. -+PrintMotd no -+ - #PrintLastLog yes - #TCPKeepAlive yes - #PermitUserEnvironment no -@@ -106,6 +126,12 @@ AuthorizedKeysFile .ssh/authorized_keys - # no default banner path - #Banner none - -+# Accept locale-related environment variables -+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+AcceptEnv XMODIFIERS -+ - # override default of no subsystems - Subsystem sftp /usr/libexec/sftp-server - diff --git a/SOURCES/openssh-7.8p1-UsePAM-warning.patch b/SOURCES/openssh-7.8p1-UsePAM-warning.patch deleted file mode 100644 index d4ddcf1..0000000 --- a/SOURCES/openssh-7.8p1-UsePAM-warning.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/sshd.c b/sshd.c ---- a/sshd.c -+++ b/sshd.c -@@ -1701,6 +1701,10 @@ main(int ac, char **av) - parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, - cfg, NULL); - -+ /* 'UsePAM no' is not supported in RHEL */ -+ if (! options.use_pam) -+ logit("WARNING: 'UsePAM no' is not supported in RHEL and may cause several problems."); -+ - /* Fill in default values for those options not explicitly set. */ - fill_default_server_options(&options); - -diff --git a/sshd_config b/sshd_config ---- a/sshd_config -+++ b/sshd_config -@@ -101,6 +101,8 @@ GSSAPICleanupCredentials no - # If you just want the PAM account and session checks to run without - # PAM authentication, then enable this but set PasswordAuthentication - # and ChallengeResponseAuthentication to 'no'. -+# WARNING: 'UsePAM no' is not supported in RHEL and may cause several -+# problems. - UsePAM yes - - #AllowAgentForwarding yes diff --git a/SOURCES/openssh-7.9p1-ssh-copy-id.patch b/SOURCES/openssh-7.9p1-ssh-copy-id.patch deleted file mode 100644 index 6ff2b25..0000000 --- a/SOURCES/openssh-7.9p1-ssh-copy-id.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff -up openssh-7.9p1/contrib/ssh-copy-id.ssh-copy-id openssh-7.9p1/contrib/ssh-copy-id ---- openssh-7.9p1/contrib/ssh-copy-id.ssh-copy-id 2018-10-17 02:01:20.000000000 +0200 -+++ openssh-7.9p1/contrib/ssh-copy-id 2019-01-23 20:49:30.513393667 +0100 -@@ -112,7 +112,8 @@ do - usage - } - -- OPT= OPTARG= -+ OPT= -+ OPTARG= - # implement something like getopt to avoid Solaris pain - case "$1" in - -i?*|-o?*|-p?*) -@@ -185,8 +185,8 @@ - usage - fi - --# drop trailing colon --USER_HOST=$(printf "%s\n" "$1" | sed 's/:$//') -+# don't drop trailing colon because it can be a valid ipv6 address -+USER_HOST=$(printf "%s\n" "$1") - # tack the hostname onto SSH_OPTS - SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }'$(quote "$USER_HOST")'" - # and populate "$@" for later use (only way to get proper quoting of options) -@@ -261,7 +262,7 @@ populate_new_ids() { - fi - if [ -z "$NEW_IDS" ] ; then - printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n' "$0" >&2 -- printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' "$0" >&2 -+ printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' >&2 - exit 0 - fi - printf '%s: INFO: %d key(s) remain to be installed -- if you are prompted now it is to install the new keys\n' "$0" "$(printf '%s\n' "$NEW_IDS" | wc -l)" >&2 -@@ -296,7 +297,7 @@ case "$REMOTE_VERSION" in - # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX; - # 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh. - [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \ -- ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ -+ ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys || exit 1; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ - || exit 1 - ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) - ;; diff --git a/SOURCES/openssh-8.0p1-avoidkillall.patch b/SOURCES/openssh-8.0p1-avoidkillall.patch deleted file mode 100644 index 77331e8..0000000 --- a/SOURCES/openssh-8.0p1-avoidkillall.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/sftp.c b/sftp.c -index b66037f1..54538ff9 100644 ---- a/sftp.c -+++ b/sftp.c -@@ -220,9 +220,12 @@ static const struct CMD cmds[] = { - static void - killchild(int signo) - { -- if (sshpid > 1) { -- kill(sshpid, SIGTERM); -- waitpid(sshpid, NULL, 0); -+ pid_t pid; -+ -+ pid = sshpid; -+ if (pid > 1) { -+ kill(pid, SIGTERM); -+ (void)waitpid(pid, NULL, 0); - } - - _exit(1); diff --git a/SOURCES/openssh-8.0p1-bigsshdconfig.patch b/SOURCES/openssh-8.0p1-bigsshdconfig.patch deleted file mode 100644 index 2158ffe..0000000 --- a/SOURCES/openssh-8.0p1-bigsshdconfig.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/msg.c b/msg.c -index 99c25cd2..574a566e 100644 ---- a/msg.c -+++ b/msg.c -@@ -77,7 +77,7 @@ ssh_msg_recv(int fd, struct sshbuf *m) - return (-1); - } - msg_len = get_u32(buf); -- if (msg_len > 256 * 1024) { -+ if (msg_len > sshbuf_max_size(m)) { - error("ssh_msg_recv: read: bad msg_len %u", msg_len); - return (-1); - } diff --git a/SOURCES/openssh-8.0p1-channel-limits.patch b/SOURCES/openssh-8.0p1-channel-limits.patch deleted file mode 100644 index 47e1f87..0000000 --- a/SOURCES/openssh-8.0p1-channel-limits.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff -up openssh-8.0p1/channels.c.channel-limits openssh-8.0p1/channels.c ---- openssh-8.0p1/channels.c.channel-limits 2021-03-16 12:17:58.905576511 +0100 -+++ openssh-8.0p1/channels.c 2021-03-16 12:17:58.925576667 +0100 -@@ -354,6 +354,7 @@ channel_new(struct ssh *ssh, char *ctype - struct ssh_channels *sc = ssh->chanctxt; - u_int i, found; - Channel *c; -+ int r; - - /* Try to find a free slot where to put the new channel. */ - for (i = 0; i < sc->channels_alloc; i++) { -@@ -383,6 +384,8 @@ channel_new(struct ssh *ssh, char *ctype - (c->output = sshbuf_new()) == NULL || - (c->extended = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); -+ if ((r = sshbuf_set_max_size(c->input, CHAN_INPUT_MAX)) != 0) -+ fatal("%s: sshbuf_set_max_size: %s", __func__, ssh_err(r)); - c->ostate = CHAN_OUTPUT_OPEN; - c->istate = CHAN_INPUT_OPEN; - channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0); -diff -up openssh-8.0p1/channels.h.channel-limits openssh-8.0p1/channels.h ---- openssh-8.0p1/channels.h.channel-limits 2021-03-16 12:17:58.868576223 +0100 -+++ openssh-8.0p1/channels.h 2021-03-16 12:17:58.907576527 +0100 -@@ -215,6 +215,9 @@ struct Channel { - /* Read buffer size */ - #define CHAN_RBUF (16*1024) - -+/* Maximum channel input buffer size */ -+#define CHAN_INPUT_MAX (16*1024*1024) -+ - /* Hard limit on number of channels */ - #define CHANNELS_MAX_CHANNELS (16*1024) - diff --git a/SOURCES/openssh-8.0p1-client_alive_count_max.patch b/SOURCES/openssh-8.0p1-client_alive_count_max.patch deleted file mode 100644 index e0f272f..0000000 --- a/SOURCES/openssh-8.0p1-client_alive_count_max.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/serverloop.c b/serverloop.c -index e16eabe2..a8c99e2e 100644 ---- a/serverloop.c -+++ b/serverloop.c -@@ -184,7 +184,8 @@ client_alive_check(struct ssh *ssh) - int r, channel_id; - - /* timeout, check to see how many we have had */ -- if (ssh_packet_inc_alive_timeouts(ssh) > -+ if (options.client_alive_count_max > 0 && -+ ssh_packet_inc_alive_timeouts(ssh) > - options.client_alive_count_max) { - sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); - logit("Timeout, client not responding from %s", remote_id); -diff --git a/sshd_config.5 b/sshd_config.5 -index d47cb0d2..2cddbd59 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -519,6 +519,9 @@ is set to 15, and - .Cm ClientAliveCountMax - is left at the default, unresponsive SSH clients - will be disconnected after approximately 45 seconds. -+Setting a zero -+.Cm ClientAliveCountMax -+disables connection termination. - .It Cm ClientAliveInterval - Sets a timeout interval in seconds after which if no data has been received - from the client, diff --git a/SOURCES/openssh-8.0p1-crypto-policies.patch b/SOURCES/openssh-8.0p1-crypto-policies.patch deleted file mode 100644 index 5dc2289..0000000 --- a/SOURCES/openssh-8.0p1-crypto-policies.patch +++ /dev/null @@ -1,424 +0,0 @@ -diff -up openssh-8.0p1/ssh_config.5.crypto-policies openssh-8.0p1/ssh_config.5 ---- openssh-8.0p1/ssh_config.5.crypto-policies 2020-03-24 17:32:54.821789205 +0100 -+++ openssh-8.0p1/ssh_config.5 2020-03-24 17:59:58.174122920 +0100 -@@ -357,17 +357,17 @@ or - .Qq *.c.example.com - domains. - .It Cm CASignatureAlgorithms -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies which algorithms are allowed for signing of certificates - by certificate authorities (CAs). --The default is: --.Bd -literal -offset indent --ecdsa-sha2-nistp256.ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, --ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa --.Ed --.Pp - .Xr ssh 1 - will not accept host certificates signed using algorithms other than those - specified. -+.Pp - .It Cm CertificateFile - Specifies a file from which the user's certificate is read. - A corresponding private key must be provided separately in order -@@ -420,16 +420,21 @@ If the option is set to - .Cm no , - the check will not be executed. - .It Cm Ciphers -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the ciphers allowed and their order of preference. - Multiple ciphers must be comma-separated. - If the specified value begins with a - .Sq + --character, then the specified ciphers will be appended to the default set -+character, then the specified ciphers will be appended to the built-in default set - instead of replacing them. - If the specified value begins with a - .Sq - - character, then the specified ciphers (including wildcards) will be removed --from the default set instead of replacing them. -+from the built-in default set instead of replacing them. - .Pp - The supported ciphers are: - .Bd -literal -offset indent -@@ -445,13 +450,6 @@ aes256-gcm@openssh.com - chacha20-poly1305@openssh.com - .Ed - .Pp --The default is: --.Bd -literal -offset indent --chacha20-poly1305@openssh.com, --aes128-ctr,aes192-ctr,aes256-ctr, --aes128-gcm@openssh.com,aes256-gcm@openssh.com --.Ed --.Pp - The list of available ciphers may also be obtained using - .Qq ssh -Q cipher . - .It Cm ClearAllForwardings -@@ -800,6 +798,11 @@ command line will be passed untouched to - The default is - .Dq no . - .It Cm GSSAPIKexAlgorithms -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - The list of key exchange algorithms that are offered for GSSAPI - key exchange. Possible values are - .Bd -literal -offset 3n -@@ -812,9 +815,8 @@ gss-nistp256-sha256-, - gss-curve25519-sha256- - .Ed - .Pp --The default is --.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . - This option only applies to connections using GSSAPI. -+.Pp - .It Cm HashKnownHosts - Indicates that - .Xr ssh 1 -@@ -1114,26 +1115,21 @@ it may be zero or more of: - and - .Cm pam . - .It Cm KexAlgorithms -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. - Alternately if the specified value begins with a - .Sq + --character, then the specified methods will be appended to the default set -+character, then the specified methods will be appended to the built-in default set - instead of replacing them. - If the specified value begins with a - .Sq - - character, then the specified methods (including wildcards) will be removed --from the default set instead of replacing them. --The default is: --.Bd -literal -offset indent --curve25519-sha256,curve25519-sha256@libssh.org, --ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, --diffie-hellman-group-exchange-sha256, --diffie-hellman-group16-sha512, --diffie-hellman-group18-sha512, --diffie-hellman-group14-sha256, --diffie-hellman-group14-sha1 --.Ed -+from the built-in default set instead of replacing them. - .Pp - The list of available key exchange algorithms may also be obtained using - .Qq ssh -Q kex . -@@ -1193,33 +1189,29 @@ The default is INFO. - DEBUG and DEBUG1 are equivalent. - DEBUG2 and DEBUG3 each specify higher levels of verbose output. - .It Cm MACs -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the MAC (message authentication code) algorithms - in order of preference. - The MAC algorithm is used for data integrity protection. - Multiple algorithms must be comma-separated. - If the specified value begins with a - .Sq + --character, then the specified algorithms will be appended to the default set -+character, then the specified algorithms will be appended to the built-in default set - instead of replacing them. - If the specified value begins with a - .Sq - - character, then the specified algorithms (including wildcards) will be removed --from the default set instead of replacing them. -+from the built-in default set instead of replacing them. - .Pp - The algorithms that contain - .Qq -etm - calculate the MAC after encryption (encrypt-then-mac). - These are considered safer and their use recommended. - .Pp --The default is: --.Bd -literal -offset indent --umac-64-etm@openssh.com,umac-128-etm@openssh.com, --hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, --hmac-sha1-etm@openssh.com, --umac-64@openssh.com,umac-128@openssh.com, --hmac-sha2-256,hmac-sha2-512,hmac-sha1 --.Ed --.Pp - The list of available MAC algorithms may also be obtained using - .Qq ssh -Q mac . - .It Cm NoHostAuthenticationForLocalhost -@@ -1352,27 +1344,21 @@ instead of continuing to execute and pas - The default is - .Cm no . - .It Cm PubkeyAcceptedKeyTypes -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the key types that will be used for public key authentication - as a comma-separated list of patterns. - Alternately if the specified value begins with a - .Sq + --character, then the key types after it will be appended to the default -+character, then the key types after it will be appended to the built-in default - instead of replacing it. - If the specified value begins with a - .Sq - - character, then the specified key types (including wildcards) will be removed --from the default set instead of replacing them. --The default for this option is: --.Bd -literal -offset 3n --ecdsa-sha2-nistp256-cert-v01@openssh.com, --ecdsa-sha2-nistp384-cert-v01@openssh.com, --ecdsa-sha2-nistp521-cert-v01@openssh.com, --ssh-ed25519-cert-v01@openssh.com, --rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com, --ssh-rsa-cert-v01@openssh.com, --ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, --ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa --.Ed -+from the built-in default set instead of replacing them. - .Pp - The list of available key types may also be obtained using - .Qq ssh -Q key . -diff -up openssh-8.0p1/sshd_config.5.crypto-policies openssh-8.0p1/sshd_config.5 ---- openssh-8.0p1/sshd_config.5.crypto-policies 2020-03-24 17:32:54.802788908 +0100 -+++ openssh-8.0p1/sshd_config.5 2020-03-24 17:54:13.347740176 +0100 -@@ -383,16 +383,16 @@ If the argument is - then no banner is displayed. - By default, no banner is displayed. - .It Cm CASignatureAlgorithms -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies which algorithms are allowed for signing of certificates - by certificate authorities (CAs). --The default is: --.Bd -literal -offset indent --ecdsa-sha2-nistp256.ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, --ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa --.Ed --.Pp - Certificates signed using other algorithms will not be accepted for - public key or host-based authentication. -+.Pp - .It Cm ChallengeResponseAuthentication - Specifies whether challenge-response authentication is allowed (e.g. via - PAM or through authentication styles supported in -@@ -454,16 +454,21 @@ The default is - indicating not to - .Xr chroot 2 . - .It Cm Ciphers -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the ciphers allowed. - Multiple ciphers must be comma-separated. - If the specified value begins with a - .Sq + --character, then the specified ciphers will be appended to the default set -+character, then the specified ciphers will be appended to the built-in default set - instead of replacing them. - If the specified value begins with a - .Sq - - character, then the specified ciphers (including wildcards) will be removed --from the default set instead of replacing them. -+from the built-in default set instead of replacing them. - .Pp - The supported ciphers are: - .Pp -@@ -490,13 +495,6 @@ aes256-gcm@openssh.com - chacha20-poly1305@openssh.com - .El - .Pp --The default is: --.Bd -literal -offset indent --chacha20-poly1305@openssh.com, --aes128-ctr,aes192-ctr,aes256-ctr, --aes128-gcm@openssh.com,aes256-gcm@openssh.com --.Ed --.Pp - The list of available ciphers may also be obtained using - .Qq ssh -Q cipher . - .It Cm ClientAliveCountMax -@@ -688,6 +686,11 @@ For this to work - .Cm GSSAPIKeyExchange - needs to be enabled in the server and also used by the client. - .It Cm GSSAPIKexAlgorithms -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - The list of key exchange algorithms that are accepted by GSSAPI - key exchange. Possible values are - .Bd -literal -offset 3n -@@ -700,8 +703,6 @@ gss-nistp256-sha256-, - gss-curve25519-sha256- - .Ed - .Pp --The default is --.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . - This option only applies to connections using GSSAPI. - .It Cm HostbasedAcceptedKeyTypes - Specifies the key types that will be accepted for hostbased authentication -@@ -791,19 +791,13 @@ is specified, the location of the socket - .Ev SSH_AUTH_SOCK - environment variable. - .It Cm HostKeyAlgorithms -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the host key algorithms - that the server offers. --The default for this option is: --.Bd -literal -offset 3n --ecdsa-sha2-nistp256-cert-v01@openssh.com, --ecdsa-sha2-nistp384-cert-v01@openssh.com, --ecdsa-sha2-nistp521-cert-v01@openssh.com, --ssh-ed25519-cert-v01@openssh.com, --rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com, --ssh-rsa-cert-v01@openssh.com, --ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, --ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa --.Ed - .Pp - The list of available key types may also be obtained using - .Qq ssh -Q key . -@@ -922,16 +916,21 @@ Specifies whether to look at .k5login fi - The default is - .Cm yes . - .It Cm KexAlgorithms -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. - Alternately if the specified value begins with a - .Sq + --character, then the specified methods will be appended to the default set -+character, then the specified methods will be appended to the built-in default set - instead of replacing them. - If the specified value begins with a - .Sq - - character, then the specified methods (including wildcards) will be removed --from the default set instead of replacing them. -+from the built-in default set instead of replacing them. - The supported algorithms are: - .Pp - .Bl -item -compact -offset indent -@@ -961,15 +960,6 @@ ecdh-sha2-nistp384 - ecdh-sha2-nistp521 - .El - .Pp --The default is: --.Bd -literal -offset indent --curve25519-sha256,curve25519-sha256@libssh.org, --ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, --diffie-hellman-group-exchange-sha256, --diffie-hellman-group16-sha512,diffie-hellman-group18-sha512, --diffie-hellman-group14-sha256,diffie-hellman-group14-sha1 --.Ed --.Pp - The list of available key exchange algorithms may also be obtained using - .Qq ssh -Q kex . - .It Cm ListenAddress -@@ -1038,17 +1028,22 @@ DEBUG and DEBUG1 are equivalent. - DEBUG2 and DEBUG3 each specify higher levels of debugging output. - Logging with a DEBUG level violates the privacy of users and is not recommended. - .It Cm MACs -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the available MAC (message authentication code) algorithms. - The MAC algorithm is used for data integrity protection. - Multiple algorithms must be comma-separated. - If the specified value begins with a - .Sq + --character, then the specified algorithms will be appended to the default set -+character, then the specified algorithms will be appended to the built-in default set - instead of replacing them. - If the specified value begins with a - .Sq - - character, then the specified algorithms (including wildcards) will be removed --from the default set instead of replacing them. -+from the built-in default set instead of replacing them. - .Pp - The algorithms that contain - .Qq -etm -@@ -1091,15 +1086,6 @@ umac-64-etm@openssh.com - umac-128-etm@openssh.com - .El - .Pp --The default is: --.Bd -literal -offset indent --umac-64-etm@openssh.com,umac-128-etm@openssh.com, --hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, --hmac-sha1-etm@openssh.com, --umac-64@openssh.com,umac-128@openssh.com, --hmac-sha2-256,hmac-sha2-512,hmac-sha1 --.Ed --.Pp - The list of available MAC algorithms may also be obtained using - .Qq ssh -Q mac . - .It Cm Match -@@ -1446,27 +1432,21 @@ or equivalent.) - The default is - .Cm yes . - .It Cm PubkeyAcceptedKeyTypes -+The default is handled system-wide by -+.Xr crypto-policies 7 . -+To see the current defaults and how to modify them, see manual page -+.Xr update-crypto-policies 8 . -+.Pp - Specifies the key types that will be accepted for public key authentication - as a list of comma-separated patterns. - Alternately if the specified value begins with a - .Sq + --character, then the specified key types will be appended to the default set -+character, then the specified key types will be appended to the built-in default set - instead of replacing them. - If the specified value begins with a - .Sq - - character, then the specified key types (including wildcards) will be removed --from the default set instead of replacing them. --The default for this option is: --.Bd -literal -offset 3n --ecdsa-sha2-nistp256-cert-v01@openssh.com, --ecdsa-sha2-nistp384-cert-v01@openssh.com, --ecdsa-sha2-nistp521-cert-v01@openssh.com, --ssh-ed25519-cert-v01@openssh.com, --rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com, --ssh-rsa-cert-v01@openssh.com, --ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, --ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa --.Ed -+from the built-in default set instead of replacing them. - .Pp - The list of available key types may also be obtained using - .Qq ssh -Q key . diff --git a/SOURCES/openssh-8.0p1-crypto-policy-doc.patch b/SOURCES/openssh-8.0p1-crypto-policy-doc.patch deleted file mode 100644 index 483f1c8..0000000 --- a/SOURCES/openssh-8.0p1-crypto-policy-doc.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --color -ru a/sshd.8 b/sshd.8 ---- a/sshd.8 2022-05-31 13:39:10.231843926 +0200 -+++ b/sshd.8 2022-05-31 14:34:01.460815420 +0200 -@@ -78,6 +78,7 @@ - .Xr sshd_config 5 ) ; - command-line options override values specified in the - configuration file. -+This mechanism is used by systemd to apply system-wide crypto-policies to ssh server. - .Nm - rereads its configuration file when it receives a hangup signal, - .Dv SIGHUP , -@@ -207,6 +208,13 @@ - rules may be applied by specifying the connection parameters using one or more - .Fl C - options. -+The configuration does not contain the system-wide crypto-policy configuration. -+To show the most accurate runtime configuration, use: -+.Bd -literal -offset 3n -+source /etc/crypto-policies/back-ends/opensshserver.config -+source /etc/sysconfig/sshd -+sshd -T $OPTIONS $CRYPTO_POLICY -+.Ed - .It Fl t - Test mode. - Only check the validity of the configuration file and sanity of the keys. diff --git a/SOURCES/openssh-8.0p1-cve-2020-14145.patch b/SOURCES/openssh-8.0p1-cve-2020-14145.patch deleted file mode 100644 index c296bc4..0000000 --- a/SOURCES/openssh-8.0p1-cve-2020-14145.patch +++ /dev/null @@ -1,127 +0,0 @@ -diff -up openssh-8.0p1/hostfile.c.cve-2020-14145 openssh-8.0p1/hostfile.c ---- openssh-8.0p1/hostfile.c.cve-2020-14145 2019-04-18 00:52:57.000000000 +0200 -+++ openssh-8.0p1/hostfile.c 2021-05-17 16:53:38.694577251 +0200 -@@ -409,6 +409,18 @@ lookup_key_in_hostkeys_by_type(struct ho - found) == HOST_FOUND); - } - -+int -+lookup_marker_in_hostkeys(struct hostkeys *hostkeys, int want_marker) -+{ -+ u_int i; -+ -+ for (i = 0; i < hostkeys->num_entries; i++) { -+ if (hostkeys->entries[i].marker == (HostkeyMarker)want_marker) -+ return 1; -+ } -+ return 0; -+} -+ - static int - write_host_entry(FILE *f, const char *host, const char *ip, - const struct sshkey *key, int store_hash) -diff -up openssh-8.0p1/hostfile.h.cve-2020-14145 openssh-8.0p1/hostfile.h ---- openssh-8.0p1/hostfile.h.cve-2020-14145 2019-04-18 00:52:57.000000000 +0200 -+++ openssh-8.0p1/hostfile.h 2021-05-17 16:53:38.694577251 +0200 -@@ -39,6 +39,7 @@ HostStatus check_key_in_hostkeys(struct - const struct hostkey_entry **); - int lookup_key_in_hostkeys_by_type(struct hostkeys *, int, - const struct hostkey_entry **); -+int lookup_marker_in_hostkeys(struct hostkeys *, int); - - int hostfile_read_key(char **, u_int *, struct sshkey *); - int add_host_to_hostfile(const char *, const char *, -diff -up openssh-8.0p1/sshconnect2.c.cve-2020-14145 openssh-8.0p1/sshconnect2.c ---- openssh-8.0p1/sshconnect2.c.cve-2020-14145 2021-05-17 16:53:38.610576561 +0200 -+++ openssh-8.0p1/sshconnect2.c 2021-05-17 16:54:58.169230103 +0200 -@@ -98,12 +98,25 @@ verify_host_key_callback(struct sshkey * - return 0; - } - -+/* Returns the first item from a comma-separated algorithm list */ -+static char * -+first_alg(const char *algs) -+{ -+ char *ret, *cp; -+ -+ ret = xstrdup(algs); -+ if ((cp = strchr(ret, ',')) != NULL) -+ *cp = '\0'; -+ return ret; -+} -+ - static char * - order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) - { -- char *oavail, *avail, *first, *last, *alg, *hostname, *ret; -+ char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL; -+ char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL; - size_t maxlen; -- struct hostkeys *hostkeys; -+ struct hostkeys *hostkeys = NULL; - int ktype; - u_int i; - -@@ -115,6 +128,26 @@ order_hostkeyalgs(char *host, struct soc - for (i = 0; i < options.num_system_hostfiles; i++) - load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]); - -+ /* -+ * If a plain public key exists that matches the type of the best -+ * preference HostkeyAlgorithms, then use the whole list as is. -+ * Note that we ignore whether the best preference algorithm is a -+ * certificate type, as sshconnect.c will downgrade certs to -+ * plain keys if necessary. -+ */ -+ best = first_alg(options.hostkeyalgorithms); -+ if (lookup_key_in_hostkeys_by_type(hostkeys, -+ sshkey_type_plain(sshkey_type_from_name(best)), NULL)) { -+ debug3("%s: have matching best-preference key type %s, " -+ "using HostkeyAlgorithms verbatim", __func__, best); -+ ret = xstrdup(options.hostkeyalgorithms); -+ goto out; -+ } -+ -+ /* -+ * Otherwise, prefer the host key algorithms that match known keys -+ * while keeping the ordering of HostkeyAlgorithms as much as possible. -+ */ - oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG); - maxlen = strlen(avail) + 1; - first = xmalloc(maxlen); -@@ -131,11 +164,23 @@ order_hostkeyalgs(char *host, struct soc - while ((alg = strsep(&avail, ",")) && *alg != '\0') { - if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) - fatal("%s: unknown alg %s", __func__, alg); -+ /* -+ * If we have a @cert-authority marker in known_hosts then -+ * prefer all certificate algorithms. -+ */ -+ if (sshkey_type_is_cert(ktype) && -+ lookup_marker_in_hostkeys(hostkeys, MRK_CA)) { -+ ALG_APPEND(first, alg); -+ continue; -+ } -+ /* If the key appears in known_hosts then prefer it */ - if (lookup_key_in_hostkeys_by_type(hostkeys, -- sshkey_type_plain(ktype), NULL)) -+ sshkey_type_plain(ktype), NULL)) { - ALG_APPEND(first, alg); -- else -- ALG_APPEND(last, alg); -+ continue; -+ } -+ /* Otherwise, put it last */ -+ ALG_APPEND(last, alg); - } - #undef ALG_APPEND - xasprintf(&ret, "%s%s%s", first, -@@ -143,6 +188,8 @@ order_hostkeyalgs(char *host, struct soc - if (*first != '\0') - debug3("%s: prefer hostkeyalgs: %s", __func__, first); - -+ out: -+ free(best); - free(first); - free(last); - free(hostname); diff --git a/SOURCES/openssh-8.0p1-entropy.patch b/SOURCES/openssh-8.0p1-entropy.patch deleted file mode 100644 index 5dfee95..0000000 --- a/SOURCES/openssh-8.0p1-entropy.patch +++ /dev/null @@ -1,302 +0,0 @@ -diff --git a/entropy.c b/entropy.c -index 2d483b3..b361a04 100644 ---- a/entropy.c -+++ b/entropy.c -@@ -234,6 +234,9 @@ seed_rng(void) - } - #endif /* OPENSSL_PRNG_ONLY */ - -+#ifdef __linux__ -+ linux_seed(); -+#endif /* __linux__ */ - if (RAND_status() != 1) - fatal("PRNG is not seeded"); - -diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in -index b912dbe..9206337 100644 ---- a/openbsd-compat/Makefile.in -+++ b/openbsd-compat/Makefile.in -@@ -20,6 +20,7 @@ OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o di - port-solaris.o \ - port-net.o \ - port-uw.o \ -+ port-linux-prng.o \ - port-linux-sshd.o - - .c.o: -diff -up openssh-7.4p1/openbsd-compat/port-linux.h.entropy openssh-7.4p1/openbsd-compat/port-linux.h ---- openssh-7.4p1/openbsd-compat/port-linux.h.entropy 2016-12-23 18:34:27.747753563 +0100 -+++ openssh-7.4p1/openbsd-compat/port-linux.h 2016-12-23 18:34:27.769753570 +0100 -@@ -34,4 +34,6 @@ void oom_adjust_restore(void); - void oom_adjust_setup(void); - #endif - -+void linux_seed(void); -+ - #endif /* ! _PORT_LINUX_H */ -diff --git a/openbsd-compat/port-linux-prng.c b/openbsd-compat/port-linux-prng.c -new file mode 100644 -index 0000000..92a617c ---- /dev/null -+++ b/openbsd-compat/port-linux-prng.c -@@ -0,0 +1,78 @@ -+/* -+ * Copyright (c) 2011 - 2020 Red Hat, Inc. -+ * -+ * Authors: -+ * Jan F. Chadima -+ * Jakub Jelen -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Linux-specific portability code - prng support -+ */ -+ -+#include "includes.h" -+ -+#include -+#include -+#include -+#include -+ -+#include "log.h" -+ -+void -+linux_seed(void) -+{ -+ char *env = NULL; -+ size_t randlen = 14, left; -+ unsigned int flags = 0; -+ unsigned char buf[256], *p; -+ -+ env = getenv("SSH_USE_STRONG_RNG"); -+ if (env && strcmp(env, "0") != 0) { -+ size_t ienv = atoi(env); -+ -+ /* Max on buffer length */ -+ if (ienv > sizeof(buf)) -+ ienv = sizeof(buf); -+ /* Minimum is always 14 B */ -+ if (ienv > randlen) -+ randlen = ienv; -+ flags = GRND_RANDOM; -+ } -+ -+ errno = 0; -+ left = randlen; -+ p = buf; -+ do { -+ ssize_t len = getrandom(p, left, flags); -+ if (len == -1) { -+ if (errno != EINTR) { -+ if (flags) { -+ /* With the variable present, this is fatal error */ -+ fatal("Failed to seed from getrandom: %s", strerror(errno)); -+ } else { -+ /* Otherwise we log the issue drop out from here */ -+ debug("Failed to seed from getrandom: %s", strerror(errno)); -+ return; -+ } -+ } -+ } else if (len > 0) { -+ left -= len; -+ p += len; -+ } -+ } while (left > 0); -+ -+ RAND_seed(buf, randlen); -+} -diff --git a/ssh-add.1 b/ssh-add.1 -index 4812448..16305bf 100644 ---- a/ssh-add.1 -+++ b/ssh-add.1 -@@ -161,6 +161,22 @@ to make this work.) - Identifies the path of a - .Ux Ns -domain - socket used to communicate with the agent. -+.It Ev SSH_USE_STRONG_RNG -+The reseeding of the OpenSSL random generator is usually done from -+.Cm getrandom(1) -+without any specific flags. -+If the -+.Cm SSH_USE_STRONG_RNG -+environment variable is set to value other than -+.Cm 0 -+the OpenSSL random generator is reseeded from -+.Cm getrandom(1) -+with GRND_RANDOM flag specified. -+The number of bytes read is defined by the SSH_USE_STRONG_RNG value. -+Minimum is 14 bytes. -+This setting is not recommended on the computers without the hardware -+random generator because insufficient entropy causes the connection to -+be blocked until enough entropy is available. - .El - .Sh FILES - .Bl -tag -width Ds -diff --git a/ssh-agent.1 b/ssh-agent.1 -index 281ecbd..1a9a635 100644 ---- a/ssh-agent.1 -+++ b/ssh-agent.1 -@@ -201,6 +201,26 @@ sockets used to contain the connection to the authentication agent. - These sockets should only be readable by the owner. - The sockets should get automatically removed when the agent exits. - .El -+.Sh ENVIRONMENT -+.Bl -tag -width Ds -compact -+.Pp -+.It Pa SSH_USE_STRONG_RNG -+The reseeding of the OpenSSL random generator is usually done from -+.Cm getrandom(1) -+without any specific flags. -+If the -+.Cm SSH_USE_STRONG_RNG -+environment variable is set to value other than -+.Cm 0 -+the OpenSSL random generator is reseeded from -+.Cm getrandom(1) -+with GRND_RANDOM flag specified. -+The number of bytes read is defined by the SSH_USE_STRONG_RNG value. -+Minimum is 14 bytes. -+This setting is not recommended on the computers without the hardware -+random generator because insufficient entropy causes the connection to -+be blocked until enough entropy is available. -+.El - .Sh SEE ALSO - .Xr ssh 1 , - .Xr ssh-add 1 , -diff --git a/ssh-keygen.1 b/ssh-keygen.1 -index 12e00d4..1b51a4a 100644 ---- a/ssh-keygen.1 -+++ b/ssh-keygen.1 -@@ -832,6 +832,26 @@ Contains Diffie-Hellman groups used for DH-GEX. - The file format is described in - .Xr moduli 5 . - .El -+.Sh ENVIRONMENT -+.Bl -tag -width Ds -compact -+.Pp -+.It Pa SSH_USE_STRONG_RNG -+The reseeding of the OpenSSL random generator is usually done from -+.Cm getrandom(1) -+without any specific flags. -+If the -+.Cm SSH_USE_STRONG_RNG -+environment variable is set to value other than -+.Cm 0 -+the OpenSSL random generator is reseeded from -+.Cm getrandom(1) -+with GRND_RANDOM flag specified. -+The number of bytes read is defined by the SSH_USE_STRONG_RNG value. -+Minimum is 14 bytes. -+This setting is not recommended on the computers without the hardware -+random generator because insufficient entropy causes the connection to -+be blocked until enough entropy is available. -+.El - .Sh SEE ALSO - .Xr ssh 1 , - .Xr ssh-add 1 , -diff --git a/ssh-keysign.8 b/ssh-keysign.8 -index 69d0829..02d79f8 100644 ---- a/ssh-keysign.8 -+++ b/ssh-keysign.8 -@@ -80,6 +80,26 @@ must be set-uid root if host-based authentication is used. - If these files exist they are assumed to contain public certificate - information corresponding with the private keys above. - .El -+.Sh ENVIRONMENT -+.Bl -tag -width Ds -compact -+.Pp -+.It Pa SSH_USE_STRONG_RNG -+The reseeding of the OpenSSL random generator is usually done from -+.Cm getrandom(1) -+without any specific flags. -+If the -+.Cm SSH_USE_STRONG_RNG -+environment variable is set to value other than -+.Cm 0 -+the OpenSSL random generator is reseeded from -+.Cm getrandom(1) -+with GRND_RANDOM flag specified. -+The number of bytes read is defined by the SSH_USE_STRONG_RNG value. -+Minimum is 14 bytes. -+This setting is not recommended on the computers without the hardware -+random generator because insufficient entropy causes the connection to -+be blocked until enough entropy is available. -+.El - .Sh SEE ALSO - .Xr ssh 1 , - .Xr ssh-keygen 1 , -diff --git a/ssh.1 b/ssh.1 -index 929904b..f65e42f 100644 ---- a/ssh.1 -+++ b/ssh.1 -@@ -1309,6 +1309,25 @@ For more information, see the - .Cm PermitUserEnvironment - option in - .Xr sshd_config 5 . -+.Bl -tag -width "SSH_ORIGINAL_COMMAND" -+.Pp -+.It Ev SSH_USE_STRONG_RNG -+The reseeding of the OpenSSL random generator is usually done from -+.Cm getrandom(1) -+without any specific flags. -+If the -+.Cm SSH_USE_STRONG_RNG -+environment variable is set to value other than -+.Cm 0 -+the OpenSSL random generator is reseeded from -+.Cm getrandom(1) -+with GRND_RANDOM flag specified. -+The number of bytes read is defined by the SSH_USE_STRONG_RNG value. -+Minimum is 14 bytes. -+This setting is not recommended on the computers without the hardware -+random generator because insufficient entropy causes the connection to -+be blocked until enough entropy is available. -+.El - .Sh FILES - .Bl -tag -width Ds -compact - .It Pa ~/.rhosts -diff --git a/sshd.8 b/sshd.8 -index c2c237f..058d37a 100644 ---- a/sshd.8 -+++ b/sshd.8 -@@ -951,6 +951,26 @@ concurrently for different ports, this contains the process ID of the one - started last). - The content of this file is not sensitive; it can be world-readable. - .El -+.Sh ENVIRONMENT -+.Bl -tag -width Ds -compact -+.Pp -+.It Ev SSH_USE_STRONG_RNG -+The reseeding of the OpenSSL random generator is usually done from -+.Cm getrandom(1) -+without any specific flags. -+If the -+.Cm SSH_USE_STRONG_RNG -+environment variable is set to value other than -+.Cm 0 -+the OpenSSL random generator is reseeded from -+.Cm getrandom(1) -+with GRND_RANDOM flag specified. -+The number of bytes read is defined by the SSH_USE_STRONG_RNG value. -+Minimum is 14 bytes. -+This setting is not recommended on the computers without the hardware -+random generator because insufficient entropy causes the connection to -+be blocked until enough entropy is available. -+.El - .Sh IPV6 - IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell. - .Sh SEE ALSO - diff --git a/SOURCES/openssh-8.0p1-ipv6-process.patch b/SOURCES/openssh-8.0p1-ipv6-process.patch deleted file mode 100644 index cb76938..0000000 --- a/SOURCES/openssh-8.0p1-ipv6-process.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/sftp.c b/sftp.c -index 04881c83..03c7a5c7 100644 ---- a/sftp.c -+++ b/sftp.c -@@ -2527,12 +2527,17 @@ main(int argc, char **argv) - port = tmp; - break; - default: -+ /* Try with user, host and path. */ - if (parse_user_host_path(*argv, &user, &host, -- &file1) == -1) { -- /* Treat as a plain hostname. */ -- host = xstrdup(*argv); -- host = cleanhostname(host); -- } -+ &file1) == 0) -+ break; -+ /* Try with user and host. */ -+ if (parse_user_host_port(*argv, &user, &host, NULL) -+ == 0) -+ break; -+ /* Treat as a plain hostname. */ -+ host = xstrdup(*argv); -+ host = cleanhostname(host); - break; - } - file2 = *(argv + 1); diff --git a/SOURCES/openssh-8.0p1-keygen-sha2.patch b/SOURCES/openssh-8.0p1-keygen-sha2.patch deleted file mode 100644 index 31927fa..0000000 --- a/SOURCES/openssh-8.0p1-keygen-sha2.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 4a41d245d6b13bd3882c8dc058dbd2e2b39a9f67 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 24 Jan 2020 00:27:04 +0000 -Subject: [PATCH] upstream: when signing a certificate with an RSA key, default - to - -a safe signature algorithm (rsa-sha-512) if not is explicitly specified by -the user; ok markus@ - -OpenBSD-Commit-ID: e05f638f0be6c0266e1d3d799716b461011e83a9 ---- - ssh-keygen.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/ssh-keygen.c b/ssh-keygen.c -index 564c3c481..f2192edb9 100644 ---- a/ssh-keygen.c -+++ b/ssh-keygen.c -@@ -1788,10 +1788,14 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, - } - free(tmp); - -- if (key_type_name != NULL && -- sshkey_type_from_name(key_type_name) != ca->type) { -- fatal("CA key type %s doesn't match specified %s", -- sshkey_ssh_name(ca), key_type_name); -+ if (key_type_name != NULL) { -+ if (sshkey_type_from_name(key_type_name) != ca->type) { -+ fatal("CA key type %s doesn't match specified %s", -+ sshkey_ssh_name(ca), key_type_name); -+ } -+ } else if (ca->type == KEY_RSA) { -+ /* Default to a good signature algorithm */ -+ key_type_name = "rsa-sha2-512"; - } - - for (i = 0; i < argc; i++) { - -From 476e3551b2952ef73acc43d995e832539bf9bc4d Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Mon, 20 May 2019 00:20:35 +0000 -Subject: [PATCH] upstream: When signing certificates with an RSA key, default - to - -using the rsa-sha2-512 signature algorithm. Certificates signed by RSA keys -will therefore be incompatible with OpenSSH < 7.2 unless the default is -overridden. - -Document the ability of the ssh-keygen -t flag to override the -signature algorithm when signing certificates, and the new default. - -ok deraadt@ - -OpenBSD-Commit-ID: 400c9c15013978204c2cb80f294b03ae4cfc8b95 ---- - ssh-keygen.1 | 13 +++++++++++-- - sshkey.c | 9 ++++++++- - 2 files changed, 19 insertions(+), 3 deletions(-) - -diff --git a/ssh-keygen.1 b/ssh-keygen.1 -index f29774249..673bf6e2f 100644 ---- a/ssh-keygen.1 -+++ b/ssh-keygen.1 -@@ -35,7 +35,7 @@ - .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - .\" --.Dd $Mdocdate: March 5 2019 $ -+.Dd $Mdocdate: May 20 2019 $ - .Dt SSH-KEYGEN 1 - .Os - .Sh NAME -@@ -577,6 +577,15 @@ The possible values are - .Dq ed25519 , - or - .Dq rsa . -+.Pp -+This flag may also be used to specify the desired signature type when -+signing certificates using a RSA CA key. -+The available RSA signature variants are -+.Dq ssh-rsa -+(SHA1 signatures, not recommended), -+.Dq rsa-sha2-256 -+.Dq rsa-sha2-512 -+(the default). - .It Fl U - When used in combination with - .Fl s , -diff --git a/sshkey.c b/sshkey.c -index 9849cb237..379a579cf 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -2528,6 +2528,13 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, - strcmp(alg, k->cert->signature_type) != 0) - return SSH_ERR_INVALID_ARGUMENT; - -+ /* -+ * If no signing algorithm or signature_type was specified and we're -+ * using a RSA key, then default to a good signature algorithm. -+ */ -+ if (alg == NULL && ca->type == KEY_RSA) -+ alg = "rsa-sha2-512"; -+ - if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) - return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; - - diff --git a/SOURCES/openssh-8.0p1-keyscan-rsa-sha2.patch b/SOURCES/openssh-8.0p1-keyscan-rsa-sha2.patch deleted file mode 100644 index 954ece9..0000000 --- a/SOURCES/openssh-8.0p1-keyscan-rsa-sha2.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 7250879c72d28275a53f2f220e49646c3e42ef18 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 12 Jul 2019 04:08:39 +0000 -Subject: [PATCH] upstream: include SHA2-variant RSA key algorithms in KEX - proposal; - -allows ssh-keyscan to harvest keys from servers that disable olde SHA1 -ssh-rsa. bz#3029 from Jakub Jelen - -OpenBSD-Commit-ID: 9f95ebf76a150c2f727ca4780fb2599d50bbab7a ---- - ssh-keyscan.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/ssh-keyscan.c b/ssh-keyscan.c -index d95ba1b37..d383b57b9 100644 ---- a/ssh-keyscan.c -+++ b/ssh-keyscan.c -@@ -233,7 +233,12 @@ keygrab_ssh2(con *c) - break; - case KT_RSA: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? -- "ssh-rsa-cert-v01@openssh.com" : "ssh-rsa"; -+ "rsa-sha2-512-cert-v01@openssh.com," -+ "rsa-sha2-256-cert-v01@openssh.com," -+ "ssh-rsa-cert-v01@openssh.com" : -+ "rsa-sha2-512," -+ "rsa-sha2-256," -+ "ssh-rsa"; - break; - case KT_ED25519: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - diff --git a/SOURCES/openssh-8.0p1-openssl-evp.patch b/SOURCES/openssh-8.0p1-openssl-evp.patch deleted file mode 100644 index ade0bbb..0000000 --- a/SOURCES/openssh-8.0p1-openssl-evp.patch +++ /dev/null @@ -1,720 +0,0 @@ -From ed7ec0cdf577ffbb0b15145340cf51596ca3eb89 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 14 May 2019 10:45:45 +0200 -Subject: [PATCH] Use high-level OpenSSL API for signatures - ---- - digest-openssl.c | 16 ++++ - digest.h | 6 ++ - ssh-dss.c | 65 ++++++++++------ - ssh-ecdsa.c | 69 ++++++++++------- - ssh-rsa.c | 193 +++++++++-------------------------------------- - sshkey.c | 77 +++++++++++++++++++ - sshkey.h | 4 + - 7 files changed, 221 insertions(+), 209 deletions(-) - -diff --git a/digest-openssl.c b/digest-openssl.c -index da7ed72bc..6a21d8adb 100644 ---- a/digest-openssl.c -+++ b/digest-openssl.c -@@ -63,6 +63,22 @@ const struct ssh_digest digests[] = { - { -1, NULL, 0, NULL }, - }; - -+const EVP_MD * -+ssh_digest_to_md(int digest_type) -+{ -+ switch (digest_type) { -+ case SSH_DIGEST_SHA1: -+ return EVP_sha1(); -+ case SSH_DIGEST_SHA256: -+ return EVP_sha256(); -+ case SSH_DIGEST_SHA384: -+ return EVP_sha384(); -+ case SSH_DIGEST_SHA512: -+ return EVP_sha512(); -+ } -+ return NULL; -+} -+ - static const struct ssh_digest * - ssh_digest_by_alg(int alg) - { -diff --git a/digest.h b/digest.h -index 274574d0e..c7ceeb36f 100644 ---- a/digest.h -+++ b/digest.h -@@ -32,6 +32,12 @@ - struct sshbuf; - struct ssh_digest_ctx; - -+#ifdef WITH_OPENSSL -+#include -+/* Converts internal digest representation to the OpenSSL one */ -+const EVP_MD *ssh_digest_to_md(int digest_type); -+#endif -+ - /* Looks up a digest algorithm by name */ - int ssh_digest_alg_by_name(const char *name); - -diff --git a/ssh-dss.c b/ssh-dss.c -index a23c383dc..ea45e7275 100644 ---- a/ssh-dss.c -+++ b/ssh-dss.c -@@ -52,11 +52,15 @@ int - ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat) - { -+ EVP_PKEY *pkey = NULL; - DSA_SIG *sig = NULL; - const BIGNUM *sig_r, *sig_s; -- u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; -- size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); -+ u_char sigblob[SIGBLOB_LEN]; -+ size_t rlen, slen; -+ int len; - struct sshbuf *b = NULL; -+ u_char *sigb = NULL; -+ const u_char *psig = NULL; - int ret = SSH_ERR_INVALID_ARGUMENT; - - if (lenp != NULL) -@@ -67,17 +71,24 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA) - return SSH_ERR_INVALID_ARGUMENT; -- if (dlen == 0) -- return SSH_ERR_INTERNAL_ERROR; - -- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, -- digest, sizeof(digest))) != 0) -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; -+ ret = sshkey_calculate_signature(pkey, SSH_DIGEST_SHA1, &sigb, &len, -+ data, datalen); -+ EVP_PKEY_free(pkey); -+ if (ret < 0) { - goto out; -+ } - -- if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { -+ psig = sigb; -+ if ((sig = d2i_DSA_SIG(NULL, &psig, len)) == NULL) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -+ free(sigb); -+ sigb = NULL; - - DSA_SIG_get0(sig, &sig_r, &sig_s); - rlen = BN_num_bytes(sig_r); -@@ -110,7 +121,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - DSA_SIG_free(sig); - sshbuf_free(b); - return ret; -@@ -121,20 +132,20 @@ ssh_dss_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat) - { -+ EVP_PKEY *pkey = NULL; - DSA_SIG *sig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; -- u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; -- size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); -+ u_char *sigblob = NULL; -+ size_t len, slen; - int ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; - char *ktype = NULL; -+ u_char *sigb = NULL, *psig = NULL; - - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA || - signature == NULL || signaturelen == 0) - return SSH_ERR_INVALID_ARGUMENT; -- if (dlen == 0) -- return SSH_ERR_INTERNAL_ERROR; - - /* fetch signature */ - if ((b = sshbuf_from(signature, signaturelen)) == NULL) -@@ -176,25 +187,31 @@ ssh_dss_verify(const struct sshkey *key, - } - sig_r = sig_s = NULL; /* transferred */ - -- /* sha1 the data */ -- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, -- digest, sizeof(digest))) != 0) -+ if ((slen = i2d_DSA_SIG(sig, NULL)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; -- -- switch (DSA_do_verify(digest, dlen, sig, key->dsa)) { -- case 1: -- ret = 0; -- break; -- case 0: -- ret = SSH_ERR_SIGNATURE_INVALID; -+ } -+ if ((sigb = malloc(slen)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; -- default: -+ } -+ psig = sigb; -+ if ((slen = i2d_DSA_SIG(sig, &psig)) == 0) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, datalen, -+ sigb, slen); -+ EVP_PKEY_free(pkey); -+ - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - DSA_SIG_free(sig); - BN_clear_free(sig_r); - BN_clear_free(sig_s); -diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c -index 599c7199d..b036796e8 100644 ---- a/ssh-ecdsa.c -+++ b/ssh-ecdsa.c -@@ -50,11 +50,13 @@ int - ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat) - { -+ EVP_PKEY *pkey = NULL; - ECDSA_SIG *sig = NULL; -+ unsigned char *sigb = NULL; -+ const unsigned char *psig; - const BIGNUM *sig_r, *sig_s; - int hash_alg; -- u_char digest[SSH_DIGEST_MAX_LENGTH]; -- size_t len, dlen; -+ int len; - struct sshbuf *b = NULL, *bb = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; - -@@ -67,18 +69,24 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - sshkey_type_plain(key->type) != KEY_ECDSA) - return SSH_ERR_INVALID_ARGUMENT; - -- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || -- (dlen = ssh_digest_bytes(hash_alg)) == 0) -+ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) - return SSH_ERR_INTERNAL_ERROR; -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, -- digest, sizeof(digest))) != 0) -+ -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; -+ ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data, -+ datalen); -+ EVP_PKEY_free(pkey); -+ if (ret < 0) { - goto out; -+ } - -- if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) { -+ psig = sigb; -+ if ((sig = d2i_ECDSA_SIG(NULL, &psig, len)) == NULL) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- - if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; -@@ -102,7 +110,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - sshbuf_free(b); - sshbuf_free(bb); - ECDSA_SIG_free(sig); -@@ -115,22 +123,21 @@ ssh_ecdsa_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat) - { -+ EVP_PKEY *pkey = NULL; - ECDSA_SIG *sig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; -- int hash_alg; -- u_char digest[SSH_DIGEST_MAX_LENGTH]; -- size_t dlen; -+ int hash_alg, len; - int ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL, *sigbuf = NULL; - char *ktype = NULL; -+ unsigned char *sigb = NULL, *psig = NULL; - - if (key == NULL || key->ecdsa == NULL || - sshkey_type_plain(key->type) != KEY_ECDSA || - signature == NULL || signaturelen == 0) - return SSH_ERR_INVALID_ARGUMENT; - -- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || -- (dlen = ssh_digest_bytes(hash_alg)) == 0) -+ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) - return SSH_ERR_INTERNAL_ERROR; - - /* fetch signature */ -@@ -166,28 +173,36 @@ ssh_ecdsa_verify(const struct sshkey *key, - } - sig_r = sig_s = NULL; /* transferred */ - -- if (sshbuf_len(sigbuf) != 0) { -- ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; -+ /* Figure out the length */ -+ if ((len = i2d_ECDSA_SIG(sig, NULL)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ if ((sigb = malloc(len)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, -- digest, sizeof(digest))) != 0) -+ psig = sigb; -+ if ((len = i2d_ECDSA_SIG(sig, &psig)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; -+ } - -- switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) { -- case 1: -- ret = 0; -- break; -- case 0: -- ret = SSH_ERR_SIGNATURE_INVALID; -+ if (sshbuf_len(sigbuf) != 0) { -+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; -- default: -- ret = SSH_ERR_LIBCRYPTO_ERROR; -+ } -+ -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, sigb, len); -+ EVP_PKEY_free(pkey); - - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - sshbuf_free(sigbuf); - sshbuf_free(b); - ECDSA_SIG_free(sig); -diff --git a/ssh-rsa.c b/ssh-rsa.c -index 9b14f9a9a..8ef3a6aca 100644 ---- a/ssh-rsa.c -+++ b/ssh-rsa.c -@@ -37,7 +37,7 @@ - - #include "openbsd-compat/openssl-compat.h" - --static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); -+static int openssh_RSA_verify(int, const u_char *, size_t, u_char *, size_t, EVP_PKEY *); - - static const char * - rsa_hash_alg_ident(int hash_alg) -@@ -90,21 +90,6 @@ rsa_hash_id_from_keyname(const char *alg) - return -1; - } - --static int --rsa_hash_alg_nid(int type) --{ -- switch (type) { -- case SSH_DIGEST_SHA1: -- return NID_sha1; -- case SSH_DIGEST_SHA256: -- return NID_sha256; -- case SSH_DIGEST_SHA512: -- return NID_sha512; -- default: -- return -1; -- } --} -- - int - ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp) - { -@@ -164,11 +149,10 @@ int - ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, const char *alg_ident) - { -- const BIGNUM *rsa_n; -- u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; -- size_t slen = 0; -- u_int dlen, len; -- int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; -+ EVP_PKEY *pkey = NULL; -+ u_char *sig = NULL; -+ int len, slen = 0; -+ int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; - - if (lenp != NULL) -@@ -180,33 +164,24 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - hash_alg = SSH_DIGEST_SHA1; - else - hash_alg = rsa_hash_id_from_keyname(alg_ident); -+ - if (key == NULL || key->rsa == NULL || hash_alg == -1 || - sshkey_type_plain(key->type) != KEY_RSA) - return SSH_ERR_INVALID_ARGUMENT; -- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); -- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) -- return SSH_ERR_KEY_LENGTH; - slen = RSA_size(key->rsa); -- if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) -- return SSH_ERR_INVALID_ARGUMENT; -- -- /* hash the data */ -- nid = rsa_hash_alg_nid(hash_alg); -- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) -- return SSH_ERR_INTERNAL_ERROR; -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, -- digest, sizeof(digest))) != 0) -- goto out; -+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) -+ return SSH_ERR_KEY_LENGTH; - -- if ((sig = malloc(slen)) == NULL) { -- ret = SSH_ERR_ALLOC_FAIL; -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; -+ ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data, -+ datalen); -+ EVP_PKEY_free(pkey); -+ if (ret < 0) { - goto out; - } - -- if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { -- ret = SSH_ERR_LIBCRYPTO_ERROR; -- goto out; -- } - if (len < slen) { - size_t diff = slen - len; - memmove(sig + diff, sig, len); -@@ -215,6 +190,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - ret = SSH_ERR_INTERNAL_ERROR; - goto out; - } -+ - /* encode signature */ - if ((b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; -@@ -235,7 +211,6 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); - freezero(sig, slen); - sshbuf_free(b); - return ret; -@@ -246,10 +221,10 @@ ssh_rsa_verify(const struct sshkey *key, - const u_char *sig, size_t siglen, const u_char *data, size_t datalen, - const char *alg) - { -- const BIGNUM *rsa_n; -+ EVP_PKEY *pkey = NULL; - char *sigtype = NULL; - int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; -- size_t len = 0, diff, modlen, dlen; -+ size_t len = 0, diff, modlen; - struct sshbuf *b = NULL; - u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; - -@@ -257,8 +232,7 @@ ssh_rsa_verify(const struct sshkey *key, - sshkey_type_plain(key->type) != KEY_RSA || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; -- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); -- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) -+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) - return SSH_ERR_KEY_LENGTH; - - if ((b = sshbuf_from(sig, siglen)) == NULL) -@@ -310,16 +284,15 @@ ssh_rsa_verify(const struct sshkey *key, - explicit_bzero(sigblob, diff); - len = modlen; - } -- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { -- ret = SSH_ERR_INTERNAL_ERROR; -+ -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, -- digest, sizeof(digest))) != 0) -- goto out; -+ ret = openssh_RSA_verify(hash_alg, data, datalen, sigblob, len, pkey); -+ EVP_PKEY_free(pkey); - -- ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, -- key->rsa); - out: - freezero(sigblob, len); - free(sigtype); -@@ -328,122 +301,26 @@ ssh_rsa_verify(const struct sshkey *key, - return ret; - } - --/* -- * See: -- * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ -- * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn -- */ -- --/* -- * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) -- * oiw(14) secsig(3) algorithms(2) 26 } -- */ --static const u_char id_sha1[] = { -- 0x30, 0x21, /* type Sequence, length 0x21 (33) */ -- 0x30, 0x09, /* type Sequence, length 0x09 */ -- 0x06, 0x05, /* type OID, length 0x05 */ -- 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ -- 0x05, 0x00, /* NULL */ -- 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ --}; -- --/* -- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html -- * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) -- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) -- * id-sha256(1) } -- */ --static const u_char id_sha256[] = { -- 0x30, 0x31, /* type Sequence, length 0x31 (49) */ -- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ -- 0x06, 0x09, /* type OID, length 0x09 */ -- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ -- 0x05, 0x00, /* NULL */ -- 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ --}; -- --/* -- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html -- * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) -- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) -- * id-sha256(3) } -- */ --static const u_char id_sha512[] = { -- 0x30, 0x51, /* type Sequence, length 0x51 (81) */ -- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ -- 0x06, 0x09, /* type OID, length 0x09 */ -- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ -- 0x05, 0x00, /* NULL */ -- 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ --}; -- - static int --rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) -+openssh_RSA_verify(int hash_alg, const u_char *data, size_t datalen, -+ u_char *sigbuf, size_t siglen, EVP_PKEY *pkey) - { -- switch (hash_alg) { -- case SSH_DIGEST_SHA1: -- *oidp = id_sha1; -- *oidlenp = sizeof(id_sha1); -- break; -- case SSH_DIGEST_SHA256: -- *oidp = id_sha256; -- *oidlenp = sizeof(id_sha256); -- break; -- case SSH_DIGEST_SHA512: -- *oidp = id_sha512; -- *oidlenp = sizeof(id_sha512); -- break; -- default: -- return SSH_ERR_INVALID_ARGUMENT; -- } -- return 0; --} -+ size_t rsasize = 0; -+ const RSA *rsa; -+ int ret; - --static int --openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, -- u_char *sigbuf, size_t siglen, RSA *rsa) --{ -- size_t rsasize = 0, oidlen = 0, hlen = 0; -- int ret, len, oidmatch, hashmatch; -- const u_char *oid = NULL; -- u_char *decrypted = NULL; -- -- if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) -- return ret; -- ret = SSH_ERR_INTERNAL_ERROR; -- hlen = ssh_digest_bytes(hash_alg); -- if (hashlen != hlen) { -- ret = SSH_ERR_INVALID_ARGUMENT; -- goto done; -- } -+ rsa = EVP_PKEY_get0_RSA(pkey); - rsasize = RSA_size(rsa); - if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || - siglen == 0 || siglen > rsasize) { - ret = SSH_ERR_INVALID_ARGUMENT; - goto done; - } -- if ((decrypted = malloc(rsasize)) == NULL) { -- ret = SSH_ERR_ALLOC_FAIL; -- goto done; -- } -- if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, -- RSA_PKCS1_PADDING)) < 0) { -- ret = SSH_ERR_LIBCRYPTO_ERROR; -- goto done; -- } -- if (len < 0 || (size_t)len != hlen + oidlen) { -- ret = SSH_ERR_INVALID_FORMAT; -- goto done; -- } -- oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; -- hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; -- if (!oidmatch || !hashmatch) { -- ret = SSH_ERR_SIGNATURE_INVALID; -- goto done; -- } -- ret = 0; -+ -+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, -+ sigbuf, siglen); -+ - done: -- freezero(decrypted, rsasize); - return ret; - } - #endif /* WITH_OPENSSL */ -diff --git a/sshkey.c b/sshkey.c -index ad1957762..b95ed0b10 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -358,6 +358,83 @@ sshkey_type_plain(int type) - } - - #ifdef WITH_OPENSSL -+int -+sshkey_calculate_signature(EVP_PKEY *pkey, int hash_alg, u_char **sigp, -+ int *lenp, const u_char *data, size_t datalen) -+{ -+ EVP_MD_CTX *ctx = NULL; -+ u_char *sig = NULL; -+ int ret, slen, len; -+ -+ if (sigp == NULL || lenp == NULL) { -+ return SSH_ERR_INVALID_ARGUMENT; -+ } -+ -+ slen = EVP_PKEY_size(pkey); -+ if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) -+ return SSH_ERR_INVALID_ARGUMENT; -+ -+ len = slen; -+ if ((sig = malloc(slen)) == NULL) { -+ return SSH_ERR_ALLOC_FAIL; -+ } -+ -+ if ((ctx = EVP_MD_CTX_new()) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto error; -+ } -+ if (EVP_SignInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || -+ EVP_SignUpdate(ctx, data, datalen) <= 0 || -+ EVP_SignFinal(ctx, sig, &len, pkey) <= 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto error; -+ } -+ -+ *sigp = sig; -+ *lenp = len; -+ /* Now owned by the caller */ -+ sig = NULL; -+ ret = 0; -+ -+error: -+ EVP_MD_CTX_free(ctx); -+ free(sig); -+ return ret; -+} -+ -+int -+sshkey_verify_signature(EVP_PKEY *pkey, int hash_alg, const u_char *data, -+ size_t datalen, u_char *sigbuf, int siglen) -+{ -+ EVP_MD_CTX *ctx = NULL; -+ int ret; -+ -+ if ((ctx = EVP_MD_CTX_new()) == NULL) { -+ return SSH_ERR_ALLOC_FAIL; -+ } -+ if (EVP_VerifyInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || -+ EVP_VerifyUpdate(ctx, data, datalen) <= 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto done; -+ } -+ ret = EVP_VerifyFinal(ctx, sigbuf, siglen, pkey); -+ switch (ret) { -+ case 1: -+ ret = 0; -+ break; -+ case 0: -+ ret = SSH_ERR_SIGNATURE_INVALID; -+ break; -+ default: -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ break; -+ } -+ -+done: -+ EVP_MD_CTX_free(ctx); -+ return ret; -+} -+ - /* XXX: these are really begging for a table-driven approach */ - int - sshkey_curve_name_to_nid(const char *name) -diff --git a/sshkey.h b/sshkey.h -index a91e60436..270901a87 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -179,6 +179,10 @@ const char *sshkey_ssh_name(const struct sshkey *); - const char *sshkey_ssh_name_plain(const struct sshkey *); - int sshkey_names_valid2(const char *, 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 **); - diff --git a/SOURCES/openssh-8.0p1-openssl-pem.patch b/SOURCES/openssh-8.0p1-openssl-pem.patch deleted file mode 100644 index 7e4fa81..0000000 --- a/SOURCES/openssh-8.0p1-openssl-pem.patch +++ /dev/null @@ -1,324 +0,0 @@ -From eb0d8e708a1f958aecd2d6e2ff2450af488d4c2a Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Mon, 15 Jul 2019 13:16:29 +0000 -Subject: [PATCH] upstream: support PKCS8 as an optional format for storage of - -private keys, enabled via "ssh-keygen -m PKCS8" on operations that save -private keys to disk. - -The OpenSSH native key format remains the default, but PKCS8 is a -superior format to PEM if interoperability with non-OpenSSH software -is required, as it may use a less terrible KDF (IIRC PEM uses a single -round of MD5 as a KDF). - -adapted from patch by Jakub Jelen via bz3013; ok markus - -OpenBSD-Commit-ID: 027824e3bc0b1c243dc5188504526d73a55accb1 ---- - authfile.c | 6 ++-- - ssh-keygen.1 | 9 +++--- - ssh-keygen.c | 25 +++++++++-------- - sshkey.c | 78 +++++++++++++++++++++++++++++++++++++--------------- - sshkey.h | 11 ++++++-- - 5 files changed, 87 insertions(+), 42 deletions(-) - -diff --git a/authfile.c b/authfile.c -index 2166c1689..851c1a8a1 100644 ---- a/authfile.c -+++ b/authfile.c -@@ -74,7 +74,7 @@ sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename) - int - sshkey_save_private(struct sshkey *key, const char *filename, - const char *passphrase, const char *comment, -- int force_new_format, const char *new_format_cipher, int new_format_rounds) -+ int format, const char *openssh_format_cipher, int openssh_format_rounds) - { - struct sshbuf *keyblob = NULL; - int r; -@@ -82,7 +82,7 @@ sshkey_save_private(struct sshkey *key, const char *filename, - if ((keyblob = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment, -- force_new_format, new_format_cipher, new_format_rounds)) != 0) -+ format, openssh_format_cipher, openssh_format_rounds)) != 0) - goto out; - if ((r = sshkey_save_private_blob(keyblob, filename)) != 0) - goto out; -diff --git a/ssh-keygen.1 b/ssh-keygen.1 -index f42127c60..8184a1797 100644 ---- a/ssh-keygen.1 -+++ b/ssh-keygen.1 -@@ -419,11 +419,12 @@ The supported key formats are: - .Dq RFC4716 - (RFC 4716/SSH2 public or private key), - .Dq PKCS8 --(PEM PKCS8 public key) -+(PKCS8 public or private key) - or - .Dq PEM - (PEM public key). --The default conversion format is -+By default OpenSSH will write newly-generated private keys in its own -+format, but when converting public keys for export the default format is - .Dq RFC4716 . - Setting a format of - .Dq PEM -diff --git a/ssh-keygen.c b/ssh-keygen.c -index b019a02ff..5dcad1f61 100644 ---- a/ssh-keygen.c -+++ b/ssh-keygen.c -@@ -147,11 +147,11 @@ static char *key_type_name = NULL; - /* Load key from this PKCS#11 provider */ - static char *pkcs11provider = NULL; - --/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */ --static int use_new_format = 1; -+/* Format for writing private keys */ -+static int private_key_format = SSHKEY_PRIVATE_OPENSSH; - - /* Cipher for new-format private keys */ --static char *new_format_cipher = NULL; -+static char *openssh_format_cipher = NULL; - - /* - * Number of KDF rounds to derive new format keys / -@@ -1048,7 +1048,8 @@ do_gen_all_hostkeys(struct passwd *pw) - snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, - hostname); - if ((r = sshkey_save_private(private, prv_tmp, "", -- comment, use_new_format, new_format_cipher, rounds)) != 0) { -+ comment, private_key_format, openssh_format_cipher, -+ rounds)) != 0) { - error("Saving key \"%s\" failed: %s", - prv_tmp, ssh_err(r)); - goto failnext; -@@ -1391,7 +1392,7 @@ do_change_passphrase(struct passwd *pw) - - /* Save the file using the new passphrase. */ - if ((r = sshkey_save_private(private, identity_file, passphrase1, -- comment, use_new_format, new_format_cipher, rounds)) != 0) { -+ comment, private_key_format, openssh_format_cipher, rounds)) != 0) { - error("Saving key \"%s\" failed: %s.", - identity_file, ssh_err(r)); - explicit_bzero(passphrase1, strlen(passphrase1)); -@@ -1480,7 +1481,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment) - } - - if (private->type != KEY_ED25519 && private->type != KEY_XMSS && -- !use_new_format) { -+ private_key_format != SSHKEY_PRIVATE_OPENSSH) { - error("Comments are only supported for keys stored in " - "the new format (-o)."); - explicit_bzero(passphrase, strlen(passphrase)); -@@ -1514,7 +1515,8 @@ do_change_comment(struct passwd *pw, const char *identity_comment) - - /* Save the file using the new passphrase. */ - if ((r = sshkey_save_private(private, identity_file, passphrase, -- new_comment, use_new_format, new_format_cipher, rounds)) != 0) { -+ new_comment, private_key_format, openssh_format_cipher, -+ rounds)) != 0) { - error("Saving key \"%s\" failed: %s", - identity_file, ssh_err(r)); - explicit_bzero(passphrase, strlen(passphrase)); -@@ -2525,11 +2527,12 @@ main(int argc, char **argv) - } - if (strcasecmp(optarg, "PKCS8") == 0) { - convert_format = FMT_PKCS8; -+ private_key_format = SSHKEY_PRIVATE_PKCS8; - break; - } - if (strcasecmp(optarg, "PEM") == 0) { - convert_format = FMT_PEM; -- use_new_format = 0; -+ private_key_format = SSHKEY_PRIVATE_PEM; - break; - } - fatal("Unsupported conversion format \"%s\"", optarg); -@@ -2567,7 +2570,7 @@ main(int argc, char **argv) - add_cert_option(optarg); - break; - case 'Z': -- new_format_cipher = optarg; -+ openssh_format_cipher = optarg; - break; - case 'C': - identity_comment = optarg; -@@ -2912,7 +2915,7 @@ main(int argc, char **argv) - - /* Save the key with the given passphrase and comment. */ - if ((r = sshkey_save_private(private, identity_file, passphrase1, -- comment, use_new_format, new_format_cipher, rounds)) != 0) { -+ comment, private_key_format, openssh_format_cipher, rounds)) != 0) { - error("Saving key \"%s\" failed: %s", - identity_file, ssh_err(r)); - explicit_bzero(passphrase1, strlen(passphrase1)); -diff --git a/sshkey.c b/sshkey.c -index 6b5ff0485..a0cea9257 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -3975,10 +3975,10 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, - - - #ifdef WITH_OPENSSL --/* convert SSH v2 key in OpenSSL PEM format */ -+/* convert SSH v2 key to PEM or PKCS#8 format */ - static int --sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, -- const char *_passphrase, const char *comment) -+sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *blob, -+ int format, const char *_passphrase, const char *comment) - { - int success, r; - int blen, len = strlen(_passphrase); -@@ -3988,26 +3988,46 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf, - const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; - char *bptr; - BIO *bio = NULL; -+ EVP_PKEY *pkey = NULL; - - if (len > 0 && len <= 4) - return SSH_ERR_PASSPHRASE_TOO_SHORT; -- if ((bio = BIO_new(BIO_s_mem())) == NULL) -- return SSH_ERR_ALLOC_FAIL; -+ if ((bio = BIO_new(BIO_s_mem())) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } - - switch (key->type) { - case KEY_DSA: -- success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, -- cipher, passphrase, len, NULL, NULL); -+ if (format == SSHKEY_PRIVATE_PEM) { -+ success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, -+ cipher, passphrase, len, NULL, NULL); -+ } else { -+ success = EVP_PKEY_set1_DSA(pkey, key->dsa); -+ } - break; - #ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: -- success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, -- cipher, passphrase, len, NULL, NULL); -+ if (format == SSHKEY_PRIVATE_PEM) { -+ success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, -+ cipher, passphrase, len, NULL, NULL); -+ } else { -+ success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); -+ } - break; - #endif - case KEY_RSA: -- success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, -- cipher, passphrase, len, NULL, NULL); -+ if (format == SSHKEY_PRIVATE_PEM) { -+ success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, -+ cipher, passphrase, len, NULL, NULL); -+ } else { -+ success = EVP_PKEY_set1_RSA(pkey, key->rsa); -+ } - break; - default: - success = 0; -@@ -4023,6 +4040,13 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf, - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -+ if (format == SSHKEY_PRIVATE_PKCS8) { -+ if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher, -+ passphrase, len, NULL, NULL)) == 0) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ } - if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; -@@ -4035,6 +4059,7 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf, - goto out; - r = 0; - out: -+ EVP_PKEY_free(pkey); - BIO_free(bio); - return r; - } -@@ -4046,29 +4071,38 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf, - int - sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, - const char *passphrase, const char *comment, -- int force_new_format, const char *new_format_cipher, int new_format_rounds) -+ int format, const char *openssh_format_cipher, int openssh_format_rounds) - { - switch (key->type) { - #ifdef WITH_OPENSSL - case KEY_DSA: - case KEY_ECDSA: - case KEY_RSA: -- if (force_new_format) { -- return sshkey_private_to_blob2(key, blob, passphrase, -- comment, new_format_cipher, new_format_rounds); -- } -- return sshkey_private_pem_to_blob(key, blob, -- passphrase, comment); -+ break; /* see below */ - #endif /* WITH_OPENSSL */ - case KEY_ED25519: - #ifdef WITH_XMSS - case KEY_XMSS: - #endif /* WITH_XMSS */ - return sshkey_private_to_blob2(key, blob, passphrase, -- comment, new_format_cipher, new_format_rounds); -+ comment, openssh_format_cipher, openssh_format_rounds); - default: - return SSH_ERR_KEY_TYPE_UNKNOWN; - } -+ -+#ifdef WITH_OPENSSL -+ switch (format) { -+ case SSHKEY_PRIVATE_OPENSSH: -+ return sshkey_private_to_blob2(key, blob, passphrase, -+ comment, openssh_format_cipher, openssh_format_rounds); -+ case SSHKEY_PRIVATE_PEM: -+ case SSHKEY_PRIVATE_PKCS8: -+ return sshkey_private_to_blob_pem_pkcs8(key, blob, -+ format, passphrase, comment); -+ default: -+ return SSH_ERR_INVALID_ARGUMENT; -+ } -+#endif /* WITH_OPENSSL */ - } - - -diff --git a/sshkey.h b/sshkey.h -index 41d159a1b..d30a69cc9 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -88,6 +88,13 @@ enum sshkey_serialize_rep { - SSHKEY_SERIALIZE_INFO = 254, - }; - -+/* Private key disk formats */ -+enum sshkey_private_format { -+ SSHKEY_PRIVATE_OPENSSH = 0, -+ SSHKEY_PRIVATE_PEM = 1, -+ SSHKEY_PRIVATE_PKCS8 = 2, -+}; -+ - /* key is stored in external hardware */ - #define SSHKEY_FLAG_EXT 0x0001 - -@@ -221,7 +228,7 @@ int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp); - /* private key file format parsing and serialisation */ - int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, - const char *passphrase, const char *comment, -- int force_new_format, const char *new_format_cipher, int new_format_rounds); -+ int format, const char *openssh_format_cipher, int openssh_format_rounds); - int sshkey_parse_private_fileblob(struct sshbuf *buffer, - const char *passphrase, struct sshkey **keyp, char **commentp); - int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, - diff --git a/SOURCES/openssh-8.0p1-proxyjump-loops.patch b/SOURCES/openssh-8.0p1-proxyjump-loops.patch deleted file mode 100644 index 578eff3..0000000 --- a/SOURCES/openssh-8.0p1-proxyjump-loops.patch +++ /dev/null @@ -1,33 +0,0 @@ -From de1f3564cd85915b3002859873a37cb8d31ac9ce Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Tue, 18 Feb 2020 08:49:49 +0000 -Subject: [PATCH] upstream: Detect and prevent simple configuration loops when - using - -ProxyJump. bz#3057, ok djm@ - -OpenBSD-Commit-ID: 077d21c564c886c98309d871ed6f8ef267b9f037 ---- - ssh.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/ssh.c b/ssh.c -index 15aee569e..a983a108b 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -1208,6 +1208,14 @@ main(int ac, char **av) - if (options.jump_host != NULL) { - char port_s[8]; - const char *sshbin = argv0; -+ int port = options.port, jumpport = options.jump_port; -+ -+ if (port <= 0) -+ port = default_ssh_port(); -+ if (jumpport <= 0) -+ jumpport = default_ssh_port(); -+ if (strcmp(options.jump_host, host) == 0 && port == jumpport) -+ fatal("jumphost loop via %s", options.jump_host); - - /* - * Try to use SSH indicated by argv[0], but fall back to - diff --git a/SOURCES/openssh-8.0p1-rdomain.patch b/SOURCES/openssh-8.0p1-rdomain.patch deleted file mode 100644 index 610c8b3..0000000 --- a/SOURCES/openssh-8.0p1-rdomain.patch +++ /dev/null @@ -1,44 +0,0 @@ -commit 5481d0b4036b33b92c372ee36258ed11bff57d5d -Author: Jakub Jelen -Date: Thu Feb 27 10:07:33 2020 +0100 - - Mark the RDomain configuration option unsupported on non-openbsd builds - -diff --git a/servconf.c b/servconf.c -index db80e943..153d2525 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -698,7 +698,11 @@ static struct { - { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, - { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, - { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, -+#if defined(__OpenBSD__) - { "rdomain", sRDomain, SSHCFG_ALL }, -+#else -+ { "rdomain", sUnsupported, SSHCFG_ALL }, -+#endif - { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, - { NULL, sBadOption, 0 } - }; -@@ -2841,7 +2845,9 @@ dump_config(ServerOptions *o) - o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG); - dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ? - o->pubkey_key_types : KEX_DEFAULT_PK_ALG); -+#if defined(__OpenBSD__) - dump_cfg_string(sRDomain, o->routing_domain); -+#endif - - /* string arguments requiring a lookup */ - dump_cfg_string(sLogLevel, log_level_name(o->log_level)); -diff --git a/sshd_config.5 b/sshd_config.5 -index 5dca8981..766e9b90 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -1542,6 +1542,7 @@ will be bound to this - If the routing domain is set to - .Cm \&%D , - then the domain in which the incoming connection was received will be applied. -+This feature is available on OpenBSD only. - .It Cm SetEnv - Specifies one or more environment variables to set in child sessions started - by diff --git a/SOURCES/openssh-8.0p1-restore-nonblock.patch b/SOURCES/openssh-8.0p1-restore-nonblock.patch deleted file mode 100644 index b16e17e..0000000 --- a/SOURCES/openssh-8.0p1-restore-nonblock.patch +++ /dev/null @@ -1,311 +0,0 @@ -diff -up openssh-8.0p1/channels.c.restore-nonblock openssh-8.0p1/channels.c ---- openssh-8.0p1/channels.c.restore-nonblock 2021-06-21 10:44:26.380559612 +0200 -+++ openssh-8.0p1/channels.c 2021-06-21 10:48:47.754579151 +0200 -@@ -333,7 +333,27 @@ channel_register_fds(struct ssh *ssh, Ch - #endif - - /* enable nonblocking mode */ -- if (nonblock) { -+ c->restore_block = 0; -+ if (nonblock == CHANNEL_NONBLOCK_STDIO) { -+ /* -+ * Special handling for stdio file descriptors: do not set -+ * non-blocking mode if they are TTYs. Otherwise prepare to -+ * restore their blocking state on exit to avoid interfering -+ * with other programs that follow. -+ */ -+ if (rfd != -1 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) { -+ c->restore_block |= CHANNEL_RESTORE_RFD; -+ set_nonblock(rfd); -+ } -+ if (wfd != -1 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) { -+ c->restore_block |= CHANNEL_RESTORE_WFD; -+ set_nonblock(wfd); -+ } -+ if (efd != -1 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) { -+ c->restore_block |= CHANNEL_RESTORE_EFD; -+ set_nonblock(efd); -+ } -+ } else if (nonblock) { - if (rfd != -1) - set_nonblock(rfd); - if (wfd != -1) -@@ -422,17 +442,23 @@ channel_find_maxfd(struct ssh_channels * - } - - int --channel_close_fd(struct ssh *ssh, int *fdp) -+channel_close_fd(struct ssh *ssh, Channel *c, int *fdp) - { - struct ssh_channels *sc = ssh->chanctxt; -- int ret = 0, fd = *fdp; -+ int ret, fd = *fdp; - -- if (fd != -1) { -- ret = close(fd); -- *fdp = -1; -- if (fd == sc->channel_max_fd) -- channel_find_maxfd(sc); -- } -+ if (fd == -1) -+ return 0; -+ -+ if ((*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) || -+ (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) || -+ (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0)) -+ (void)fcntl(*fdp, F_SETFL, 0); /* restore blocking */ -+ -+ ret = close(fd); -+ *fdp = -1; -+ if (fd == sc->channel_max_fd) -+ channel_find_maxfd(sc); - return ret; - } - -@@ -442,13 +468,13 @@ channel_close_fds(struct ssh *ssh, Chann - { - int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd; - -- channel_close_fd(ssh, &c->sock); -+ channel_close_fd(ssh, c, &c->sock); - if (rfd != sock) -- channel_close_fd(ssh, &c->rfd); -+ channel_close_fd(ssh, c, &c->rfd); - if (wfd != sock && wfd != rfd) -- channel_close_fd(ssh, &c->wfd); -+ channel_close_fd(ssh, c, &c->wfd); - if (efd != sock && efd != rfd && efd != wfd) -- channel_close_fd(ssh, &c->efd); -+ channel_close_fd(ssh, c, &c->efd); - } - - static void -@@ -681,7 +707,7 @@ channel_stop_listening(struct ssh *ssh) - case SSH_CHANNEL_X11_LISTENER: - case SSH_CHANNEL_UNIX_LISTENER: - case SSH_CHANNEL_RUNIX_LISTENER: -- channel_close_fd(ssh, &c->sock); -+ channel_close_fd(ssh, c, &c->sock); - channel_free(ssh, c); - break; - } -@@ -1487,7 +1513,8 @@ channel_decode_socks5(Channel *c, struct - - Channel * - channel_connect_stdio_fwd(struct ssh *ssh, -- const char *host_to_connect, u_short port_to_connect, int in, int out) -+ const char *host_to_connect, u_short port_to_connect, -+ int in, int out, int nonblock) - { - Channel *c; - -@@ -1495,7 +1522,7 @@ channel_connect_stdio_fwd(struct ssh *ss - - c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out, - -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, -- 0, "stdio-forward", /*nonblock*/0); -+ 0, "stdio-forward", nonblock); - - c->path = xstrdup(host_to_connect); - c->host_port = port_to_connect; -@@ -1650,7 +1677,7 @@ channel_post_x11_listener(struct ssh *ss - if (c->single_connection) { - oerrno = errno; - debug2("single_connection: closing X11 listener."); -- channel_close_fd(ssh, &c->sock); -+ channel_close_fd(ssh, c, &c->sock); - chan_mark_dead(ssh, c); - errno = oerrno; - } -@@ -2087,7 +2114,7 @@ channel_handle_efd_write(struct ssh *ssh - return 1; - if (len <= 0) { - debug2("channel %d: closing write-efd %d", c->self, c->efd); -- channel_close_fd(ssh, &c->efd); -+ channel_close_fd(ssh, c, &c->efd); - } else { - if ((r = sshbuf_consume(c->extended, len)) != 0) { - fatal("%s: channel %d: consume: %s", -@@ -2119,7 +2146,7 @@ channel_handle_efd_read(struct ssh *ssh, - if (len <= 0) { - debug2("channel %d: closing read-efd %d", - c->self, c->efd); -- channel_close_fd(ssh, &c->efd); -+ channel_close_fd(ssh, c, &c->efd); - } else { - if (c->extended_usage == CHAN_EXTENDED_IGNORE) { - debug3("channel %d: discard efd", -diff -up openssh-8.0p1/channels.h.restore-nonblock openssh-8.0p1/channels.h ---- openssh-8.0p1/channels.h.restore-nonblock 2021-06-21 10:44:26.380559612 +0200 -+++ openssh-8.0p1/channels.h 2021-06-21 10:44:26.387559665 +0200 -@@ -63,6 +63,16 @@ - - #define CHANNEL_CANCEL_PORT_STATIC -1 - -+/* nonblocking flags for channel_new */ -+#define CHANNEL_NONBLOCK_LEAVE 0 /* don't modify non-blocking state */ -+#define CHANNEL_NONBLOCK_SET 1 /* set non-blocking state */ -+#define CHANNEL_NONBLOCK_STDIO 2 /* set non-blocking and restore on close */ -+ -+/* c->restore_block mask flags */ -+#define CHANNEL_RESTORE_RFD 0x01 -+#define CHANNEL_RESTORE_WFD 0x02 -+#define CHANNEL_RESTORE_EFD 0x04 -+ - /* TCP forwarding */ - #define FORWARD_DENY 0 - #define FORWARD_REMOTE (1) -@@ -131,6 +141,7 @@ struct Channel { - * to a matching pre-select handler. - * this way post-select handlers are not - * accidentally called if a FD gets reused */ -+ int restore_block; /* fd mask to restore blocking status */ - struct sshbuf *input; /* data read from socket, to be sent over - * encrypted connection */ - struct sshbuf *output; /* data received over encrypted connection for -@@ -258,7 +269,7 @@ void channel_register_filter(struct ssh - void channel_register_status_confirm(struct ssh *, int, - channel_confirm_cb *, channel_confirm_abandon_cb *, void *); - void channel_cancel_cleanup(struct ssh *, int); --int channel_close_fd(struct ssh *, int *); -+int channel_close_fd(struct ssh *, Channel *, int *); - void channel_send_window_changes(struct ssh *); - - /* mux proxy support */ -@@ -305,7 +316,7 @@ Channel *channel_connect_to_port(struct - char *, char *, int *, const char **); - Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *); - Channel *channel_connect_stdio_fwd(struct ssh *, const char*, -- u_short, int, int); -+ u_short, int, int, int); - Channel *channel_connect_by_listen_address(struct ssh *, const char *, - u_short, char *, char *); - Channel *channel_connect_by_listen_path(struct ssh *, const char *, -diff -up openssh-8.0p1/clientloop.c.restore-nonblock openssh-8.0p1/clientloop.c ---- openssh-8.0p1/clientloop.c.restore-nonblock 2021-06-21 10:44:26.290558923 +0200 -+++ openssh-8.0p1/clientloop.c 2021-06-21 10:44:26.387559665 +0200 -@@ -1436,14 +1436,6 @@ client_loop(struct ssh *ssh, int have_pt - if (have_pty) - leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); - -- /* restore blocking io */ -- if (!isatty(fileno(stdin))) -- unset_nonblock(fileno(stdin)); -- if (!isatty(fileno(stdout))) -- unset_nonblock(fileno(stdout)); -- if (!isatty(fileno(stderr))) -- unset_nonblock(fileno(stderr)); -- - /* - * If there was no shell or command requested, there will be no remote - * exit status to be returned. In that case, clear error code if the -diff -up openssh-8.0p1/mux.c.restore-nonblock openssh-8.0p1/mux.c ---- openssh-8.0p1/mux.c.restore-nonblock 2019-04-18 00:52:57.000000000 +0200 -+++ openssh-8.0p1/mux.c 2021-06-21 10:50:51.007537336 +0200 -@@ -454,14 +454,6 @@ mux_master_process_new_session(struct ss - if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1) - error("%s: tcgetattr: %s", __func__, strerror(errno)); - -- /* enable nonblocking unless tty */ -- if (!isatty(new_fd[0])) -- set_nonblock(new_fd[0]); -- if (!isatty(new_fd[1])) -- set_nonblock(new_fd[1]); -- if (!isatty(new_fd[2])) -- set_nonblock(new_fd[2]); -- - window = CHAN_SES_WINDOW_DEFAULT; - packetmax = CHAN_SES_PACKET_DEFAULT; - if (cctx->want_tty) { -@@ -471,7 +463,7 @@ mux_master_process_new_session(struct ss - - nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING, - new_fd[0], new_fd[1], new_fd[2], window, packetmax, -- CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); -+ CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO); - - nc->ctl_chan = c->self; /* link session -> control channel */ - c->remote_id = nc->self; /* link control -> session channel */ -@@ -1033,13 +1025,8 @@ mux_master_process_stdio_fwd(struct ssh - } - } - -- /* enable nonblocking unless tty */ -- if (!isatty(new_fd[0])) -- set_nonblock(new_fd[0]); -- if (!isatty(new_fd[1])) -- set_nonblock(new_fd[1]); -- -- nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]); -+ nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1], -+ CHANNEL_NONBLOCK_STDIO); - free(chost); - - nc->ctl_chan = c->self; /* link session -> control channel */ -diff -up openssh-8.0p1/nchan.c.restore-nonblock openssh-8.0p1/nchan.c ---- openssh-8.0p1/nchan.c.restore-nonblock 2021-06-21 10:44:26.388559673 +0200 -+++ openssh-8.0p1/nchan.c 2021-06-21 10:52:42.685405537 +0200 -@@ -387,7 +387,7 @@ chan_shutdown_write(struct ssh *ssh, Cha - strerror(errno)); - } - } else { -- if (channel_close_fd(ssh, &c->wfd) < 0) { -+ if (channel_close_fd(ssh, c, &c->wfd) < 0) { - logit("channel %d: %s: close() failed for " - "fd %d [i%d o%d]: %.100s", - c->self, __func__, c->wfd, c->istate, c->ostate, -@@ -417,7 +417,7 @@ chan_shutdown_read(struct ssh *ssh, Chan - strerror(errno)); - } - } else { -- if (channel_close_fd(ssh, &c->rfd) < 0) { -+ if (channel_close_fd(ssh, c, &c->rfd) < 0) { - logit("channel %d: %s: close() failed for " - "fd %d [i%d o%d]: %.100s", - c->self, __func__, c->rfd, c->istate, c->ostate, -@@ -437,7 +437,7 @@ chan_shutdown_extended_read(struct ssh * - debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])", - c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd, - channel_format_extended_usage(c)); -- if (channel_close_fd(ssh, &c->efd) < 0) { -+ if (channel_close_fd(ssh, c, &c->efd) < 0) { - logit("channel %d: %s: close() failed for " - "extended fd %d [i%d o%d]: %.100s", - c->self, __func__, c->efd, c->istate, c->ostate, -diff -up openssh-8.0p1/ssh.c.restore-nonblock openssh-8.0p1/ssh.c ---- openssh-8.0p1/ssh.c.restore-nonblock 2021-06-21 10:44:26.389559681 +0200 -+++ openssh-8.0p1/ssh.c 2021-06-21 10:54:47.651377045 +0200 -@@ -1709,7 +1709,8 @@ ssh_init_stdio_forwarding(struct ssh *ss - (out = dup(STDOUT_FILENO)) < 0) - fatal("channel_connect_stdio_fwd: dup() in/out failed"); - if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host, -- options.stdio_forward_port, in, out)) == NULL) -+ options.stdio_forward_port, in, out, -+ CHANNEL_NONBLOCK_STDIO)) == NULL) - fatal("%s: channel_connect_stdio_fwd failed", __func__); - channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0); - channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL); -@@ -1862,14 +1863,6 @@ ssh_session2_open(struct ssh *ssh) - if (in < 0 || out < 0 || err < 0) - fatal("dup() in/out/err failed"); - -- /* enable nonblocking unless tty */ -- if (!isatty(in)) -- set_nonblock(in); -- if (!isatty(out)) -- set_nonblock(out); -- if (!isatty(err)) -- set_nonblock(err); -- - window = CHAN_SES_WINDOW_DEFAULT; - packetmax = CHAN_SES_PACKET_DEFAULT; - if (tty_flag) { -@@ -1879,7 +1872,7 @@ ssh_session2_open(struct ssh *ssh) - c = channel_new(ssh, - "session", SSH_CHANNEL_OPENING, in, out, err, - window, packetmax, CHAN_EXTENDED_WRITE, -- "client-session", /*nonblock*/0); -+ "client-session", CHANNEL_NONBLOCK_STDIO); - - debug3("%s: channel_new: %d", __func__, c->self); - diff --git a/SOURCES/openssh-8.0p1-scp-tests.patch b/SOURCES/openssh-8.0p1-scp-tests.patch deleted file mode 100644 index e0a63c4..0000000 --- a/SOURCES/openssh-8.0p1-scp-tests.patch +++ /dev/null @@ -1,61 +0,0 @@ -diff --git a/regress/scp-ssh-wrapper.sh b/regress/scp-ssh-wrapper.sh -index 59f1ff63..dd48a482 100644 ---- a/regress/scp-ssh-wrapper.sh -+++ b/regress/scp-ssh-wrapper.sh -@@ -51,6 +51,18 @@ badserver_4) - echo "C755 2 file" - echo "X" - ;; -+badserver_5) -+ echo "D0555 0 " -+ echo "X" -+ ;; -+badserver_6) -+ echo "D0555 0 ." -+ echo "X" -+ ;; -+badserver_7) -+ echo "C0755 2 extrafile" -+ echo "X" -+ ;; - *) - set -- $arg - shift -diff --git a/regress/scp.sh b/regress/scp.sh -index 57cc7706..104c89e1 100644 ---- a/regress/scp.sh -+++ b/regress/scp.sh -@@ -25,6 +25,7 @@ export SCP # used in scp-ssh-wrapper.scp - scpclean() { - rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2} - mkdir ${DIR} ${DIR2} -+ chmod 755 ${DIR} ${DIR2} - } - - verbose "$tid: simple copy local file to local file" -@@ -101,7 +102,7 @@ if [ ! -z "$SUDO" ]; then - $SUDO rm ${DIR2}/copy - fi - --for i in 0 1 2 3 4; do -+for i in 0 1 2 3 4 5 6 7; do - verbose "$tid: disallow bad server #$i" - SCPTESTMODE=badserver_$i - export DIR SCPTESTMODE -@@ -113,6 +114,15 @@ for i in 0 1 2 3 4; do - scpclean - $SCP -r $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null - [ -d ${DIR}/dotpathdir ] && fail "allows dir creation outside of subdir" -+ -+ scpclean -+ $SCP -pr $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null -+ [ ! -w ${DIR2} ] && fail "allows target root attribute change" -+ -+ scpclean -+ $SCP $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null -+ [ -e ${DIR2}/extrafile ] && fail "allows extranous object creation" -+ rm -f ${DIR2}/extrafile - done - - verbose "$tid: detect non-directory target" - diff --git a/SOURCES/openssh-8.0p1-sftp-realpath.patch b/SOURCES/openssh-8.0p1-sftp-realpath.patch deleted file mode 100644 index 37e32ca..0000000 --- a/SOURCES/openssh-8.0p1-sftp-realpath.patch +++ /dev/null @@ -1,273 +0,0 @@ -diff --color -ruN a/Makefile.in b/Makefile.in ---- a/Makefile.in 2022-06-23 11:31:10.168186838 +0200 -+++ b/Makefile.in 2022-06-23 11:32:19.146513347 +0200 -@@ -125,7 +125,7 @@ - monitor.o monitor_wrap.o auth-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 md5crypt.o \ -- sftp-server.o sftp-common.o \ -+ sftp-server.o sftp-common.o sftp-realpath.o \ - sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ - sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \ - sandbox-solaris.o uidswap.o -@@ -217,8 +217,8 @@ - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) - --sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o -- $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-realpath.o sftp-server.o sftp-server-main.o -+ $(LD) -o $@ sftp-server.o sftp-common.o sftp-realpath.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) - - sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o - $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) -diff --color -ruN a/sftp-realpath.c b/sftp-realpath.c ---- a/sftp-realpath.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/sftp-realpath.c 2022-06-23 11:35:33.193244873 +0200 -@@ -0,0 +1,225 @@ -+/* $OpenBSD: sftp-realpath.c,v 1.2 2021/09/02 21:03:54 deraadt Exp $ */ -+/* -+ * Copyright (c) 2003 Constantin S. Svintsoff -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the authors may not be used to endorse or promote -+ * products derived from this software without specific prior written -+ * permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+#include "includes.h" -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef SYMLOOP_MAX -+# define SYMLOOP_MAX 32 -+#endif -+ -+/* XXX rewrite sftp-server to use POSIX realpath and remove this hack */ -+ -+char *sftp_realpath(const char *path, char *resolved); -+ -+/* -+ * char *realpath(const char *path, char resolved[PATH_MAX]); -+ * -+ * Find the real name of path, by removing all ".", ".." and symlink -+ * components. Returns (resolved) on success, or (NULL) on failure, -+ * in which case the path which caused trouble is left in (resolved). -+ */ -+char * -+sftp_realpath(const char *path, char *resolved) -+{ -+ struct stat sb; -+ char *p, *q, *s; -+ size_t left_len, resolved_len; -+ unsigned symlinks; -+ int serrno, slen, mem_allocated; -+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; -+ -+ if (path[0] == '\0') { -+ errno = ENOENT; -+ return (NULL); -+ } -+ -+ serrno = errno; -+ -+ if (resolved == NULL) { -+ resolved = malloc(PATH_MAX); -+ if (resolved == NULL) -+ return (NULL); -+ mem_allocated = 1; -+ } else -+ mem_allocated = 0; -+ -+ symlinks = 0; -+ if (path[0] == '/') { -+ resolved[0] = '/'; -+ resolved[1] = '\0'; -+ if (path[1] == '\0') -+ return (resolved); -+ resolved_len = 1; -+ left_len = strlcpy(left, path + 1, sizeof(left)); -+ } else { -+ if (getcwd(resolved, PATH_MAX) == NULL) { -+ if (mem_allocated) -+ free(resolved); -+ else -+ strlcpy(resolved, ".", PATH_MAX); -+ return (NULL); -+ } -+ resolved_len = strlen(resolved); -+ left_len = strlcpy(left, path, sizeof(left)); -+ } -+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { -+ errno = ENAMETOOLONG; -+ goto err; -+ } -+ -+ /* -+ * Iterate over path components in `left'. -+ */ -+ while (left_len != 0) { -+ /* -+ * Extract the next path component and adjust `left' -+ * and its length. -+ */ -+ p = strchr(left, '/'); -+ s = p ? p : left + left_len; -+ if (s - left >= (ptrdiff_t)sizeof(next_token)) { -+ errno = ENAMETOOLONG; -+ goto err; -+ } -+ memcpy(next_token, left, s - left); -+ next_token[s - left] = '\0'; -+ left_len -= s - left; -+ if (p != NULL) -+ memmove(left, s + 1, left_len + 1); -+ if (resolved[resolved_len - 1] != '/') { -+ if (resolved_len + 1 >= PATH_MAX) { -+ errno = ENAMETOOLONG; -+ goto err; -+ } -+ resolved[resolved_len++] = '/'; -+ resolved[resolved_len] = '\0'; -+ } -+ if (next_token[0] == '\0') -+ continue; -+ else if (strcmp(next_token, ".") == 0) -+ continue; -+ else if (strcmp(next_token, "..") == 0) { -+ /* -+ * Strip the last path component except when we have -+ * single "/" -+ */ -+ if (resolved_len > 1) { -+ resolved[resolved_len - 1] = '\0'; -+ q = strrchr(resolved, '/') + 1; -+ *q = '\0'; -+ resolved_len = q - resolved; -+ } -+ continue; -+ } -+ -+ /* -+ * Append the next path component and lstat() it. If -+ * lstat() fails we still can return successfully if -+ * there are no more path components left. -+ */ -+ resolved_len = strlcat(resolved, next_token, PATH_MAX); -+ if (resolved_len >= PATH_MAX) { -+ errno = ENAMETOOLONG; -+ goto err; -+ } -+ if (lstat(resolved, &sb) != 0) { -+ if (errno == ENOENT && p == NULL) { -+ errno = serrno; -+ return (resolved); -+ } -+ goto err; -+ } -+ if (S_ISLNK(sb.st_mode)) { -+ if (symlinks++ > SYMLOOP_MAX) { -+ errno = ELOOP; -+ goto err; -+ } -+ slen = readlink(resolved, symlink, sizeof(symlink) - 1); -+ if (slen < 0) -+ goto err; -+ symlink[slen] = '\0'; -+ if (symlink[0] == '/') { -+ resolved[1] = 0; -+ resolved_len = 1; -+ } else if (resolved_len > 1) { -+ /* Strip the last path component. */ -+ resolved[resolved_len - 1] = '\0'; -+ q = strrchr(resolved, '/') + 1; -+ *q = '\0'; -+ resolved_len = q - resolved; -+ } -+ -+ /* -+ * If there are any path components left, then -+ * append them to symlink. The result is placed -+ * in `left'. -+ */ -+ if (p != NULL) { -+ if (symlink[slen - 1] != '/') { -+ if (slen + 1 >= -+ (ptrdiff_t)sizeof(symlink)) { -+ errno = ENAMETOOLONG; -+ goto err; -+ } -+ symlink[slen] = '/'; -+ symlink[slen + 1] = 0; -+ } -+ left_len = strlcat(symlink, left, sizeof(symlink)); -+ if (left_len >= sizeof(symlink)) { -+ errno = ENAMETOOLONG; -+ goto err; -+ } -+ } -+ left_len = strlcpy(left, symlink, sizeof(left)); -+ } -+ } -+ -+ /* -+ * Remove trailing slash except when the resolved pathname -+ * is a single "/". -+ */ -+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/') -+ resolved[resolved_len - 1] = '\0'; -+ return (resolved); -+ -+err: -+ if (mem_allocated) -+ free(resolved); -+ return (NULL); -+} -diff --color -ruN a/sftp-server.c b/sftp-server.c ---- a/sftp-server.c 2022-06-23 11:31:10.147186434 +0200 -+++ b/sftp-server.c 2022-06-23 11:32:19.147513366 +0200 -@@ -51,6 +51,8 @@ - #include "sftp.h" - #include "sftp-common.h" - -+char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ -+ - /* Our verbosity */ - static LogLevel log_level = SYSLOG_LEVEL_ERROR; - -@@ -1185,7 +1187,7 @@ - } - debug3("request %u: realpath", id); - verbose("realpath \"%s\"", path); -- if (realpath(path, resolvedname) == NULL) { -+ if (sftp_realpath(path, resolvedname) == NULL) { - send_status(id, errno_to_portable(errno)); - } else { - Stat s; diff --git a/SOURCES/openssh-8.0p1-sftp-timespeccmp.patch b/SOURCES/openssh-8.0p1-sftp-timespeccmp.patch deleted file mode 100644 index 7254b4a..0000000 --- a/SOURCES/openssh-8.0p1-sftp-timespeccmp.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff -up openssh-8.0p1/sftp.c.original openssh-8.0p1/sftp.c ---- openssh-8.0p1/sftp.c.original 2020-12-22 17:05:02.105698989 +0900 -+++ openssh-8.0p1/sftp.c 2020-12-22 17:05:42.922035780 +0900 -@@ -937,7 +937,11 @@ sglob_comp(const void *aa, const void *b - return (rmul * strcmp(ap, bp)); - else if (sort_flag & LS_TIME_SORT) { - #if defined(HAVE_STRUCT_STAT_ST_MTIM) -- return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <)); -+ if (timespeccmp(&as->st_mtim, &bs->st_mtim, <)){ -+ return rmul; -+ } else { -+ return -rmul; -+ } - #elif defined(HAVE_STRUCT_STAT_ST_MTIME) - return (rmul * NCMP(as->st_mtime, bs->st_mtime)); - #else diff --git a/SOURCES/openssh-8.0p1-sshd_config.patch b/SOURCES/openssh-8.0p1-sshd_config.patch deleted file mode 100644 index e4b7912..0000000 --- a/SOURCES/openssh-8.0p1-sshd_config.patch +++ /dev/null @@ -1,97 +0,0 @@ -diff --git a/servconf.c b/servconf.c -index ffac5d2c..340045b2 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -1042,7 +1042,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - return -1; - } - if (strcasecmp(attrib, "user") == 0) { -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->user == NULL)) { - result = 0; - continue; - } -@@ -1054,7 +1054,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - debug("user %.100s matched 'User %.100s' at " - "line %d", ci->user, arg, line); - } else if (strcasecmp(attrib, "group") == 0) { -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->user == NULL)) { - result = 0; - continue; - } -@@ -1067,7 +1067,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - result = 0; - } - } else if (strcasecmp(attrib, "host") == 0) { -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->host == NULL)) { - result = 0; - continue; - } -@@ -1079,7 +1079,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - debug("connection from %.100s matched 'Host " - "%.100s' at line %d", ci->host, arg, line); - } else if (strcasecmp(attrib, "address") == 0) { -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->address == NULL)) { - result = 0; - continue; - } -@@ -1098,7 +1098,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - return -1; - } - } else if (strcasecmp(attrib, "localaddress") == 0){ -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->laddress == NULL)) { - result = 0; - continue; - } -@@ -1124,7 +1124,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - arg); - return -1; - } -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->lport == -1)) { - result = 0; - continue; - } -@@ -1138,10 +1138,12 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - else - result = 0; - } else if (strcasecmp(attrib, "rdomain") == 0) { -- if (ci == NULL || ci->rdomain == NULL) { -+ if (ci == NULL || (ci->test && ci->rdomain == NULL)) { - result = 0; - continue; - } -+ if (ci->rdomain == NULL) -+ match_test_missing_fatal("RDomain", "rdomain"); - if (match_pattern_list(ci->rdomain, arg, 0) != 1) - result = 0; - else -diff --git a/servconf.h b/servconf.h -index 54e0a8d8..5483da05 100644 ---- a/servconf.h -+++ b/servconf.h -@@ -221,6 +221,8 @@ struct connection_info { - const char *laddress; /* local address */ - int lport; /* local port */ - const char *rdomain; /* routing domain if available */ -+ int test; /* test mode, allow some attributes to be -+ * unspecified */ - }; - - -diff --git a/sshd.c b/sshd.c -index cbd3bce9..1fcde502 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -1843,6 +1843,7 @@ main(int ac, char **av) - */ - if (connection_info == NULL) - connection_info = get_connection_info(ssh, 0, 0); -+ connection_info->test = 1; - parse_server_match_config(&options, connection_info); - dump_config(&options); - } diff --git a/SOURCES/openssh-8.0p1-sshd_include.patch b/SOURCES/openssh-8.0p1-sshd_include.patch deleted file mode 100644 index ff51340..0000000 --- a/SOURCES/openssh-8.0p1-sshd_include.patch +++ /dev/null @@ -1,805 +0,0 @@ -diff -up openssh-8.0p1/auth.c.sshdinclude openssh-8.0p1/auth.c ---- openssh-8.0p1/auth.c.sshdinclude 2021-10-20 15:18:49.740331098 +0200 -+++ openssh-8.0p1/auth.c 2021-10-20 15:19:41.324781344 +0200 -@@ -80,6 +80,7 @@ - - /* import */ - extern ServerOptions options; -+extern struct include_list includes; - extern int use_privsep; - extern struct sshbuf *loginmsg; - extern struct passwd *privsep_pw; -@@ -573,7 +574,7 @@ getpwnamallow(struct ssh *ssh, const cha - - ci = get_connection_info(ssh, 1, options.use_dns); - ci->user = user; -- parse_server_match_config(&options, ci); -+ parse_server_match_config(&options, &includes, ci); - log_change_level(options.log_level); - process_permitopen(ssh, &options); - -diff -up openssh-8.0p1/readconf.c.sshdinclude openssh-8.0p1/readconf.c ---- openssh-8.0p1/readconf.c.sshdinclude 2021-10-20 15:21:43.541848103 +0200 -+++ openssh-8.0p1/readconf.c 2021-10-20 15:22:06.302046768 +0200 -@@ -711,7 +711,7 @@ match_cfg_line(Options *options, char ** - static void - rm_env(Options *options, const char *arg, const char *filename, int linenum) - { -- int i, j; -+ int i, j, onum_send_env = options->num_send_env; - char *cp; - - /* Remove an environment variable */ -@@ -734,6 +734,11 @@ rm_env(Options *options, const char *arg - options->num_send_env--; - /* NB. don't increment i */ - } -+ if (onum_send_env != options->num_send_env) { -+ options->send_env = xrecallocarray(options->send_env, -+ onum_send_env, options->num_send_env, -+ sizeof(*options->send_env)); -+ } - } - - /* -diff -up openssh-8.0p1/regress/Makefile.sshdinclude openssh-8.0p1/regress/Makefile ---- openssh-8.0p1/regress/Makefile.sshdinclude 2021-10-20 15:18:49.742331115 +0200 -+++ openssh-8.0p1/regress/Makefile 2021-10-20 15:19:41.324781344 +0200 -@@ -82,6 +82,7 @@ LTESTS= connect \ - principals-command \ - cert-file \ - cfginclude \ -+ servcfginclude \ - allow-deny-users \ - authinfo - -@@ -118,7 +119,7 @@ CLEANFILES= *.core actual agent-key.* au - sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ - ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \ - ssh_proxy_envpass sshd.log sshd_config sshd_config_minimal \ -- sshd_config.orig sshd_proxy sshd_proxy.* sshd_proxy_bak \ -+ sshd_config.* sshd_proxy sshd_proxy.* sshd_proxy_bak \ - sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \ - t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \ - t8.out t8.out.pub t9.out t9.out.pub testdata \ -diff -up openssh-8.0p1/regress/servcfginclude.sh.sshdinclude openssh-8.0p1/regress/servcfginclude.sh ---- openssh-8.0p1/regress/servcfginclude.sh.sshdinclude 2021-10-20 15:18:49.744331132 +0200 -+++ openssh-8.0p1/regress/servcfginclude.sh 2021-10-20 15:22:06.303046777 +0200 -@@ -0,0 +1,188 @@ -+# Placed in the Public Domain. -+ -+tid="server config include" -+ -+cat > $OBJ/sshd_config.i << _EOF -+HostKey $OBJ/host.ssh-ed25519 -+Match host a -+ Banner /aa -+ -+Match host b -+ Banner /bb -+ Include $OBJ/sshd_config.i.* -+ -+Match host c -+ Include $OBJ/sshd_config.i.* -+ Banner /cc -+ -+Match host m -+ Include $OBJ/sshd_config.i.* -+ -+Match Host d -+ Banner /dd -+ -+Match Host e -+ Banner /ee -+ Include $OBJ/sshd_config.i.* -+ -+Match Host f -+ Include $OBJ/sshd_config.i.* -+ Banner /ff -+ -+Match Host n -+ Include $OBJ/sshd_config.i.* -+_EOF -+ -+cat > $OBJ/sshd_config.i.0 << _EOF -+Match host xxxxxx -+_EOF -+ -+cat > $OBJ/sshd_config.i.1 << _EOF -+Match host a -+ Banner /aaa -+ -+Match host b -+ Banner /bbb -+ -+Match host c -+ Banner /ccc -+ -+Match Host d -+ Banner /ddd -+ -+Match Host e -+ Banner /eee -+ -+Match Host f -+ Banner /fff -+_EOF -+ -+cat > $OBJ/sshd_config.i.2 << _EOF -+Match host a -+ Banner /aaaa -+ -+Match host b -+ Banner /bbbb -+ -+Match host c -+ Banner /cccc -+ -+Match Host d -+ Banner /dddd -+ -+Match Host e -+ Banner /eeee -+ -+Match Host f -+ Banner /ffff -+ -+Match all -+ Banner /xxxx -+_EOF -+ -+trial() { -+ _host="$1" -+ _exp="$2" -+ _desc="$3" -+ test -z "$_desc" && _desc="test match" -+ trace "$_desc host=$_host expect=$_exp" -+ ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \ -+ -C "host=$_host,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || -+ fatal "ssh config parse failed: $_desc host=$_host expect=$_exp" -+ _got=`grep -i '^banner ' $OBJ/sshd_config.out | awk '{print $2}'` -+ if test "x$_exp" != "x$_got" ; then -+ fail "$desc_ host $_host include fail: expected $_exp got $_got" -+ fi -+} -+ -+trial a /aa -+trial b /bb -+trial c /ccc -+trial d /dd -+trial e /ee -+trial f /fff -+trial m /xxxx -+trial n /xxxx -+trial x none -+ -+# Prepare an included config with an error. -+ -+cat > $OBJ/sshd_config.i.3 << _EOF -+Banner xxxx -+ Junk -+_EOF -+ -+trace "disallow invalid config host=a" -+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \ -+ -C "host=a,user=test,addr=127.0.0.1" 2>/dev/null && \ -+ fail "sshd include allowed invalid config" -+ -+trace "disallow invalid config host=x" -+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \ -+ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \ -+ fail "sshd include allowed invalid config" -+ -+rm -f $OBJ/sshd_config.i.* -+ -+# Ensure that a missing include is not fatal. -+cat > $OBJ/sshd_config.i << _EOF -+HostKey $OBJ/host.ssh-ed25519 -+Include $OBJ/sshd_config.i.* -+Banner /aa -+_EOF -+ -+trial a /aa "missing include non-fatal" -+ -+# Ensure that Match/Host in an included config does not affect parent. -+cat > $OBJ/sshd_config.i.x << _EOF -+Match host x -+_EOF -+ -+trial a /aa "included file does not affect match state" -+ -+# Ensure the empty include directive is not accepted -+cat > $OBJ/sshd_config.i.x << _EOF -+Include -+_EOF -+ -+trace "disallow invalid with no argument" -+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i.x -T \ -+ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \ -+ fail "sshd allowed Include with no argument" -+ -+# Ensure the Include before any Match block works as expected (bug #3122) -+cat > $OBJ/sshd_config.i << _EOF -+Banner /xx -+HostKey $OBJ/host.ssh-ed25519 -+Include $OBJ/sshd_config.i.2 -+Match host a -+ Banner /aaaa -+_EOF -+cat > $OBJ/sshd_config.i.2 << _EOF -+Match host a -+ Banner /aa -+_EOF -+ -+trace "Include before match blocks" -+trial a /aa "included file before match blocks is properly evaluated" -+ -+# Port in included file is correctly interpretted (bug #3169) -+cat > $OBJ/sshd_config.i << _EOF -+Include $OBJ/sshd_config.i.2 -+Port 7722 -+_EOF -+cat > $OBJ/sshd_config.i.2 << _EOF -+HostKey $OBJ/host.ssh-ed25519 -+_EOF -+ -+trace "Port after included files" -+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \ -+ -C "host=x,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || \ -+ fail "failed to parse Port after included files" -+_port=`grep -i '^port ' $OBJ/sshd_config.out | awk '{print $2}'` -+if test "x7722" != "x$_port" ; then -+ fail "The Port in included file was intertepretted wrongly. Expected 7722, got $_port" -+fi -+ -+# cleanup -+rm -f $OBJ/sshd_config.i $OBJ/sshd_config.i.* $OBJ/sshd_config.out -diff -up openssh-8.0p1/regress/test-exec.sh.sshdinclude openssh-8.0p1/regress/test-exec.sh ---- openssh-8.0p1/regress/test-exec.sh.sshdinclude 2021-10-20 15:18:49.746331150 +0200 -+++ openssh-8.0p1/regress/test-exec.sh 2021-10-20 15:19:41.324781344 +0200 -@@ -220,6 +220,7 @@ echo "exec ${SSH} -E${TEST_SSH_LOGFILE} - - chmod a+rx $OBJ/ssh-log-wrapper.sh - REAL_SSH="$SSH" -+REAL_SSHD="$SSHD" - SSH="$SSHLOGWRAP" - - # Some test data. We make a copy because some tests will overwrite it. -diff -up openssh-8.0p1/servconf.c.sshdinclude openssh-8.0p1/servconf.c ---- openssh-8.0p1/servconf.c.sshdinclude 2021-10-20 15:18:49.748331167 +0200 -+++ openssh-8.0p1/servconf.c 2021-10-20 15:22:06.303046777 +0200 -@@ -40,6 +40,11 @@ - #ifdef HAVE_UTIL_H - #include - #endif -+#ifdef USE_SYSTEM_GLOB -+# include -+#else -+# include "openbsd-compat/glob.h" -+#endif - - #include "openbsd-compat/sys-queue.h" - #include "xmalloc.h" -@@ -70,6 +75,9 @@ static void add_listen_addr(ServerOption - const char *, int); - static void add_one_listen_addr(ServerOptions *, const char *, - const char *, int); -+static void parse_server_config_depth(ServerOptions *options, -+ const char *filename, struct sshbuf *conf, struct include_list *includes, -+ struct connection_info *connectinfo, int flags, int *activep, int depth); - - /* Use of privilege separation or not */ - extern int use_privsep; -@@ -528,7 +536,7 @@ typedef enum { - sAcceptEnv, sSetEnv, sPermitTunnel, - sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, -- sHostCertificate, -+ sHostCertificate, sInclude, - sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, - sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, - sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, -@@ -540,9 +548,11 @@ typedef enum { - sDeprecated, sIgnore, sUnsupported - } ServerOpCodes; - --#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ --#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ --#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) -+#define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */ -+#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ -+#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) -+#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */ -+#define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */ - - /* Textual representation of the tokens. */ - static struct { -@@ -687,6 +697,7 @@ static struct { - { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, - { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, - { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, -+ { "include", sInclude, SSHCFG_ALL }, - { "ipqos", sIPQoS, SSHCFG_ALL }, - { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, - { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, -@@ -1259,13 +1270,14 @@ static const struct multistate multistat - { NULL, -1 } - }; - --int --process_server_config_line(ServerOptions *options, char *line, -+static int -+process_server_config_line_depth(ServerOptions *options, char *line, - const char *filename, int linenum, int *activep, -- struct connection_info *connectinfo) -+ struct connection_info *connectinfo, int *inc_flags, int depth, -+ struct include_list *includes) - { - char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; -- int cmdline = 0, *intptr, value, value2, n, port; -+ int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found; - SyslogFacility *log_facility_ptr; - LogLevel *log_level_ptr; - ServerOpCodes opcode; -@@ -1274,6 +1286,8 @@ process_server_config_line(ServerOptions - long long val64; - const struct multistate *multistate_ptr; - const char *errstr; -+ struct include_item *item; -+ glob_t gbuf; - - /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ - if ((len = strlen(line)) == 0) -@@ -1300,7 +1314,7 @@ process_server_config_line(ServerOptions - cmdline = 1; - activep = &cmdline; - } -- if (*activep && opcode != sMatch) -+ if (*activep && opcode != sMatch && opcode != sInclude) - debug3("%s:%d setting %s %s", filename, linenum, arg, cp); - if (*activep == 0 && !(flags & SSHCFG_MATCH)) { - if (connectinfo == NULL) { -@@ -1980,15 +1994,112 @@ process_server_config_line(ServerOptions - *intptr = value; - break; - -+ case sInclude: -+ if (cmdline) { -+ fatal("Include directive not supported as a " -+ "command-line option"); -+ } -+ value = 0; -+ while ((arg2 = strdelim(&cp)) != NULL && *arg2 != '\0') { -+ value++; -+ found = 0; -+ if (*arg2 != '/' && *arg2 != '~') { -+ xasprintf(&arg, "%s/%s", SSHDIR, arg2); -+ } else -+ arg = xstrdup(arg2); -+ -+ /* -+ * Don't let included files clobber the containing -+ * file's Match state. -+ */ -+ oactive = *activep; -+ -+ /* consult cache of include files */ -+ TAILQ_FOREACH(item, includes, entry) { -+ if (strcmp(item->selector, arg) != 0) -+ continue; -+ if (item->filename != NULL) { -+ parse_server_config_depth(options, -+ item->filename, item->contents, -+ includes, connectinfo, -+ (*inc_flags & SSHCFG_MATCH_ONLY -+ ? SSHCFG_MATCH_ONLY : (oactive -+ ? 0 : SSHCFG_NEVERMATCH)), -+ activep, depth + 1); -+ } -+ found = 1; -+ *activep = oactive; -+ } -+ if (found != 0) { -+ free(arg); -+ continue; -+ } -+ -+ /* requested glob was not in cache */ -+ debug2("%s line %d: new include %s", -+ filename, linenum, arg); -+ if ((r = glob(arg, 0, NULL, &gbuf)) != 0) { -+ if (r != GLOB_NOMATCH) { -+ fatal("%s line %d: include \"%s\" " -+ "glob failed", filename, -+ linenum, arg); -+ } -+ /* -+ * If no entry matched then record a -+ * placeholder to skip later glob calls. -+ */ -+ debug2("%s line %d: no match for %s", -+ filename, linenum, arg); -+ item = xcalloc(1, sizeof(*item)); -+ item->selector = strdup(arg); -+ TAILQ_INSERT_TAIL(includes, -+ item, entry); -+ } -+ if (gbuf.gl_pathc > INT_MAX) -+ fatal("%s: too many glob results", __func__); -+ for (n = 0; n < (int)gbuf.gl_pathc; n++) { -+ debug2("%s line %d: including %s", -+ filename, linenum, gbuf.gl_pathv[n]); -+ item = xcalloc(1, sizeof(*item)); -+ item->selector = strdup(arg); -+ item->filename = strdup(gbuf.gl_pathv[n]); -+ if ((item->contents = sshbuf_new()) == NULL) { -+ fatal("%s: sshbuf_new failed", -+ __func__); -+ } -+ load_server_config(item->filename, -+ item->contents); -+ parse_server_config_depth(options, -+ item->filename, item->contents, -+ includes, connectinfo, -+ (*inc_flags & SSHCFG_MATCH_ONLY -+ ? SSHCFG_MATCH_ONLY : (oactive -+ ? 0 : SSHCFG_NEVERMATCH)), -+ activep, depth + 1); -+ *activep = oactive; -+ TAILQ_INSERT_TAIL(includes, item, entry); -+ } -+ globfree(&gbuf); -+ free(arg); -+ } -+ if (value == 0) { -+ fatal("%s line %d: Include missing filename argument", -+ filename, linenum); -+ } -+ break; -+ - case sMatch: - if (cmdline) - fatal("Match directive not supported as a command-line " - "option"); -- value = match_cfg_line(&cp, linenum, connectinfo); -+ value = match_cfg_line(&cp, linenum, -+ (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo)); - if (value < 0) - fatal("%s line %d: Bad Match condition", filename, - linenum); -- *activep = value; -+ *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; -+ /* The MATCH_ONLY is applicable only until the first match block */ -+ *inc_flags &= ~SSHCFG_MATCH_ONLY; - break; - - case sKerberosUseKuserok: -@@ -2275,6 +2386,18 @@ process_server_config_line(ServerOptions - return 0; - } - -+int -+process_server_config_line(ServerOptions *options, char *line, -+ const char *filename, int linenum, int *activep, -+ struct connection_info *connectinfo, struct include_list *includes) -+{ -+ int inc_flags = 0; -+ -+ return process_server_config_line_depth(options, line, filename, -+ linenum, activep, connectinfo, &inc_flags, 0, includes); -+} -+ -+ - /* Reads the server configuration file. */ - - void -@@ -2313,12 +2436,13 @@ load_server_config(const char *filename, - - void - parse_server_match_config(ServerOptions *options, -- struct connection_info *connectinfo) -+ struct include_list *includes, struct connection_info *connectinfo) - { - ServerOptions mo; - - initialize_server_options(&mo); -- parse_server_config(&mo, "reprocess config", cfg, connectinfo); -+ parse_server_config(&mo, "reprocess config", cfg, includes, -+ connectinfo); - copy_set_server_options(options, &mo, 0); - } - -@@ -2464,28 +2588,44 @@ copy_set_server_options(ServerOptions *d - #undef M_CP_STROPT - #undef M_CP_STRARRAYOPT - --void --parse_server_config(ServerOptions *options, const char *filename, -- struct sshbuf *conf, struct connection_info *connectinfo) -+#define SERVCONF_MAX_DEPTH 16 -+static void -+parse_server_config_depth(ServerOptions *options, const char *filename, -+ struct sshbuf *conf, struct include_list *includes, -+ struct connection_info *connectinfo, int flags, int *activep, int depth) - { -- int active, linenum, bad_options = 0; -+ int linenum, bad_options = 0; - char *cp, *obuf, *cbuf; - -- debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf)); -+ if (depth < 0 || depth > SERVCONF_MAX_DEPTH) -+ fatal("Too many recursive configuration includes"); -+ -+ debug2("%s: config %s len %zu%s", __func__, filename, sshbuf_len(conf), -+ (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : "")); - - if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) - fatal("%s: sshbuf_dup_string failed", __func__); -- active = connectinfo ? 0 : 1; - linenum = 1; - while ((cp = strsep(&cbuf, "\n")) != NULL) { -- if (process_server_config_line(options, cp, filename, -- linenum++, &active, connectinfo) != 0) -+ if (process_server_config_line_depth(options, cp, -+ filename, linenum++, activep, connectinfo, &flags, -+ depth, includes) != 0) - bad_options++; - } - free(obuf); - if (bad_options > 0) - fatal("%s: terminating, %d bad configuration options", - filename, bad_options); -+} -+ -+void -+parse_server_config(ServerOptions *options, const char *filename, -+ struct sshbuf *conf, struct include_list *includes, -+ struct connection_info *connectinfo) -+{ -+ int active = connectinfo ? 0 : 1; -+ parse_server_config_depth(options, filename, conf, includes, -+ connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0); - process_queued_listen_addrs(options); - } - -diff -up openssh-8.0p1/servconf.h.sshdinclude openssh-8.0p1/servconf.h ---- openssh-8.0p1/servconf.h.sshdinclude 2021-10-20 15:18:49.750331185 +0200 -+++ openssh-8.0p1/servconf.h 2021-10-20 15:19:41.325781353 +0200 -@@ -16,6 +16,8 @@ - #ifndef SERVCONF_H - #define SERVCONF_H - -+#include -+ - #define MAX_PORTS 256 /* Max # ports. */ - - #define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ -@@ -234,6 +236,15 @@ struct connection_info { - * unspecified */ - }; - -+/* List of included files for re-exec from the parsed configuration */ -+struct include_item { -+ char *selector; -+ char *filename; -+ struct sshbuf *contents; -+ TAILQ_ENTRY(include_item) entry; -+}; -+TAILQ_HEAD(include_list, include_item); -+ - - /* - * These are string config options that must be copied between the -@@ -273,12 +284,13 @@ struct connection_info *get_connection_i - void initialize_server_options(ServerOptions *); - void fill_default_server_options(ServerOptions *); - int process_server_config_line(ServerOptions *, char *, const char *, int, -- int *, struct connection_info *); -+ int *, struct connection_info *, struct include_list *includes); - void process_permitopen(struct ssh *ssh, ServerOptions *options); - void load_server_config(const char *, struct sshbuf *); - void parse_server_config(ServerOptions *, const char *, struct sshbuf *, -- struct connection_info *); --void parse_server_match_config(ServerOptions *, struct connection_info *); -+ struct include_list *includes, struct connection_info *); -+void parse_server_match_config(ServerOptions *, -+ struct include_list *includes, struct connection_info *); - int parse_server_match_testspec(struct connection_info *, char *); - int server_match_spec_complete(struct connection_info *); - void copy_set_server_options(ServerOptions *, ServerOptions *, int); -diff -up openssh-8.0p1/sshd_config.5.sshdinclude openssh-8.0p1/sshd_config.5 ---- openssh-8.0p1/sshd_config.5.sshdinclude 2021-10-20 15:18:49.754331220 +0200 -+++ openssh-8.0p1/sshd_config.5 2021-10-20 15:19:41.325781353 +0200 -@@ -825,7 +825,20 @@ during - and use only the system-wide known hosts file - .Pa /etc/ssh/known_hosts . - The default is --.Cm no . -+.Dq no . -+.It Cm Include -+Include the specified configuration file(s). -+Multiple path names may be specified and each pathname may contain -+.Xr glob 7 -+wildcards. -+Files without absolute paths are assumed to be in -+.Pa /etc/ssh . -+A -+.Cm Include -+directive may appear inside a -+.Cm Match -+block -+to perform conditional inclusion. - .It Cm IPQoS - Specifies the IPv4 type-of-service or DSCP class for the connection. - Accepted values are -diff -up openssh-8.0p1/sshd.c.sshdinclude openssh-8.0p1/sshd.c ---- openssh-8.0p1/sshd.c.sshdinclude 2021-10-20 15:18:49.752331202 +0200 -+++ openssh-8.0p1/sshd.c 2021-10-20 15:19:41.325781353 +0200 -@@ -257,6 +257,9 @@ struct sshauthopt *auth_opts = NULL; - /* sshd_config buffer */ - struct sshbuf *cfg; - -+/* Included files from the configuration file */ -+struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); -+ - /* message to be displayed after login */ - struct sshbuf *loginmsg; - -@@ -927,30 +930,45 @@ usage(void) - static void - send_rexec_state(int fd, struct sshbuf *conf) - { -- struct sshbuf *m; -+ struct sshbuf *m = NULL, *inc = NULL; -+ struct include_item *item = NULL; - int r; - - debug3("%s: entering fd = %d config len %zu", __func__, fd, - sshbuf_len(conf)); - -+ if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); -+ -+ /* pack includes into a string */ -+ TAILQ_FOREACH(item, &includes, entry) { -+ if ((r = sshbuf_put_cstring(inc, item->selector)) != 0 || -+ (r = sshbuf_put_cstring(inc, item->filename)) != 0 || -+ (r = sshbuf_put_stringb(inc, item->contents)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } -+ - /* - * Protocol from reexec master to child: - * string configuration -- * string rngseed (only if OpenSSL is not self-seeded) -+ * string included_files[] { -+ * string selector -+ * string filename -+ * string contents -+ * } -+ * string rng_seed (if required) - */ -- if ((m = sshbuf_new()) == NULL) -- fatal("%s: sshbuf_new failed", __func__); -- if ((r = sshbuf_put_stringb(m, conf)) != 0) -+ if ((r = sshbuf_put_stringb(m, conf)) != 0 || -+ (r = sshbuf_put_stringb(m, inc)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -- - #if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) - rexec_send_rng_seed(m); - #endif -- - if (ssh_msg_send(fd, 0, m) == -1) - fatal("%s: ssh_msg_send failed", __func__); - - sshbuf_free(m); -+ sshbuf_free(inc); - - debug3("%s: done", __func__); - } -@@ -958,14 +976,15 @@ send_rexec_state(int fd, struct sshbuf * - static void - recv_rexec_state(int fd, struct sshbuf *conf) - { -- struct sshbuf *m; -+ struct sshbuf *m, *inc; - u_char *cp, ver; - size_t len; - int r; -+ struct include_item *item; - - debug3("%s: entering fd = %d", __func__, fd); - -- if ((m = sshbuf_new()) == NULL) -+ if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); - if (ssh_msg_recv(fd, m) == -1) - fatal("%s: ssh_msg_recv failed", __func__); -@@ -973,14 +992,28 @@ recv_rexec_state(int fd, struct sshbuf * - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (ver != 0) - fatal("%s: rexec version mismatch", __func__); -- if ((r = sshbuf_get_string(m, &cp, &len)) != 0) -- fatal("%s: buffer error: %s", __func__, ssh_err(r)); -- if (conf != NULL && (r = sshbuf_put(conf, cp, len))) -+ if ((r = sshbuf_get_string(m, &cp, &len)) != 0 || -+ (r = sshbuf_get_stringb(m, inc)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ - #if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) - rexec_recv_rng_seed(m); - #endif - -+ if (conf != NULL && (r = sshbuf_put(conf, cp, len))) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ -+ while (sshbuf_len(inc) != 0) { -+ item = xcalloc(1, sizeof(*item)); -+ if ((item->contents = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); -+ if ((r = sshbuf_get_cstring(inc, &item->selector, NULL)) != 0 || -+ (r = sshbuf_get_cstring(inc, &item->filename, NULL)) != 0 || -+ (r = sshbuf_get_stringb(inc, item->contents)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ TAILQ_INSERT_TAIL(&includes, item, entry); -+ } -+ - free(cp); - sshbuf_free(m); - -@@ -1661,7 +1694,7 @@ main(int ac, char **av) - case 'o': - line = xstrdup(optarg); - if (process_server_config_line(&options, line, -- "command-line", 0, NULL, NULL) != 0) -+ "command-line", 0, NULL, NULL, &includes) != 0) - exit(1); - free(line); - break; -@@ -1692,7 +1725,7 @@ main(int ac, char **av) - SYSLOG_LEVEL_INFO : options.log_level, - options.log_facility == SYSLOG_FACILITY_NOT_SET ? - SYSLOG_FACILITY_AUTH : options.log_facility, -- log_stderr || !inetd_flag); -+ log_stderr || !inetd_flag || debug_flag); - - /* - * Unset KRB5CCNAME, otherwise the user's session may inherit it from -@@ -1725,12 +1758,11 @@ main(int ac, char **av) - */ - (void)atomicio(vwrite, startup_pipe, "\0", 1); - } -- } -- else if (strcasecmp(config_file_name, "none") != 0) -+ } else if (strcasecmp(config_file_name, "none") != 0) - load_server_config(config_file_name, cfg); - - parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, -- cfg, NULL); -+ cfg, &includes, NULL); - - /* 'UsePAM no' is not supported in RHEL */ - if (! options.use_pam) -@@ -1946,7 +1978,7 @@ main(int ac, char **av) - if (connection_info == NULL) - connection_info = get_connection_info(ssh, 0, 0); - connection_info->test = 1; -- parse_server_match_config(&options, connection_info); -+ parse_server_match_config(&options, &includes, connection_info); - dump_config(&options); - } - -diff -up openssh-8.0p1/sshbuf-getput-basic.c.stringb openssh-8.0p1/sshbuf-getput-basic.c ---- openssh-8.0p1/sshbuf-getput-basic.c.stringb 2022-12-21 12:18:43.274799163 +0100 -+++ openssh-8.0p1/sshbuf-getput-basic.c 2022-12-21 12:19:19.758081516 +0100 -@@ -371,6 +371,9 @@ sshbuf_put_cstring(struct sshbuf *buf, c - int - sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v) - { -+ if (v == NULL) -+ return sshbuf_put_string(buf, NULL, 0); -+ - return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v)); - } - diff --git a/SOURCES/openssh-8.0p1-upstream-ignore-SIGPIPE.patch b/SOURCES/openssh-8.0p1-upstream-ignore-SIGPIPE.patch deleted file mode 100644 index 0e85815..0000000 --- a/SOURCES/openssh-8.0p1-upstream-ignore-SIGPIPE.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d33ff14309e33aa79fdf95e1bc4facafa80b90a9 Mon Sep 17 00:00:00 2001 -From: Stepan Broz -Date: Tue, 25 Jun 2024 17:38:22 +0200 -Subject: [PATCH] upstream: ignore SIGPIPE earlier in main(), specifically - before - -muxclient() which performs operations that could cause one; Reported by Noam -Lewis via bz3454, ok dtucker@ - -OpenBSD-Commit-ID: 63d8e13276869eebac6d7a05d5a96307f9026e47 ---- - ssh.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/ssh.c b/ssh.c -index 786e26d..e037c66 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -1115,6 +1115,8 @@ main(int ac, char **av) - } - } - -+ signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ -+ - /* - * Initialize "log" output. Since we are the client all output - * goes to stderr unless otherwise specified by -y or -E. -@@ -1545,7 +1547,6 @@ main(int ac, char **av) - options.num_system_hostfiles); - tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles); - -- signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ - signal(SIGCHLD, main_sigchld_handler); - - /* Log into the remote system. Never returns if the login fails. */ --- -2.45.2 - diff --git a/SOURCES/openssh-8.0p1.tar.gz.asc b/SOURCES/openssh-8.0p1.tar.gz.asc deleted file mode 100644 index b0f648e..0000000 --- a/SOURCES/openssh-8.0p1.tar.gz.asc +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQHDBAABCgAdFiEEWcIRjtIG2SfmZ+vj0+X1a22SDTAFAly3ro8ACgkQ0+X1a22S -DTCAiAx/W9XHoDs5NijyNIP43W2nFYuf6HG1duoLjdJ8rnsC3e90gx8h5RpUUh24 -JDACoUFnbJsNgiQBaYpO7bOnf3Vw5Oui1gPeKnQ76KQsXDwD/N/0wLUf55+XdNJ6 -tcgm6/x1W4b8bWje5bcS3qhxv6t/hSL/OxusA8zoNmnTD5XMg6QtJ0Rp9ZHPriCJ -C4eCPdHfmyHCr1IATMX9+n5CO5JUPexaDjQug7k/Z1XA/UlwVfRRs1JMpviBodC+ -ZUOuk9tH11RKSBcUeR3Ef4iaR3FchryyyBZUZdYBkmDrnHrYpUK5ifdHT+ZXdzPl -laX03Kz094LqrP6L3lafk6b1PKOVjKwx1vM5fhnv+pfx4dmao9BwZMuIq6Fa5uMX -w2oHGhlIDmeT66Yny5d0APn2wCewyYUGPanSZY/HolHAPs+doOBgI361kMAR9J3e -Ii3VKhIdE8i4K3fC19uDkf7xL8UVvRVXjgM7i+GNndh1ou/vDYxmEAsW9IR/D3XC -HM/jMdq+UewAiRG46aI5rsi/A8J8/A== -=YtoH ------END PGP SIGNATURE----- diff --git a/SOURCES/openssh-8.7p1-minimize-sha1-use.patch b/SOURCES/openssh-8.7p1-minimize-sha1-use.patch deleted file mode 100644 index e5a8dee..0000000 --- a/SOURCES/openssh-8.7p1-minimize-sha1-use.patch +++ /dev/null @@ -1,166 +0,0 @@ -diff --color -ru a/kex.c b/kex.c ---- a/kex.c 2022-06-23 10:25:29.529922670 +0200 -+++ b/kex.c 2022-06-23 10:26:12.911762100 +0200 -@@ -906,6 +906,18 @@ - return (1); - } - -+/* returns non-zero if proposal contains any algorithm from algs */ -+static int -+has_any_alg(const char *proposal, const char *algs) -+{ -+ char *cp; -+ -+ if ((cp = match_list(proposal, algs, NULL)) == NULL) -+ return 0; -+ free(cp); -+ return 1; -+} -+ - static int - kex_choose_conf(struct ssh *ssh) - { -@@ -941,6 +953,16 @@ - free(ext); - } - -+ /* Check whether client supports rsa-sha2 algorithms */ -+ if (kex->server && (kex->flags & KEX_INITIAL)) { -+ if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com")) -+ kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; -+ if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com")) -+ kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; -+ } -+ - /* Algorithm Negotiation */ - if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], - sprop[PROPOSAL_KEX_ALGS])) != 0) { -diff --color -ru a/kex.h b/kex.h ---- a/kex.h 2022-06-23 10:25:29.511922322 +0200 -+++ b/kex.h 2022-06-23 10:26:12.902761926 +0200 -@@ -117,6 +117,8 @@ - - #define KEX_INIT_SENT 0x0001 - #define KEX_INITIAL 0x0002 -+#define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */ -+#define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */ - - struct sshenc { - char *name; -diff --color -ru a/serverloop.c b/serverloop.c ---- a/serverloop.c 2022-06-23 10:25:29.537922825 +0200 -+++ b/serverloop.c 2022-06-23 10:26:12.918762235 +0200 -@@ -736,16 +736,17 @@ - struct sshbuf *resp = NULL; - struct sshbuf *sigbuf = NULL; - struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; -- int r, ndx, kexsigtype, use_kexsigtype, success = 0; -+ int r, ndx, success = 0; - const u_char *blob; -+ const char *sigalg, *kex_rsa_sigalg = NULL; - u_char *sig = 0; - size_t blen, slen; - - if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); -- -- kexsigtype = sshkey_type_plain( -- sshkey_type_from_name(ssh->kex->hostkey_alg)); -+ if (sshkey_type_plain(sshkey_type_from_name( -+ ssh->kex->hostkey_alg)) == KEY_RSA) -+ kex_rsa_sigalg = ssh->kex->hostkey_alg; - while (ssh_packet_remaining(ssh) > 0) { - sshkey_free(key); - key = NULL; -@@ -780,16 +781,24 @@ - * For RSA keys, prefer to use the signature type negotiated - * during KEX to the default (SHA1). - */ -- use_kexsigtype = kexsigtype == KEY_RSA && -- sshkey_type_plain(key->type) == KEY_RSA; -+ sigalg = NULL; -+ if (sshkey_type_plain(key->type) == KEY_RSA) { -+ if (kex_rsa_sigalg != NULL) -+ sigalg = kex_rsa_sigalg; -+ else if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) -+ sigalg = "rsa-sha2-512"; -+ else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) -+ sigalg = "rsa-sha2-256"; -+ } -+ debug3("%s: sign %s key (index %d) using sigalg %s", __func__, -+ sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); - if ((r = sshbuf_put_cstring(sigbuf, - "hostkeys-prove-00@openssh.com")) != 0 || - (r = sshbuf_put_string(sigbuf, - ssh->kex->session_id, ssh->kex->session_id_len)) != 0 || - (r = sshkey_puts(key, sigbuf)) != 0 || - (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, -- sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), -- use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 || -+ sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), sigalg)) != 0 || - (r = sshbuf_put_string(resp, sig, slen)) != 0) { - error("%s: couldn't prepare signature: %s", - __func__, ssh_err(r)); -diff --color -ru a/sshkey.c b/sshkey.c ---- a/sshkey.c 2022-06-23 10:25:29.532922728 +0200 -+++ b/sshkey.c 2022-06-23 10:26:12.914762158 +0200 -@@ -82,7 +82,6 @@ - struct sshbuf *buf, enum sshkey_serialize_rep); - static int sshkey_from_blob_internal(struct sshbuf *buf, - struct sshkey **keyp, int allow_cert); --static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep); - - /* Supported key types */ - struct keytype { -@@ -2092,7 +2091,8 @@ - if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, - sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) - goto out; -- if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0) -+ if ((ret = sshkey_get_sigtype(sig, slen, -+ &key->cert->signature_type)) != 0) - goto out; - - /* Success */ -@@ -2394,8 +2394,8 @@ - return r; - } - --static int --get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) -+int -+sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) - { - int r; - struct sshbuf *b = NULL; -@@ -2477,7 +2477,7 @@ - return 0; - if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL) - return SSH_ERR_INVALID_ARGUMENT; -- if ((r = get_sigtype(sig, siglen, &sigtype)) != 0) -+ if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) - return r; - r = strcmp(expected_alg, sigtype) == 0; - free(sigtype); -@@ -2739,7 +2739,7 @@ - sshbuf_len(cert), alg, 0, signer_ctx)) != 0) - goto out; - /* Check and update signature_type against what was actually used */ -- if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0) -+ if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0) - goto out; - if (alg != NULL && strcmp(alg, sigtype) != 0) { - ret = SSH_ERR_SIGN_ALG_UNSUPPORTED; -diff --color -ru a/sshkey.h b/sshkey.h ---- a/sshkey.h 2022-06-23 10:25:29.521922515 +0200 -+++ b/sshkey.h 2022-06-23 10:26:12.907762022 +0200 -@@ -211,6 +211,7 @@ - const u_char *, size_t, const char *, u_int); - int sshkey_check_sigtype(const u_char *, size_t, const char *); - const char *sshkey_sigalg_by_name(const char *); -+int sshkey_get_sigtype(const u_char *, size_t, char **); - - /* for debug */ - void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *); diff --git a/SOURCES/openssh-8.7p1-upstream-cve-2021-41617.patch b/SOURCES/openssh-8.7p1-upstream-cve-2021-41617.patch deleted file mode 100644 index a68aebd..0000000 --- a/SOURCES/openssh-8.7p1-upstream-cve-2021-41617.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/auth.c b/auth.c -index b8d1040d..0134d694 100644 ---- a/auth.c -+++ b/auth.c -@@ -56,6 +56,7 @@ - # include - #endif - #include -+#include - #ifdef HAVE_LOGIN_H - #include - #endif -@@ -2695,6 +2696,12 @@ subprocess(const char *tag, const char *command, - } - closefrom(STDERR_FILENO + 1); - -+ if (geteuid() == 0 && -+ initgroups(pw->pw_name, pw->pw_gid) == -1) { -+ error("%s: initgroups(%s, %u): %s", tag, -+ pw->pw_name, (u_int)pw->pw_gid, strerror(errno)); -+ _exit(1); -+ } - /* Don't use permanently_set_uid() here to avoid fatal() */ - if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { - error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, diff --git a/SOURCES/openssh-9.1p1-sshbanner.patch b/SOURCES/openssh-9.1p1-sshbanner.patch deleted file mode 100644 index 0e40770..0000000 --- a/SOURCES/openssh-9.1p1-sshbanner.patch +++ /dev/null @@ -1,32 +0,0 @@ -diff --git a/ssh-keyscan.c b/ssh-keyscan.c -index d29a03b4..d7283136 100644 ---- a/ssh-keyscan.c -+++ b/ssh-keyscan.c -@@ -490,6 +490,15 @@ congreet(int s) - return; - } - -+ /* -+ * Read the server banner as per RFC4253 section 4.2. The "SSH-" -+ * protocol identification string may be preceeded by an arbitarily -+ * large banner which we must read and ignore. Loop while reading -+ * newline-terminated lines until we have one starting with "SSH-". -+ * The ID string cannot be longer than 255 characters although the -+ * preceeding banner lines may (in which case they'll be discarded -+ * in multiple iterations of the outer loop). -+ */ - for (;;) { - memset(buf, '\0', sizeof(buf)); - bufsiz = sizeof(buf); -@@ -517,6 +526,11 @@ congreet(int s) - conrecycle(s); - return; - } -+ if (cp >= buf + sizeof(buf)) { -+ error("%s: greeting exceeds allowable length", c->c_name); -+ confree(s); -+ return; -+ } - if (*cp != '\n' && *cp != '\r') { - error("%s: bad greeting", c->c_name); - confree(s); diff --git a/SOURCES/openssh-9.3p1-upstream-cve-2023-38408.patch b/SOURCES/openssh-9.3p1-upstream-cve-2023-38408.patch deleted file mode 100644 index 5632ba1..0000000 --- a/SOURCES/openssh-9.3p1-upstream-cve-2023-38408.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c -index 6be647ec..ebddf6c3 100644 ---- a/ssh-pkcs11.c -+++ b/ssh-pkcs11.c -@@ -1537,10 +1537,8 @@ pkcs11_register_provider(char *provider_id, char *pin, - error("dlopen %s failed: %s", provider_module, dlerror()); - goto fail; - } -- if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) { -- error("dlsym(C_GetFunctionList) failed: %s", dlerror()); -- goto fail; -- } -+ if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) -+ fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); - - p->module->handle = handle; - /* setup the pkcs11 callbacks */ diff --git a/SOURCES/openssh-9.4p2-limit-delay.patch b/SOURCES/openssh-9.4p2-limit-delay.patch deleted file mode 100644 index 009fcc7..0000000 --- a/SOURCES/openssh-9.4p2-limit-delay.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff -u -p -r1.166 auth2.c ---- a/auth2.c 8 Mar 2023 04:43:12 -0000 1.166 -+++ b/auth2.c 28 Aug 2023 08:32:44 -0000 -@@ -208,6 +208,7 @@ input_service_request(int type, u_int32_ - } - - #define MIN_FAIL_DELAY_SECONDS 0.005 -+#define MAX_FAIL_DELAY_SECONDS 5.0 - static double - user_specific_delay(const char *user) - { -@@ -233,6 +234,12 @@ ensure_minimum_time_since(double start, - struct timespec ts; - double elapsed = monotime_double() - start, req = seconds, remain; - -+ if (elapsed > MAX_FAIL_DELAY_SECONDS) { -+ debug3("elapsed %0.3lfms exceeded the max delay " -+ "requested %0.3lfms)", elapsed*1000, req*1000); -+ return; -+ } -+ - /* if we've already passed the requested time, scale up */ - while ((remain = seconds - elapsed) < 0.0) - seconds *= 2; -@@ -317,7 +324,7 @@ input_userauth_request(int type, u_int32 - debug2("input_userauth_request: try method %s", method); - authenticated = m->userauth(ssh); - } -- if (!authctxt->authenticated) -+ if (!authctxt->authenticated && strcmp(method, "none") != 0) - ensure_minimum_time_since(tstart, - user_specific_delay(authctxt->user)); - userauth_finish(ssh, authenticated, method, NULL); diff --git a/SOURCES/openssh-9.6p1-CVE-2023-48795.patch b/SOURCES/openssh-9.6p1-CVE-2023-48795.patch deleted file mode 100644 index 16ff4c4..0000000 --- a/SOURCES/openssh-9.6p1-CVE-2023-48795.patch +++ /dev/null @@ -1,447 +0,0 @@ -diff --git a/PROTOCOL b/PROTOCOL -index d453c779..ded935eb 100644 ---- a/PROTOCOL -+++ b/PROTOCOL -@@ -137,6 +137,32 @@ than as a named global or channel request to allow pings with very - described at: - http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519 - -+1.9 transport: strict key exchange extension -+ -+OpenSSH supports a number of transport-layer hardening measures under -+a "strict KEX" feature. This feature is signalled similarly to the -+RFC8308 ext-info feature: by including a additional algorithm in the -+initiial SSH2_MSG_KEXINIT kex_algorithms field. The client may append -+"kex-strict-c-v00@openssh.com" to its kex_algorithms and the server -+may append "kex-strict-s-v00@openssh.com". These pseudo-algorithms -+are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored -+if they are present in subsequent SSH2_MSG_KEXINIT packets. -+ -+When an endpoint that supports this extension observes this algorithm -+name in a peer's KEXINIT packet, it MUST make the following changes to -+the the protocol: -+ -+a) During initial KEX, terminate the connection if any unexpected or -+ out-of-sequence packet is received. This includes terminating the -+ connection if the first packet received is not SSH2_MSG_KEXINIT. -+ Unexpected packets for the purpose of strict KEX include messages -+ that are otherwise valid at any time during the connection such as -+ SSH2_MSG_DEBUG and SSH2_MSG_IGNORE. -+b) After sending or receiving a SSH2_MSG_NEWKEYS message, reset the -+ packet sequence number to zero. This behaviour persists for the -+ duration of the connection (i.e. not just the first -+ SSH2_MSG_NEWKEYS). -+ - 2. Connection protocol changes - - 2.1. connection: Channel write close extension "eow@openssh.com" -diff --git a/kex.c b/kex.c -index aa5e792d..d478ff6e 100644 ---- a/kex.c -+++ b/kex.c -@@ -65,7 +65,7 @@ - #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 *); - - static const char *proposal_names[PROPOSAL_MAX] = { -@@ -177,6 +177,18 @@ kex_names_valid(const char *names) - return 1; - } - -+/* returns non-zero if proposal contains any algorithm from algs */ -+static int -+has_any_alg(const char *proposal, const char *algs) -+{ -+ char *cp; -+ -+ if ((cp = match_list(proposal, algs, NULL)) == NULL) -+ return 0; -+ free(cp); -+ return 1; -+} -+ - /* - * Concatenate algorithm names, avoiding duplicates in the process. - * Caller must free returned string. -@@ -184,7 +196,7 @@ kex_names_valid(const char *names) - char * - kex_names_cat(const char *a, const char *b) - { -- char *ret = NULL, *tmp = NULL, *cp, *p, *m; -+ char *ret = NULL, *tmp = NULL, *cp, *p; - size_t len; - - if (a == NULL || *a == '\0') -@@ -201,10 +213,8 @@ kex_names_cat(const char *a, const char *b) - } - strlcpy(ret, a, len); - for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { -- if ((m = match_list(ret, p, NULL)) != NULL) { -- free(m); -+ if (has_any_alg(ret, p)) - continue; /* Algorithm already present */ -- } - if (strlcat(ret, ",", len) >= len || - strlcat(ret, p, len) >= len) { - free(tmp); -@@ -466,7 +485,12 @@ kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh) - { - int r; - -- error("kex protocol error: type %d seq %u", type, seq); -+ /* If in strict mode, any unexpected message is an error */ -+ if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) { -+ ssh_packet_disconnect(ssh, "strict KEX violation: " -+ "unexpected packet type %u (seqnr %u)", type, seq); -+ } -+ error("type %u seq %u", type, seq); - if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || - (r = sshpkt_put_u32(ssh, seq)) != 0 || - (r = sshpkt_send(ssh)) != 0) -@@ -548,6 +572,11 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) - ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error); - if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0) - return r; -+ if (ninfo >= 1024) { -+ error("SSH2_MSG_EXT_INFO with too many entries, expected " -+ "<=1024, received %u", ninfo); -+ return dispatch_protocol_error(type, seq, ssh); -+ } - for (i = 0; i < ninfo; i++) { - if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) - return r; -@@ -681,7 +705,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) - if (kex == NULL) - return SSH_ERR_INVALID_ARGUMENT; - -- ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error); - ptr = sshpkt_ptr(ssh, &dlen); - if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) - return r; -@@ -717,7 +741,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) - if (!(kex->flags & KEX_INIT_SENT)) - if ((r = kex_send_kexinit(ssh)) != 0) - return r; -- if ((r = kex_choose_conf(ssh)) != 0) -+ if ((r = kex_choose_conf(ssh, seq)) != 0) - return r; - - if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) -@@ -981,20 +1005,14 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) - return (1); - } - --/* returns non-zero if proposal contains any algorithm from algs */ - static int --has_any_alg(const char *proposal, const char *algs) -+kexalgs_contains(char **peer, const char *ext) - { -- char *cp; -- -- if ((cp = match_list(proposal, algs, NULL)) == NULL) -- return 0; -- free(cp); -- return 1; -+ return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext); - } - - static int --kex_choose_conf(struct ssh *ssh) -+kex_choose_conf(struct ssh *ssh, uint32_t seq) - { - struct kex *kex = ssh->kex; - struct newkeys *newkeys; -@@ -1019,13 +1037,23 @@ kex_choose_conf(struct ssh *ssh) - sprop=peer; - } - -- /* Check whether client supports ext_info_c */ -- if (kex->server && (kex->flags & KEX_INITIAL)) { -- char *ext; -- -- ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL); -- kex->ext_info_c = (ext != NULL); -- free(ext); -+ /* Check whether peer supports ext_info/kex_strict */ -+ if ((kex->flags & KEX_INITIAL) != 0) { -+ if (kex->server) { -+ kex->ext_info_c = kexalgs_contains(peer, "ext-info-c"); -+ kex->kex_strict = kexalgs_contains(peer, -+ "kex-strict-c-v00@openssh.com"); -+ } else { -+ kex->kex_strict = kexalgs_contains(peer, -+ "kex-strict-s-v00@openssh.com"); -+ } -+ if (kex->kex_strict) { -+ debug3("will use strict KEX ordering"); -+ if (seq != 0) -+ ssh_packet_disconnect(ssh, -+ "strict KEX violation: " -+ "KEXINIT was not the first packet"); -+ } - } - - /* Check whether client supports rsa-sha2 algorithms */ -diff --git a/kex.h b/kex.h -index 5f7ef784..272ebb43 100644 ---- a/kex.h -+++ b/kex.h -@@ -149,6 +149,7 @@ struct kex { - u_int kex_type; - char *server_sig_algs; - int ext_info_c; -+ int kex_strict; - struct sshbuf *my; - struct sshbuf *peer; - struct sshbuf *client_version; -diff --git a/packet.c b/packet.c -index 52017def..beb214f9 100644 ---- a/packet.c -+++ b/packet.c -@@ -1207,8 +1207,13 @@ ssh_packet_send2_wrapped(struct ssh *ssh) - sshbuf_dump(state->output, stderr); - #endif - /* increment sequence number for outgoing packets */ -- if (++state->p_send.seqnr == 0) -+ if (++state->p_send.seqnr == 0) { -+ if ((ssh->kex->flags & KEX_INITIAL) != 0) { -+ ssh_packet_disconnect(ssh, "outgoing sequence number " -+ "wrapped during initial key exchange"); -+ } - logit("outgoing seqnr wraps around"); -+ } - if (++state->p_send.packets == 0) - if (!(ssh->compat & SSH_BUG_NOREKEY)) - return SSH_ERR_NEED_REKEY; -@@ -1216,6 +1221,11 @@ ssh_packet_send2_wrapped(struct ssh *ssh) - state->p_send.bytes += len; - sshbuf_reset(state->outgoing_packet); - -+ if (type == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) { -+ debug("resetting send seqnr %u", state->p_send.seqnr); -+ state->p_send.seqnr = 0; -+ } -+ - if (type == SSH2_MSG_NEWKEYS) - r = ssh_set_newkeys(ssh, MODE_OUT); - else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side) -@@ -1344,8 +1354,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) - /* Stay in the loop until we have received a complete packet. */ - for (;;) { - /* Try to read a packet from the buffer. */ -- r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); -- if (r != 0) -+ if ((r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p)) != 0) - break; - /* If we got a packet, return it. */ - if (*typep != SSH_MSG_NONE) -@@ -1629,10 +1615,16 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) - if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) - goto out; - } -+ - if (seqnr_p != NULL) - *seqnr_p = state->p_read.seqnr; -- if (++state->p_read.seqnr == 0) -+ if (++state->p_read.seqnr == 0) { -+ if ((ssh->kex->flags & KEX_INITIAL) != 0) { -+ ssh_packet_disconnect(ssh, "incoming sequence number " -+ "wrapped during initial key exchange"); -+ } - logit("incoming seqnr wraps around"); -+ } - if (++state->p_read.packets == 0) - if (!(ssh->compat & SSH_BUG_NOREKEY)) - return SSH_ERR_NEED_REKEY; -@@ -1698,6 +1690,10 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) - #endif - /* reset for next packet */ - state->packlen = 0; -+ if (*typep == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) { -+ debug("resetting read seqnr %u", state->p_read.seqnr); -+ state->p_read.seqnr = 0; -+ } - - /* do we need to rekey? */ - if (ssh_packet_need_rekeying(ssh, 0)) { -@@ -1720,10 +1716,39 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) - r = ssh_packet_read_poll2(ssh, typep, seqnr_p); - if (r != 0) - return r; -- if (*typep) { -- state->keep_alive_timeouts = 0; -- DBG(debug("received packet type %d", *typep)); -+ if (*typep == 0) { -+ /* no message ready */ -+ return 0; - } -+ state->keep_alive_timeouts = 0; -+ DBG(debug("received packet type %d", *typep)); -+ -+ /* Always process disconnect messages */ -+ if (*typep == SSH2_MSG_DISCONNECT) { -+ if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || -+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) -+ return r; -+ /* Ignore normal client exit notifications */ -+ do_log2(ssh->state->server_side && -+ reason == SSH2_DISCONNECT_BY_APPLICATION ? -+ SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, -+ "Received disconnect from %s port %d:" -+ "%u: %.400s", ssh_remote_ipaddr(ssh), -+ ssh_remote_port(ssh), reason, msg); -+ free(msg); -+ return SSH_ERR_DISCONNECTED; -+ } -+ -+ /* -+ * Do not implicitly handle any messages here during initial -+ * KEX when in strict mode. They will be need to be allowed -+ * explicitly by the KEX dispatch table or they will generate -+ * protocol errors. -+ */ -+ if (ssh->kex != NULL && -+ (ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) -+ return 0; -+ /* Implicitly handle transport-level messages */ - switch (*typep) { - case SSH2_MSG_IGNORE: - debug3("Received SSH2_MSG_IGNORE"); -@@ -1738,19 +1763,6 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) - debug("Remote: %.900s", msg); - free(msg); - break; -- case SSH2_MSG_DISCONNECT: -- if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || -- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) -- return r; -- /* Ignore normal client exit notifications */ -- do_log2(ssh->state->server_side && -- reason == SSH2_DISCONNECT_BY_APPLICATION ? -- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, -- "Received disconnect from %s port %d:" -- "%u: %.400s", ssh_remote_ipaddr(ssh), -- ssh_remote_port(ssh), reason, msg); -- free(msg); -- return SSH_ERR_DISCONNECTED; - case SSH2_MSG_UNIMPLEMENTED: - if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) - return r; -@@ -2242,6 +2254,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex) - (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || - (r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 || - (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || -+ (r = sshbuf_put_u32(m, kex->kex_strict)) != 0 || - (r = sshbuf_put_stringb(m, kex->my)) != 0 || - (r = sshbuf_put_stringb(m, kex->peer)) != 0 || - (r = sshbuf_put_stringb(m, kex->client_version)) != 0 || -@@ -2404,6 +2417,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) - (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || - (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 || - (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || -+ (r = sshbuf_get_u32(m, &kex->kex_strict)) != 0 || - (r = sshbuf_get_stringb(m, kex->my)) != 0 || - (r = sshbuf_get_stringb(m, kex->peer)) != 0 || - (r = sshbuf_get_stringb(m, kex->client_version)) != 0 || -@@ -2732,6 +2746,7 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - -+ debug2("sending SSH2_MSG_DISCONNECT: %s", buf); - if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || - (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || - (r = sshpkt_put_cstring(ssh, buf)) != 0 || -diff --git a/sshconnect2.c b/sshconnect2.c -index df6caf81..0cccbcc4 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -253,7 +253,8 @@ ssh_kex2(struct ssh *ssh, char *host, st - xxx_host = host; - xxx_hostaddr = hostaddr; - -- if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) -+ if ((s = kex_names_cat(options.kex_algorithms, -+ "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) - fatal("%s: kex_names_cat", __func__); - myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s); - myproposal[PROPOSAL_ENC_ALGS_CTOS] = -@@ -358,7 +358,6 @@ struct cauthmethod { - }; - - static int input_userauth_service_accept(int, u_int32_t, struct ssh *); --static int input_userauth_ext_info(int, u_int32_t, struct ssh *); - static int input_userauth_success(int, u_int32_t, struct ssh *); - static int input_userauth_failure(int, u_int32_t, struct ssh *); - static int input_userauth_banner(int, u_int32_t, struct ssh *); -@@ -472,7 +471,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, - - ssh->authctxt = &authctxt; - ssh_dispatch_init(ssh, &input_userauth_error); -- ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info); -+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info); - ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); - ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ - pubkey_cleanup(ssh); -@@ -531,12 +530,6 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) - } - - /* ARGSUSED */ --static int --input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) --{ -- return kex_input_ext_info(type, seqnr, ssh); --} -- - void - userauth(struct ssh *ssh, char *authlist) - { -@@ -615,6 +608,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) - free(authctxt->methoddata); - authctxt->methoddata = NULL; - authctxt->success = 1; /* break out */ -+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error); - return 0; - } - -diff -up openssh-8.7p1/sshd.c.kexstrict openssh-8.7p1/sshd.c ---- openssh-8.7p1/sshd.c.kexstrict 2023-11-27 13:19:18.855433602 +0100 -+++ openssh-8.7p1/sshd.c 2023-11-27 13:28:10.441325314 +0100 -@@ -2531,10 +2531,14 @@ do_ssh2_kex(struct ssh *ssh) - { - char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; - struct kex *kex; -+ char *cp; - int r; - -- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( -- options.kex_algorithms); -+ if ((cp = kex_names_cat(options.kex_algorithms, -+ "kex-strict-s-v00@openssh.com")) == NULL) -+ fatal("kex_names_cat"); -+ -+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(cp); - myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal( - options.ciphers); - myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal( -@@ -2586,7 +2586,7 @@ do_ssh2_kex(struct ssh *ssh) - if (gss && orig) - xasprintf(&newstr, "%s,%s", gss, orig); - else if (gss) -- newstr = gss; -+ xasprintf(&newstr, "%s,%s", gss, "kex-strict-s-v00@openssh.com"); - else if (orig) - newstr = orig; - -@@ -2650,6 +2654,7 @@ do_ssh2_kex(struct ssh *ssh) - packet_send(); - packet_write_wait(); - #endif -+ free(cp); - debug("KEX done"); - } - diff --git a/SOURCES/openssh-9.6p1-CVE-2023-51385.patch b/SOURCES/openssh-9.6p1-CVE-2023-51385.patch deleted file mode 100644 index a7e6a32..0000000 --- a/SOURCES/openssh-9.6p1-CVE-2023-51385.patch +++ /dev/null @@ -1,57 +0,0 @@ -diff --git a/ssh.c b/ssh.c -index 35c48e62..48d93ddf 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -626,6 +626,41 @@ ssh_conn_info_free(struct ssh_conn_info *cinfo) - } - } - -+static int -+valid_hostname(const char *s) -+{ -+ size_t i; -+ -+ if (*s == '-') -+ return 0; -+ for (i = 0; s[i] != 0; i++) { -+ if (strchr("'`\"$\\;&<>|(){}", s[i]) != NULL || -+ isspace((u_char)s[i]) || iscntrl((u_char)s[i])) -+ return 0; -+ } -+ return 1; -+} -+ -+static int -+valid_ruser(const char *s) -+{ -+ size_t i; -+ -+ if (*s == '-') -+ return 0; -+ for (i = 0; s[i] != 0; i++) { -+ if (strchr("'`\";&<>|(){}", s[i]) != NULL) -+ return 0; -+ /* Disallow '-' after whitespace */ -+ if (isspace((u_char)s[i]) && s[i + 1] == '-') -+ return 0; -+ /* Disallow \ in last position */ -+ if (s[i] == '\\' && s[i + 1] == '\0') -+ return 0; -+ } -+ return 1; -+} -+ - /* - * Main program for the ssh client. - */ -@@ -1118,6 +1153,10 @@ main(int ac, char **av) - if (!host) - usage(); - -+ if (!valid_hostname(host)) -+ fatal("hostname contains invalid characters"); -+ if (options.user != NULL && !valid_ruser(options.user)) -+ fatal("remote username contains invalid characters"); - host_arg = xstrdup(host); - - /* Initialize the command to execute on remote host. */ diff --git a/SOURCES/pam_ssh_agent-rmheaders b/SOURCES/pam_ssh_agent-rmheaders deleted file mode 100644 index 06d899d..0000000 --- a/SOURCES/pam_ssh_agent-rmheaders +++ /dev/null @@ -1,37 +0,0 @@ -authfd.c -authfd.h -atomicio.c -atomicio.h -bufaux.c -bufbn.c -buffer.h -buffer.c -cleanup.c -cipher.h -compat.h -defines.h -entropy.c -entropy.h -fatal.c -includes.h -kex.h -key.c -key.h -log.c -log.h -match.h -misc.c -misc.h -pathnames.h -platform.h -rsa.h -ssh-dss.c -ssh-rsa.c -ssh.h -ssh2.h -uidswap.c -uidswap.h -uuencode.c -uuencode.h -xmalloc.c -xmalloc.h diff --git a/SOURCES/pam_ssh_agent_auth-0.10.2-compat.patch b/SOURCES/pam_ssh_agent_auth-0.10.2-compat.patch deleted file mode 100644 index 6352bfa..0000000 --- a/SOURCES/pam_ssh_agent_auth-0.10.2-compat.patch +++ /dev/null @@ -1,939 +0,0 @@ -diff -up openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c ---- openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c 2018-08-24 10:22:56.281930322 +0200 -@@ -27,6 +27,7 @@ - * or implied, of Jamie Beverly. - */ - -+#include - #include - #include - #include -@@ -65,8 +66,8 @@ proc_pid_cmdline(char *** inargv) - case EOF: - case '\0': - if (len > 0) { -- argv = pamsshagentauth_xrealloc(argv, count + 1, sizeof(*argv)); -- argv[count] = pamsshagentauth_xcalloc(len + 1, sizeof(*argv[count])); -+ argv = xreallocarray(argv, count + 1, sizeof(*argv)); -+ argv[count] = xcalloc(len + 1, sizeof(*argv[count])); - strncpy(argv[count++], argbuf, len); - memset(argbuf, '\0', MAX_LEN_PER_CMDLINE_ARG + 1); - len = 0; -@@ -105,9 +106,9 @@ pamsshagentauth_free_command_line(char * - { - size_t i; - for (i = 0; i < n_args; i++) -- pamsshagentauth_xfree(argv[i]); -+ free(argv[i]); - -- pamsshagentauth_xfree(argv); -+ free(argv); - return; - } - -diff -up openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/identity.h ---- openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/identity.h 2018-08-24 10:18:05.009393312 +0200 -@@ -30,8 +30,8 @@ - #include "openbsd-compat/sys-queue.h" - #include "xmalloc.h" - #include "log.h" --#include "buffer.h" --#include "key.h" -+#include "sshbuf.h" -+#include "sshkey.h" - #include "authfd.h" - #include - -@@ -41,7 +41,7 @@ typedef struct idlist Idlist; - struct identity { - TAILQ_ENTRY(identity) next; - AuthenticationConnection *ac; /* set if agent supports key */ -- Key *key; /* public/private key */ -+ struct sshkey *key; /* public/private key */ - char *filename; /* comment for agent-only keys */ - int tried; - int isprivate; /* key points to the private key */ -diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c ---- openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat 2018-08-24 10:18:05.007393297 +0200 -+++ openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2018-08-24 10:18:32.937612513 +0200 -@@ -36,8 +36,8 @@ - #include "openbsd-compat/sys-queue.h" - #include "xmalloc.h" - #include "log.h" --#include "buffer.h" --#include "key.h" -+#include "sshbuf.h" -+#include "sshkey.h" - #include "authfd.h" - #include - #include -@@ -58,6 +58,8 @@ - #include "get_command_line.h" - extern char **environ; - -+#define PAM_SSH_AGENT_AUTH_REQUESTv1 101 -+ - /* - * Added by Jamie Beverly, ensure socket fd points to a socket owned by the user - * A cursory check is done, but to avoid race conditions, it is necessary -@@ -77,7 +79,7 @@ log_action(char ** action, size_t count) - if (count == 0) - return NULL; - -- buf = pamsshagentauth_xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf)); -+ buf = xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf)); - for (i = 0; i < count; i++) { - strcat(buf, (i > 0) ? " '" : "'"); - strncat(buf, action[i], MAX_LEN_PER_CMDLINE_ARG); -@@ -87,21 +89,25 @@ log_action(char ** action, size_t count) - } - - void --agent_action(Buffer *buf, char ** action, size_t count) -+agent_action(struct sshbuf **buf, char ** action, size_t count) - { - size_t i; -- pamsshagentauth_buffer_init(buf); -+ int r; - -- pamsshagentauth_buffer_put_int(buf, count); -+ if ((*buf = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); -+ if ((r = sshbuf_put_u32(*buf, count)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - - for (i = 0; i < count; i++) { -- pamsshagentauth_buffer_put_cstring(buf, action[i]); -+ if ((r = sshbuf_put_cstring(*buf, action[i])) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - } - } - - --void --pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user, -+static void -+pamsshagentauth_session_id2_gen(struct sshbuf ** session_id2, const char * user, - const char * ruser, const char * servicename) - { - u_char *cookie = NULL; -@@ -114,22 +116,23 @@ pamsshagentauth_session_id2_gen(Buffer * - char ** reported_argv = NULL; - size_t count = 0; - char * action_logbuf = NULL; -- Buffer action_agentbuf; -+ struct sshbuf *action_agentbuf = NULL; - uint8_t free_logbuf = 0; - char * retc; - int32_t reti; -+ int r; - -- rnd = pamsshagentauth_arc4random(); -+ rnd = arc4random(); - cookie_len = ((uint8_t) rnd); - while (cookie_len < 16) { - cookie_len += 16; /* Add 16 bytes to the size to ensure that while the length is random, the length is always reasonable; ticket #18 */ - } - -- cookie = pamsshagentauth_xcalloc(1,cookie_len); -+ cookie = xcalloc(1, cookie_len); - - for (i = 0; i < cookie_len; i++) { - if (i % 4 == 0) { -- rnd = pamsshagentauth_arc4random(); -+ rnd = arc4random(); - } - cookie[i] = (u_char) rnd; - rnd >>= 8; -@@ -139,12 +141,13 @@ pamsshagentauth_session_id2_gen(Buffer * - if (count > 0) { - free_logbuf = 1; - action_logbuf = log_action(reported_argv, count); -- agent_action(&action_agentbuf, reported_argv, count); -+ agent_action(&action_agentbuf, reported_argv, count); - pamsshagentauth_free_command_line(reported_argv, count); - } - else { - action_logbuf = "unknown on this platform"; -- pamsshagentauth_buffer_init(&action_agentbuf); /* stays empty, means unavailable */ -+ if ((action_agentbuf = sshbuf_new()) == NULL) /* stays empty, means unavailable */ -+ fatal("%s: sshbuf_new failed", __func__); - } - - /* -@@ -161,35 +163,39 @@ pamsshagentauth_session_id2_gen(Buffer * - retc = getcwd(pwd, sizeof(pwd) - 1); - time(&ts); - -- pamsshagentauth_buffer_init(session_id2); -+ if ((*session_id2 = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); - -- pamsshagentauth_buffer_put_int(session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1); -- /* pamsshagentauth_debug3("cookie: %s", pamsshagentauth_tohex(cookie, cookie_len)); */ -- pamsshagentauth_buffer_put_string(session_id2, cookie, cookie_len); -- /* pamsshagentauth_debug3("user: %s", user); */ -- pamsshagentauth_buffer_put_cstring(session_id2, user); -- /* pamsshagentauth_debug3("ruser: %s", ruser); */ -- pamsshagentauth_buffer_put_cstring(session_id2, ruser); -- /* pamsshagentauth_debug3("servicename: %s", servicename); */ -- pamsshagentauth_buffer_put_cstring(session_id2, servicename); -- /* pamsshagentauth_debug3("pwd: %s", pwd); */ -- if(retc) -- pamsshagentauth_buffer_put_cstring(session_id2, pwd); -- else -- pamsshagentauth_buffer_put_cstring(session_id2, ""); -- /* pamsshagentauth_debug3("action: %s", action_logbuf); */ -- pamsshagentauth_buffer_put_string(session_id2, action_agentbuf.buf + action_agentbuf.offset, action_agentbuf.end - action_agentbuf.offset); -+ if ((r = sshbuf_put_u32(*session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1)) != 0 || -+ (r = sshbuf_put_string(*session_id2, cookie, cookie_len)) != 0 || -+ (r = sshbuf_put_cstring(*session_id2, user)) != 0 || -+ (r = sshbuf_put_cstring(*session_id2, ruser)) != 0 || -+ (r = sshbuf_put_cstring(*session_id2, servicename)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ if (retc) { -+ if ((r = sshbuf_put_cstring(*session_id2, pwd)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } else { -+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } -+ if ((r = sshbuf_put_stringb(*session_id2, action_agentbuf)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (free_logbuf) { -- pamsshagentauth_xfree(action_logbuf); -- pamsshagentauth_buffer_free(&action_agentbuf); -+ free(action_logbuf); -+ sshbuf_free(action_agentbuf); - } -- /* pamsshagentauth_debug3("hostname: %s", hostname); */ -- if(reti >= 0) -- pamsshagentauth_buffer_put_cstring(session_id2, hostname); -- else -- pamsshagentauth_buffer_put_cstring(session_id2, ""); -- /* pamsshagentauth_debug3("ts: %ld", ts); */ -- pamsshagentauth_buffer_put_int64(session_id2, (uint64_t) ts); -+ /* debug3("hostname: %s", hostname); */ -+ if (reti >= 0) { -+ if ((r = sshbuf_put_cstring(*session_id2, hostname)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } else { -+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } -+ /* debug3("ts: %ld", ts); */ -+ if ((r = sshbuf_put_u64(*session_id2, (uint64_t) ts)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - - free(cookie); - return; -@@ -278,7 +280,8 @@ ssh_get_authentication_connection_for_ui - - auth = xmalloc(sizeof(*auth)); - auth->fd = sock; -- buffer_init(&auth->identities); -+ if ((auth->identities = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); - auth->howmany = 0; - - return auth; -@@ -287,43 +289,42 @@ ssh_get_authentication_connection_for_ui - int - pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename) - { -- Buffer session_id2 = { 0 }; -+ struct sshbuf *session_id2 = NULL; - Identity *id; -- Key *key; -+ struct sshkey *key; - AuthenticationConnection *ac; - char *comment; - uint8_t retval = 0; - uid_t uid = getpwnam(ruser)->pw_uid; - - OpenSSL_add_all_digests(); -- pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); -+ pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); - - if ((ac = ssh_get_authentication_connection_for_uid(uid))) { -- pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); -+ verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); - for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) - { - if(key != NULL) { -- id = pamsshagentauth_xcalloc(1, sizeof(*id)); -+ id = xcalloc(1, sizeof(*id)); - id->key = key; - id->filename = comment; - id->ac = ac; -- if(userauth_pubkey_from_id(ruser, id, &session_id2)) { -+ if(userauth_pubkey_from_id(ruser, id, session_id2)) { - retval = 1; - } -- pamsshagentauth_xfree(id->filename); -- pamsshagentauth_key_free(id->key); -- pamsshagentauth_xfree(id); -+ free(id->filename); -+ key_free(id->key); -+ free(id); - if(retval == 1) - break; - } - } -- pamsshagentauth_buffer_free(&session_id2); -+ sshbuf_free(session_id2); - ssh_close_authentication_connection(ac); - } - else { -- pamsshagentauth_verbose("No ssh-agent could be contacted"); -+ verbose("No ssh-agent could be contacted"); - } -- /* pamsshagentauth_xfree(session_id2); */ - EVP_cleanup(); - return retval; - } -diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c ---- openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c.psaa-compat 2018-08-24 10:18:05.008393305 +0200 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c 2018-08-24 10:18:05.009393312 +0200 -@@ -104,7 +104,7 @@ pam_sm_authenticate(pam_handle_t * pamh, - * a patch 8-) - */ - #if ! HAVE___PROGNAME || HAVE_BUNDLE -- __progname = pamsshagentauth_xstrdup(servicename); -+ __progname = xstrdup(servicename); - #endif - - for(i = argc, argv_ptr = (char **) argv; i > 0; ++argv_ptr, i--) { -@@ -130,11 +130,11 @@ pam_sm_authenticate(pam_handle_t * pamh, - #endif - } - -- pamsshagentauth_log_init(__progname, log_lvl, facility, getenv("PAM_SSH_AGENT_AUTH_DEBUG") ? 1 : 0); -+ log_init(__progname, log_lvl, facility, getenv("PAM_SSH_AGENT_AUTH_DEBUG") ? 1 : 0); - pam_get_item(pamh, PAM_USER, (void *) &user); - pam_get_item(pamh, PAM_RUSER, (void *) &ruser_ptr); - -- pamsshagentauth_verbose("Beginning pam_ssh_agent_auth for user %s", user); -+ verbose("Beginning pam_ssh_agent_auth for user %s", user); - - if(ruser_ptr) { - strncpy(ruser, ruser_ptr, sizeof(ruser) - 1); -@@ -149,12 +149,12 @@ pam_sm_authenticate(pam_handle_t * pamh, - #ifdef ENABLE_SUDO_HACK - if( (strlen(sudo_service_name) > 0) && strncasecmp(servicename, sudo_service_name, sizeof(sudo_service_name) - 1) == 0 && getenv("SUDO_USER") ) { - strncpy(ruser, getenv("SUDO_USER"), sizeof(ruser) - 1 ); -- pamsshagentauth_verbose( "Using environment variable SUDO_USER (%s)", ruser ); -+ verbose( "Using environment variable SUDO_USER (%s)", ruser ); - } else - #endif - { - if( ! getpwuid(getuid()) ) { -- pamsshagentauth_verbose("Unable to getpwuid(getuid())"); -+ verbose("Unable to getpwuid(getuid())"); - goto cleanexit; - } - strncpy(ruser, getpwuid(getuid())->pw_name, sizeof(ruser) - 1); -@@ -163,11 +163,11 @@ pam_sm_authenticate(pam_handle_t * pamh, - - /* Might as well explicitely confirm the user exists here */ - if(! getpwnam(ruser) ) { -- pamsshagentauth_verbose("getpwnam(%s) failed, bailing out", ruser); -+ verbose("getpwnam(%s) failed, bailing out", ruser); - goto cleanexit; - } - if( ! getpwnam(user) ) { -- pamsshagentauth_verbose("getpwnam(%s) failed, bailing out", user); -+ verbose("getpwnam(%s) failed, bailing out", user); - goto cleanexit; - } - -@@ -177,8 +177,8 @@ pam_sm_authenticate(pam_handle_t * pamh, - */ - parse_authorized_key_file(user, authorized_keys_file_input); - } else { -- pamsshagentauth_verbose("Using default file=/etc/security/authorized_keys"); -- authorized_keys_file = pamsshagentauth_xstrdup("/etc/security/authorized_keys"); -+ verbose("Using default file=/etc/security/authorized_keys"); -+ authorized_keys_file = xstrdup("/etc/security/authorized_keys"); - } - - /* -@@ -187,19 +187,19 @@ pam_sm_authenticate(pam_handle_t * pamh, - */ - - if(user && strlen(ruser) > 0) { -- pamsshagentauth_verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file); -+ verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file); - - /* - * this pw_uid is used to validate the SSH_AUTH_SOCK, and so must be the uid of the ruser invoking the program, not the target-user - */ - if(pamsshagentauth_find_authorized_keys(user, ruser, servicename)) { /* getpwnam(ruser)->pw_uid)) { */ -- pamsshagentauth_logit("Authenticated: `%s' as `%s' using %s", ruser, user, authorized_keys_file); -+ logit("Authenticated: `%s' as `%s' using %s", ruser, user, authorized_keys_file); - retval = PAM_SUCCESS; - } else { -- pamsshagentauth_logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file); -+ logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file); - } - } else { -- pamsshagentauth_logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" ); -+ logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" ); - } - - cleanexit: -diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c ---- openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c 2018-08-24 10:18:05.009393312 +0200 -@@ -66,8 +66,8 @@ - #include "xmalloc.h" - #include "match.h" - #include "log.h" --#include "buffer.h" --#include "key.h" -+#include "sshbuf.h" -+#include "sshkey.h" - #include "misc.h" - - #include "xmalloc.h" -@@ -77,7 +77,6 @@ - #include "pathnames.h" - #include "secure_filename.h" - --#include "identity.h" - #include "pam_user_key_allowed2.h" - - extern char *authorized_keys_file; -@@ -117,12 +116,12 @@ parse_authorized_key_file(const char *us - } else { - slash_ptr = strchr(auth_keys_file_buf, '/'); - if(!slash_ptr) -- pamsshagentauth_fatal -+ fatal - ("cannot expand tilde in path without a `/'"); - - owner_uname_len = slash_ptr - auth_keys_file_buf - 1; - if(owner_uname_len > (sizeof(owner_uname) - 1)) -- pamsshagentauth_fatal("Username too long"); -+ fatal("Username too long"); - - strncat(owner_uname, auth_keys_file_buf + 1, owner_uname_len); - if(!authorized_keys_file_allowed_owner_uid) -@@ -130,11 +129,11 @@ parse_authorized_key_file(const char *us - getpwnam(owner_uname)->pw_uid; - } - authorized_keys_file = -- pamsshagentauth_tilde_expand_filename(auth_keys_file_buf, -+ tilde_expand_filename(auth_keys_file_buf, - authorized_keys_file_allowed_owner_uid); - strncpy(auth_keys_file_buf, authorized_keys_file, - sizeof(auth_keys_file_buf) - 1); -- pamsshagentauth_xfree(authorized_keys_file) /* when we -+ free(authorized_keys_file) /* when we - percent_expand - later, we'd step - on this, so free -@@ -150,13 +149,13 @@ parse_authorized_key_file(const char *us - strncat(hostname, fqdn, strcspn(fqdn, ".")); - #endif - authorized_keys_file = -- pamsshagentauth_percent_expand(auth_keys_file_buf, "h", -+ percent_expand(auth_keys_file_buf, "h", - getpwnam(user)->pw_dir, "H", hostname, - "f", fqdn, "u", user, NULL); - } - - int --pam_user_key_allowed(const char *ruser, Key * key) -+pam_user_key_allowed(const char *ruser, struct sshkey * key) - { - return - pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), -diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h ---- openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h 2018-08-24 10:18:05.010393320 +0200 -@@ -32,7 +32,7 @@ - #define _PAM_USER_KEY_ALLOWED_H - - #include "identity.h" --int pam_user_key_allowed(const char *, Key *); -+int pam_user_key_allowed(const char *, struct sshkey *); - void parse_authorized_key_file(const char *, const char *); - - #endif -diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c ---- openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c 2018-08-24 10:18:05.010393320 +0200 -@@ -45,44 +45,46 @@ - #include "xmalloc.h" - #include "ssh.h" - #include "ssh2.h" --#include "buffer.h" -+#include "sshbuf.h" - #include "log.h" - #include "compat.h" --#include "key.h" -+#include "digest.h" -+#include "sshkey.h" - #include "pathnames.h" - #include "misc.h" - #include "secure_filename.h" - #include "uidswap.h" -- --#include "identity.h" -+#include - - /* return 1 if user allows given key */ - /* Modified slightly from original found in auth2-pubkey.c */ - static int --pamsshagentauth_check_authkeys_file(FILE * f, char *file, Key * key) -+pamsshagentauth_check_authkeys_file(FILE * f, char *file, struct sshkey * key) - { -- char line[SSH_MAX_PUBKEY_BYTES]; -+ char *line = NULL; - int found_key = 0; - u_long linenum = 0; -- Key *found; -+ struct sshkey *found; - char *fp; -+ size_t linesize = 0; - - found_key = 0; -- found = pamsshagentauth_key_new(key->type); -+ found = sshkey_new(key->type); - -- while(read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { -+ while ((getline(&line, &linesize, f)) != -1) { - char *cp = NULL; /* *key_options = NULL; */ - -+ linenum++; - /* Skip leading whitespace, empty and comment lines. */ - for(cp = line; *cp == ' ' || *cp == '\t'; cp++); - if(!*cp || *cp == '\n' || *cp == '#') - continue; - -- if(pamsshagentauth_key_read(found, &cp) != 1) { -+ if (sshkey_read(found, &cp) != 0) { - /* no key? check if there are options for this key */ - int quoted = 0; - -- pamsshagentauth_verbose("user_key_allowed: check options: '%s'", cp); -+ verbose("user_key_allowed: check options: '%s'", cp); - /* key_options = cp; */ - for(; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { - if(*cp == '\\' && cp[1] == '"') -@@ -92,26 +94,27 @@ pamsshagentauth_check_authkeys_file(FILE - } - /* Skip remaining whitespace. */ - for(; *cp == ' ' || *cp == '\t'; cp++); -- if(pamsshagentauth_key_read(found, &cp) != 1) { -- pamsshagentauth_verbose("user_key_allowed: advance: '%s'", cp); -+ if(sshkey_read(found, &cp) != 0) { -+ verbose("user_key_allowed: advance: '%s'", cp); - /* still no key? advance to next line */ - continue; - } - } -- if(pamsshagentauth_key_equal(found, key)) { -+ if(sshkey_equal(found, key)) { - found_key = 1; -- pamsshagentauth_logit("matching key found: file/command %s, line %lu", file, -+ logit("matching key found: file/command %s, line %lu", file, - linenum); -- fp = pamsshagentauth_key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); -- pamsshagentauth_logit("Found matching %s key: %s", -- pamsshagentauth_key_type(found), fp); -- pamsshagentauth_xfree(fp); -+ fp = sshkey_fingerprint(found, SSH_DIGEST_SHA256, SSH_FP_BASE64); -+ logit("Found matching %s key: %s", -+ sshkey_type(found), fp); -+ free(fp); - break; - } - } -- pamsshagentauth_key_free(found); -+ free(line); -+ sshkey_free(found); - if(!found_key) -- pamsshagentauth_verbose("key not found"); -+ verbose("key not found"); - return found_key; - } - -@@ -120,19 +123,19 @@ pamsshagentauth_check_authkeys_file(FILE - * returns 1 if the key is allowed or 0 otherwise. - */ - int --pamsshagentauth_user_key_allowed2(struct passwd *pw, Key * key, char *file) -+pamsshagentauth_user_key_allowed2(struct passwd *pw, struct sshkey * key, char *file) - { - FILE *f; - int found_key = 0; - struct stat st; -- char buf[SSH_MAX_PUBKEY_BYTES]; -+ char buf[256]; - - /* Temporarily use the user's uid. */ -- pamsshagentauth_verbose("trying public key file %s", file); -+ verbose("trying public key file %s", file); - - /* Fail not so quietly if file does not exist */ - if(stat(file, &st) < 0) { -- pamsshagentauth_verbose("File not found: %s", file); -+ verbose("File not found: %s", file); - return 0; - } - -@@ -144,7 +147,7 @@ pamsshagentauth_user_key_allowed2(struct - - if(pamsshagentauth_secure_filename(f, file, pw, buf, sizeof(buf)) != 0) { - fclose(f); -- pamsshagentauth_logit("Authentication refused: %s", buf); -+ logit("Authentication refused: %s", buf); - return 0; - } - -@@ -160,7 +163,7 @@ pamsshagentauth_user_key_allowed2(struct - int - pamsshagentauth_user_key_command_allowed2(char *authorized_keys_command, - char *authorized_keys_command_user, -- struct passwd *user_pw, Key * key) -+ struct passwd *user_pw, struct sshkey * key) - { - FILE *f; - int ok, found_key = 0; -@@ -187,44 +190,44 @@ pamsshagentauth_user_key_command_allowed - else { - pw = getpwnam(authorized_keys_command_user); - if(pw == NULL) { -- pamsshagentauth_logerror("authorized_keys_command_user \"%s\" not found: %s", -+ error("authorized_keys_command_user \"%s\" not found: %s", - authorized_keys_command_user, strerror(errno)); - return 0; - } - } - -- pamsshagentauth_temporarily_use_uid(pw); -+ temporarily_use_uid(pw); - - if(stat(authorized_keys_command, &st) < 0) { -- pamsshagentauth_logerror -+ error - ("Could not stat AuthorizedKeysCommand \"%s\": %s", - authorized_keys_command, strerror(errno)); - goto out; - } - if(pamsshagentauth_auth_secure_path - (authorized_keys_command, &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { -- pamsshagentauth_logerror("Unsafe AuthorizedKeysCommand: %s", errmsg); -+ error("Unsafe AuthorizedKeysCommand: %s", errmsg); - goto out; - } - - /* open the pipe and read the keys */ - if(pipe(p) != 0) { -- pamsshagentauth_logerror("%s: pipe: %s", __func__, strerror(errno)); -+ error("%s: pipe: %s", __func__, strerror(errno)); - goto out; - } - -- pamsshagentauth_debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"", -+ debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"", - authorized_keys_command, pw->pw_name, username); - - /* - * Don't want to call this in the child, where it can fatal() and - * run cleanup_exit() code. - */ -- pamsshagentauth_restore_uid(); -+ restore_uid(); - - switch ((pid = fork())) { - case -1: /* error */ -- pamsshagentauth_logerror("%s: fork: %s", __func__, strerror(errno)); -+ error("%s: fork: %s", __func__, strerror(errno)); - close(p[0]); - close(p[1]); - return 0; -@@ -234,13 +237,13 @@ pamsshagentauth_user_key_command_allowed - - /* do this before the setresuid so thta they can be logged */ - if((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { -- pamsshagentauth_logerror("%s: open %s: %s", __func__, _PATH_DEVNULL, -+ error("%s: open %s: %s", __func__, _PATH_DEVNULL, - strerror(errno)); - _exit(1); - } - if(dup2(devnull, STDIN_FILENO) == -1 || dup2(p[1], STDOUT_FILENO) == -1 - || dup2(devnull, STDERR_FILENO) == -1) { -- pamsshagentauth_logerror("%s: dup2: %s", __func__, strerror(errno)); -+ error("%s: dup2: %s", __func__, strerror(errno)); - _exit(1); - } - #if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID) -@@ -248,7 +251,7 @@ pamsshagentauth_user_key_command_allowed - #else - if (setgid(pw->pw_gid) != 0 || setegid(pw->pw_gid) != 0) { - #endif -- pamsshagentauth_logerror("setresgid %u: %s", (u_int) pw->pw_gid, -+ error("setresgid %u: %s", (u_int) pw->pw_gid, - strerror(errno)); - _exit(1); - } -@@ -258,7 +261,7 @@ pamsshagentauth_user_key_command_allowed - #else - if (setuid(pw->pw_uid) != 0 || seteuid(pw->pw_uid) != 0) { - #endif -- pamsshagentauth_logerror("setresuid %u: %s", (u_int) pw->pw_uid, -+ error("setresuid %u: %s", (u_int) pw->pw_uid, - strerror(errno)); - _exit(1); - } -@@ -270,18 +273,18 @@ pamsshagentauth_user_key_command_allowed - - /* pretty sure this will barf because we are now suid, but since we - should't reach this anyway, I'll leave it here */ -- pamsshagentauth_logerror("AuthorizedKeysCommand %s exec failed: %s", -+ error("AuthorizedKeysCommand %s exec failed: %s", - authorized_keys_command, strerror(errno)); - _exit(127); - default: /* parent */ - break; - } - -- pamsshagentauth_temporarily_use_uid(pw); -+ temporarily_use_uid(pw); - - close(p[1]); - if((f = fdopen(p[0], "r")) == NULL) { -- pamsshagentauth_logerror("%s: fdopen: %s", __func__, strerror(errno)); -+ error("%s: fdopen: %s", __func__, strerror(errno)); - close(p[0]); - /* Don't leave zombie child */ - while(waitpid(pid, NULL, 0) == -1 && errno == EINTR); -@@ -292,22 +295,22 @@ pamsshagentauth_user_key_command_allowed - - while(waitpid(pid, &status, 0) == -1) { - if(errno != EINTR) { -- pamsshagentauth_logerror("%s: waitpid: %s", __func__, -+ error("%s: waitpid: %s", __func__, - strerror(errno)); - goto out; - } - } - if(WIFSIGNALED(status)) { -- pamsshagentauth_logerror("AuthorizedKeysCommand %s exited on signal %d", -+ error("AuthorizedKeysCommand %s exited on signal %d", - authorized_keys_command, WTERMSIG(status)); - goto out; - } else if(WEXITSTATUS(status) != 0) { -- pamsshagentauth_logerror("AuthorizedKeysCommand %s returned status %d", -+ error("AuthorizedKeysCommand %s returned status %d", - authorized_keys_command, WEXITSTATUS(status)); - goto out; - } - found_key = ok; - out: -- pamsshagentauth_restore_uid(); -+ restore_uid(); - return found_key; - } -diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h ---- openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h 2018-08-24 10:18:05.010393320 +0200 -@@ -32,7 +32,7 @@ - #define _PAM_USER_KEY_ALLOWED_H - - #include "identity.h" --int pamsshagentauth_user_key_allowed2(struct passwd *, Key *, char *); --int pamsshagentauth_user_key_command_allowed2(char *, char *, struct passwd *, Key *); -+int pamsshagentauth_user_key_allowed2(struct passwd *, struct sshkey *, char *); -+int pamsshagentauth_user_key_command_allowed2(char *, char *, struct passwd *, struct sshkey *); - - #endif -diff -up openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c ---- openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c 2018-08-24 10:18:05.010393320 +0200 -@@ -53,8 +53,8 @@ - #include "xmalloc.h" - #include "match.h" - #include "log.h" --#include "buffer.h" --#include "key.h" -+#include "sshbuf.h" -+#include "sshkey.h" - #include "misc.h" - - -@@ -80,7 +80,7 @@ pamsshagentauth_auth_secure_path(const c - int comparehome = 0; - struct stat st; - -- pamsshagentauth_verbose("auth_secure_filename: checking for uid: %u", uid); -+ verbose("auth_secure_filename: checking for uid: %u", uid); - - if (realpath(name, buf) == NULL) { - snprintf(err, errlen, "realpath %s failed: %s", name, -@@ -115,9 +115,9 @@ pamsshagentauth_auth_secure_path(const c - snprintf(err, errlen, "dirname() failed"); - return -1; - } -- pamsshagentauth_strlcpy(buf, cp, sizeof(buf)); -+ strlcpy(buf, cp, sizeof(buf)); - -- pamsshagentauth_verbose("secure_filename: checking '%s'", buf); -+ verbose("secure_filename: checking '%s'", buf); - if (stat(buf, &st) < 0 || - (st.st_uid != 0 && st.st_uid != uid) || - (st.st_mode & 022) != 0) { -@@ -128,7 +128,7 @@ pamsshagentauth_auth_secure_path(const c - - /* If are passed the homedir then we can stop */ - if (comparehome && strcmp(homedir, buf) == 0) { -- pamsshagentauth_verbose("secure_filename: terminating check at '%s'", -+ verbose("secure_filename: terminating check at '%s'", - buf); - break; - } -diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c ---- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c 2018-08-24 10:22:13.202657025 +0200 -@@ -37,10 +37,11 @@ - #include "xmalloc.h" - #include "ssh.h" - #include "ssh2.h" --#include "buffer.h" -+#include "sshbuf.h" - #include "log.h" - #include "compat.h" --#include "key.h" -+#include "sshkey.h" -+#include "ssherr.h" - #include "pathnames.h" - #include "misc.h" - #include "secure_filename.h" -@@ -48,54 +48,59 @@ - #include "identity.h" - #include "pam_user_authorized_keys.h" - -+#define SSH2_MSG_USERAUTH_TRUST_REQUEST 54 -+ - /* extern u_char *session_id2; - extern uint8_t session_id_len; - */ - - int --userauth_pubkey_from_id(const char *ruser, Identity * id, Buffer * session_id2) -+userauth_pubkey_from_id(const char *ruser, Identity * id, struct sshbuf * session_id2) - { -- Buffer b = { 0 }; -+ struct sshbuf *b = NULL; - char *pkalg = NULL; - u_char *pkblob = NULL, *sig = NULL; -- u_int blen = 0, slen = 0; -+ size_t blen = 0, slen = 0; -- int authenticated = 0; -+ int r, authenticated = 0; - -- pkalg = (char *) key_ssh_name(id->key); -+ pkalg = (char *) sshkey_ssh_name(id->key); - - /* first test if this key is even allowed */ - if(! pam_user_key_allowed(ruser, id->key)) -- goto user_auth_clean_exit; -+ goto user_auth_clean_exit_without_buffer; - -- if(pamsshagentauth_key_to_blob(id->key, &pkblob, &blen) == 0) -- goto user_auth_clean_exit; -+ if(sshkey_to_blob(id->key, &pkblob, &blen) != 0) -+ goto user_auth_clean_exit_without_buffer; - - /* construct packet to sign and test */ -- pamsshagentauth_buffer_init(&b); -+ if ((b = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); - -- pamsshagentauth_buffer_put_string(&b, session_id2->buf + session_id2->offset, session_id2->end - session_id2->offset); -- pamsshagentauth_buffer_put_char(&b, SSH2_MSG_USERAUTH_TRUST_REQUEST); -- pamsshagentauth_buffer_put_cstring(&b, ruser); -- pamsshagentauth_buffer_put_cstring(&b, "pam_ssh_agent_auth"); -- pamsshagentauth_buffer_put_cstring(&b, "publickey"); -- pamsshagentauth_buffer_put_char(&b, 1); -- pamsshagentauth_buffer_put_cstring(&b, pkalg); -- pamsshagentauth_buffer_put_string(&b, pkblob, blen); -+ if ((r = sshbuf_put_string(b, sshbuf_ptr(session_id2), sshbuf_len(session_id2))) != 0 || -+ (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_TRUST_REQUEST)) != 0 || -+ (r = sshbuf_put_cstring(b, ruser)) != 0 || -+ (r = sshbuf_put_cstring(b, "pam_ssh_agent_auth")) != 0 || -+ (r = sshbuf_put_cstring(b, "publickey")) != 0 || -+ (r = sshbuf_put_u8(b, 1)) != 0 || -+ (r = sshbuf_put_cstring(b, pkalg)) != 0 || -+ (r = sshbuf_put_string(b, pkblob, blen)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - -- if(ssh_agent_sign(id->ac, id->key, &sig, &slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) != 0) -+ if (ssh_agent_sign(id->ac, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b)) != 0) - goto user_auth_clean_exit; - - /* test for correct signature */ -- if(pamsshagentauth_key_verify(id->key, sig, slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) == 1) -+ if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) == 0) - authenticated = 1; - - user_auth_clean_exit: - /* if(&b != NULL) */ -- pamsshagentauth_buffer_free(&b); -+ sshbuf_free(b); -+ user_auth_clean_exit_without_buffer: - if(sig != NULL) -- pamsshagentauth_xfree(sig); -+ free(sig); - if(pkblob != NULL) -- pamsshagentauth_xfree(pkblob); -+ free(pkblob); - CRYPTO_cleanup_all_ex_data(); - return authenticated; - } -diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h ---- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h 2018-08-24 10:18:05.010393320 +0200 -@@ -31,7 +31,7 @@ - #ifndef _USERAUTH_PUBKEY_FROM_ID_H - #define _USERAUTH_PUBKEY_FROM_ID_H - --#include --int userauth_pubkey_from_id(const char *, Identity *, Buffer *); -+#include "identity.h" -+int userauth_pubkey_from_id(const char *, Identity *, struct sshbuf *); - - #endif -diff -up openssh/pam_ssh_agent_auth-0.10.3/uuencode.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/uuencode.c ---- openssh/pam_ssh_agent_auth-0.10.3/uuencode.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/uuencode.c 2018-08-24 10:18:05.010393320 +0200 -@@ -56,7 +56,7 @@ pamsshagentauth_uudecode(const char *src - /* and remove trailing whitespace because __b64_pton needs this */ - *p = '\0'; - len = pamsshagentauth___b64_pton(encoded, target, targsize); -- pamsshagentauth_xfree(encoded); -+ xfree(encoded); - return len; - } - -@@ -70,7 +70,7 @@ pamsshagentauth_dump_base64(FILE *fp, co - fprintf(fp, "dump_base64: len > 65536\n"); - return; - } -- buf = pamsshagentauth_xmalloc(2*len); -+ buf = malloc(2*len); - n = pamsshagentauth_uuencode(data, len, buf, 2*len); - for (i = 0; i < n; i++) { - fprintf(fp, "%c", buf[i]); -@@ -79,5 +79,5 @@ pamsshagentauth_dump_base64(FILE *fp, co - } - if (i % 70 != 69) - fprintf(fp, "\n"); -- pamsshagentauth_xfree(buf); -+ free(buf); - } diff --git a/SOURCES/pam_ssh_agent_auth-0.10.2-dereference.patch b/SOURCES/pam_ssh_agent_auth-0.10.2-dereference.patch deleted file mode 100644 index bf49c37..0000000 --- a/SOURCES/pam_ssh_agent_auth-0.10.2-dereference.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c b/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c ---- a/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c -+++ b/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c -@@ -158,11 +158,12 @@ parse_authorized_key_file(const char *user, - int - pam_user_key_allowed(const char *ruser, struct sshkey * key) - { -+ struct passwd *pw; - return -- pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), -- key, authorized_keys_file) -- || pamsshagentauth_user_key_allowed2(getpwuid(0), key, -- authorized_keys_file) -+ ( (pw = getpwuid(authorized_keys_file_allowed_owner_uid)) && -+ pamsshagentauth_user_key_allowed2(pw, key, authorized_keys_file)) -+ || ((pw = getpwuid(0)) && -+ pamsshagentauth_user_key_allowed2(pw, key, authorized_keys_file)) - || pamsshagentauth_user_key_command_allowed2(authorized_keys_command, - authorized_keys_command_user, - getpwnam(ruser), key); diff --git a/SOURCES/pam_ssh_agent_auth-0.10.3-seteuid.patch b/SOURCES/pam_ssh_agent_auth-0.10.3-seteuid.patch deleted file mode 100644 index be1f8e5..0000000 --- a/SOURCES/pam_ssh_agent_auth-0.10.3-seteuid.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-seteuid openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c ---- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-seteuid 2017-02-07 15:41:53.172334151 +0100 -+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-02-07 15:41:53.174334149 +0100 -@@ -238,17 +238,26 @@ ssh_get_authentication_socket_for_uid(ui - } - - errno = 0; -- seteuid(uid); /* To ensure a race condition is not used to circumvent the stat -- above, we will temporarily drop UID to the caller */ -- if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) { -+ /* To ensure a race condition is not used to circumvent the stat -+ above, we will temporarily drop UID to the caller */ -+ if (seteuid(uid) == -1) { - close(sock); -- if(errno == EACCES) -- fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid); -+ error("seteuid(%lu) failed with error: %s", -+ (unsigned long) uid, strerror(errno)); - return -1; - } -+ if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) { -+ close(sock); -+ sock = -1; -+ if(errno == EACCES) -+ fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid); -+ } - -- seteuid(0); /* we now continue the regularly scheduled programming */ -- -+ /* we now continue the regularly scheduled programming */ -+ if (0 != seteuid(0)) { -+ fatal("setuid(0) failed with error: %s", strerror(errno)); -+ return -1; -+ } - return sock; - } - diff --git a/SOURCES/pam_ssh_agent_auth-0.9.2-visibility.patch b/SOURCES/pam_ssh_agent_auth-0.9.2-visibility.patch deleted file mode 100644 index aea068d..0000000 --- a/SOURCES/pam_ssh_agent_auth-0.9.2-visibility.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visibility openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c ---- openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visibility 2014-03-31 19:35:17.000000000 +0200 -+++ openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c 2016-01-22 15:22:40.984469774 +0100 -@@ -72,7 +72,7 @@ char *__progname; - extern char *__progname; - #endif - --PAM_EXTERN int -+PAM_EXTERN int __attribute__ ((visibility ("default"))) - pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv) - { - char **argv_ptr; -@@ -214,7 +214,7 @@ cleanexit: - } - - --PAM_EXTERN int -+PAM_EXTERN int __attribute__ ((visibility ("default"))) - pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv) - { - UNUSED(pamh); diff --git a/SOURCES/pam_ssh_agent_auth-0.9.3-agent_structure.patch b/SOURCES/pam_ssh_agent_auth-0.9.3-agent_structure.patch deleted file mode 100644 index 1f2c02c..0000000 --- a/SOURCES/pam_ssh_agent_auth-0.9.3-agent_structure.patch +++ /dev/null @@ -1,96 +0,0 @@ -diff -up openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/identity.h ---- openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-agent 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/identity.h 2017-09-27 14:25:49.421739027 +0200 -@@ -38,6 +38,12 @@ - typedef struct identity Identity; - typedef struct idlist Idlist; - -+typedef struct { -+ int fd; -+ struct sshbuf *identities; -+ int howmany; -+} AuthenticationConnection; -+ - struct identity { - TAILQ_ENTRY(identity) next; - AuthenticationConnection *ac; /* set if agent supports key */ -diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c ---- openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-agent 2017-09-27 14:25:49.420739021 +0200 -+++ openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-09-27 14:25:49.421739027 +0200 -@@ -39,6 +39,7 @@ - #include "sshbuf.h" - #include "sshkey.h" - #include "authfd.h" -+#include "ssherr.h" - #include - #include - #include "ssh2.h" -@@ -291,36 +292,43 @@ pamsshagentauth_find_authorized_keys(con - { - struct sshbuf *session_id2 = NULL; - Identity *id; -- struct sshkey *key; - AuthenticationConnection *ac; -- char *comment; - uint8_t retval = 0; - uid_t uid = getpwnam(ruser)->pw_uid; -+ struct ssh_identitylist *idlist; -+ int r; -+ unsigned int i; - - OpenSSL_add_all_digests(); - pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); - - if ((ac = ssh_get_authentication_connection_for_uid(uid))) { - verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); -- for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) -- { -- if(key != NULL) { -+ if ((r = ssh_fetch_identitylist(ac->fd, &idlist)) != 0) { -+ if (r != SSH_ERR_AGENT_NO_IDENTITIES) -+ fprintf(stderr, "error fetching identities for " -+ "protocol %d: %s\n", 2, ssh_err(r)); -+ } else { -+ for (i = 0; i < idlist->nkeys; i++) -+ { -+ if (idlist->keys[i] != NULL) { - id = xcalloc(1, sizeof(*id)); -- id->key = key; -- id->filename = comment; -+ id->key = idlist->keys[i]; -+ id->filename = idlist->comments[i]; - id->ac = ac; - if(userauth_pubkey_from_id(ruser, id, session_id2)) { - retval = 1; - } -- free(id->filename); -- key_free(id->key); - free(id); - if(retval == 1) - break; -- } -- } -+ } -+ } -- sshbuf_free(session_id2); -- ssh_close_authentication_connection(ac); -+ sshbuf_free(session_id2); -+ ssh_free_identitylist(idlist); -+ } -+ ssh_close_authentication_socket(ac->fd); -+ free(ac); - } - else { - verbose("No ssh-agent could be contacted"); -diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c ---- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-agent 2017-09-27 14:25:49.420739021 +0200 -+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c 2017-09-27 14:25:49.422739032 +0200 -@@ -84,7 +85,7 @@ userauth_pubkey_from_id(const char *ruse - (r = sshbuf_put_string(b, pkblob, blen)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - -- if (ssh_agent_sign(id->ac, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b)) != 0) -+ if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0) - goto user_auth_clean_exit; - - /* test for correct signature */ diff --git a/SOURCES/pam_ssh_agent_auth-0.9.3-build.patch b/SOURCES/pam_ssh_agent_auth-0.9.3-build.patch deleted file mode 100644 index f269b97..0000000 --- a/SOURCES/pam_ssh_agent_auth-0.9.3-build.patch +++ /dev/null @@ -1,196 +0,0 @@ -diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c ---- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build 2016-11-13 04:24:32.000000000 +0100 -+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-02-07 14:29:41.626116675 +0100 -@@ -43,12 +43,31 @@ - #include - #include "ssh2.h" - #include "misc.h" -+#include "ssh.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include - - #include "userauth_pubkey_from_id.h" - #include "identity.h" - #include "get_command_line.h" - extern char **environ; - -+/* -+ * Added by Jamie Beverly, ensure socket fd points to a socket owned by the user -+ * A cursory check is done, but to avoid race conditions, it is necessary -+ * to drop effective UID when connecting to the socket. -+ * -+ * If the cause of error is EACCES, because we verified we would not have that -+ * problem initially, we can safely assume that somebody is attempting to find a -+ * race condition; so a more "direct" log message is generated. -+ */ -+ - static char * - log_action(char ** action, size_t count) - { -@@ -85,7 +104,7 @@ void - pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user, - const char * ruser, const char * servicename) - { -- char *cookie = NULL; -+ u_char *cookie = NULL; - uint8_t i = 0; - uint32_t rnd = 0; - uint8_t cookie_len; -@@ -112,7 +131,7 @@ pamsshagentauth_session_id2_gen(Buffer * - if (i % 4 == 0) { - rnd = pamsshagentauth_arc4random(); - } -- cookie[i] = (char) rnd; -+ cookie[i] = (u_char) rnd; - rnd >>= 8; - } - -@@ -177,6 +196,86 @@ pamsshagentauth_session_id2_gen(Buffer * - } - - int -+ssh_get_authentication_socket_for_uid(uid_t uid) -+{ -+ const char *authsocket; -+ int sock; -+ struct sockaddr_un sunaddr; -+ struct stat sock_st; -+ -+ authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); -+ if (!authsocket) -+ return -1; -+ -+ /* Advisory only; seteuid ensures no race condition; but will only log if we see EACCES */ -+ if( stat(authsocket,&sock_st) == 0) { -+ if(uid != 0 && sock_st.st_uid != uid) { -+ fatal("uid %lu attempted to open an agent socket owned by uid %lu", (unsigned long) uid, (unsigned long) sock_st.st_uid); -+ return -1; -+ } -+ } -+ -+ /* -+ * Ensures that the EACCES tested for below can _only_ happen if somebody -+ * is attempting to race the stat above to bypass authentication. -+ */ -+ if( (sock_st.st_mode & S_IWUSR) != S_IWUSR || (sock_st.st_mode & S_IRUSR) != S_IRUSR) { -+ error("ssh-agent socket has incorrect permissions for owner"); -+ return -1; -+ } -+ -+ sunaddr.sun_family = AF_UNIX; -+ strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); -+ -+ sock = socket(AF_UNIX, SOCK_STREAM, 0); -+ if (sock < 0) -+ return -1; -+ -+ /* close on exec */ -+ if (fcntl(sock, F_SETFD, 1) == -1) { -+ close(sock); -+ return -1; -+ } -+ -+ errno = 0; -+ seteuid(uid); /* To ensure a race condition is not used to circumvent the stat -+ above, we will temporarily drop UID to the caller */ -+ if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) { -+ close(sock); -+ if(errno == EACCES) -+ fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid); -+ return -1; -+ } -+ -+ seteuid(0); /* we now continue the regularly scheduled programming */ -+ -+ return sock; -+} -+ -+AuthenticationConnection * -+ssh_get_authentication_connection_for_uid(uid_t uid) -+{ -+ AuthenticationConnection *auth; -+ int sock; -+ -+ sock = ssh_get_authentication_socket_for_uid(uid); -+ -+ /* -+ * Fail if we couldn't obtain a connection. This happens if we -+ * exited due to a timeout. -+ */ -+ if (sock < 0) -+ return NULL; -+ -+ auth = xmalloc(sizeof(*auth)); -+ auth->fd = sock; -+ buffer_init(&auth->identities); -+ auth->howmany = 0; -+ -+ return auth; -+} -+ -+int - pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename) - { - Buffer session_id2 = { 0 }; -@@ -190,7 +289,7 @@ pamsshagentauth_find_authorized_keys(con - OpenSSL_add_all_digests(); - pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); - -- if ((ac = ssh_get_authentication_connection(uid))) { -+ if ((ac = ssh_get_authentication_connection_for_uid(uid))) { - pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); - for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) - { -diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in ---- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build 2016-11-13 04:24:32.000000000 +0100 -+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in 2017-02-07 14:40:14.407566921 +0100 -@@ -52,7 +52,7 @@ PATHS= - CC=@CC@ - LD=@LD@ - CFLAGS=@CFLAGS@ --CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ -+CPPFLAGS=-I.. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ - LIBS=@LIBS@ - AR=@AR@ - AWK=@AWK@ -@@ -61,7 +61,7 @@ INSTALL=@INSTALL@ - PERL=@PERL@ - SED=@SED@ - ENT=@ENT@ --LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ -+LDFLAGS=-L.. -L../openbsd-compat/ @LDFLAGS@ - LDFLAGS_SHARED = @LDFLAGS_SHARED@ - EXEEXT=@EXEEXT@ - -@@ -74,7 +74,7 @@ SSHOBJS=xmalloc.o atomicio.o authfd.o bu - - ED25519OBJS=ed25519-donna/ed25519.o - --PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o -+PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o secure_filename.o - - - MANPAGES_IN = pam_ssh_agent_auth.pod -@@ -94,13 +94,13 @@ $(PAM_MODULES): Makefile.in config.h - .c.o: - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ - --LIBCOMPAT=openbsd-compat/libopenbsd-compat.a -+LIBCOMPAT=../openbsd-compat/libopenbsd-compat.a - $(LIBCOMPAT): always - (cd openbsd-compat && $(MAKE)) - always: - --pam_ssh_agent_auth.so: $(LIBCOMPAT) $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o -- $(LD) $(LDFLAGS_SHARED) -o $@ $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lopenbsd-compat pam_ssh_agent_auth.o $(LIBS) -lpam -+pam_ssh_agent_auth.so: $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o ../uidswap.o -+ $(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat pam_ssh_agent_auth.o ../uidswap.o $(LIBS) -lpam - - $(MANPAGES): $(MANPAGES_IN) - pod2man --section=8 --release=v0.10.3 --name=pam_ssh_agent_auth --official --center "PAM" pam_ssh_agent_auth.pod > pam_ssh_agent_auth.8 diff --git a/SOURCES/sshd.tmpfiles b/SOURCES/sshd.tmpfiles deleted file mode 100644 index c35a2b8..0000000 --- a/SOURCES/sshd.tmpfiles +++ /dev/null @@ -1 +0,0 @@ -d /var/empty/sshd 711 root root - diff --git a/SOURCES/sshd@.service b/SOURCES/sshd@.service deleted file mode 100644 index 9b8e012..0000000 --- a/SOURCES/sshd@.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=OpenSSH per-connection server daemon -Documentation=man:sshd(8) man:sshd_config(5) -Wants=sshd-keygen.target -After=sshd-keygen.target - -[Service] -EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config -EnvironmentFile=-/etc/sysconfig/sshd -ExecStart=-/usr/sbin/sshd -i $OPTIONS $CRYPTO_POLICY -StandardInput=socket diff --git a/openssh-4.3p2-askpass-grab-info.patch b/openssh-4.3p2-askpass-grab-info.patch new file mode 100644 index 0000000..120ed1b --- /dev/null +++ b/openssh-4.3p2-askpass-grab-info.patch @@ -0,0 +1,18 @@ +diff -up openssh-8.6p1/contrib/gnome-ssh-askpass2.c.grab-info openssh-8.6p1/contrib/gnome-ssh-askpass2.c +--- openssh-8.6p1/contrib/gnome-ssh-askpass2.c.grab-info 2021-04-19 13:57:11.720113536 +0200 ++++ openssh-8.6p1/contrib/gnome-ssh-askpass2.c 2021-04-19 13:59:29.842163204 +0200 +@@ -70,8 +70,12 @@ report_failed_grab (GtkWidget *parent_wi + + err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, +- "Could not grab %s. A malicious client may be eavesdropping " +- "on your session.", what); ++ "SSH password dialog could not grab the %s input.\n" ++ "This might be caused by application such as screensaver, " ++ "however it could also mean that someone may be eavesdropping " ++ "on your session.\n" ++ "Either close the application which grabs the %s or " ++ "log out and log in again to prevent this from happening.", what, what); + gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); + + gtk_dialog_run(GTK_DIALOG(err)); diff --git a/openssh-5.1p1-askpass-progress.patch b/openssh-5.1p1-askpass-progress.patch new file mode 100644 index 0000000..ff609da --- /dev/null +++ b/openssh-5.1p1-askpass-progress.patch @@ -0,0 +1,83 @@ +diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contrib/gnome-ssh-askpass2.c +--- openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress 2016-12-19 05:59:41.000000000 +0100 ++++ openssh-7.4p1/contrib/gnome-ssh-askpass2.c 2016-12-23 13:31:16.545211926 +0100 +@@ -53,6 +53,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -81,14 +82,25 @@ ok_dialog(GtkWidget *entry, gpointer dia + return 1; + } + ++static void ++move_progress(GtkWidget *entry, gpointer progress) ++{ ++ gdouble step; ++ g_return_if_fail(GTK_IS_PROGRESS_BAR(progress)); ++ ++ step = g_random_double_range(0.03, 0.1); ++ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress), step); ++ gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress)); ++} ++ + static int + passphrase_dialog(char *message, int prompt_type) + { + const char *failed; + char *passphrase, *local; + int result, grab_tries, grab_server, grab_pointer; + int buttons, default_response; +- GtkWidget *parent_window, *dialog, *entry; ++ GtkWidget *parent_window, *dialog, *entry, *progress, *hbox; + GdkGrabStatus status; + GdkColor fg, bg; + int fg_set = 0, bg_set = 0; +@@ -104,14 +116,19 @@ passphrase_dialog(char *message) + gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg); + + if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) { ++ hbox = gtk_hbox_new(FALSE, 0); ++ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, ++ FALSE, 0); ++ gtk_widget_show(hbox); ++ + entry = gtk_entry_new(); + if (fg_set) + gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg); + if (bg_set) + gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg); + gtk_box_pack_start( +- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), +- entry, FALSE, FALSE, 0); ++ GTK_BOX(hbox), entry, TRUE, FALSE, 0); ++ gtk_entry_set_width_chars(GTK_ENTRY(entry), 2); + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); + gtk_widget_grab_focus(entry); + if (prompt_type == PROMPT_ENTRY) { +@@ -130,6 +145,22 @@ passphrase_dialog(char *message) + g_signal_connect(G_OBJECT(entry), "key_press_event", + G_CALLBACK(check_none), dialog); + } ++ ++ hbox = gtk_hbox_new(FALSE, 0); ++ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), ++ hbox, FALSE, FALSE, 8); ++ gtk_widget_show(hbox); ++ ++ progress = gtk_progress_bar_new(); ++ ++ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), ++ "Passphrase length hidden intentionally"); ++ gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE, ++ TRUE, 5); ++ gtk_widget_show(progress); ++ g_signal_connect(G_OBJECT(entry), "changed", ++ G_CALLBACK(move_progress), progress); ++ + } + + /* Grab focus */ diff --git a/SOURCES/openssh-5.8p2-sigpipe.patch b/openssh-5.8p2-sigpipe.patch similarity index 62% rename from SOURCES/openssh-5.8p2-sigpipe.patch rename to openssh-5.8p2-sigpipe.patch index 56af045..554e346 100644 --- a/SOURCES/openssh-5.8p2-sigpipe.patch +++ b/openssh-5.8p2-sigpipe.patch @@ -1,12 +1,14 @@ diff -up openssh-5.8p2/ssh-keyscan.c.sigpipe openssh-5.8p2/ssh-keyscan.c --- openssh-5.8p2/ssh-keyscan.c.sigpipe 2011-08-23 18:30:33.873025916 +0200 +++ openssh-5.8p2/ssh-keyscan.c 2011-08-23 18:32:24.574025362 +0200 -@@ -715,6 +715,8 @@ main(int argc, char **argv) +@@ -715,6 +715,9 @@ main(int argc, char **argv) + if (maxfd > fdlim_get(0)) fdlim_set(maxfd); fdcon = xcalloc(maxfd, sizeof(con)); - ++ + signal(SIGPIPE, SIG_IGN); + - read_wait_nfdset = howmany(maxfd, NFDBITS); - read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask)); + read_wait = xcalloc(maxfd, sizeof(struct pollfd)); + for (j = 0; j < maxfd; j++) + read_wait[j].fd = -1; diff --git a/SOURCES/openssh-5.9p1-ipv6man.patch b/openssh-5.9p1-ipv6man.patch similarity index 100% rename from SOURCES/openssh-5.9p1-ipv6man.patch rename to openssh-5.9p1-ipv6man.patch diff --git a/SOURCES/openssh-6.4p1-fromto-remote.patch b/openssh-6.4p1-fromto-remote.patch similarity index 100% rename from SOURCES/openssh-6.4p1-fromto-remote.patch rename to openssh-6.4p1-fromto-remote.patch diff --git a/SOURCES/openssh-6.6.1p1-log-in-chroot.patch b/openssh-6.6.1p1-log-in-chroot.patch similarity index 54% rename from SOURCES/openssh-6.6.1p1-log-in-chroot.patch rename to openssh-6.6.1p1-log-in-chroot.patch index b009d99..0f65279 100644 --- a/SOURCES/openssh-6.6.1p1-log-in-chroot.patch +++ b/openssh-6.6.1p1-log-in-chroot.patch @@ -1,19 +1,19 @@ -diff -up openssh-7.4p1/log.c.log-in-chroot openssh-7.4p1/log.c ---- openssh-7.4p1/log.c.log-in-chroot 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/log.c 2016-12-23 15:14:33.330168088 +0100 -@@ -250,6 +250,11 @@ debug3(const char *fmt,...) - void - log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) +diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c +--- openssh-8.6p1/log.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/log.c 2021-04-19 14:43:08.544843434 +0200 +@@ -194,6 +194,11 @@ void + log_init(const char *av0, LogLevel level, SyslogFacility facility, + int on_stderr) { + log_init_handler(av0, level, facility, on_stderr, 1); +} + +void -+log_init_handler(char *av0, LogLevel level, SyslogFacility facility, int on_stderr, int reset_handler) { ++log_init_handler(const char *av0, LogLevel level, SyslogFacility facility, int on_stderr, int reset_handler) { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) struct syslog_data sdata = SYSLOG_DATA_INIT; #endif -@@ -273,8 +278,10 @@ log_init(char *av0, LogLevel level, Sysl +@@ -206,8 +211,10 @@ log_init(const char *av0, LogLevel level exit(1); } @@ -26,21 +26,21 @@ diff -up openssh-7.4p1/log.c.log-in-chroot openssh-7.4p1/log.c log_on_stderr = on_stderr; if (on_stderr) -diff -up openssh-7.4p1/log.h.log-in-chroot openssh-7.4p1/log.h ---- openssh-7.4p1/log.h.log-in-chroot 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/log.h 2016-12-23 15:14:33.330168088 +0100 -@@ -49,6 +49,7 @@ typedef enum { - typedef void (log_handler_fn)(LogLevel, const char *, void *); +diff -up openssh-8.6p1/log.h.log-in-chroot openssh-8.6p1/log.h +--- openssh-8.6p1/log.h.log-in-chroot 2021-04-19 14:43:08.544843434 +0200 ++++ openssh-8.6p1/log.h 2021-04-19 14:56:46.931042176 +0200 +@@ -52,6 +52,7 @@ typedef enum { + typedef void (log_handler_fn)(LogLevel, int, const char *, void *); - void log_init(char *, LogLevel, SyslogFacility, int); -+void log_init_handler(char *, LogLevel, SyslogFacility, int, int); + void log_init(const char *, LogLevel, SyslogFacility, int); ++void log_init_handler(const char *, LogLevel, SyslogFacility, int, int); LogLevel log_level_get(void); int log_change_level(LogLevel); int log_is_on_stderr(void); -diff -up openssh-7.4p1/monitor.c.log-in-chroot openssh-7.4p1/monitor.c ---- openssh-7.4p1/monitor.c.log-in-chroot 2016-12-23 15:14:33.311168085 +0100 -+++ openssh-7.4p1/monitor.c 2016-12-23 15:16:42.154193100 +0100 -@@ -307,6 +307,8 @@ monitor_child_preauth(Authctxt *_authctx +diff -up openssh-8.6p1/monitor.c.log-in-chroot openssh-8.6p1/monitor.c +--- openssh-8.6p1/monitor.c.log-in-chroot 2021-04-19 14:43:08.526843298 +0200 ++++ openssh-8.6p1/monitor.c 2021-04-19 14:55:25.286424043 +0200 +@@ -297,6 +297,8 @@ monitor_child_preauth(struct ssh *ssh, s close(pmonitor->m_log_sendfd); pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; @@ -49,25 +49,25 @@ diff -up openssh-7.4p1/monitor.c.log-in-chroot openssh-7.4p1/monitor.c authctxt = (Authctxt *)ssh->authctxt; memset(authctxt, 0, sizeof(*authctxt)); ssh->authctxt = authctxt; -@@ -405,6 +407,8 @@ monitor_child_postauth(struct monitor *p +@@ -408,6 +410,8 @@ monitor_child_postauth(struct ssh *ssh, close(pmonitor->m_recvfd); pmonitor->m_recvfd = -1; + pmonitor->m_state = "postauth"; + monitor_set_child_handler(pmonitor->m_pid); - signal(SIGHUP, &monitor_child_handler); - signal(SIGTERM, &monitor_child_handler); -@@ -472,7 +476,7 @@ monitor_read_log(struct monitor *pmonito + ssh_signal(SIGHUP, &monitor_child_handler); + ssh_signal(SIGTERM, &monitor_child_handler); +@@ -480,7 +484,7 @@ monitor_read_log(struct monitor *pmonito + /* Log it */ if (log_level_name(level) == NULL) - fatal("%s: invalid log level %u (corrupted message?)", - __func__, level); -- do_log2(level, "%s [preauth]", msg); -+ do_log2(level, "%s [%s]", msg, pmonitor->m_state); + fatal_f("invalid log level %u (corrupted message?)", level); +- sshlogdirect(level, forced, "%s [preauth]", msg); ++ sshlogdirect(level, forced, "%s [%s]", msg, pmonitor->m_state); sshbuf_free(logmsg); free(msg); -@@ -1719,13 +1723,28 @@ monitor_init(void) +@@ -1868,13 +1872,28 @@ monitor_init(void) mon = xcalloc(1, sizeof(*mon)); monitor_openfds(mon, 1); @@ -89,7 +89,7 @@ diff -up openssh-7.4p1/monitor.c.log-in-chroot openssh-7.4p1/monitor.c + xasprintf(&dev_log_path, "%s/dev/log", chroot_dir); + + if (stat(dev_log_path, &dev_log_stat) != 0) { -+ debug("%s: /dev/log doesn't exist in %s chroot - will try to log via monitor using [postauth] suffix", __func__, chroot_dir); ++ debug_f("/dev/log doesn't exist in %s chroot - will try to log via monitor using [postauth] suffix", chroot_dir); + do_logfds = 1; + } + free(dev_log_path); @@ -98,10 +98,10 @@ diff -up openssh-7.4p1/monitor.c.log-in-chroot openssh-7.4p1/monitor.c } #ifdef GSSAPI -diff -up openssh-7.4p1/monitor.h.log-in-chroot openssh-7.4p1/monitor.h ---- openssh-7.4p1/monitor.h.log-in-chroot 2016-12-23 15:14:33.330168088 +0100 -+++ openssh-7.4p1/monitor.h 2016-12-23 15:16:28.372190424 +0100 -@@ -83,10 +83,11 @@ struct monitor { +diff -up openssh-8.6p1/monitor.h.log-in-chroot openssh-8.6p1/monitor.h +--- openssh-8.6p1/monitor.h.log-in-chroot 2021-04-19 14:43:08.527843305 +0200 ++++ openssh-8.6p1/monitor.h 2021-04-19 14:43:08.545843441 +0200 +@@ -80,10 +80,11 @@ struct monitor { int m_log_sendfd; struct kex **m_pkex; pid_t m_pid; @@ -114,9 +114,9 @@ diff -up openssh-7.4p1/monitor.h.log-in-chroot openssh-7.4p1/monitor.h struct Authctxt; void monitor_child_preauth(struct ssh *, struct monitor *); -diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c ---- openssh-7.4p1/session.c.log-in-chroot 2016-12-23 15:14:33.319168086 +0100 -+++ openssh-7.4p1/session.c 2016-12-23 15:18:18.742211853 +0100 +diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c +--- openssh-8.6p1/session.c.log-in-chroot 2021-04-19 14:43:08.534843358 +0200 ++++ openssh-8.6p1/session.c 2021-04-19 14:43:08.545843441 +0200 @@ -160,6 +160,7 @@ login_cap_t *lc; static int is_child = 0; @@ -125,7 +125,7 @@ diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c /* File containing userauth info, if ExposeAuthInfo set */ static char *auth_info_file = NULL; -@@ -619,6 +620,7 @@ do_exec(Session *s, const char *command) +@@ -661,6 +662,7 @@ do_exec(struct ssh *ssh, Session *s, con int ret; const char *forced = NULL, *tty = NULL; char session_type[1024]; @@ -133,7 +133,7 @@ diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c if (options.adm_forced_command) { original_command = command; -@@ -676,6 +678,10 @@ do_exec(Session *s, const char *command) +@@ -720,6 +722,10 @@ do_exec(struct ssh *ssh, Session *s, con tty += 5; } @@ -144,10 +144,10 @@ diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c verbose("Starting session: %s%s%s for %s from %.200s port %d id %d", session_type, tty == NULL ? "" : " on ", -@@ -1486,14 +1492,6 @@ child_close_fds(void) - * descriptors left by system functions. They will be closed later. - */ - endpwent(); +@@ -1524,14 +1530,6 @@ child_close_fds(struct ssh *ssh) + + /* Stop directing logs to a high-numbered fd before we close it */ + log_redirect_stderr_to(NULL); - - /* - * Close any extra open file descriptors so that we don't have them @@ -159,7 +159,7 @@ diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c } /* -@@ -1629,8 +1627,6 @@ do_child(Session *s, const char *command +@@ -1665,8 +1663,6 @@ do_child(struct ssh *ssh, Session *s, co exit(1); } @@ -168,7 +168,7 @@ diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c do_rc_files(ssh, s, shell); /* restore SIGPIPE for child */ -@@ -1653,9 +1649,17 @@ do_child(Session *s, const char *command +@@ -1691,9 +1687,17 @@ do_child(struct ssh *ssh, Session *s, co argv[i] = NULL; optind = optreset = 1; __progname = argv[0]; @@ -187,9 +187,9 @@ diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c fflush(NULL); /* Get the last component of the shell name. */ -diff -up openssh-7.4p1/sftp.h.log-in-chroot openssh-7.4p1/sftp.h ---- openssh-7.4p1/sftp.h.log-in-chroot 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/sftp.h 2016-12-23 15:14:33.331168088 +0100 +diff -up openssh-8.6p1/sftp.h.log-in-chroot openssh-8.6p1/sftp.h +--- openssh-8.6p1/sftp.h.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/sftp.h 2021-04-19 14:43:08.545843441 +0200 @@ -97,5 +97,5 @@ struct passwd; @@ -197,28 +197,28 @@ diff -up openssh-7.4p1/sftp.h.log-in-chroot openssh-7.4p1/sftp.h -int sftp_server_main(int, char **, struct passwd *); +int sftp_server_main(int, char **, struct passwd *, int); void sftp_server_cleanup_exit(int) __attribute__((noreturn)); -diff -up openssh-7.4p1/sftp-server.c.log-in-chroot openssh-7.4p1/sftp-server.c ---- openssh-7.4p1/sftp-server.c.log-in-chroot 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/sftp-server.c 2016-12-23 15:14:33.331168088 +0100 -@@ -1497,7 +1497,7 @@ sftp_server_usage(void) +diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c +--- openssh-8.6p1/sftp-server.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/sftp-server.c 2021-04-19 14:43:08.545843441 +0200 +@@ -1644,7 +1644,7 @@ sftp_server_usage(void) } int -sftp_server_main(int argc, char **argv, struct passwd *user_pw) +sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handler) { - fd_set *rset, *wset; - int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0; -@@ -1511,7 +1511,7 @@ sftp_server_main(int argc, char **argv, + int i, r, in, out, ch, skipargs = 0, log_stderr = 0; + ssize_t len, olen; +@@ -1657,7 +1657,7 @@ sftp_server_main(int argc, char **argv, + extern char *__progname; - ssh_malloc_init(); /* must be called before any mallocs */ __progname = ssh_get_progname(argv[0]); - log_init(__progname, log_level, log_facility, log_stderr); + log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler); pw = pwcopy(user_pw); -@@ -1582,7 +1582,7 @@ sftp_server_main(int argc, char **argv, +@@ -1730,7 +1730,7 @@ sftp_server_main(int argc, char **argv, } } @@ -227,21 +227,21 @@ diff -up openssh-7.4p1/sftp-server.c.log-in-chroot openssh-7.4p1/sftp-server.c /* * On platforms where we can, avoid making /proc/self/{mem,maps} -diff -up openssh-7.4p1/sftp-server-main.c.log-in-chroot openssh-7.4p1/sftp-server-main.c ---- openssh-7.4p1/sftp-server-main.c.log-in-chroot 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/sftp-server-main.c 2016-12-23 15:14:33.331168088 +0100 -@@ -49,5 +49,5 @@ main(int argc, char **argv) +diff -up openssh-8.6p1/sftp-server-main.c.log-in-chroot openssh-8.6p1/sftp-server-main.c +--- openssh-8.6p1/sftp-server-main.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/sftp-server-main.c 2021-04-19 14:43:08.545843441 +0200 +@@ -50,5 +50,5 @@ main(int argc, char **argv) return 1; } - return (sftp_server_main(argc, argv, user_pw)); + return (sftp_server_main(argc, argv, user_pw, 0)); } -diff -up openssh-7.4p1/sshd.c.log-in-chroot openssh-7.4p1/sshd.c ---- openssh-7.4p1/sshd.c.log-in-chroot 2016-12-23 15:14:33.328168088 +0100 -+++ openssh-7.4p1/sshd.c 2016-12-23 15:14:33.332168088 +0100 -@@ -650,7 +650,7 @@ privsep_postauth(Authctxt *authctxt) - } +diff -up openssh-8.6p1/sshd-session.c.log-in-chroot openssh-8.6p1/sshd-session.c +--- openssh-8.6p1/sshd-session.c.log-in-chroot 2021-04-19 14:43:08.543843426 +0200 ++++ openssh-8.6p1/sshd-session.c 2021-04-19 14:43:08.545843441 +0200 +@@ -559,7 +559,7 @@ privsep_postauth(struct ssh *ssh, Authct + #endif /* New socket pair */ - monitor_reinit(pmonitor); @@ -249,7 +249,7 @@ diff -up openssh-7.4p1/sshd.c.log-in-chroot openssh-7.4p1/sshd.c pmonitor->m_pid = fork(); if (pmonitor->m_pid == -1) -@@ -668,6 +668,11 @@ privsep_postauth(Authctxt *authctxt) +@@ -578,6 +578,11 @@ privsep_postauth(struct ssh *ssh, Authct close(pmonitor->m_sendfd); pmonitor->m_sendfd = -1; diff --git a/SOURCES/openssh-6.6.1p1-scp-non-existing-directory.patch b/openssh-6.6.1p1-scp-non-existing-directory.patch similarity index 81% rename from SOURCES/openssh-6.6.1p1-scp-non-existing-directory.patch rename to openssh-6.6.1p1-scp-non-existing-directory.patch index 5412bc5..bb55c0b 100644 --- a/SOURCES/openssh-6.6.1p1-scp-non-existing-directory.patch +++ b/openssh-6.6.1p1-scp-non-existing-directory.patch @@ -10,5 +10,5 @@ + } omode = mode; mode |= S_IWUSR; - if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { + if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { -- diff --git a/SOURCES/openssh-6.6.1p1-selinux-contexts.patch b/openssh-6.6.1p1-selinux-contexts.patch similarity index 74% rename from SOURCES/openssh-6.6.1p1-selinux-contexts.patch rename to openssh-6.6.1p1-selinux-contexts.patch index 3a7193e..96161cb 100644 --- a/SOURCES/openssh-6.6.1p1-selinux-contexts.patch +++ b/openssh-6.6.1p1-selinux-contexts.patch @@ -34,19 +34,19 @@ index 8f32464..18a2ca4 100644 + + contexts_path = selinux_openssh_contexts_path(); + if (contexts_path == NULL) { -+ debug3("%s: Failed to get the path to SELinux context", __func__); ++ debug3_f("Failed to get the path to SELinux context"); + return; + } + + if ((contexts_file = fopen(contexts_path, "r")) == NULL) { -+ debug("%s: Failed to open SELinux context file", __func__); ++ debug_f("Failed to open SELinux context file"); + return; + } + + if (fstat(fileno(contexts_file), &sb) != 0 || + sb.st_uid != 0 || (sb.st_mode & 022) != 0) { -+ logit("%s: SELinux context file needs to be owned by root" -+ " and not writable by anyone else", __func__); ++ logit_f("SELinux context file needs to be owned by root" ++ " and not writable by anyone else"); + fclose(contexts_file); + return; + } @@ -70,7 +70,7 @@ index 8f32464..18a2ca4 100644 + if (arg && strcmp(arg, "privsep_preauth") == 0) { + arg = strdelim(&cp); + if (!arg || *arg == '\0') { -+ debug("%s: privsep_preauth is empty", __func__); ++ debug_f("privsep_preauth is empty"); + fclose(contexts_file); + return; + } @@ -80,8 +80,8 @@ index 8f32464..18a2ca4 100644 + fclose(contexts_file); + + if (preauth_context == NULL) { -+ debug("%s: Unable to find 'privsep_preauth' option in" -+ " SELinux context file", __func__); ++ debug_f("Unable to find 'privsep_preauth' option in" ++ " SELinux context file"); + return; + } + @@ -93,18 +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("%s: setting context from '%s' to '%s'", __func__, - 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) - switchlog("%s: setcon %s from %s failed with %s", __func__, + 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 @@ -117,10 +116,10 @@ index cb51f99..8b7cda2 100644 #endif #ifdef LINUX_OOM_ADJUST -diff --git a/sshd.c b/sshd.c +diff --git a/sshd-session.c b/sshd-session.c index 2871fe9..39b9c08 100644 ---- a/sshd.c -+++ b/sshd.c +--- a/sshd-session.c ++++ b/sshd-session.c @@ -629,7 +629,7 @@ privsep_preauth_child(void) demote_sensitive_data(); diff --git a/SOURCES/openssh-6.6p1-GSSAPIEnablek5users.patch b/openssh-6.6p1-GSSAPIEnablek5users.patch similarity index 91% rename from SOURCES/openssh-6.6p1-GSSAPIEnablek5users.patch rename to openssh-6.6p1-GSSAPIEnablek5users.patch index d943f41..7fef831 100644 --- a/SOURCES/openssh-6.6p1-GSSAPIEnablek5users.patch +++ b/openssh-6.6p1-GSSAPIEnablek5users.patch @@ -28,7 +28,7 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c + options->enable_k5users = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; - options->challenge_response_authentication = -1; + options->permit_empty_passwd = -1; @@ -345,6 +346,8 @@ fill_default_server_options(ServerOption #endif if (options->use_kuserok == -1) @@ -38,16 +38,16 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -418,7 +421,7 @@ typedef enum { - sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes, - sHostKeyAlgorithms, +@@ -578,7 +578,7 @@ typedef enum { + sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, + sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, - sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, + sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor, sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, -@@ -497,14 +500,16 @@ static struct { +@@ -600,14 +600,16 @@ static struct { { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, @@ -72,9 +72,9 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c + intptr = &options->enable_k5users; + goto parse_flag; + - case sPermitListen: - case sPermitOpen: - if (opcode == sPermitListen) { + case sMatch: + if (cmdline) + fatal("Match directive not supported as a command-line " @@ -2026,6 +2035,7 @@ copy_set_server_options(ServerOptions *d M_CP_INTOPT(ip_qos_interactive); M_CP_INTOPT(ip_qos_bulk); @@ -122,10 +122,13 @@ diff -up openssh-7.4p1/sshd_config.GSSAPIEnablek5users openssh-7.4p1/sshd_config --- openssh-7.4p1/sshd_config.GSSAPIEnablek5users 2016-12-23 15:18:40.616216100 +0100 +++ openssh-7.4p1/sshd_config 2016-12-23 15:18:40.631216103 +0100 @@ -80,6 +80,7 @@ GSSAPIAuthentication yes - GSSAPICleanupCredentials no + #GSSAPICleanupCredentials yes #GSSAPIStrictAcceptorCheck yes #GSSAPIKeyExchange no +#GSSAPIEnablek5users no # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will +diff -up openssh-9.8p1/servconf.c.xxx openssh-9.8p1/servconf.c +--- openssh-9.8p1/servconf.c.xxx 2024-07-11 13:51:19.969960781 +0200 ++++ openssh-9.8p1/servconf.c 2024-07-11 13:51:30.938231250 +0200 diff --git a/SOURCES/openssh-6.6p1-allow-ip-opts.patch b/openssh-6.6p1-allow-ip-opts.patch similarity index 72% rename from SOURCES/openssh-6.6p1-allow-ip-opts.patch rename to openssh-6.6p1-allow-ip-opts.patch index 953d613..d969b5c 100644 --- a/SOURCES/openssh-6.6p1-allow-ip-opts.patch +++ b/openssh-6.6p1-allow-ip-opts.patch @@ -1,7 +1,7 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c ---- openssh/sshd.c.ip-opts 2016-07-25 13:58:48.998507834 +0200 -+++ openssh/sshd.c 2016-07-25 14:01:28.346469878 +0200 -@@ -1507,12 +1507,29 @@ check_ip_options(struct ssh *ssh) +--- openssh/sshd-session.c.ip-opts 2016-07-25 13:58:48.998507834 +0200 ++++ openssh/sshd-session.c 2016-07-25 14:01:28.346469878 +0200 +@@ -1507,12 +1507,32 @@ check_ip_options(struct ssh *ssh) if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, &option_size) >= 0 && option_size != 0) { @@ -21,11 +21,14 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c + case 130: + case 133: + case 134: -+ i += opts[i + 1]; -+ break; ++ if (i + 1 < option_size && opts[i + 1] >= 2) { ++ i += opts[i + 1]; ++ break; ++ } ++ /* FALLTHROUGH */ + default: + /* Fail, fatally, if we detect either loose or strict -+ * source routing options. */ ++ * or incorrect source routing options. */ + text[0] = '\0'; + for (i = 0; i < option_size; i++) + snprintf(text + i*3, sizeof(text) - i*3, diff --git a/SOURCES/openssh-6.6p1-force_krb.patch b/openssh-6.6p1-force_krb.patch similarity index 100% rename from SOURCES/openssh-6.6p1-force_krb.patch rename to openssh-6.6p1-force_krb.patch diff --git a/SOURCES/openssh-6.6p1-keycat.patch b/openssh-6.6p1-keycat.patch similarity index 86% rename from SOURCES/openssh-6.6p1-keycat.patch rename to openssh-6.6p1-keycat.patch index c658a87..4eb0998 100644 --- a/SOURCES/openssh-6.6p1-keycat.patch +++ b/openssh-6.6p1-keycat.patch @@ -1,10 +1,10 @@ -diff -up openssh/auth.c.keycat openssh/misc.c ---- openssh/auth.c.keycat 2015-06-24 10:57:50.158849606 +0200 -+++ openssh/auth.c 2015-06-24 11:04:23.989868638 +0200 -@@ -966,6 +966,14 @@ subprocess(const char *tag, struct passw +diff -up openssh/misc.c.keycat openssh/misc.c +--- openssh/misc.c.keycat 2015-06-24 10:57:50.158849606 +0200 ++++ openssh/misc.c 2015-06-24 11:04:23.989868638 +0200 +@@ -966,6 +966,13 @@ subprocess(const char *tag, struct passw + error("%s: dup2: %s", tag, strerror(errno)); _exit(1); } - +#ifdef WITH_SELINUX + if (sshd_selinux_setup_env_variables() < 0) { + error ("failed to copy environment: %s", @@ -12,10 +12,9 @@ diff -up openssh/auth.c.keycat openssh/misc.c + _exit(127); + } +#endif -+ - execve(av[0], av, child_env); - error("%s exec \"%s\": %s", tag, command, strerror(errno)); - _exit(127); + if (env != NULL) + execve(av[0], av, env); + else diff -up openssh/HOWTO.ssh-keycat.keycat openssh/HOWTO.ssh-keycat --- openssh/HOWTO.ssh-keycat.keycat 2015-06-24 10:57:50.157849608 +0200 +++ openssh/HOWTO.ssh-keycat 2015-06-24 10:57:50.157849608 +0200 @@ -36,44 +35,44 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in --- openssh/Makefile.in.keycat 2015-06-24 10:57:50.152849621 +0200 +++ openssh/Makefile.in 2015-06-24 10:57:50.157849608 +0200 @@ -27,6 +27,7 @@ SFTP_SERVER=$(libexecdir)/sftp-server + ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass + SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign - SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper - SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper +SSH_KEYCAT=$(libexecdir)/ssh-keycat + SSHD_SESSION=$(libexecdir)/sshd-session SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper - PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper @@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@ + K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ - SSHLIBS=@SSHLIBS@ SSHDLIBS=@SSHDLIBS@ +KEYCATLIBS=@KEYCATLIBS@ LIBEDIT=@LIBEDIT@ + LIBFIDO2=@LIBFIDO2@ AR=@AR@ - AWK=@AWK@ @@ -65,7 +66,7 @@ EXEEXT=@EXEEXT@ - MKDIR_P=@MKDIR_P@ - INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ --TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) -+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) + .SUFFIXES: .lo + +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT) XMSS_OBJS=\ ssh-xmss.o \ @@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) - ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o - $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LDAPLIBS) + ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) + $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) +ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o + $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS) + - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) @@ -321,6 +325,7 @@ install-files: - $(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \ - $(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ - fi + $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) @@ -96,8 +95,8 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ --- openssh/openbsd-compat/port-linux-sshd.c.keycat 2015-06-24 10:57:50.150849626 +0200 +++ openssh/openbsd-compat/port-linux-sshd.c 2015-06-24 10:57:50.159849603 +0200 @@ -54,6 +54,20 @@ extern Authctxt *the_authctxt; + extern Authctxt *the_authctxt; extern int inetd_flag; - extern int rexeced_flag; +/* Wrapper around is_selinux_enabled() to log its return value once only */ +int @@ -132,7 +131,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ - rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); + rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); - if (inetd_flag && !rexeced_flag) { + if (inetd_flag) { use_current = "1"; } else { use_current = ""; @@ -466,16 +465,16 @@ index 3bbccfd..6481f1f 100644 esac fi @@ -4042,6 +4044,7 @@ AC_ARG_WITH([selinux], + fi ] ) - AC_SUBST([SSHLIBS]) AC_SUBST([SSHDLIBS]) +AC_SUBST([KEYCATLIBS]) # Check whether user wants Kerberos 5 support KRB5_MSG="no" @@ -5031,6 +5034,9 @@ fi - if test ! -z "${SSHLIBS}"; then - echo " +for ssh: ${SSHLIBS}" + if test ! -z "${SSHDLIBS}"; then + echo " +for sshd: ${SSHDLIBS}" fi +if test ! -z "${KEYCATLIBS}"; then +echo " +for ssh-keycat: ${KEYCATLIBS}" diff --git a/SOURCES/openssh-6.6p1-kuserok.patch b/openssh-6.6p1-kuserok.patch similarity index 94% rename from SOURCES/openssh-6.6p1-kuserok.patch rename to openssh-6.6p1-kuserok.patch index 56a6950..e43128b 100644 --- a/SOURCES/openssh-6.6p1-kuserok.patch +++ b/openssh-6.6p1-kuserok.patch @@ -155,8 +155,8 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c * because if they are on a krb5-protected filesystem, user credentials * to access these files aren't available yet. */ - if (krb5_kuserok(krb_context, princ, name) && k5login_exists) { -+ if (ssh_krb5_kuserok(krb_context, princ, name, k5login_exists) -+ && k5login_exists) { ++ if (k5login_exists && ++ ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)) { retval = 1; logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", name, (char *)client->displayname.value); @@ -182,7 +182,7 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c + options->use_kuserok = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; - options->challenge_response_authentication = -1; + options->permit_empty_passwd = -1; @@ -278,6 +279,8 @@ fill_default_server_options(ServerOption if (options->gss_kex_algorithms == NULL) options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX); @@ -193,14 +193,14 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) @@ -399,7 +402,7 @@ typedef enum { - sPermitRootLogin, sLogFacility, sLogLevel, - sRhostsRSAAuthentication, sRSAAuthentication, - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, -- sKerberosGetAFSToken, sKerberosUniqueCCache, -+ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, - sChallengeResponseAuthentication, - sPasswordAuthentication, sKbdInteractiveAuthentication, - sListenAddress, sAddressFamily, + sPort, sHostKeyFile, sLoginGraceTime, + sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, +- sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication, ++ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication, + sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, @@ -478,12 +481,14 @@ static struct { { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif @@ -217,16 +217,16 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, @@ -1644,6 +1649,10 @@ process_server_config_line(ServerOptions - *activep = value; - break; - + } + break; + + case sKerberosUseKuserok: + intptr = &options->use_kuserok; + goto parse_flag; + - case sPermitListen: - case sPermitOpen: - if (opcode == sPermitListen) { + case sMatch: + if (cmdline) + fatal("Match directive not supported as a command-line " @@ -2016,6 +2025,7 @@ copy_set_server_options(ServerOptions *d M_CP_INTOPT(client_alive_interval); M_CP_INTOPT(ip_qos_interactive); @@ -266,8 +266,8 @@ diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5 +The default is +.Cm yes . .It Cm KexAlgorithms - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. + Specifies the permitted KEX (Key Exchange) algorithms that the server will + offer to clients. @@ -1078,6 +1082,7 @@ Available keywords are .Cm IPQoS , .Cm KbdInteractiveAuthentication , @@ -286,4 +286,4 @@ diff -up openssh-7.4p1/sshd_config.kuserok openssh-7.4p1/sshd_config +#KerberosUseKuserok yes # GSSAPI options - GSSAPIAuthentication yes + #GSSAPIAuthentication no diff --git a/SOURCES/openssh-6.6p1-privsep-selinux.patch b/openssh-6.6p1-privsep-selinux.patch similarity index 82% rename from SOURCES/openssh-6.6p1-privsep-selinux.patch rename to openssh-6.6p1-privsep-selinux.patch index 3d4c287..16d98cd 100644 --- a/SOURCES/openssh-6.6p1-privsep-selinux.patch +++ b/openssh-6.6p1-privsep-selinux.patch @@ -13,7 +13,7 @@ diff -up openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux openssh- --- openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100 +++ openssh-7.4p1/openbsd-compat/port-linux-sshd.c 2016-12-23 18:58:52.974122201 +0100 @@ -419,6 +419,28 @@ sshd_selinux_setup_exec_context(char *pw - debug3("%s: done", __func__); + debug3_f("done"); } +void @@ -25,15 +25,15 @@ diff -up openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux openssh- + return; + + if (getexeccon((security_context_t *)&ctx) != 0) { -+ logit("%s: getexeccon failed with %s", __func__, strerror(errno)); ++ logit_f("getexeccon failed with %s", strerror(errno)); + return; + } + if (ctx != NULL) { + /* unset exec context before we will lose this capabililty */ + if (setexeccon(NULL) != 0) -+ fatal("%s: setexeccon failed with %s", __func__, strerror(errno)); ++ fatal_f("setexeccon failed with %s", strerror(errno)); + if (setcon(ctx) != 0) -+ fatal("%s: setcon failed with %s", __func__, strerror(errno)); ++ fatal_f("setcon failed with %s", strerror(errno)); + freecon(ctx); + } +} @@ -49,7 +49,7 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c platform_setusercontext(pw); - if (platform_privileged_uidswap()) { -+ if (platform_privileged_uidswap() && (!is_child || !use_privsep)) { ++ if (platform_privileged_uidswap() && !is_child) { #ifdef HAVE_LOGIN_CAP if (setusercontext(lc, pw, pw->pw_uid, (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { @@ -96,8 +96,8 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c } diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c ---- openssh-7.4p1/sshd.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100 -+++ openssh-7.4p1/sshd.c 2016-12-23 18:59:13.808124269 +0100 +--- openssh-7.4p1/sshd-session.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100 ++++ openssh-7.4p1/sshd-session.c 2016-12-23 18:59:13.808124269 +0100 @@ -540,6 +540,10 @@ privsep_preauth_child(void) /* Demote the private keys to public keys. */ demote_sensitive_data(); @@ -109,13 +109,12 @@ diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c /* Demote the child */ if (privsep_chroot) { /* Change our root directory */ -@@ -633,6 +637,9 @@ privsep_postauth(Authctxt *authctxt) - { - #ifdef DISABLE_FD_PASSING - if (1) { -+#elif defined(WITH_SELINUX) -+ if (0) { -+ /* even root user can be confined by SELinux */ - #else - if (authctxt->pw->pw_uid == 0) { +@@ -403,7 +403,7 @@ privsep_postauth(struct ssh *ssh, Authct + * fd passing, as AFAIK PTY allocation on this platform doesn't require + * special privileges to begin with. + */ +-#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) ++#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) && !defined(WITH_SELINUX) + skip_privdrop = 1; #endif + diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch new file mode 100644 index 0000000..d98da28 --- /dev/null +++ b/openssh-6.7p1-coverity.patch @@ -0,0 +1,264 @@ +diff -up openssh-8.5p1/auth-krb5.c.coverity openssh-8.5p1/auth-krb5.c +--- openssh-8.5p1/auth-krb5.c.coverity 2021-03-24 12:03:33.724967756 +0100 ++++ openssh-8.5p1/auth-krb5.c 2021-03-24 12:03:33.782968159 +0100 +@@ -426,6 +426,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, + umask(old_umask); + if (tmpfd == -1) { + logit("mkstemp(): %.100s", strerror(oerrno)); ++ free(ccname); + return oerrno; + } + +@@ -433,6 +434,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, + oerrno = errno; + logit("fchmod(): %.100s", strerror(oerrno)); + close(tmpfd); ++ free(ccname); + return oerrno; + } + /* make sure the KRB5CCNAME is set for non-standard location */ +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 +@@ -167,8 +167,9 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup + enclen = __b64_ntop(digest, + ssh_digest_bytes(SSH_DIGEST_MD5), encoded, + ssh_digest_bytes(SSH_DIGEST_MD5) * 2); +- ++#pragma GCC diagnostic ignored "-Wstringop-overflow" + cp = strncpy(s, kex, strlen(kex)); ++#pragma GCC diagnostic pop + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + if (sshbuf_len(buf) != 0 && +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 +@@ -1261,6 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, cons + return r; + erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); + free(rb.blob); ++ rb.blob = NULL; /* make coverity happy */ + if (erb != NULL) { + KRL_DBG(("revoked by key SHA1")); + return SSH_ERR_KEY_REVOKED; +@@ -1271,6 +1273,7 @@ is_key_revoked(struct ssh_krl *krl, cons + return r; + erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb); + free(rb.blob); ++ rb.blob = NULL; /* make coverity happy */ + if (erb != NULL) { + KRL_DBG(("revoked by key SHA256")); + return SSH_ERR_KEY_REVOKED; +@@ -1282,6 +1285,7 @@ is_key_revoked(struct ssh_krl *krl, cons + return r; + erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); + free(rb.blob); ++ rb.blob = NULL; /* make coverity happy */ + if (erb != NULL) { + KRL_DBG(("revoked by explicit key")); + return SSH_ERR_KEY_REVOKED; +diff -up openssh-8.5p1/loginrec.c.coverity openssh-8.5p1/loginrec.c +--- openssh-8.5p1/loginrec.c.coverity 2021-03-24 13:18:53.793225885 +0100 ++++ openssh-8.5p1/loginrec.c 2021-03-24 13:21:27.948404751 +0100 +@@ -690,9 +690,11 @@ construct_utmp(struct logininfo *li, + */ + + /* Use strncpy because we don't necessarily want null termination */ ++ /* coverity[buffer_size_warning : FALSE] */ + strncpy(ut->ut_name, li->username, + MIN_SIZEOF(ut->ut_name, li->username)); + # ifdef HAVE_HOST_IN_UTMP ++ /* coverity[buffer_size_warning : FALSE] */ + strncpy(ut->ut_host, li->hostname, + MIN_SIZEOF(ut->ut_host, li->hostname)); + # endif +@@ -1690,6 +1692,7 @@ record_failed_login(struct ssh *ssh, con + + memset(&ut, 0, sizeof(ut)); + /* strncpy because we don't necessarily want nul termination */ ++ /* coverity[buffer_size_warning : FALSE] */ + strncpy(ut.ut_user, username, sizeof(ut.ut_user)); + strlcpy(ut.ut_line, "ssh:notty", sizeof(ut.ut_line)); + +@@ -1699,6 +1702,7 @@ record_failed_login(struct ssh *ssh, con + ut.ut_pid = getpid(); + + /* strncpy because we don't necessarily want nul termination */ ++ /* coverity[buffer_size_warning : FALSE] */ + strncpy(ut.ut_host, hostname, sizeof(ut.ut_host)); + + if (ssh_packet_connection_is_on_socket(ssh) && +diff -up openssh-8.5p1/misc.c.coverity openssh-8.5p1/misc.c +--- openssh-8.5p1/misc.c.coverity 2021-03-24 12:03:33.745967902 +0100 ++++ openssh-8.5p1/misc.c 2021-03-24 13:31:47.037079617 +0100 +@@ -1425,6 +1425,8 @@ sanitise_stdfd(void) + } + if (nullfd > STDERR_FILENO) + close(nullfd); ++ /* coverity[leaked_handle : FALSE]*/ ++ /* coverity[leaked_handle : FALSE]*/ + } + + char * +@@ -2511,6 +2513,7 @@ stdfd_devnull(int do_stdin, int do_stdou + } + if (devnull > STDERR_FILENO) + close(devnull); ++ /* coverity[leaked_handle : FALSE]*/ + return ret; + } + +diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c +--- openssh-7.4p1/monitor.c.coverity 2016-12-23 16:40:26.888788688 +0100 ++++ openssh-7.4p1/monitor.c 2016-12-23 16:40:26.900788691 +0100 +@@ -411,7 +411,7 @@ monitor_child_preauth(Authctxt *_authctx + mm_get_keystate(ssh, pmonitor); + + /* Drain any buffered messages from the child */ +- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) ++ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) + ; + + if (pmonitor->m_recvfd >= 0) +@@ -1678,7 +1678,7 @@ mm_answer_pty(struct ssh *ssh, int sock, + s->ptymaster = s->ptyfd; + + debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd); +- ++ /* coverity[leaked_handle : FALSE] */ + return (0); + + error: +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 +@@ -58,7 +58,7 @@ bindresvport_sa(int sd, struct sockaddr + struct sockaddr_in6 *in6; + u_int16_t *portp; + u_int16_t port; +- socklen_t salen; ++ socklen_t salen = sizeof(struct sockaddr_storage); + int i; + + if (sa == NULL) { +diff -up openssh-8.7p1/openbsd-compat/bsd-pselect.c.coverity openssh-8.7p1/openbsd-compat/bsd-pselect.c +--- openssh-8.7p1/openbsd-compat/bsd-pselect.c.coverity 2021-08-30 16:36:11.357288009 +0200 ++++ openssh-8.7p1/openbsd-compat/bsd-pselect.c 2021-08-30 16:37:21.791897976 +0200 +@@ -113,13 +113,13 @@ pselect_notify_setup(void) + static void + pselect_notify_parent(void) + { +- if (notify_pipe[1] != -1) ++ if (notify_pipe[1] >= 0) + (void)write(notify_pipe[1], "", 1); + } + static void + pselect_notify_prepare(fd_set *readset) + { +- if (notify_pipe[0] != -1) ++ if (notify_pipe[0] >= 0) + FD_SET(notify_pipe[0], readset); + } + static void +@@ -127,8 +127,8 @@ pselect_notify_done(fd_set *readset) + { + char c; + +- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) { +- while (read(notify_pipe[0], &c, 1) != -1) ++ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) { ++ while (read(notify_pipe[0], &c, 1) >= 0) + debug2_f("reading"); + FD_CLR(notify_pipe[0], readset); + } +diff -up openssh-8.5p1/readconf.c.coverity openssh-8.5p1/readconf.c +--- openssh-8.5p1/readconf.c.coverity 2021-03-24 12:03:33.778968131 +0100 ++++ openssh-8.5p1/readconf.c 2021-03-24 12:03:33.785968180 +0100 +@@ -1847,6 +1847,7 @@ parse_pubkey_algos: + } else if (r != 0) { + error("%.200s line %d: glob failed for %s.", + filename, linenum, arg2); ++ free(arg2); + goto out; + } + free(arg2); +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 +@@ -1638,8 +1638,9 @@ process_server_config_line(ServerOptions + if (*activep && *charptr == NULL) { + *charptr = tilde_expand_filename(arg, getuid()); + /* increase optional counter */ +- if (intptr != NULL) +- *intptr = *intptr + 1; ++ /* DEAD CODE intptr is still NULL ;) ++ if (intptr != NULL) ++ *intptr = *intptr + 1; */ + } + break; + +diff -up openssh-8.7p1/serverloop.c.coverity openssh-8.7p1/serverloop.c +--- openssh-8.7p1/serverloop.c.coverity 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/serverloop.c 2021-08-30 16:28:22.416226981 +0200 +@@ -547,7 +547,7 @@ server_request_tun(struct ssh *ssh) + debug_f("invalid tun"); + goto done; + } +- if (auth_opts->force_tun_device != -1) { ++ if (auth_opts->force_tun_device >= 0) { + if (tun != SSH_TUNID_ANY && + auth_opts->force_tun_device != (int)tun) + goto done; +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 +@@ -869,6 +869,7 @@ sanitize_pkcs11_provider(const char *pro + + if (pkcs11_uri_parse(provider, uri) != 0) { + error("Failed to parse PKCS#11 URI"); ++ pkcs11_uri_cleanup(uri); + return NULL; + } + /* validate also provider from URI */ +diff -up openssh-7.4p1/sshd-session.c.coverity openssh-7.4p1/sshd-session.c +--- openssh-7.4p1/sshd-session.c.coverity 2016-12-23 16:40:26.897788690 +0100 ++++ openssh-7.4p1/sshd-session.c 2016-12-23 16:40:26.904788692 +0100 +@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt) + + privsep_preauth_child(ssh); + setproctitle("%s", "[net]"); +- if (box != NULL) ++ if (box != NULL) { + ssh_sandbox_child(box); ++ free(box); ++ } + + return 0; + } +@@ -2519,8 +2524,11 @@ do_ssh2_kex(struct ssh *ssh) + + if (newstr) + myproposal[PROPOSAL_KEX_ALGS] = newstr; +- else ++ else { + fatal("No supported key exchange algorithms"); ++ free(gss); ++ } ++ /* coverity[leaked_storage: FALSE]*/ + } + #endif + +diff -up openssh-8.5p1/ssh-keygen.c.coverity openssh-8.5p1/ssh-keygen.c +--- openssh-8.5p1/ssh-keygen.c.coverity 2021-03-24 12:03:33.780968145 +0100 ++++ openssh-8.5p1/ssh-keygen.c 2021-03-24 12:03:33.787968194 +0100 +@@ -2332,6 +2332,9 @@ update_krl_from_file(struct passwd *pw, + r = ssh_krl_revoke_key_sha256(krl, blob, blen); + if (r != 0) + fatal_fr(r, "revoke key failed"); ++ freezero(blob, blen); ++ blob = NULL; ++ blen = 0; + } else { + if (strncasecmp(cp, "key:", 4) == 0) { + cp += 4; diff --git a/SOURCES/openssh-6.7p1-sftp-force-permission.patch b/openssh-6.7p1-sftp-force-permission.patch similarity index 69% rename from SOURCES/openssh-6.7p1-sftp-force-permission.patch rename to openssh-6.7p1-sftp-force-permission.patch index c6a28e5..1cfa309 100644 --- a/SOURCES/openssh-6.7p1-sftp-force-permission.patch +++ b/openssh-6.7p1-sftp-force-permission.patch @@ -1,15 +1,15 @@ -diff --color -ru a/sftp-server.8 b/sftp-server.8 ---- a/sftp-server.8 2019-04-18 00:52:57.000000000 +0200 -+++ b/sftp-server.8 2022-06-20 16:03:47.892540068 +0200 +diff -up openssh-7.2p2/sftp-server.8.sftp-force-mode openssh-7.2p2/sftp-server.8 +--- openssh-7.2p2/sftp-server.8.sftp-force-mode 2016-03-09 19:04:48.000000000 +0100 ++++ openssh-7.2p2/sftp-server.8 2016-06-23 16:18:20.463854117 +0200 @@ -38,6 +38,7 @@ - .Op Fl P Ar blacklisted_requests - .Op Fl p Ar whitelisted_requests + .Op Fl P Ar denied_requests + .Op Fl p Ar allowed_requests .Op Fl u Ar umask +.Op Fl m Ar force_file_perms .Ek .Nm .Fl Q Ar protocol_feature -@@ -138,6 +139,12 @@ +@@ -138,6 +139,12 @@ Sets an explicit .Xr umask 2 to be applied to newly-created files and directories, instead of the user's default mask. @@ -22,10 +22,10 @@ diff --color -ru a/sftp-server.8 b/sftp-server.8 .El .Pp On some systems, -diff --color -ru a/sftp-server.c b/sftp-server.c ---- a/sftp-server.c 2022-06-20 16:01:26.183793633 +0200 -+++ b/sftp-server.c 2022-06-20 16:02:12.442690608 +0200 -@@ -65,6 +65,10 @@ +diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c +--- openssh-7.2p2/sftp-server.c.sftp-force-mode 2016-06-23 16:18:20.446854128 +0200 ++++ openssh-7.2p2/sftp-server.c 2016-06-23 16:20:37.950766082 +0200 +@@ -69,6 +69,10 @@ struct sshbuf *oqueue; /* Version of client */ static u_int version; @@ -36,7 +36,7 @@ diff --color -ru a/sftp-server.c b/sftp-server.c /* SSH2_FXP_INIT received */ static int init_done; -@@ -683,6 +687,7 @@ +@@ -683,6 +687,7 @@ process_open(u_int32_t id) Attrib a; char *name; int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; @@ -44,7 +44,7 @@ diff --color -ru a/sftp-server.c b/sftp-server.c if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ -@@ -692,6 +697,10 @@ +@@ -692,6 +697,10 @@ process_open(u_int32_t id) debug3("request %u: open flags %d", id, pflags); flags = flags_from_portable(pflags); mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; @@ -55,7 +55,7 @@ diff --color -ru a/sftp-server.c b/sftp-server.c logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); if (readonly && -@@ -713,6 +722,8 @@ +@@ -713,6 +722,8 @@ process_open(u_int32_t id) } } } @@ -64,16 +64,16 @@ diff --color -ru a/sftp-server.c b/sftp-server.c if (status != SSH2_FX_OK) send_status(id, status); free(name); -@@ -1555,7 +1566,7 @@ +@@ -1494,7 +1505,7 @@ sftp_server_usage(void) fprintf(stderr, "usage: %s [-ehR] [-d start_directory] [-f log_facility] " - "[-l log_level]\n\t[-P blacklisted_requests] " -- "[-p whitelisted_requests] [-u umask]\n" -+ "[-p whitelisted_requests] [-u umask] [-m force_file_perms]\n" + "[-l log_level]\n\t[-P denied_requests] " +- "[-p allowed_requests] [-u umask]\n" ++ "[-p allowed_requests] [-u umask] [-m force_file_perms]\n" " %s -Q protocol_feature\n", __progname, __progname); exit(1); -@@ -1581,7 +1592,7 @@ +@@ -1520,7 +1531,7 @@ sftp_server_main(int argc, char **argv, pw = pwcopy(user_pw); while (!skipargs && (ch = getopt(argc, argv, @@ -82,7 +82,7 @@ diff --color -ru a/sftp-server.c b/sftp-server.c switch (ch) { case 'Q': if (strcasecmp(optarg, "requests") != 0) { -@@ -1643,6 +1654,15 @@ +@@ -1580,6 +1591,15 @@ sftp_server_main(int argc, char **argv, fatal("Invalid umask \"%s\"", optarg); (void)umask((mode_t)mask); break; diff --git a/SOURCES/openssh-6.8p1-sshdT-output.patch b/openssh-6.8p1-sshdT-output.patch similarity index 80% rename from SOURCES/openssh-6.8p1-sshdT-output.patch rename to openssh-6.8p1-sshdT-output.patch index ac9169a..156e66d 100644 --- a/SOURCES/openssh-6.8p1-sshdT-output.patch +++ b/openssh-6.8p1-sshdT-output.patch @@ -3,8 +3,8 @@ diff -up openssh/servconf.c.sshdt openssh/servconf.c +++ openssh/servconf.c 2015-06-24 11:44:39.734745802 +0200 @@ -2317,7 +2317,7 @@ dump_config(ServerOptions *o) dump_cfg_string(sXAuthLocation, o->xauth_location); - dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT); - dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC); + dump_cfg_string(sCiphers, o->ciphers); + dump_cfg_string(sMacs, o->macs); - dump_cfg_string(sBanner, o->banner); + dump_cfg_string(sBanner, o->banner != NULL ? o->banner : "none"); dump_cfg_string(sForceCommand, o->adm_forced_command); diff --git a/SOURCES/openssh-7.1p2-audit-race-condition.patch b/openssh-7.1p2-audit-race-condition.patch similarity index 88% rename from SOURCES/openssh-7.1p2-audit-race-condition.patch rename to openssh-7.1p2-audit-race-condition.patch index 9c9a680..57ad148 100644 --- a/SOURCES/openssh-7.1p2-audit-race-condition.patch +++ b/openssh-7.1p2-audit-race-condition.patch @@ -13,33 +13,33 @@ diff -up openssh-7.4p1/monitor_wrap.c.audit-race openssh-7.4p1/monitor_wrap.c + struct sshbuf *m; + int r, ret = 0; + -+ debug3("%s: entering", __func__); ++ debug3_f("entering"); + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + do { + blen = atomicio(read, fdin, buf, sizeof(buf)); + if (blen == 0) /* closed pipe */ + break; + if (blen != sizeof(buf)) { -+ error("%s: Failed to read the buffer from child", __func__); ++ error_f("Failed to read the buffer from child"); + ret = -1; + break; + } + + msg_len = get_u32(buf); + if (msg_len > 256 * 1024) -+ fatal("%s: read: bad msg_len %d", __func__, msg_len); ++ fatal_f("read: bad msg_len %d", msg_len); + sshbuf_reset(m); + if ((r = sshbuf_reserve(m, msg_len, NULL)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + if (atomicio(read, fdin, sshbuf_mutable_ptr(m), msg_len) != msg_len) { -+ error("%s: Failed to read the the buffer content from the child", __func__); ++ error_f("Failed to read the the buffer content from the child"); + ret = -1; + break; + } + if (atomicio(vwrite, pmonitor->m_recvfd, buf, blen) != blen || + atomicio(vwrite, pmonitor->m_recvfd, sshbuf_mutable_ptr(m), msg_len) != msg_len) { -+ error("%s: Failed to write the message to the monitor", __func__); ++ error_f("Failed to write the message to the monitor"); + ret = -1; + break; + } @@ -109,7 +109,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c @@ -717,6 +728,8 @@ do_exec(Session *s, const char *command) } if (s->command != NULL && s->ptyfd == -1) - s->command_handle = PRIVSEP(audit_run_command(ssh, s->command)); + s->command_handle = mm_audit_run_command(ssh, s->command); + if (pipe(paudit) < 0) + fatal("pipe: %s", strerror(errno)); #endif @@ -121,7 +121,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c +#ifdef SSH_AUDIT_EVENTS + close(paudit[1]); -+ if (use_privsep && ret == 0) { ++ if (ret == 0) { + /* + * Read the audit messages from forked child and send them + * back to monitor. We don't want to communicate directly, @@ -136,8 +136,8 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c return ret; } -@@ -1538,6 +1565,34 @@ child_close_fds(void) - endpwent(); +@@ -1538,6 +1565,33 @@ child_close_fds(void) + log_redirect_stderr_to(NULL); } +void @@ -147,12 +147,11 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c + int pparent = paudit[1]; + close(paudit[0]); + /* Hack the monitor pipe to avoid race condition with parent */ -+ if (use_privsep) -+ mm_set_monitor_pipe(pparent); ++ mm_set_monitor_pipe(pparent); +#endif + + /* remove hostkey from the child's memory */ -+ destroy_sensitive_data(ssh, use_privsep); ++ destroy_sensitive_data(ssh); + /* + * We can audit this, because we hacked the pipe to direct the + * messages over postauth child. But this message requires answer @@ -176,7 +175,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); - /* remove hostkey from the child's memory */ -- destroy_sensitive_data(ssh, 1); +- destroy_sensitive_data(ssh); - ssh_packet_clear_keys(ssh); - /* Don't audit this - both us and the parent would be talking to the - monitor over a single socket, with no synchronization. */ diff --git a/SOURCES/openssh-7.2p2-k5login_directory.patch b/openssh-7.2p2-k5login_directory.patch similarity index 91% rename from SOURCES/openssh-7.2p2-k5login_directory.patch rename to openssh-7.2p2-k5login_directory.patch index 600117f..80e7678 100644 --- a/SOURCES/openssh-7.2p2-k5login_directory.patch +++ b/openssh-7.2p2-k5login_directory.patch @@ -28,14 +28,15 @@ diff --git a/auth.h b/auth.h index f9d191c..c432d2f 100644 --- a/auth.h +++ b/auth.h -@@ -222,5 +222,7 @@ int sys_auth_passwd(Authctxt *, const char *); +@@ -222,6 +222,8 @@ int sys_auth_passwd(Authctxt *, const char *); + #if defined(KRB5) && !defined(HEIMDAL) - #include krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *); +krb5_error_code ssh_krb5_get_k5login_directory(krb5_context ctx, + char **k5login_directory); #endif - #endif + + #endif /* AUTH_H */ diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c index a7c0c5f..df8cc9a 100644 --- a/gss-serv-krb5.c @@ -48,7 +49,7 @@ index a7c0c5f..df8cc9a 100644 + int ret = 0; + + ret = ssh_krb5_get_k5login_directory(krb_context, &k5login_directory); -+ debug3("%s: k5login_directory = %s (rv=%d)", __func__, k5login_directory, ret); ++ debug3_f("k5login_directory = %s (rv=%d)", k5login_directory, ret); + if (k5login_directory == NULL || ret != 0) { + /* If not set, the library will look for k5login + * files in the user's home directory, with the filename .k5login. @@ -63,7 +64,7 @@ index a7c0c5f..df8cc9a 100644 + k5login_directory[strlen(k5login_directory)-1] != '/' ? "/" : "", + pw->pw_name); + } -+ debug("%s: Checking existence of file %s", __func__, file); ++ debug_f("Checking existence of file %s", file); - snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir); return access(file, F_OK) == 0; diff --git a/SOURCES/openssh-7.2p2-s390-closefrom.patch b/openssh-7.2p2-s390-closefrom.patch similarity index 99% rename from SOURCES/openssh-7.2p2-s390-closefrom.patch rename to openssh-7.2p2-s390-closefrom.patch index 301a523..363538c 100644 --- a/SOURCES/openssh-7.2p2-s390-closefrom.patch +++ b/openssh-7.2p2-s390-closefrom.patch @@ -48,5 +48,5 @@ Author: Harald Freudenberger +#endif } (void) closedir(dirp); - } else + return; diff --git a/SOURCES/openssh-7.2p2-x11.patch b/openssh-7.2p2-x11.patch similarity index 80% rename from SOURCES/openssh-7.2p2-x11.patch rename to openssh-7.2p2-x11.patch index 48ce840..6db16be 100644 --- a/SOURCES/openssh-7.2p2-x11.patch +++ b/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; sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) + 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/SOURCES/openssh-7.3p1-x11-max-displays.patch b/openssh-7.3p1-x11-max-displays.patch similarity index 94% rename from SOURCES/openssh-7.3p1-x11-max-displays.patch rename to openssh-7.3p1-x11-max-displays.patch index 94dac8f..e28c62e 100644 --- a/SOURCES/openssh-7.3p1-x11-max-displays.patch +++ b/openssh-7.3p1-x11-max-displays.patch @@ -2,7 +2,7 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c --- openssh-7.4p1/channels.c.x11max 2016-12-23 15:46:32.071506625 +0100 +++ openssh-7.4p1/channels.c 2016-12-23 15:46:32.139506636 +0100 @@ -152,8 +152,8 @@ static int all_opens_permitted = 0; - #define FWD_PERMIT_ANY_HOST "*" + #define NUM_SOCKS 10 /* -- X11 forwarding */ -/* Maximum number of fake X11 displays to try. */ @@ -10,8 +10,8 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c +/* Minimum port number for X11 forwarding */ +#define X11_PORT_MIN 6000 - /* Per-channel callback for pre/post select() actions */ - typedef void chan_fn(struct ssh *, Channel *c, + /* Per-channel callback for pre/post IO actions */ + typedef void chan_fn(struct ssh *, Channel *c); @@ -4228,7 +4228,7 @@ channel_send_window_changes(void) */ int @@ -59,7 +59,7 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c ssh_gai_strerror(gaierr)); @@ -4457,7 +4463,7 @@ x11_connect_display(void) /* Connect it to the display. */ - if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { + if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { debug2("connect %.100s port %u: %.100s", buf, - 6000 + display_number, strerror(errno)); + X11_PORT_MIN + display_number, strerror(errno)); @@ -82,7 +82,7 @@ diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h +++ openssh-7.4p1/channels.h 2016-12-23 15:46:32.139506636 +0100 @@ -293,7 +293,7 @@ int permitopen_port(const char *); - void channel_set_x11_refuse_time(struct ssh *, u_int); + void channel_set_x11_refuse_time(struct ssh *, time_t); int x11_connect_display(struct ssh *); -int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **); +int x11_create_display_inet(struct ssh *, int, int, int, int, u_int *, int **); @@ -110,9 +110,9 @@ diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c options->x11_use_localhost = 1; if (options->xauth_location == NULL) @@ -419,7 +422,7 @@ typedef enum { - sPasswordAuthentication, sKbdInteractiveAuthentication, - sListenAddress, sAddressFamily, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, + sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication, + sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, + sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost, sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, @@ -191,13 +191,13 @@ diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5 --- openssh-7.4p1/sshd_config.5.x11max 2016-12-23 15:46:32.134506635 +0100 +++ openssh-7.4p1/sshd_config.5 2016-12-23 15:46:32.141506636 +0100 @@ -1133,6 +1133,7 @@ Available keywords are - .Cm StreamLocalBindUnlink , .Cm TrustedUserCAKeys , + .Cm UnusedConnectionTimeout , .Cm X11DisplayOffset , +.Cm X11MaxDisplays , .Cm X11Forwarding and - .Cm X11UseLocalHost . + .Cm X11UseLocalhost . @@ -1566,6 +1567,12 @@ Specifies the first display number avail X11 forwarding. This prevents sshd from interfering with real X11 servers. diff --git a/SOURCES/openssh-7.5p1-sandbox.patch b/openssh-7.5p1-sandbox.patch similarity index 51% rename from SOURCES/openssh-7.5p1-sandbox.patch rename to openssh-7.5p1-sandbox.patch index 7190813..90640a0 100644 --- a/SOURCES/openssh-7.5p1-sandbox.patch +++ b/openssh-7.5p1-sandbox.patch @@ -21,7 +21,7 @@ index ca75cc7..6e7de31 100644 + SC_ALLOW(__NR_flock), +#endif #ifdef __NR_futex - SC_ALLOW(__NR_futex), + SC_FUTEX(__NR_futex), #endif @@ -178,6 +181,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_gettimeofday @@ -69,29 +69,6 @@ index 6e7de31..e86aa2c 100644 SC_ALLOW(__NR_getrandom), #endif -- 1.9.1 - -The EP11 crypto card needs to make an ioctl call, which receives an -specific argument. This crypto card is for s390 only. - -Signed-off-by: Eduardo Barretto ---- - sandbox-seccomp-filter.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index e86aa2c..98062f1 100644 ---- a/sandbox-seccomp-filter.c -+++ b/sandbox-seccomp-filter.c -@@ -250,6 +250,8 @@ static const struct sock_filter preauth_insns[] = { - SC_ALLOW_ARG(__NR_ioctl, 1, Z90STAT_STATUS_MASK), - SC_ALLOW_ARG(__NR_ioctl, 1, ICARSAMODEXPO), - SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT), -+ /* Allow ioctls for EP11 crypto card on s390 */ -+ SC_ALLOW_ARG(__NR_ioctl, 1, ZSENDEP11CPRB), - #endif - #if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT) - /* --- 1.9.1 diff -up openssh-7.6p1/sandbox-seccomp-filter.c.sandbox openssh-7.6p1/sandbox-seccomp-filter.c --- openssh-7.6p1/sandbox-seccomp-filter.c.sandbox 2017-12-12 13:59:30.563874059 +0100 @@ -107,40 +84,3 @@ diff -up openssh-7.6p1/sandbox-seccomp-filter.c.sandbox openssh-7.6p1/sandbox-se SC_ALLOW(__NR_getrandom), #endif - -From ef34ea4521b042dd8a9c4c7455f5d1a8f8ee5bb2 Mon Sep 17 00:00:00 2001 -From: Harald Freudenberger -Date: Fri, 24 May 2019 10:11:15 +0200 -Subject: [PATCH] allow s390 specific ioctl for ecc hardware support - -Adding another s390 specific ioctl to be able to support ECC hardware acceleration -to the sandbox seccomp filter rules. - -Now the ibmca openssl engine provides elliptic curve cryptography support with the -help of libica and CCA crypto cards. This is done via jet another ioctl call to the zcrypt -device driver and so there is a need to enable this on the openssl sandbox. - -Code is s390 specific and has been tested, verified and reviewed. - -Please note that I am also the originator of the previous changes in that area. -I posted these changes to Eduardo and he forwarded the patches to the openssl -community. - -Signed-off-by: Harald Freudenberger -Reviewed-by: Joerg Schmidbauer ---- - sandbox-seccomp-filter.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index 5edbc6946..56eb9317f 100644 ---- a/sandbox-seccomp-filter.c -+++ b/sandbox-seccomp-filter.c -@@ -252,6 +252,7 @@ static const struct sock_filter preauth_insns[] = { - SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT), - /* Allow ioctls for EP11 crypto card on s390 */ - SC_ALLOW_ARG(__NR_ioctl, 1, ZSENDEP11CPRB), -+ SC_ALLOW_ARG(__NR_ioctl, 1, ZSECSENDCPRB), - #endif - #if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT) - /* diff --git a/SOURCES/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch similarity index 76% rename from SOURCES/openssh-7.6p1-audit.patch rename to openssh-7.6p1-audit.patch index 01e509e..c884292 100644 --- a/SOURCES/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -1,7 +1,7 @@ -diff -up openssh/audit-bsm.c.audit openssh/audit-bsm.c ---- openssh/audit-bsm.c.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/audit-bsm.c 2019-04-03 17:02:20.713886041 +0200 -@@ -372,13 +372,26 @@ audit_connection_from(const char *host, +diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c +--- openssh-8.6p1/audit-bsm.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/audit-bsm.c 2021-04-19 16:47:35.753062106 +0200 +@@ -373,13 +373,26 @@ audit_connection_from(const char *host, #endif } @@ -29,7 +29,7 @@ diff -up openssh/audit-bsm.c.audit openssh/audit-bsm.c audit_session_open(struct logininfo *li) { /* not implemented */ -@@ -390,6 +403,12 @@ audit_session_close(struct logininfo *li +@@ -391,6 +404,12 @@ audit_session_close(struct logininfo *li /* not implemented */ } @@ -42,7 +42,7 @@ diff -up openssh/audit-bsm.c.audit openssh/audit-bsm.c void audit_event(struct ssh *ssh, ssh_audit_event_t event) { -@@ -451,4 +470,28 @@ audit_event(struct ssh *ssh, ssh_audit_e +@@ -452,4 +471,28 @@ audit_event(struct ssh *ssh, ssh_audit_e debug("%s: unhandled event %d", __func__, event); } } @@ -71,9 +71,9 @@ diff -up openssh/audit-bsm.c.audit openssh/audit-bsm.c + /* not implemented */ +} #endif /* BSM */ -diff -up openssh/audit.c.audit openssh/audit.c ---- openssh/audit.c.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/audit.c 2019-04-03 17:02:20.713886041 +0200 +diff -up openssh-8.6p1/audit.c.audit openssh-8.6p1/audit.c +--- openssh-8.6p1/audit.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/audit.c 2021-04-19 16:47:35.753062106 +0200 @@ -34,6 +34,12 @@ #include "log.h" #include "hostfile.h" @@ -129,19 +129,19 @@ diff -up openssh/audit.c.audit openssh/audit.c +void +audit_unsupported(struct ssh *ssh, int what) +{ -+ PRIVSEP(audit_unsupported_body(ssh, what)); ++ mm_audit_unsupported_body(ssh, what); +} + +void +audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) +{ -+ PRIVSEP(audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid())); ++ mm_audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid()); +} + +void +audit_session_key_free(struct ssh *ssh, int ctos) +{ -+ PRIVSEP(audit_session_key_free_body(ssh, ctos, getpid(), getuid())); ++ mm_audit_session_key_free_body(ssh, ctos, getpid(), getuid()); +} + # ifndef CUSTOM_SSH_AUDIT_EVENTS @@ -251,9 +251,9 @@ diff -up openssh/audit.c.audit openssh/audit.c } # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh/audit.h.audit openssh/audit.h ---- openssh/audit.h.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/audit.h 2019-04-03 17:02:20.713886041 +0200 +diff -up openssh-8.6p1/audit.h.audit openssh-8.6p1/audit.h +--- openssh-8.6p1/audit.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/audit.h 2021-04-19 16:47:35.753062106 +0200 @@ -26,6 +26,7 @@ # define _SSH_AUDIT_H @@ -296,9 +296,9 @@ diff -up openssh/audit.h.audit openssh/audit.h +void audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); #endif /* _SSH_AUDIT_H */ -diff -up openssh/audit-linux.c.audit openssh/audit-linux.c ---- openssh/audit-linux.c.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/audit-linux.c 2019-04-03 17:02:20.713886041 +0200 +diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c +--- openssh-8.6p1/audit-linux.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/audit-linux.c 2021-04-19 16:47:35.753062106 +0200 @@ -33,27 +33,40 @@ #include "log.h" @@ -446,7 +446,7 @@ diff -up openssh/audit-linux.c.audit openssh/audit-linux.c /* Below is the sshd audit API code */ void -@@ -76,49 +176,210 @@ audit_connection_from(const char *host, +@@ -76,49 +176,211 @@ audit_connection_from(const char *host, /* not implemented */ } @@ -525,6 +525,7 @@ diff -up openssh/audit-linux.c.audit openssh/audit-linux.c case SSH_AUTH_FAIL_PASSWD: + if (options.use_pam) + break; ++ /* Fallthrough */ + case SSH_LOGIN_EXCEED_MAXTRIES: case SSH_AUTH_FAIL_KBDINT: case SSH_AUTH_FAIL_PUBKEY: @@ -564,7 +565,7 @@ diff -up openssh/audit-linux.c.audit openssh/audit-linux.c +{ +#ifdef AUDIT_CRYPTO_SESSION + char buf[AUDIT_LOG_SIZE]; -+ const static char *name[] = { "cipher", "mac", "comp" }; ++ static const char *name[] = { "cipher", "mac", "comp" }; + char *s; + int audit_fd; + @@ -582,7 +583,7 @@ diff -up openssh/audit-linux.c.audit openssh/audit-linux.c +#endif +} + -+const static char *direction[] = { "from-server", "from-client", "both" }; ++static const char *direction[] = { "from-server", "from-client", "both" }; + +void +audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, @@ -661,7 +662,7 @@ diff -up openssh/audit-linux.c.audit openssh/audit-linux.c + } + audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, + buf, NULL, -+ listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh), ++ ssh_remote_ipaddr(ssh), /*FIXME listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh) */ + NULL, 1); + audit_close(audit_fd); + /* do not abort if the error is EPERM and sshd is run as non root user */ @@ -669,9 +670,9 @@ diff -up openssh/audit-linux.c.audit openssh/audit-linux.c + error("cannot write into audit"); +} #endif /* USE_LINUX_AUDIT */ -diff -up openssh/auditstub.c.audit openssh/auditstub.c ---- openssh/auditstub.c.audit 2019-04-03 17:02:20.714886050 +0200 -+++ openssh/auditstub.c 2019-04-03 17:02:20.714886050 +0200 +diff -up openssh-8.6p1/auditstub.c.audit openssh-8.6p1/auditstub.c +--- openssh-8.6p1/auditstub.c.audit 2021-04-19 16:47:35.754062114 +0200 ++++ openssh-8.6p1/auditstub.c 2021-04-19 16:47:35.754062114 +0200 @@ -0,0 +1,52 @@ +/* $Id: auditstub.c,v 1.1 jfch Exp $ */ + @@ -725,42 +726,43 @@ diff -up openssh/auditstub.c.audit openssh/auditstub.c +audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) +{ +} -diff -up openssh/auth2.c.audit openssh/auth2.c ---- openssh/auth2.c.audit 2019-04-03 17:02:20.651885453 +0200 -+++ openssh/auth2.c 2019-04-03 17:02:20.714886050 +0200 -@@ -303,9 +303,6 @@ input_userauth_request(int type, u_int32 - } else { +diff -up openssh-8.6p1/auth2.c.audit openssh-8.6p1/auth2.c +--- openssh-8.6p1/auth2.c.audit 2021-04-19 16:47:35.682061561 +0200 ++++ openssh-8.6p1/auth2.c 2021-04-19 16:47:35.754062114 +0200 +@@ -298,9 +298,6 @@ input_userauth_request(int type, u_int32 + authctxt->valid = 0; /* Invalid user, fake password information */ authctxt->pw = fakepw(); -#ifdef SSH_AUDIT_EVENTS -- PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); +- mm_audit_event(ssh, SSH_INVALID_USER); -#endif } #ifdef USE_PAM if (options.use_pam) -diff -up openssh/auth2-hostbased.c.audit openssh/auth2-hostbased.c ---- openssh/auth2-hostbased.c.audit 2019-04-03 17:02:20.612885083 +0200 -+++ openssh/auth2-hostbased.c 2019-04-03 17:02:20.714886050 +0200 +diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c +--- openssh-8.6p1/auth2-hostbased.c.audit 2021-04-19 16:47:35.656061361 +0200 ++++ openssh-8.6p1/auth2-hostbased.c 2021-04-19 16:47:35.754062114 +0200 @@ -158,7 +158,7 @@ userauth_hostbased(struct ssh *ssh) authenticated = 0; - if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser, - chost, key)) && -- PRIVSEP(sshkey_verify(key, sig, slen, -+ PRIVSEP(hostbased_key_verify(ssh, key, sig, slen, - sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0) + if (mm_hostbased_key_allowed(ssh, authctxt->pw, cuser, + chost, key) && +- mm_sshkey_verify(key, sig, slen, ++ mm_hostbased_key_verify(ssh, key, sig, slen, + sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL) == 0) authenticated = 1; -@@ -175,6 +175,19 @@ done: +@@ -175,6 +175,20 @@ done: return authenticated; } +int +hostbased_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, -+ size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat) ++ size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ + int rv; + -+ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat); ++ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat, detailsp); +#ifdef SSH_AUDIT_EVENTS + audit_key(ssh, 0, &rv, key); +#endif @@ -770,29 +772,30 @@ diff -up openssh/auth2-hostbased.c.audit openssh/auth2-hostbased.c /* return 1 if given hostkey is allowed */ int hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, -diff -up openssh/auth2-pubkey.c.audit openssh/auth2-pubkey.c ---- openssh/auth2-pubkey.c.audit 2019-04-03 17:02:20.691885832 +0200 -+++ openssh/auth2-pubkey.c 2019-04-03 17:02:20.714886050 +0200 -@@ -219,7 +219,7 @@ userauth_pubkey(struct ssh *ssh) +diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c +--- openssh-8.6p1/auth2-pubkey.c.audit 2021-04-19 16:47:35.726061899 +0200 ++++ openssh-8.6p1/auth2-pubkey.c 2021-04-19 16:47:35.754062114 +0200 +@@ -213,7 +213,7 @@ userauth_pubkey(struct ssh *ssh) /* test for correct signature */ authenticated = 0; - if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) && -- PRIVSEP(sshkey_verify(key, sig, slen, -+ PRIVSEP(user_key_verify(ssh, key, sig, slen, + if (mm_user_key_allowed(ssh, pw, key, 1, &authopts) && +- mm_sshkey_verify(key, sig, slen, ++ mm_user_key_verify(ssh, key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, - ssh->compat)) == 0) { -@@ -278,6 +278,19 @@ done: + ssh->compat, &sig_details) == 0) { +@@ -305,6 +305,20 @@ done: return authenticated; } +int +user_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, -+ size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat) ++ size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ + int rv; + -+ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat); ++ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat, detailsp); +#ifdef SSH_AUDIT_EVENTS + audit_key(ssh, 1, &rv, key); +#endif @@ -800,21 +803,12 @@ diff -up openssh/auth2-pubkey.c.audit openssh/auth2-pubkey.c +} + static int - match_principals_option(const char *principal_list, struct sshkey_cert *cert) - { -diff -up openssh/auth.c.audit openssh/auth.c ---- openssh/auth.c.audit 2019-04-03 17:02:20.691885832 +0200 -+++ openssh/auth.c 2019-04-03 17:02:20.714886050 +0200 -@@ -366,7 +366,7 @@ auth_log(struct ssh *ssh, int authentica - # endif - #endif - #ifdef SSH_AUDIT_EVENTS -- if (authenticated == 0 && !authctxt->postponed) -+ if (authenticated == 0 && !authctxt->postponed && !partial) - audit_event(ssh, audit_classify_auth(method)); - #endif - } -@@ -592,9 +592,6 @@ getpwnamallow(struct ssh *ssh, const cha + match_principals_file(struct passwd *pw, char *file, + struct sshkey_cert *cert, struct sshauthopt **authoptsp) +diff -up openssh-8.6p1/auth.c.audit openssh-8.6p1/auth.c +--- openssh-8.6p1/auth.c.audit 2021-04-19 16:47:35.681061553 +0200 ++++ openssh-8.6p1/auth.c 2021-04-19 16:47:35.754062114 +0200 +@@ -597,9 +597,6 @@ getpwnamallow(struct ssh *ssh, const cha record_failed_login(ssh, user, auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); #endif @@ -824,31 +818,31 @@ diff -up openssh/auth.c.audit openssh/auth.c return (NULL); } if (!allowed_user(ssh, pw)) -diff -up openssh/auth.h.audit openssh/auth.h ---- openssh/auth.h.audit 2019-04-03 17:02:20.692885842 +0200 -+++ openssh/auth.h 2019-04-03 17:02:20.714886050 +0200 -@@ -195,6 +195,8 @@ struct passwd * getpwnamallow(struct ssh - - char *expand_authorized_keys(const char *, struct passwd *pw); - char *authorized_principals_file(struct passwd *); -+int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int); - - FILE *auth_openkeyfile(const char *, struct passwd *, int); - FILE *auth_openprincipals(const char *, struct passwd *, int); -@@ -214,6 +216,8 @@ struct sshkey *get_hostkey_private_by_ty +diff -up openssh-8.6p1/auth.h.audit openssh-8.6p1/auth.h +--- openssh-8.6p1/auth.h.audit 2021-04-19 16:47:35.697061676 +0200 ++++ openssh-8.6p1/auth.h 2021-04-19 16:47:35.754062114 +0200 +@@ -212,6 +214,8 @@ struct sshkey *get_hostkey_private_by_ty int get_hostkey_index(struct sshkey *, int, struct ssh *); int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *); +int hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int); ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); /* Key / cert options linkage to auth layer */ - const struct sshauthopt *auth_options(struct ssh *); -diff -up openssh/cipher.c.audit openssh/cipher.c ---- openssh/cipher.c.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/cipher.c 2019-04-03 17:02:20.714886050 +0200 -@@ -61,25 +61,6 @@ struct sshcipher_ctx { + int auth_activate_options(struct ssh *, struct sshauthopt *); +@@ -239,6 +241,8 @@ struct passwd * getpwnamallow(struct ssh + char *, const char *, const char *, const char *, struct sshauthopt **); + int auth_check_authkeys_file(struct passwd *, FILE *, char *, + struct sshkey *, const char *, const char *, struct sshauthopt **); ++int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); + FILE *auth_openkeyfile(const char *, struct passwd *, int); + FILE *auth_openprincipals(const char *, struct passwd *, int); + +diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c +--- openssh-8.6p1/cipher.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/cipher.c 2021-04-19 16:47:35.755062122 +0200 +@@ -64,25 +64,6 @@ struct sshcipher_ctx { const struct sshcipher *cipher; }; @@ -874,19 +868,19 @@ diff -up openssh/cipher.c.audit openssh/cipher.c static const struct sshcipher ciphers[] = { #ifdef WITH_OPENSSL #ifndef OPENSSL_NO_DES -@@ -410,7 +391,7 @@ cipher_get_length(struct sshcipher_ctx * +@@ -422,7 +403,7 @@ cipher_get_length(struct sshcipher_ctx * void cipher_free(struct sshcipher_ctx *cc) { - if (cc == NULL) + if (cc == NULL || cc->cipher == NULL) return; - if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) - explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); -diff -up openssh/cipher.h.audit openssh/cipher.h ---- openssh/cipher.h.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/cipher.h 2019-04-03 17:02:20.714886050 +0200 -@@ -45,7 +45,25 @@ + if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { + chachapoly_free(cc->cp_ctx); +diff -up openssh-8.6p1/cipher.h.audit openssh-8.6p1/cipher.h +--- openssh-8.6p1/cipher.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/cipher.h 2021-04-19 16:47:35.755062122 +0200 +@@ -47,7 +47,25 @@ #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 @@ -913,18 +907,18 @@ diff -up openssh/cipher.h.audit openssh/cipher.h struct sshcipher_ctx; const struct sshcipher *cipher_by_name(const char *); -diff -up openssh/kex.c.audit openssh/kex.c ---- openssh/kex.c.audit 2019-04-03 17:02:20.652885462 +0200 -+++ openssh/kex.c 2019-04-03 17:02:20.715886060 +0200 -@@ -60,6 +60,7 @@ - #include "ssherr.h" +diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c +--- openssh-8.6p1/kex.c.audit 2021-04-19 16:47:35.743062030 +0200 ++++ openssh-8.6p1/kex.c 2021-04-19 16:47:35.755062122 +0200 +@@ -65,6 +65,7 @@ #include "sshbuf.h" #include "digest.h" + #include "xmalloc.h" +#include "audit.h" - #ifdef GSSAPI - #include "ssh-gss.h" -@@ -758,12 +759,16 @@ kex_start_rekex(struct ssh *ssh) + /* prototype */ + static int kex_choose_conf(struct ssh *, uint32_t seq); +@@ -816,12 +817,16 @@ kex_start_rekex(struct ssh *ssh) } static int @@ -941,9 +935,9 @@ diff -up openssh/kex.c.audit openssh/kex.c return SSH_ERR_NO_CIPHER_ALG_MATCH; + } if ((enc->cipher = cipher_by_name(name)) == NULL) { + error_f("unsupported cipher %s", name); free(name); - return SSH_ERR_INTERNAL_ERROR; -@@ -783,8 +788,12 @@ choose_mac(struct ssh *ssh, struct sshma +@@ -842,8 +847,12 @@ choose_mac(struct ssh *ssh, struct sshma { char *name = match_list(client, server, NULL); @@ -955,9 +949,9 @@ diff -up openssh/kex.c.audit openssh/kex.c return SSH_ERR_NO_MAC_ALG_MATCH; + } if (mac_setup(mac, name) < 0) { + error_f("unsupported MAC %s", name); free(name); - return SSH_ERR_INTERNAL_ERROR; -@@ -796,12 +805,16 @@ choose_mac(struct ssh *ssh, struct sshma +@@ -856,12 +865,16 @@ choose_mac(struct ssh *ssh, struct sshma } static int @@ -973,10 +967,10 @@ diff -up openssh/kex.c.audit openssh/kex.c +#endif return SSH_ERR_NO_COMPRESS_ALG_MATCH; + } + #ifdef WITH_ZLIB if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; - } else if (strcmp(name, "zlib") == 0) { -@@ -933,7 +946,7 @@ kex_choose_conf(struct ssh *ssh) +@@ -1002,7 +1015,7 @@ kex_choose_conf(struct ssh *ssh) nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; @@ -985,7 +979,7 @@ diff -up openssh/kex.c.audit openssh/kex.c sprop[nenc])) != 0) { kex->failed_choice = peer[nenc]; peer[nenc] = NULL; -@@ -948,7 +961,7 @@ kex_choose_conf(struct ssh *ssh) +@@ -1017,7 +1030,7 @@ kex_choose_conf(struct ssh *ssh) peer[nmac] = NULL; goto out; } @@ -994,7 +988,7 @@ diff -up openssh/kex.c.audit openssh/kex.c sprop[ncomp])) != 0) { kex->failed_choice = peer[ncomp]; peer[ncomp] = NULL; -@@ -971,6 +984,10 @@ kex_choose_conf(struct ssh *ssh) +@@ -1040,6 +1053,10 @@ kex_choose_conf(struct ssh *ssh) dh_need = MAXIMUM(dh_need, newkeys->enc.block_size); dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len); dh_need = MAXIMUM(dh_need, newkeys->mac.key_len); @@ -1005,7 +999,7 @@ diff -up openssh/kex.c.audit openssh/kex.c } /* XXX need runden? */ kex->we_need = need; -@@ -1129,6 +1146,36 @@ dump_digest(const char *msg, const u_cha +@@ -1297,6 +1314,36 @@ dump_digest(const char *msg, const u_cha } #endif @@ -1042,9 +1036,9 @@ diff -up openssh/kex.c.audit openssh/kex.c /* * Send a plaintext error message to the peer, suffixed by \r\n. * Only used during banner exchange, and there only for the server. -diff -up openssh/kex.h.audit openssh/kex.h ---- openssh/kex.h.audit 2019-04-03 17:02:20.652885462 +0200 -+++ openssh/kex.h 2019-04-03 17:02:20.715886060 +0200 +diff -up openssh-8.6p1/kex.h.audit openssh-8.6p1/kex.h +--- openssh-8.6p1/kex.h.audit 2021-04-19 16:47:35.683061568 +0200 ++++ openssh-8.6p1/kex.h 2021-04-19 16:47:35.756062129 +0200 @@ -226,6 +226,8 @@ int kexgss_client(struct ssh *); int kexgss_server(struct ssh *); #endif @@ -1054,10 +1048,10 @@ diff -up openssh/kex.h.audit openssh/kex.h int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); -diff -up openssh/mac.c.audit openssh/mac.c ---- openssh/mac.c.audit 2019-04-03 17:02:20.652885462 +0200 -+++ openssh/mac.c 2019-04-03 17:02:20.715886060 +0200 -@@ -243,6 +243,20 @@ mac_clear(struct sshmac *mac) +diff -up openssh-8.6p1/mac.c.audit openssh-8.6p1/mac.c +--- openssh-8.6p1/mac.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/mac.c 2021-04-19 16:47:35.756062129 +0200 +@@ -239,6 +239,20 @@ mac_clear(struct sshmac *mac) mac->umac_ctx = NULL; } @@ -1078,9 +1072,9 @@ diff -up openssh/mac.c.audit openssh/mac.c /* XXX copied from ciphers_valid */ #define MAC_SEP "," int -diff -up openssh/mac.h.audit openssh/mac.h ---- openssh/mac.h.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/mac.h 2019-04-03 17:02:20.715886060 +0200 +diff -up openssh-8.6p1/mac.h.audit openssh-8.6p1/mac.h +--- openssh-8.6p1/mac.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/mac.h 2021-04-19 16:47:35.756062129 +0200 @@ -49,5 +49,6 @@ int mac_compute(struct sshmac *, u_int3 int mac_check(struct sshmac *, u_int32_t, const u_char *, size_t, const u_char *, size_t); @@ -1088,22 +1082,21 @@ diff -up openssh/mac.h.audit openssh/mac.h +void mac_destroy(struct sshmac *); #endif /* SSHMAC_H */ -diff -up openssh/Makefile.in.audit openssh/Makefile.in ---- openssh/Makefile.in.audit 2019-04-03 17:02:20.705885965 +0200 -+++ openssh/Makefile.in 2019-04-03 17:02:20.715886060 +0200 -@@ -109,7 +109,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kexgexc.o kexgexs.o \ - sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ +diff -up openssh-8.6p1/Makefile.in.audit openssh-8.6p1/Makefile.in +--- openssh-8.6p1/Makefile.in.audit 2021-04-19 16:47:35.731061937 +0200 ++++ openssh-8.6p1/Makefile.in 2021-04-19 16:47:35.756062129 +0200 +@@ -112,7 +112,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kexsntrup761x25519.o sntrup761.o kexgen.o \ kexgssc.o \ -- platform-pledge.o platform-tracing.o platform-misc.o -+ platform-pledge.o platform-tracing.o platform-misc.o \ -+ auditstub.o + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ +- sshbuf-io.o ++ sshbuf-io.o auditstub.o + SKOBJS= ssh-sk-client.o - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ -diff -up openssh/monitor.c.audit openssh/monitor.c ---- openssh/monitor.c.audit 2019-04-03 17:02:20.674885671 +0200 -+++ openssh/monitor.c 2019-04-03 17:03:17.201421405 +0200 +diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c +--- openssh-8.6p1/monitor.c.audit 2021-04-19 16:47:35.707061753 +0200 ++++ openssh-8.6p1/monitor.c 2021-04-19 16:47:35.756062129 +0200 @@ -93,6 +93,7 @@ #include "compat.h" #include "ssh2.h" @@ -1111,12 +1104,12 @@ diff -up openssh/monitor.c.audit openssh/monitor.c +#include "audit.h" #include "match.h" #include "ssherr.h" - -@@ -107,6 +108,8 @@ extern u_char session_id[]; + #include "sk-api.h" +@@ -107,6 +108,8 @@ extern u_int utmp_len; extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ -+extern void destroy_sensitive_data(struct ssh *, int); ++extern void destroy_sensitive_data(struct ssh *); + /* State exported from the child */ static struct sshbuf *child_state; @@ -1156,40 +1149,40 @@ diff -up openssh/monitor.c.audit openssh/monitor.c #endif {0, 0, NULL} }; -@@ -1445,8 +1462,10 @@ mm_answer_keyverify(struct ssh *ssh, int - char *sigalg; - size_t signaturelen, datalen, bloblen; - int r, ret, valid_data = 0, encoded_ret; +@@ -1444,8 +1461,10 @@ mm_answer_keyverify(struct ssh *ssh, int + int r, ret, req_presence = 0, req_verify = 0, valid_data = 0; + int encoded_ret; + struct sshkey_sig_details *sig_details = NULL; + int type = 0; -- if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || +- if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || + if ((r = sshbuf_get_u32(m, &type)) != 0 || -+ (r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || - (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || - (r = sshbuf_get_string(m, &data, &datalen)) != 0 || ++ (r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || + (r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || + (r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) -@@ -1455,6 +1474,8 @@ mm_answer_keyverify(struct ssh *ssh, int +@@ -1454,6 +1473,8 @@ mm_answer_keyverify(struct ssh *ssh, int if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) - fatal("%s: bad key, not previously allowed", __func__); + fatal_f("bad key, not previously allowed"); + if (type != key_blobtype) -+ fatal("%s: bad key type", __func__); ++ fatal_f("bad key type"); /* Empty signature algorithm means NULL. */ if (*sigalg == '\0') { -@@ -1470,21 +1491,24 @@ mm_answer_keyverify(struct ssh *ssh, int +@@ -1469,14 +1490,19 @@ mm_answer_keyverify(struct ssh *ssh, int case MM_USERKEY: - valid_data = monitor_valid_userblob(data, datalen); + valid_data = monitor_valid_userblob(ssh, data, datalen); auth_method = "publickey"; + ret = user_key_verify(ssh, key, signature, signaturelen, data, -+ datalen, sigalg, ssh->compat); ++ datalen, sigalg, ssh->compat, &sig_details); break; case MM_HOSTKEY: valid_data = monitor_valid_hostbasedblob(data, datalen, hostbased_cuser, hostbased_chost); -+ ret = hostbased_key_verify(ssh, key, signature, signaturelen, data, -+ datalen, sigalg, ssh->compat); auth_method = "hostbased"; ++ ret = hostbased_key_verify(ssh, key, signature, signaturelen, data, ++ datalen, sigalg, ssh->compat, &sig_details); break; default: valid_data = 0; @@ -1197,62 +1190,64 @@ diff -up openssh/monitor.c.audit openssh/monitor.c break; } if (!valid_data) - fatal("%s: bad signature data blob", __func__); +@@ -1488,8 +1514,6 @@ mm_answer_keyverify(struct ssh *ssh, int + SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint failed"); - ret = sshkey_verify(key, signature, signaturelen, data, datalen, -- sigalg, ssh->compat); - debug3("%s: %s %p signature %s", __func__, auth_method, key, - (ret == 0) ? "verified" : "unverified"); - auth2_record_key(authctxt, ret == 0, key); -@@ -1536,13 +1560,19 @@ mm_record_login(struct ssh *ssh, Session +- sigalg, ssh->compat, &sig_details); + debug3_f("%s %s signature using %s %s%s%s", auth_method, + sshkey_type(key), sigalg == NULL ? "default" : sigalg, + (ret == 0) ? "verified" : "unverified", +@@ -1576,13 +1600,19 @@ mm_record_login(struct ssh *ssh, Session } static void -mm_session_close(Session *s) +mm_session_close(struct ssh *ssh, Session *s) { - debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); + debug3_f("session %d pid %ld", s->self, (long)s->pid); if (s->ttyfd != -1) { - debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); + debug3_f("tty %s ptyfd %d", s->tty, s->ptyfd); session_pty_cleanup2(s); } +#ifdef SSH_AUDIT_EVENTS + if (s->command != NULL) { -+ debug3("%s: command %d", __func__, s->command_handle); ++ debug3_f("command %d", s->command_handle); + session_end_command2(ssh, s); + } +#endif session_unused(s->self); } -@@ -1609,7 +1639,7 @@ mm_answer_pty(struct ssh *ssh, int sock, +@@ -1649,7 +1679,7 @@ mm_answer_pty(struct ssh *ssh, int sock, error: if (s != NULL) - mm_session_close(s); + mm_session_close(ssh, s); if ((r = sshbuf_put_u32(m, 0)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble 0"); mm_request_send(sock, MONITOR_ANS_PTY, m); -@@ -1628,7 +1658,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, i +@@ -1668,7 +1698,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, i if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse tty"); if ((s = session_by_tty(tty)) != NULL) - mm_session_close(s); + mm_session_close(ssh, s); sshbuf_reset(m); free(tty); return (0); -@@ -1650,6 +1680,8 @@ mm_answer_term(struct ssh *ssh, int sock +@@ -1690,6 +1720,8 @@ mm_answer_term(struct ssh *ssh, int sock sshpam_cleanup(); #endif -+ destroy_sensitive_data(ssh, 0); ++ destroy_sensitive_data(ssh); + while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); -@@ -1696,12 +1728,47 @@ mm_answer_audit_command(struct ssh *ssh, +@@ -1736,12 +1768,47 @@ mm_answer_audit_command(struct ssh *ssh, { char *cmd; int r; @@ -1266,7 +1261,7 @@ diff -up openssh/monitor.c.audit openssh/monitor.c - audit_run_command(cmd); + s = session_new(); + if (s == NULL) -+ fatal("%s: error allocating a session", __func__); ++ fatal_f("error allocating a session"); + s->command = cmd; +#ifdef SSH_AUDIT_EVENTS + s->command_handle = audit_run_command(ssh, cmd); @@ -1288,31 +1283,31 @@ diff -up openssh/monitor.c.audit openssh/monitor.c + u_char *cmd = NULL; + Session *s; + -+ debug3("%s entering", __func__); ++ debug3_f("entering"); + if ((r = sshbuf_get_u32(m, &handle)) != 0 || + (r = sshbuf_get_string(m, &cmd, &len)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + s = session_by_id(handle); + if (s == NULL || s->ttyfd != -1 || s->command == NULL || + strcmp(s->command, cmd) != 0) -+ fatal("%s: invalid handle", __func__); ++ fatal_f("invalid handle"); + mm_session_close(ssh, s); free(cmd); return (0); } -@@ -1767,6 +1834,7 @@ monitor_apply_keystate(struct ssh *ssh, +@@ -1813,6 +1880,7 @@ monitor_apply_keystate(struct ssh *ssh, void mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { + struct sshbuf *m; - debug3("%s: Waiting for new keys", __func__); + debug3_f("Waiting for new keys"); if ((child_state = sshbuf_new()) == NULL) -@@ -1774,6 +1842,19 @@ mm_get_keystate(struct ssh *ssh, struct +@@ -1820,6 +1888,19 @@ mm_get_keystate(struct ssh *ssh, struct mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, child_state); - debug3("%s: GOT new keys", __func__); + debug3_f("GOT new keys"); + +#ifdef SSH_AUDIT_EVENTS + m = sshbuf_new(); @@ -1329,7 +1324,7 @@ diff -up openssh/monitor.c.audit openssh/monitor.c } -@@ -2066,3 +2147,102 @@ mm_answer_gss_updatecreds(struct ssh *ss +@@ -2111,3 +2192,102 @@ mm_answer_gss_updatecreds(struct ssh *ss #endif /* GSSAPI */ @@ -1340,7 +1335,7 @@ diff -up openssh/monitor.c.audit openssh/monitor.c + int what, r; + + if ((r = sshbuf_get_u32(m, &what)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + audit_unsupported_body(ssh, what); + @@ -1365,10 +1360,10 @@ diff -up openssh/monitor.c.audit openssh/monitor.c + (r = sshbuf_get_cstring(m, &compress, NULL)) != 0 || + (r = sshbuf_get_cstring(m, &pfs, NULL)) != 0 || + (r = sshbuf_get_u64(m, &tmp)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + pid = (pid_t) tmp; + if ((r = sshbuf_get_u64(m, &tmp)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + uid = (pid_t) tmp; + + audit_kex_body(ssh, ctos, cipher, mac, compress, pfs, pid, uid); @@ -1393,10 +1388,10 @@ diff -up openssh/monitor.c.audit openssh/monitor.c + + if ((r = sshbuf_get_u32(m, &ctos)) != 0 || + (r = sshbuf_get_u64(m, &tmp)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + pid = (pid_t) tmp; + if ((r = sshbuf_get_u64(m, &tmp)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + uid = (uid_t) tmp; + + audit_session_key_free_body(ssh, ctos, pid, uid); @@ -1418,10 +1413,10 @@ diff -up openssh/monitor.c.audit openssh/monitor.c + + if ((r = sshbuf_get_cstring(m, &fp, &len)) != 0 || + (r = sshbuf_get_u64(m, &tmp)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + pid = (pid_t) tmp; + if ((r = sshbuf_get_u64(m, &tmp)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + uid = (uid_t) tmp; + + audit_destroy_sensitive_data(ssh, fp, pid, uid); @@ -1432,9 +1427,9 @@ diff -up openssh/monitor.c.audit openssh/monitor.c + return 0; +} +#endif /* SSH_AUDIT_EVENTS */ -diff -up openssh/monitor.h.audit openssh/monitor.h ---- openssh/monitor.h.audit 2019-04-03 17:02:20.674885671 +0200 -+++ openssh/monitor.h 2019-04-03 17:02:20.715886060 +0200 +diff -up openssh-8.6p1/monitor.h.audit openssh-8.6p1/monitor.h +--- openssh-8.6p1/monitor.h.audit 2021-04-19 16:47:35.707061753 +0200 ++++ openssh-8.6p1/monitor.h 2021-04-19 16:47:35.757062137 +0200 @@ -65,7 +65,13 @@ enum monitor_reqtype { MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, @@ -1450,50 +1445,52 @@ diff -up openssh/monitor.h.audit openssh/monitor.h MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, -diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c ---- openssh/monitor_wrap.c.audit 2019-04-03 17:02:20.653885472 +0200 -+++ openssh/monitor_wrap.c 2019-04-03 17:02:20.716886069 +0200 -@@ -513,7 +513,7 @@ mm_key_allowed(enum mm_keytype type, con +diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c +--- openssh-8.6p1/monitor_wrap.c.audit 2021-04-19 16:47:35.685061584 +0200 ++++ openssh-8.6p1/monitor_wrap.c 2021-04-19 16:47:35.757062137 +0200 +@@ -520,7 +520,7 @@ mm_key_allowed(enum mm_keytype type, con */ int -mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, +mm_sshkey_verify(enum mm_keytype type, const struct sshkey *key, const u_char *sig, size_t siglen, - const u_char *data, size_t datalen, const char *sigalg, u_int compat) + const u_char *data, size_t datalen, const char *sigalg, u_int compat, + struct sshkey_sig_details **sig_detailsp) { - struct sshbuf *m; -@@ -525,7 +525,8 @@ mm_sshkey_verify(const struct sshkey *ke - +@@ -536,7 +536,8 @@ mm_sshkey_verify(const struct sshkey *ke + *sig_detailsp = NULL; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); - if ((r = sshkey_puts(key, m)) != 0 || + if ((r = sshbuf_put_u32(m, type)) != 0 || + (r = sshkey_puts(key, m)) != 0 || (r = sshbuf_put_string(m, sig, siglen)) != 0 || (r = sshbuf_put_string(m, data, datalen)) != 0 || (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0) -@@ -547,6 +548,20 @@ mm_sshkey_verify(const struct sshkey *ke +@@ -569,6 +570,22 @@ mm_sshkey_verify(const struct sshkey *ke return 0; } +int +mm_hostbased_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, size_t siglen, -+ const u_char *data, size_t datalen, const char *pkalg, u_int compat) ++ const u_char *data, size_t datalen, const char *pkalg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ -+ return mm_sshkey_verify(MM_HOSTKEY, key, sig, siglen, data, datalen, pkalg, compat); ++ return mm_sshkey_verify(MM_HOSTKEY, key, sig, siglen, data, datalen, pkalg, compat, detailsp); +} + +int +mm_user_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, size_t siglen, -+ const u_char *data, size_t datalen, const char *pkalg, u_int compat) ++ const u_char *data, size_t datalen, const char *pkalg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ -+ return mm_sshkey_verify(MM_USERKEY, key, sig, siglen, data, datalen, pkalg, compat); ++ return mm_sshkey_verify(MM_USERKEY, key, sig, siglen, data, datalen, pkalg, compat, detailsp); +} + void mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { -@@ -900,11 +915,12 @@ mm_audit_event(struct ssh *ssh, ssh_audi +@@ -921,11 +938,12 @@ mm_audit_event(struct ssh *ssh, ssh_audi sshbuf_free(m); } @@ -1508,14 +1505,14 @@ diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c debug3("%s entering command %s", __func__, command); -@@ -914,6 +930,30 @@ mm_audit_run_command(const char *command +@@ -935,6 +953,30 @@ mm_audit_run_command(const char *command fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, m); + + if ((r = sshbuf_get_u32(m, &handle)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + sshbuf_free(m); + + return (handle); @@ -1527,22 +1524,22 @@ diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c + int r; + struct sshbuf *m; + -+ debug3("%s entering command %s", __func__, command); ++ debug3_f("entering command %s", command); + + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u32(m, handle)) != 0 || + (r = sshbuf_put_cstring(m, command)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, m); sshbuf_free(m); } #endif /* SSH_AUDIT_EVENTS */ -@@ -1074,3 +1114,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc +@@ -1095,3 +1137,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc + return &ci; } - #endif /* GSSAPI */ +#ifdef SSH_AUDIT_EVENTS +void +mm_audit_unsupported_body(struct ssh *ssh, int what) @@ -1551,9 +1548,9 @@ diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c + struct sshbuf *m; + + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u32(m, what)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED, @@ -1570,7 +1567,7 @@ diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c + struct sshbuf *m; + + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u32(m, ctos)) != 0 || + (r = sshbuf_put_cstring(m, cipher)) != 0 || + (r = sshbuf_put_cstring(m, (mac ? mac : ""))) != 0 || @@ -1578,7 +1575,7 @@ diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c + (r = sshbuf_put_cstring(m, fps)) != 0 || + (r = sshbuf_put_u64(m, pid)) != 0 || + (r = sshbuf_put_u64(m, uid)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX, @@ -1594,11 +1591,11 @@ diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c + struct sshbuf *m; + + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u32(m, ctos)) != 0 || + (r = sshbuf_put_u64(m, pid)) != 0 || + (r = sshbuf_put_u64(m, uid)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SESSION_KEY_FREE, m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, @@ -1613,31 +1610,31 @@ diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c + struct sshbuf *m; + + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_cstring(m, fp)) != 0 || + (r = sshbuf_put_u64(m, pid)) != 0 || + (r = sshbuf_put_u64(m, uid)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, m); + sshbuf_free(m); +} +#endif /* SSH_AUDIT_EVENTS */ -diff -up openssh/monitor_wrap.h.audit openssh/monitor_wrap.h ---- openssh/monitor_wrap.h.audit 2019-04-03 17:02:20.653885472 +0200 -+++ openssh/monitor_wrap.h 2019-04-03 17:02:20.716886069 +0200 -@@ -57,7 +57,9 @@ int mm_user_key_allowed(struct ssh *, st +diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h +--- openssh-8.6p1/monitor_wrap.h.audit 2021-04-19 16:47:35.685061584 +0200 ++++ openssh-8.6p1/monitor_wrap.h 2021-04-19 16:47:35.757062137 +0200 +@@ -61,7 +61,9 @@ int mm_user_key_allowed(struct ssh *, st struct sshauthopt **); int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, const char *, struct sshkey *); -int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, +int mm_hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int); ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); +int mm_user_key_verify(struct ssh*, const struct sshkey *, const u_char *, size_t, - const u_char *, size_t, const char *, u_int); + const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); - #ifdef GSSAPI -@@ -82,7 +84,12 @@ void mm_sshpam_free_ctx(void *); + void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); +@@ -86,7 +88,12 @@ void mm_sshpam_free_ctx(void *); #ifdef SSH_AUDIT_EVENTS #include "audit.h" void mm_audit_event(struct ssh *, ssh_audit_event_t); @@ -1651,18 +1648,18 @@ diff -up openssh/monitor_wrap.h.audit openssh/monitor_wrap.h #endif struct Session; -diff -up openssh/packet.c.audit openssh/packet.c ---- openssh/packet.c.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/packet.c 2019-04-03 17:02:20.716886069 +0200 -@@ -77,6 +77,7 @@ - #include +diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c +--- openssh-8.6p1/packet.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/packet.c 2021-04-19 16:48:46.885608837 +0200 +@@ -81,6 +81,7 @@ + #endif #include "xmalloc.h" +#include "audit.h" - #include "crc32.h" #include "compat.h" #include "ssh2.h" -@@ -510,6 +511,13 @@ ssh_packet_get_connection_out(struct ssh + #include "cipher.h" +@@ -506,6 +507,13 @@ ssh_packet_get_connection_out(struct ssh return ssh->state->connection_out; } @@ -1676,7 +1673,7 @@ diff -up openssh/packet.c.audit openssh/packet.c /* * Returns the IP-address of the remote host as a string. The returned * string must not be freed. -@@ -587,22 +595,19 @@ ssh_packet_close_internal(struct ssh *ss +@@ -583,22 +591,19 @@ ssh_packet_close_internal(struct ssh *ss { struct session_state *state = ssh->state; u_int mode; @@ -1704,8 +1701,8 @@ diff -up openssh/packet.c.audit openssh/packet.c for (mode = 0; mode < MODE_MAX; mode++) { kex_free_newkeys(state->newkeys[mode]); /* current keys */ state->newkeys[mode] = NULL; -@@ -636,8 +641,18 @@ ssh_packet_close_internal(struct ssh *ss - } +@@ -634,8 +639,18 @@ ssh_packet_close_internal(struct ssh *ss + #endif /* WITH_ZLIB */ cipher_free(state->send_context); cipher_free(state->receive_context); + if (had_keys && state->server_side) { @@ -1723,15 +1720,15 @@ diff -up openssh/packet.c.audit openssh/packet.c free(ssh->local_ipaddr); ssh->local_ipaddr = NULL; free(ssh->remote_ipaddr); -@@ -864,6 +879,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod - (unsigned long long)state->p_send.bytes, - (unsigned long long)state->p_send.blocks); +@@ -892,6 +907,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod + (unsigned long long)state->p_send.bytes, + (unsigned long long)state->p_send.blocks); kex_free_newkeys(state->newkeys[mode]); + audit_session_key_free(ssh, mode); state->newkeys[mode] = NULL; } /* note that both bytes and the seqnr are not reset */ -@@ -2167,6 +2183,71 @@ ssh_packet_get_output(struct ssh *ssh) +@@ -2173,6 +2189,72 @@ ssh_packet_get_output(struct ssh *ssh) return (void *)ssh->state->output; } @@ -1762,6 +1759,7 @@ diff -up openssh/packet.c.audit openssh/packet.c + + cipher_free(state->receive_context); + cipher_free(state->send_context); ++ state->send_context = state->receive_context = NULL; + + sshbuf_free(state->input); + state->input = NULL; @@ -1803,28 +1801,28 @@ diff -up openssh/packet.c.audit openssh/packet.c /* Reset after_authentication and reset compression in post-auth privsep */ static int ssh_packet_set_postauth(struct ssh *ssh) -diff -up openssh/packet.h.audit openssh/packet.h ---- openssh/packet.h.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/packet.h 2019-04-03 17:02:20.716886069 +0200 -@@ -217,4 +217,5 @@ const u_char *sshpkt_ptr(struct ssh *, s +diff -up openssh-8.6p1/packet.h.audit openssh-8.6p1/packet.h +--- openssh-8.6p1/packet.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/packet.h 2021-04-19 16:47:35.758062145 +0200 +@@ -218,4 +218,5 @@ const u_char *sshpkt_ptr(struct ssh *, s # undef EC_POINT #endif +void packet_destroy_all(struct ssh *, int, int); #endif /* PACKET_H */ -diff -up openssh/session.c.audit openssh/session.c ---- openssh/session.c.audit 2019-04-03 17:02:20.712886031 +0200 -+++ openssh/session.c 2019-04-03 17:02:20.716886069 +0200 +diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c +--- openssh-8.6p1/session.c.audit 2021-04-19 16:47:35.722061868 +0200 ++++ openssh-8.6p1/session.c 2021-04-19 16:47:35.758062145 +0200 @@ -136,7 +136,7 @@ extern char *__progname; extern int debug_flag; extern u_int utmp_len; extern int startup_pipe; -extern void destroy_sensitive_data(void); -+extern void destroy_sensitive_data(struct ssh *, int); ++extern void destroy_sensitive_data(struct ssh *); extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; extern char *tun_fwd_ifnames; /* serverloop.c */ -@@ -648,6 +648,14 @@ do_exec_pty(struct ssh *ssh, Session *s, +@@ -644,6 +644,14 @@ do_exec_pty(struct ssh *ssh, Session *s, /* Parent. Close the slave side of the pseudo tty. */ close(ttyfd); @@ -1839,34 +1837,34 @@ diff -up openssh/session.c.audit openssh/session.c /* Enter interactive session. */ s->ptymaster = ptymaster; ssh_packet_set_interactive(ssh, 1, -@@ -740,15 +748,19 @@ do_exec(struct ssh *ssh, Session *s, con +@@ -736,15 +744,19 @@ do_exec(struct ssh *ssh, Session *s, con s->self); #ifdef SSH_AUDIT_EVENTS + if (s->command != NULL || s->command_handle != -1) + fatal("do_exec: command already set"); if (command != NULL) -- PRIVSEP(audit_run_command(command)); +- mm_audit_run_command(command); + s->command = xstrdup(command); else if (s->ttyfd == -1) { char *shell = s->pw->pw_shell; if (shell[0] == '\0') /* empty shell means /bin/sh */ shell =_PATH_BSHELL; -- PRIVSEP(audit_run_command(shell)); +- mm_audit_run_command(shell); + s->command = xstrdup(shell); } + if (s->command != NULL && s->ptyfd == -1) -+ s->command_handle = PRIVSEP(audit_run_command(ssh, s->command)); ++ s->command_handle = mm_audit_run_command(ssh, s->command); #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); -@@ -1556,8 +1568,11 @@ do_child(struct ssh *ssh, Session *s, co +@@ -1550,8 +1562,11 @@ do_child(struct ssh *ssh, Session *s, co sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); /* remove hostkey from the child's memory */ - destroy_sensitive_data(); -+ destroy_sensitive_data(ssh, 1); ++ destroy_sensitive_data(ssh); ssh_packet_clear_keys(ssh); + /* Don't audit this - both us and the parent would be talking to the + monitor over a single socket, with no synchronization. */ @@ -1874,7 +1872,7 @@ diff -up openssh/session.c.audit openssh/session.c /* Force a password change */ if (s->authctxt->force_pwchange) { -@@ -1769,6 +1784,9 @@ session_unused(int id) +@@ -1763,6 +1778,9 @@ session_unused(int id) sessions[id].ttyfd = -1; sessions[id].ptymaster = -1; sessions[id].x11_chanids = NULL; @@ -1884,7 +1882,7 @@ diff -up openssh/session.c.audit openssh/session.c sessions[id].next_unused = sessions_first_unused; sessions_first_unused = id; } -@@ -1851,6 +1869,19 @@ session_open(Authctxt *authctxt, int cha +@@ -1843,6 +1861,19 @@ session_open(Authctxt *authctxt, int cha } Session * @@ -1895,7 +1893,7 @@ diff -up openssh/session.c.audit openssh/session.c + if (s->used) + return s; + } -+ debug("%s: unknown id %d", __func__, id); ++ debug_f("unknown id %d", id); + session_dump(); + return NULL; +} @@ -1904,7 +1902,7 @@ diff -up openssh/session.c.audit openssh/session.c session_by_tty(char *tty) { int i; -@@ -2461,6 +2492,32 @@ session_exit_message(struct ssh *ssh, Se +@@ -2450,6 +2481,32 @@ session_exit_message(struct ssh *ssh, Se chan_write_failed(ssh, c); } @@ -1926,7 +1924,7 @@ diff -up openssh/session.c.audit openssh/session.c +{ + if (s->command != NULL) { + if (s->command_handle != -1) -+ PRIVSEP(audit_end_command(ssh, s->command_handle, s->command)); ++ mm_audit_end_command(ssh, s->command_handle, s->command); + free(s->command); + s->command = NULL; + s->command_handle = -1; @@ -1937,7 +1935,7 @@ diff -up openssh/session.c.audit openssh/session.c void session_close(struct ssh *ssh, Session *s) { -@@ -2474,6 +2531,10 @@ session_close(struct ssh *ssh, Session * +@@ -2463,6 +2520,10 @@ session_close(struct ssh *ssh, Session * if (s->ttyfd != -1) session_pty_cleanup(s); @@ -1948,7 +1946,7 @@ diff -up openssh/session.c.audit openssh/session.c free(s->term); free(s->display); free(s->x11_chanids); -@@ -2549,14 +2610,14 @@ session_close_by_channel(struct ssh *ssh +@@ -2537,14 +2598,14 @@ session_close_by_channel(struct ssh *ssh } void @@ -1965,7 +1963,7 @@ diff -up openssh/session.c.audit openssh/session.c else session_close(ssh, s); } -@@ -2683,6 +2744,15 @@ do_authenticated2(struct ssh *ssh, Authc +@@ -2671,6 +2732,15 @@ do_authenticated2(struct ssh *ssh, Authc server_loop2(ssh, authctxt); } @@ -1981,18 +1979,18 @@ diff -up openssh/session.c.audit openssh/session.c void do_cleanup(struct ssh *ssh, Authctxt *authctxt) { -@@ -2746,7 +2816,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au +@@ -2734,7 +2804,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au * or if running in monitor. */ - if (!use_privsep || mm_is_monitor()) + if (mm_is_monitor()) - session_destroy_all(ssh, session_pty_cleanup2); + session_destroy_all(ssh, do_cleanup_one_session); } /* Return a name for the remote host that fits inside utmp_size */ -diff -up openssh/session.h.audit openssh/session.h ---- openssh/session.h.audit 2019-03-27 23:26:14.000000000 +0100 -+++ openssh/session.h 2019-04-03 17:02:20.717886079 +0200 +diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h +--- openssh-8.6p1/session.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/session.h 2021-04-19 16:47:35.758062145 +0200 @@ -61,6 +61,12 @@ struct Session { char *name; char *val; @@ -2009,7 +2007,7 @@ diff -up openssh/session.h.audit openssh/session.h @@ -71,10 +77,12 @@ void session_unused(int); int session_input_channel_req(struct ssh *, Channel *, const char *); void session_close_by_pid(struct ssh *ssh, pid_t, int); - void session_close_by_channel(struct ssh *, int, void *); + void session_close_by_channel(struct ssh *, int, int, void *); -void session_destroy_all(struct ssh *, void (*)(Session *)); +void session_destroy_all(struct ssh *, void (*)(struct ssh*, Session *)); void session_pty_cleanup2(Session *); @@ -2020,30 +2018,11 @@ diff -up openssh/session.h.audit openssh/session.h Session *session_by_tty(char *); void session_close(struct ssh *, Session *); void do_setusercontext(struct passwd *); -diff -up openssh/sshd.c.audit openssh/sshd.c ---- openssh/sshd.c.audit 2019-04-03 17:02:20.692885842 +0200 -+++ openssh/sshd.c 2019-04-03 17:02:20.717886079 +0200 -@@ -122,6 +122,7 @@ - #include "ssh-gss.h" - #endif - #include "monitor_wrap.h" -+#include "audit.h" - #include "ssh-sandbox.h" - #include "auth-options.h" - #include "version.h" -@@ -261,8 +262,8 @@ struct sshbuf *loginmsg; - struct passwd *privsep_pw = NULL; - - /* Prototypes for various functions defined later in this file. */ --void destroy_sensitive_data(void); --void demote_sensitive_data(void); -+void destroy_sensitive_data(struct ssh *, int); -+void demote_sensitive_data(struct ssh *); - static void do_ssh2_kex(struct ssh *); - - /* -@@ -278,6 +279,15 @@ close_listen_socks(void) - num_listen_socks = -1; +diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c +--- openssh-8.6p1/sshd.c.audit 2021-04-19 16:47:35.727061907 +0200 ++++ openssh-8.6p1/sshd.c 2021-04-19 16:47:35.759062152 +0200 +@@ -279,6 +280,15 @@ close_listen_socks(void) + num_listen_socks = 0; } +/* @@ -2052,16 +2031,46 @@ diff -up openssh/sshd.c.audit openssh/sshd.c + */ +int listening_for_clients(void) +{ -+ return num_listen_socks >= 0; ++ return num_listen_socks > 0; +} + + /* Allocate and initialise the children array */ static void - close_startup_pipes(void) - { -@@ -380,18 +390,45 @@ grace_alarm_handler(int sig) - ssh_remote_port(the_active_state)); - } + child_alloc(void) +@@ -1204,6 +1259,7 @@ server_accept_loop(int *sock_in, int *so + if (received_sigterm) { + logit("Received signal %d; terminating.", + (int) received_sigterm); ++ /* destroy_sensitive_data(ssh, 0); FIXME */ + close_listen_socks(); + if (options.pid_file != NULL) + unlink(options.pid_file); +diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c +--- openssh-8.6p1/sshd-session.c.audit 2021-04-19 16:47:35.727061907 +0200 ++++ openssh-8.6p1/sshd-session.c 2021-04-19 16:47:35.759062152 +0200 +@@ -122,6 +122,7 @@ + #include "ssh-gss.h" + #endif + #include "monitor_wrap.h" ++#include "audit.h" + #include "ssh-sandbox.h" + #include "auth-options.h" + #include "version.h" +@@ -260,8 +261,8 @@ struct sshbuf *loginmsg; + struct sshbuf *loginmsg; + /* Prototypes for various functions defined later in this file. */ +-void destroy_sensitive_data(void); +-void demote_sensitive_data(void); ++void destroy_sensitive_data(struct ssh *); ++void demote_sensitive_data(struct ssh *); + static void do_ssh2_kex(struct ssh *); + + /* +@@ -377,18 +387,40 @@ grace_alarm_handler(int sig) + _exit(EXIT_LOGIN_GRACE); + } + -/* Destroy the host and server keys. They will no longer be needed. */ +/* + * Destroy the host and server keys. They will no longer be needed. Careful, @@ -2069,7 +2078,7 @@ diff -up openssh/sshd.c.audit openssh/sshd.c + */ void -destroy_sensitive_data(void) -+destroy_sensitive_data(struct ssh *ssh, int privsep) ++destroy_sensitive_data(struct ssh *ssh) { u_int i; +#ifdef SSH_AUDIT_EVENTS @@ -2091,12 +2100,7 @@ diff -up openssh/sshd.c.audit openssh/sshd.c sensitive_data.host_keys[i] = NULL; + if (fp != NULL) { +#ifdef SSH_AUDIT_EVENTS -+ if (privsep) -+ PRIVSEP(audit_destroy_sensitive_data(ssh, fp, -+ pid, uid)); -+ else -+ audit_destroy_sensitive_data(ssh, fp, -+ pid, uid); ++ audit_destroy_sensitive_data(ssh, fp, pid, uid); +#endif + free(fp); + } @@ -2107,7 +2111,7 @@ diff -up openssh/sshd.c.audit openssh/sshd.c sshkey_free(sensitive_data.host_certificates[i]); sensitive_data.host_certificates[i] = NULL; } -@@ -400,14 +437,26 @@ destroy_sensitive_data(void) +@@ -397,20 +434,38 @@ destroy_sensitive_data(void) /* Demote private to public keys for network child */ void @@ -2134,9 +2138,8 @@ diff -up openssh/sshd.c.audit openssh/sshd.c + fp = NULL; if ((r = sshkey_from_private( sensitive_data.host_keys[i], &tmp)) != 0) - fatal("could not demote host %s key: %s", -@@ -415,6 +464,12 @@ demote_sensitive_data(void) - ssh_err(r)); + fatal_r(r, "could not demote host %s key", + sshkey_type(sensitive_data.host_keys[i])); sshkey_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = tmp; + if (fp != NULL) { @@ -2148,7 +2151,7 @@ diff -up openssh/sshd.c.audit openssh/sshd.c } /* Certs do not need demotion */ } -@@ -442,7 +497,7 @@ reseed_prngs(void) +@@ -438,7 +493,7 @@ reseed_prngs(void) } static void @@ -2157,7 +2160,7 @@ diff -up openssh/sshd.c.audit openssh/sshd.c { gid_t gidset[1]; -@@ -457,7 +512,7 @@ privsep_preauth_child(void) +@@ -453,7 +508,7 @@ privsep_preauth_child(void) reseed_prngs(); /* Demote the private keys to public keys. */ @@ -2166,16 +2169,16 @@ diff -up openssh/sshd.c.audit openssh/sshd.c #ifdef WITH_SELINUX sshd_selinux_change_privsep_preauth_context(); -@@ -496,7 +551,7 @@ privsep_preauth(struct ssh *ssh) +@@ -492,7 +547,7 @@ privsep_preauth(struct ssh *ssh) + pmonitor->m_pkex = &ssh->kex; - if (use_privsep == PRIVSEP_ON) - box = ssh_sandbox_init(pmonitor); + box = ssh_sandbox_init(pmonitor); - pid = fork(); + pmonitor->m_pid = pid = fork(); if (pid == -1) { fatal("fork of unprivileged child failed"); } else if (pid != 0) { -@@ -542,7 +597,7 @@ privsep_preauth(struct ssh *ssh) +@@ -537,7 +592,7 @@ privsep_preauth(struct ssh *ssh) /* Arrange for logging to be sent to the monitor */ set_log_handler(mm_log_handler, pmonitor); @@ -2184,7 +2187,7 @@ diff -up openssh/sshd.c.audit openssh/sshd.c setproctitle("%s", "[net]"); if (box != NULL) ssh_sandbox_child(box); -@@ -594,7 +649,7 @@ privsep_postauth(struct ssh *ssh, Authct +@@ -589,7 +644,7 @@ privsep_postauth(struct ssh *ssh, Authct set_log_handler(mm_log_handler, pmonitor); /* Demote the private keys to public keys. */ @@ -2193,48 +2196,21 @@ diff -up openssh/sshd.c.audit openssh/sshd.c reseed_prngs(); -@@ -1057,7 +1112,7 @@ server_listen(void) - * from this function are in a forked subprocess. - */ - static void --server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) -+server_accept_loop(struct ssh *ssh, int *sock_in, int *sock_out, int *newsock, int *config_s) - { - fd_set *fdset; - int i, j, ret, maxfd; -@@ -1112,6 +1167,7 @@ server_accept_loop(int *sock_in, int *so - if (received_sigterm) { - logit("Received signal %d; terminating.", - (int) received_sigterm); -+ destroy_sensitive_data(ssh, 0); - close_listen_socks(); - if (options.pid_file != NULL) - unlink(options.pid_file); -@@ -1978,7 +2034,7 @@ main(int ac, char **av) - #endif - - /* Accept a connection and return in a forked child */ -- server_accept_loop(&sock_in, &sock_out, -+ server_accept_loop(ssh, &sock_in, &sock_out, - &newsock, config_s); - } - -@@ -2222,6 +2278,9 @@ main(int ac, char **av) +@@ -2333,6 +2389,9 @@ main(int ac, char **av) do_authenticated(ssh, authctxt); /* The connection has been terminated. */ + packet_destroy_all(ssh, 1, 1); -+ destroy_sensitive_data(ssh, 1); ++ destroy_sensitive_data(ssh); + ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); -@@ -2401,6 +2460,15 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2513,6 +2572,14 @@ do_ssh2_kex(struct ssh *ssh) void cleanup_exit(int i) { + static int in_cleanup = 0; -+ int is_privsep_child; + + /* cleanup_exit can be called at the very least from the privsep + wrappers used for auditing. Make sure we don't recurse @@ -2242,31 +2218,24 @@ diff -up openssh/sshd.c.audit openssh/sshd.c + if (in_cleanup) + _exit(i); + in_cleanup = 1; + extern int auth_attempted; /* monitor.c */ + if (the_active_state != NULL && the_authctxt != NULL) { - do_cleanup(the_active_state, the_authctxt); - if (use_privsep && privsep_is_preauth && -@@ -2414,9 +2482,16 @@ cleanup_exit(int i) - pmonitor->m_pid, strerror(errno)); - } - } -+ is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0; -+ if (sensitive_data.host_keys != NULL && the_active_state != NULL) -+ destroy_sensitive_data(the_active_state, is_privsep_child); -+ if (the_active_state != NULL) -+ packet_destroy_all(the_active_state, 1, is_privsep_child); +@@ -2525,7 +2593,9 @@ cleanup_exit(int i) + _exit(EXIT_AUTH_ATTEMPTED); #ifdef SSH_AUDIT_EVENTS /* done after do_cleanup so it can cancel the PAM auth 'thread' */ -- if (the_active_state != NULL && (!use_privsep || mm_is_monitor())) +- if (the_active_state != NULL && mm_is_monitor()) + if (the_active_state != NULL && + (the_authctxt == NULL || !the_authctxt->authenticated) && -+ (!use_privsep || mm_is_monitor())) ++ mm_is_monitor()) audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif _exit(i); -diff -up openssh/sshkey.c.audit openssh/sshkey.c ---- openssh/sshkey.c.audit 2019-04-03 17:02:20.657885510 +0200 -+++ openssh/sshkey.c 2019-04-03 17:02:20.718886088 +0200 -@@ -331,6 +331,38 @@ sshkey_type_is_valid_ca(int type) +diff -up openssh-8.6p1/sshkey.c.audit openssh-8.6p1/sshkey.c +--- openssh-8.6p1/sshkey.c.audit 2021-04-19 16:47:35.741062014 +0200 ++++ openssh-8.6p1/sshkey.c 2021-04-19 16:47:35.759062152 +0200 +@@ -371,6 +371,38 @@ sshkey_type_is_valid_ca(int type) } int @@ -2305,14 +2274,14 @@ diff -up openssh/sshkey.c.audit openssh/sshkey.c sshkey_is_cert(const struct sshkey *k) { if (k == NULL) -diff -up openssh/sshkey.h.audit openssh/sshkey.h ---- openssh/sshkey.h.audit 2019-04-03 17:02:20.657885510 +0200 -+++ openssh/sshkey.h 2019-04-03 17:02:20.718886088 +0200 -@@ -148,6 +148,7 @@ u_int sshkey_size(const struct sshkey - int sshkey_generate(int type, u_int bits, struct sshkey **keyp); - int sshkey_from_private(const struct sshkey *, struct sshkey **); +diff -up openssh-8.6p1/sshkey.h.audit openssh-8.6p1/sshkey.h +--- openssh-8.6p1/sshkey.h.audit 2021-04-19 16:47:35.741062014 +0200 ++++ openssh-8.6p1/sshkey.h 2021-04-19 16:47:35.759062152 +0200 +@@ -189,6 +189,7 @@ int sshkey_shield_private(struct sshke + int sshkey_unshield_private(struct sshkey *); + int sshkey_type_from_name(const char *); +int sshkey_is_private(const struct sshkey *); int sshkey_is_cert(const struct sshkey *); + int sshkey_is_sk(const struct sshkey *); int sshkey_type_is_cert(int); - int sshkey_type_plain(int); diff --git a/SOURCES/openssh-7.6p1-cleanup-selinux.patch b/openssh-7.6p1-cleanup-selinux.patch similarity index 69% rename from SOURCES/openssh-7.6p1-cleanup-selinux.patch rename to openssh-7.6p1-cleanup-selinux.patch index 08cd349..cfe11ad 100644 --- a/SOURCES/openssh-7.6p1-cleanup-selinux.patch +++ b/openssh-7.6p1-cleanup-selinux.patch @@ -1,70 +1,69 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c --- openssh/auth2-pubkey.c.refactor 2019-04-04 13:19:12.188821236 +0200 +++ openssh/auth2-pubkey.c 2019-04-04 13:19:12.276822078 +0200 -@@ -72,6 +72,9 @@ +@@ -72,6 +72,8 @@ + + /* import */ extern ServerOptions options; - extern u_char *session_id2; - extern u_int session_id2_len; +extern int inetd_flag; -+extern int rexeced_flag; +extern Authctxt *the_authctxt; + extern struct authmethod_cfg methodcfg_pubkey; static char * - format_key(const struct sshkey *key) @@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh - - if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command, + if ((pid = subprocess("AuthorizedPrincipalsCommand", command, ac, av, &f, -- SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0) -+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, -+ (inetd_flag && !rexeced_flag), the_authctxt)) == 0) + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, +- runas_pw, temporarily_use_uid, restore_uid)) == 0) ++ runas_pw, temporarily_use_uid, restore_uid, ++ inetd_flag, the_authctxt)) == 0) goto out; uid_swapped = 1; @@ -981,7 +985,8 @@ user_key_command_allowed2(struct ssh *ss - - if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command, + if ((pid = subprocess("AuthorizedKeysCommand", command, ac, av, &f, -- SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0) -+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, -+ (inetd_flag && !rexeced_flag), the_authctxt)) == 0) + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, +- runas_pw, temporarily_use_uid, restore_uid)) == 0) ++ runas_pw, temporarily_use_uid, restore_uid, ++ inetd_flag, the_authctxt)) == 0) goto out; uid_swapped = 1; -diff -up openssh/auth.c.refactor openssh/auth.c ---- openssh/auth.c.refactor 2019-04-04 13:19:12.235821686 +0200 -+++ openssh/auth.c 2019-04-04 13:19:12.276822078 +0200 +diff -up openssh/misc.c.refactor openssh/misc.c +--- openssh/misc.c.refactor 2019-04-04 13:19:12.235821686 +0200 ++++ openssh/misc.c 2019-04-04 13:19:12.276822078 +0200 @@ -756,7 +756,8 @@ auth_get_canonical_hostname(struct ssh * - */ pid_t - subprocess(const char *tag, struct passwd *pw, const char *command, -- int ac, char **av, FILE **child, u_int flags) -+ int ac, char **av, FILE **child, u_int flags, int inetd, -+ void *the_authctxt) + subprocess(const char *tag, const char *command, + int ac, char **av, FILE **child, u_int flags, +- struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs) ++ struct passwd *pw, privdrop_fn *drop_privs, ++ privrestore_fn *restore_privs, int inetd, void *the_authctxt) { FILE *f = NULL; struct stat st; @@ -872,7 +873,7 @@ subprocess(const char *tag, struct passw + _exit(1); } - #ifdef WITH_SELINUX - if (sshd_selinux_setup_env_variables() < 0) { + if (sshd_selinux_setup_env_variables(inetd, the_authctxt) < 0) { error ("failed to copy environment: %s", strerror(errno)); _exit(127); -diff -up openssh/auth.h.refactor openssh/auth.h ---- openssh/auth.h.refactor 2019-04-04 13:19:12.251821839 +0200 -+++ openssh/auth.h 2019-04-04 13:19:12.276822078 +0200 +diff -up openssh/misc.h.refactor openssh/misc.h +--- openssh/misc.h.refactor 2019-04-04 13:19:12.251821839 +0200 ++++ openssh/misc.h 2019-04-04 13:19:12.276822078 +0200 @@ -235,7 +235,7 @@ struct passwd *fakepw(void); - #define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */ - #define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */ - pid_t subprocess(const char *, struct passwd *, -- const char *, int, char **, FILE **, u_int flags); -+ const char *, int, char **, FILE **, u_int flags, int, void *); - - int sys_auth_passwd(struct ssh *, const char *); + #define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */ + #define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */ + pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int, +- struct passwd *, privdrop_fn *, privrestore_fn *); ++ struct passwd *, privdrop_fn *, privrestore_fn *, int, void *); + typedef struct arglist arglist; + struct arglist { diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/port-linux.h --- openssh/openbsd-compat/port-linux.h.refactor 2019-04-04 13:19:12.256821887 +0200 +++ openssh/openbsd-compat/port-linux.h 2019-04-04 13:19:12.276822078 +0200 @@ -82,14 +81,13 @@ diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/por diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c --- openssh/openbsd-compat/port-linux-sshd.c.refactor 2019-04-04 13:19:12.256821887 +0200 +++ openssh/openbsd-compat/port-linux-sshd.c 2019-04-04 13:19:12.276822078 +0200 -@@ -49,11 +49,6 @@ +@@ -49,10 +49,6 @@ #include #endif -extern ServerOptions options; -extern Authctxt *the_authctxt; -extern int inetd_flag; --extern int rexeced_flag; - /* Wrapper around is_selinux_enabled() to log its return value once only */ int @@ -128,7 +126,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa if (r == 0) { /* If launched from xinetd, we must use current level */ -- if (inetd_flag && !rexeced_flag) { +- if (inetd_flag) { + if (inetd) { security_context_t sshdsc=NULL; @@ -145,14 +143,14 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa char *role; @@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it - debug3("%s: setting execution context", __func__); + debug3_f("setting execution context"); - ssh_selinux_get_role_level(&role, &reqlvl); + ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt); rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); -- if (inetd_flag && !rexeced_flag) { +- if (inetd_flag) { + if (inetd) { use_current = "1"; } else { @@ -203,10 +201,10 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa + if (sshd_selinux_setup_pam_variables(inetd, pam_setenv, authctxt)) { switch (security_getenforce()) { case -1: - fatal("%s: security_getenforce() failed", __func__); + fatal_f("security_getenforce() failed"); @@ -410,7 +411,7 @@ sshd_selinux_setup_exec_context(char *pw - debug3("%s: setting execution context", __func__); + debug3_f("setting execution context"); - r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); + r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx, inetd, authctxt); @@ -216,56 +214,58 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa diff -up openssh/platform.c.refactor openssh/platform.c --- openssh/platform.c.refactor 2019-04-04 13:19:12.204821389 +0200 +++ openssh/platform.c 2019-04-04 13:19:12.277822088 +0200 -@@ -32,6 +32,9 @@ +@@ -32,6 +32,8 @@ + #include "openbsd-compat/openbsd-compat.h" - extern int use_privsep; extern ServerOptions options; +extern int inetd_flag; -+extern int rexeced_flag; +extern Authctxt *the_authctxt; - void - platform_pre_listen(void) + /* return 1 if we are running with privilege to swap UIDs, 0 otherwise */ + int @@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru } #endif /* HAVE_SETPCRED */ #ifdef WITH_SELINUX - sshd_selinux_setup_exec_context(pw->pw_name); + sshd_selinux_setup_exec_context(pw->pw_name, -+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt, ++ inetd_flag, do_pam_putenv, the_authctxt, + options.use_pam); #endif } -diff -up openssh/sshd.c.refactor openssh/sshd.c ---- openssh/sshd.c.refactor 2019-04-04 13:19:12.275822068 +0200 -+++ openssh/sshd.c 2019-04-04 13:19:51.270195262 +0200 +diff -up openssh/sshd-session.c.refactor openssh/sshd-session.c +--- openssh/sshd-session.c.refactor 2019-04-04 13:19:12.275822068 +0200 ++++ openssh/sshd-session.c 2019-04-04 13:19:51.270195262 +0200 @@ -158,7 +158,7 @@ int debug_flag = 0; - static int test_flag = 0; + int debug_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ -static int inetd_flag = 0; +int inetd_flag = 0; - /* Flag indicating that sshd should not detach and become a daemon. */ - static int no_daemon_flag = 0; -@@ -171,7 +171,7 @@ static char **saved_argv; - static int saved_argc; - - /* re-exec */ --static int rexeced_flag = 0; -+int rexeced_flag = 0; - static int rexec_flag = 1; - static int rexec_argc = 0; - static char **rexec_argv; + /* debug goes to stderr unless inetd_flag is set */ + static int log_stderr = 0; @@ -2192,7 +2192,9 @@ main(int ac, char **av) } #endif #ifdef WITH_SELINUX - sshd_selinux_setup_exec_context(authctxt->pw->pw_name); + sshd_selinux_setup_exec_context(authctxt->pw->pw_name, -+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt, ++ inetd_flag, do_pam_putenv, the_authctxt, + options.use_pam); #endif #ifdef USE_PAM if (options.use_pam) { +diff -up openssh/sshconnect.c.refactor openssh/sshconnect.c +--- openssh/sshconnect.c.refactor 2021-02-24 00:12:03.065325046 +0100 ++++ openssh/sshconnect.c 2021-02-24 00:12:12.126449544 +0100 +@@ -892,7 +892,7 @@ load_hostkeys_command(struct hostkeys *h + + if ((pid = subprocess(tag, command, ac, av, &f, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| +- SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0) ++ SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL, 0, NULL)) == 0) + goto out; + + load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch new file mode 100644 index 0000000..6a14cb3 --- /dev/null +++ b/openssh-7.7p1-fips.patch @@ -0,0 +1,715 @@ +diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c +--- openssh-8.6p1/dh.c.fips 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/dh.c 2021-05-06 12:12:10.107634472 +0200 +@@ -36,6 +36,7 @@ + + #include + #include ++#include + + #include "dh.h" + #include "pathnames.h" +@@ -164,6 +164,12 @@ choose_dh(int min, int wantbits, int max + int best, bestcount, which, linenum; + struct dhgroup dhg; + ++ if (FIPS_mode()) { ++ verbose("Using arbitrary primes is not allowed in FIPS mode." ++ " Falling back to known groups."); ++ return (dh_new_group_fallback(max)); ++ } ++ + if ((f = fopen(get_moduli_filename(), "r")) == NULL) { + logit("WARNING: could not open %s (%s), using fixed modulus", + get_moduli_filename(), strerror(errno)); +@@ -502,4 +508,38 @@ dh_estimate(int bits) + return 8192; + } + ++/* ++ * Compares the received DH parameters with known-good groups, ++ * which might be either from group14, group16 or group18. ++ */ ++int ++dh_is_known_group(const DH *dh) ++{ ++ const BIGNUM *p, *g; ++ const BIGNUM *known_p, *known_g; ++ DH *known = NULL; ++ int bits = 0, rv = 0; ++ ++ DH_get0_pqg(dh, &p, NULL, &g); ++ bits = BN_num_bits(p); ++ ++ if (bits <= 3072) { ++ known = dh_new_group14(); ++ } else if (bits <= 6144) { ++ known = dh_new_group16(); ++ } else { ++ known = dh_new_group18(); ++ } ++ ++ DH_get0_pqg(known, &known_p, NULL, &known_g); ++ ++ if (BN_cmp(g, known_g) == 0 && ++ BN_cmp(p, known_p) == 0) { ++ rv = 1; ++ } ++ ++ DH_free(known); ++ return rv; ++} ++ + #endif /* WITH_OPENSSL */ +diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h +--- openssh-8.6p1/dh.h.fips 2021-05-06 12:08:36.498926877 +0200 ++++ openssh-8.6p1/dh.h 2021-05-06 12:11:28.393298005 +0200 +@@ -45,6 +45,7 @@ DH *dh_new_group_fallback(int); + + int dh_gen_key(DH *, int); + int dh_pub_is_valid(const DH *, const BIGNUM *); ++int dh_is_known_group(const DH *); + + u_int dh_estimate(int); + void dh_set_moduli_file(const char *); +diff -up openssh-8.6p1/kex-names.c.fips openssh-8.6p1/kex-names.c +--- openssh-8.6p1/kex-names.c.fips 2021-05-06 12:08:36.489926807 +0200 ++++ openssh-8.6p1/kex-names.c 2021-05-06 12:08:36.498926877 +0200 +@@ -39,6 +39,7 @@ + + #ifdef WITH_OPENSSL + #include ++#include + #include + #endif + +@@ -203,7 +203,10 @@ kex_names_valid(const char *names) + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + if (kex_alg_by_name(p) == NULL) { +- error("Unsupported KEX algorithm \"%.100s\"", p); ++ if (FIPS_mode()) ++ error("\"%.100s\" is not allowed in FIPS mode", p); ++ else ++ error("Unsupported KEX algorithm \"%.100s\"", p); + free(s); + return 0; + } +diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c +--- openssh-8.6p1/kexgexc.c.fips 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/kexgexc.c 2021-05-06 12:08:36.498926877 +0200 +@@ -28,6 +28,7 @@ + + #ifdef WITH_OPENSSL + ++#include + #include + + #include +@@ -115,6 +116,10 @@ input_kex_dh_gex_group(int type, u_int32 + r = SSH_ERR_ALLOC_FAIL; + goto out; + } ++ if (FIPS_mode() && dh_is_known_group(kex->dh) == 0) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } + p = g = NULL; /* belong to kex->dh now */ + + /* generate and send 'e', client DH public key */ +diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h +--- openssh-8.6p1/myproposal.h.fips 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/myproposal.h 2021-05-06 12:08:36.498926877 +0200 +@@ -57,6 +57,18 @@ + "rsa-sha2-512," \ + "rsa-sha2-256" + ++#define KEX_FIPS_PK_ALG \ ++ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \ ++ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \ ++ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ ++ "rsa-sha2-512-cert-v01@openssh.com," \ ++ "rsa-sha2-256-cert-v01@openssh.com," \ ++ "ecdsa-sha2-nistp256," \ ++ "ecdsa-sha2-nistp384," \ ++ "ecdsa-sha2-nistp521," \ ++ "rsa-sha2-512," \ ++ "rsa-sha2-256" ++ + #define KEX_SERVER_ENCRYPT \ + "chacha20-poly1305@openssh.com," \ + "aes128-ctr,aes192-ctr,aes256-ctr," \ +@@ -78,6 +92,27 @@ + + #define KEX_CLIENT_MAC KEX_SERVER_MAC + ++#define KEX_FIPS_ENCRYPT \ ++ "aes128-ctr,aes192-ctr,aes256-ctr," \ ++ "aes128-cbc,3des-cbc," \ ++ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \ ++ "aes128-gcm@openssh.com,aes256-gcm@openssh.com" ++#define KEX_DEFAULT_KEX_FIPS \ ++ "ecdh-sha2-nistp256," \ ++ "ecdh-sha2-nistp384," \ ++ "ecdh-sha2-nistp521," \ ++ "diffie-hellman-group-exchange-sha256," \ ++ "diffie-hellman-group16-sha512," \ ++ "diffie-hellman-group18-sha512," \ ++ "diffie-hellman-group14-sha256" ++#define KEX_FIPS_MAC \ ++ "hmac-sha1," \ ++ "hmac-sha2-256," \ ++ "hmac-sha2-512," \ ++ "hmac-sha1-etm@openssh.com," \ ++ "hmac-sha2-256-etm@openssh.com," \ ++ "hmac-sha2-512-etm@openssh.com" ++ + /* Not a KEX value, but here so all the algorithm defaults are together */ + #define SSH_ALLOWED_CA_SIGALGS \ + "ssh-ed25519," \ +diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c +--- openssh-8.6p1/readconf.c.fips 2021-05-06 12:08:36.428926336 +0200 ++++ openssh-8.6p1/readconf.c 2021-05-06 12:08:36.499926885 +0200 +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #ifdef USE_SYSTEM_GLOB + # include + #else +@@ -2538,11 +2538,16 @@ fill_default_options(Options * options) + all_key = sshkey_alg_list(0, 0, 1, ','); + all_sig = sshkey_alg_list(0, 1, 1, ','); + /* remove unsupported algos from default lists */ +- def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); +- def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); +- def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); +- def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); +- def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); ++ def_cipher = match_filter_allowlist((FIPS_mode() ? ++ KEX_FIPS_ENCRYPT : KEX_CLIENT_ENCRYPT), all_cipher); ++ def_mac = match_filter_allowlist((FIPS_mode() ? ++ KEX_FIPS_MAC : KEX_CLIENT_MAC), all_mac); ++ def_kex = match_filter_allowlist((FIPS_mode() ? ++ KEX_DEFAULT_KEX_FIPS : KEX_CLIENT_KEX), all_kex); ++ def_key = match_filter_allowlist((FIPS_mode() ? ++ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), all_key); ++ def_sig = match_filter_allowlist((FIPS_mode() ? ++ KEX_FIPS_PK_ALG : SSH_ALLOWED_CA_SIGALGS), all_sig); + #define ASSEMBLE(what, defaults, all) \ + do { \ + if ((r = kex_assemble_names(&options->what, \ +diff -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-seccomp-filter.c +--- openssh-8.6p1/sandbox-seccomp-filter.c.fips 2021-05-06 12:08:36.463926606 +0200 ++++ openssh-8.6p1/sandbox-seccomp-filter.c 2021-05-06 12:08:36.499926885 +0200 +@@ -160,6 +160,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_open + SC_DENY(__NR_open, EACCES), + #endif ++#ifdef __NR_socket ++ SC_DENY(__NR_socket, EACCES), ++#endif + #ifdef __NR_openat + SC_DENY(__NR_openat, EACCES), + #endif +diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c +--- openssh-8.6p1/servconf.c.fips 2021-05-06 12:08:36.455926545 +0200 ++++ openssh-8.6p1/servconf.c 2021-05-06 12:08:36.500926893 +0200 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #ifdef HAVE_UTIL_H + #include + #endif +@@ -226,11 +226,16 @@ assemble_algorithms(ServerOptions *o) + all_key = sshkey_alg_list(0, 0, 1, ','); + all_sig = sshkey_alg_list(0, 1, 1, ','); + /* remove unsupported algos from default lists */ +- def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher); +- def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac); +- def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex); +- def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); +- def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); ++ def_cipher = match_filter_allowlist((FIPS_mode() ? ++ KEX_FIPS_ENCRYPT : KEX_SERVER_ENCRYPT), all_cipher); ++ def_mac = match_filter_allowlist((FIPS_mode() ? ++ KEX_FIPS_MAC : KEX_SERVER_MAC), all_mac); ++ def_kex = match_filter_allowlist((FIPS_mode() ? ++ KEX_DEFAULT_KEX_FIPS : KEX_SERVER_KEX), all_kex); ++ def_key = match_filter_allowlist((FIPS_mode() ? ++ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), all_key); ++ def_sig = match_filter_allowlist((FIPS_mode() ? ++ KEX_FIPS_PK_ALG : SSH_ALLOWED_CA_SIGALGS), all_sig); + #define ASSEMBLE(what, defaults, all) \ + do { \ + if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ +diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c +--- openssh-8.6p1/ssh.c.fips 2021-05-06 12:08:36.467926637 +0200 ++++ openssh-8.6p1/ssh.c 2021-05-06 12:08:36.500926893 +0200 +@@ -77,6 +77,7 @@ + #include + #include + #endif ++#include + #include "openbsd-compat/openssl-compat.h" + #include "openbsd-compat/sys-queue.h" + +@@ -1516,6 +1517,10 @@ main(int ac, char **av) + exit(0); + } + ++ if (FIPS_mode()) { ++ debug("FIPS mode initialized"); ++ } ++ + /* Expand SecurityKeyProvider if it refers to an environment variable */ + if (options.sk_provider != NULL && *options.sk_provider == '$' && + strlen(options.sk_provider) > 1) { +diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c +--- openssh-8.6p1/sshconnect2.c.fips 2021-05-06 12:08:36.485926777 +0200 ++++ openssh-8.6p1/sshconnect2.c 2021-05-06 12:08:36.501926900 +0200 +@@ -45,6 +45,8 @@ + #include + #endif + ++#include ++ + #include "openbsd-compat/sys-queue.h" + + #include "xmalloc.h" +@@ -269,36 +271,41 @@ ssh_kex2(struct ssh *ssh, char *host, st + + #if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { +- /* Add the GSSAPI mechanisms currently supported on this +- * client to the key exchange algorithm proposal */ +- orig = myproposal[PROPOSAL_KEX_ALGS]; +- +- if (options.gss_server_identity) { +- gss_host = xstrdup(options.gss_server_identity); +- } else if (options.gss_trust_dns) { +- gss_host = remote_hostname(ssh); +- /* Fall back to specified host if we are using proxy command +- * and can not use DNS on that socket */ +- if (strcmp(gss_host, "UNKNOWN") == 0) { +- free(gss_host); ++ if (FIPS_mode()) { ++ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); ++ options.gss_keyex = 0; ++ } else { ++ /* Add the GSSAPI mechanisms currently supported on this ++ * client to the key exchange algorithm proposal */ ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ ++ if (options.gss_server_identity) { ++ gss_host = xstrdup(options.gss_server_identity); ++ } else if (options.gss_trust_dns) { ++ gss_host = remote_hostname(ssh); ++ /* Fall back to specified host if we are using proxy command ++ * and can not use DNS on that socket */ ++ if (strcmp(gss_host, "UNKNOWN") == 0) { ++ free(gss_host); ++ gss_host = xstrdup(host); ++ } ++ } else { + gss_host = xstrdup(host); + } +- } else { +- gss_host = xstrdup(host); +- } + +- gss = ssh_gssapi_client_mechanisms(gss_host, +- options.gss_client_identity, options.gss_kex_algorithms); +- if (gss) { +- debug("Offering GSSAPI proposal: %s", gss); +- xasprintf(&myproposal[PROPOSAL_KEX_ALGS], +- "%s,%s", gss, orig); +- +- /* If we've got GSSAPI algorithms, then we also support the +- * 'null' hostkey, as a last resort */ +- orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; +- xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], +- "%s,null", orig); ++ gss = ssh_gssapi_client_mechanisms(gss_host, ++ options.gss_client_identity, options.gss_kex_algorithms); ++ if (gss) { ++ debug("Offering GSSAPI proposal: %s", gss); ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ ++ /* If we've got GSSAPI algorithms, then we also support the ++ * 'null' hostkey, as a last resort */ ++ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "%s,null", orig); ++ } + } + } + #endif +diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c +--- openssh-8.6p1/sshd.c.fips 2021-05-06 12:08:36.493926838 +0200 ++++ openssh-8.6p1/sshd.c 2021-05-06 12:13:56.501492639 +0200 +@@ -66,6 +66,7 @@ + #endif + #include + #include ++#include + #include + #include + #include +@@ -77,6 +78,7 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + #endif + +@@ -1931,6 +1931,13 @@ main(int ac, char **av) + &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) + do_log2_r(r, ll, "Unable to load host key \"%s\"", + options.host_key_files[i]); ++ if (FIPS_mode() && key != NULL && (sshkey_type_plain(key->type) == KEY_ED25519_SK ++ || sshkey_type_plain(key->type) == KEY_ED25519)) { ++ logit_f("sshd: Ed25519 keys are not allowed in FIPS mode, skipping %s", options.host_key_files[i]); ++ sshkey_free(key); ++ key = NULL; ++ continue; ++ } + if (sshkey_is_sk(key) && + key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { + debug("host key %s requires user presence, ignoring", +@@ -2110,6 +2113,10 @@ main(int ac, char **av) + /* Reinitialize the log (because of the fork above). */ + log_init(__progname, options.log_level, options.log_facility, log_stderr); + ++ if (FIPS_mode()) { ++ debug("FIPS mode initialized"); ++ } ++ + /* + * Chdir to the root directory so that the current disk can be + * unmounted if desired. +diff -up openssh-8.6p1/sshd-session.c.fips openssh-8.6p1/sshd-session.c +--- a/sshd-session.c.fips 2021-05-06 12:08:36.493926838 +0200 ++++ b/sshd-session.c 2021-05-06 12:13:56.501492639 +0200 +@@ -78,6 +79,7 @@ + #include + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + #endif + +@@ -2506,10 +2513,14 @@ do_ssh2_kex(struct ssh *ssh) + if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) + orig = NULL; + +- if (options.gss_keyex) +- gss = ssh_gssapi_server_mechanisms(); +- else +- gss = NULL; ++ if (options.gss_keyex) { ++ if (FIPS_mode()) { ++ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); ++ options.gss_keyex = 0; ++ } else { ++ gss = ssh_gssapi_server_mechanisms(); ++ } ++ } + + if (gss && orig) + xasprintf(&newstr, "%s,%s", gss, orig); +diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c +--- openssh-8.6p1/sshkey.c.fips 2021-05-06 12:08:36.493926838 +0200 ++++ openssh-8.6p1/sshkey.c 2021-05-06 12:08:36.502926908 +0200 +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + #endif + + #include "crypto_api.h" +@@ -57,6 +58,7 @@ + #define SSHKEY_INTERNAL + #include "sshkey.h" + #include "match.h" ++#include "log.h" + #include "ssh-sk.h" + + #ifdef WITH_XMSS +@@ -285,6 +285,18 @@ sshkey_alg_list(int certs_only, int plai + impl = keyimpls[i]; + if (impl->name == NULL || impl->type == KEY_NULL) + continue; ++ if (FIPS_mode()) { ++ switch (impl->type) { ++ case KEY_ED25519: ++ case KEY_ED25519_SK: ++ case KEY_ED25519_CERT: ++ case KEY_ED25519_SK_CERT: ++ continue; ++ break; ++ default: ++ break; ++ } ++ } + if (!include_sigonly && impl->sigonly) + continue; + if ((certs_only && !impl->cert) || (plain_only && impl->cert)) +@@ -1503,6 +1503,20 @@ sshkey_read(struct sshkey *ret, char **c + return SSH_ERR_EC_CURVE_MISMATCH; + } + ++ switch (type) { ++ case KEY_ED25519: ++ case KEY_ED25519_SK: ++ case KEY_ED25519_CERT: ++ case KEY_ED25519_SK_CERT: ++ if (FIPS_mode()) { ++ sshkey_free(k); ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ break; ++ default: ++ break; ++ } + /* Fill in ret from parsed key */ + sshkey_free_contents(ret); + *ret = *k; +@@ -2916,6 +2916,11 @@ sshkey_sign(struct sshkey *key, + *lenp = 0; + if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) + return SSH_ERR_INVALID_ARGUMENT; ++ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ /* Fallthrough */ + if ((impl = sshkey_impl_from_key(key)) == NULL) + return SSH_ERR_KEY_TYPE_UNKNOWN; + if ((r = sshkey_unshield_private(key)) != 0) +@@ -2973,6 +2978,10 @@ sshkey_verify(const struct sshkey *key, + *detailsp = NULL; + if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) + return SSH_ERR_INVALID_ARGUMENT; ++ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } + if ((impl = sshkey_impl_from_key(key)) == NULL) + return SSH_ERR_KEY_TYPE_UNKNOWN; + return impl->funcs->verify(key, sig, siglen, data, dlen, +diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c +--- openssh-8.6p1/ssh-keygen.c.fips 2021-05-06 12:08:36.467926637 +0200 ++++ openssh-8.6p1/ssh-keygen.c 2021-05-06 12:08:36.503926916 +0200 +@@ -20,6 +20,7 @@ + + #ifdef WITH_OPENSSL + #include ++#include + #include + #include "openbsd-compat/openssl-compat.h" + #endif +@@ -69,6 +69,7 @@ + #include "cipher.h" + + #define DEFAULT_KEY_TYPE_NAME "ed25519" ++#define FIPS_DEFAULT_KEY_TYPE_NAME "rsa" + + /* + * Default number of bits in the RSA, DSA and ECDSA keys. These value can be +@@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na + #endif + } + #ifdef WITH_OPENSSL ++ if (FIPS_mode()) { ++ if (type == KEY_DSA) ++ fatal("DSA keys are not allowed in FIPS mode"); ++ if (type == KEY_ED25519 || type == KEY_ED25519_SK) ++ fatal("ED25519 keys are not allowed in FIPS mode"); ++ } + switch (type) { + case KEY_DSA: + if (*bitsp != 1024) +@@ -266,7 +267,7 @@ ask_filename(struct passwd *pw, const ch + char *name = NULL; + + if (key_type_name == NULL) +- name = _PATH_SSH_CLIENT_ID_ED25519; ++ name = FIPS_mode() ? _PATH_SSH_CLIENT_ID_RSA : _PATH_SSH_CLIENT_ID_ED25519; + else { + switch (sshkey_type_from_name(key_type_name)) { + #ifdef WITH_DSA +@@ -1098,9 +1104,17 @@ do_gen_all_hostkeys(struct passwd *pw) + first = 1; + printf("%s: generating new host keys: ", __progname); + } ++ type = sshkey_type_from_name(key_types[i].key_type); ++ ++ /* Skip the keys that are not supported in FIPS mode */ ++ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) { ++ logit("Skipping %s key in FIPS mode", ++ key_types[i].key_type_display); ++ goto next; ++ } ++ + printf("%s ", key_types[i].key_type_display); + fflush(stdout); +- type = sshkey_type_from_name(key_types[i].key_type); + if ((fd = mkstemp(prv_tmp)) == -1) { + error("Could not save your private key in %s: %s", + prv_tmp, strerror(errno)); +@@ -3830,7 +3831,7 @@ main(int argc, char **argv) + } + + if (key_type_name == NULL) +- key_type_name = DEFAULT_KEY_TYPE_NAME; ++ key_type_name = FIPS_mode() ? FIPS_DEFAULT_KEY_TYPE_NAME : DEFAULT_KEY_TYPE_NAME; + + type = sshkey_type_from_name(key_type_name); + type_bits_valid(type, key_type_name, &bits); +diff -up openssh-9.3p1/ssh-rsa.c.evpgenrsa openssh-9.3p1/ssh-rsa.c +--- openssh-9.3p1/ssh-rsa.c.evpgenrsa 2022-06-30 15:14:58.200518353 +0200 ++++ openssh-9.3p1/ssh-rsa.c 2022-06-30 15:24:31.499641196 +0200 +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -1705,6 +1707,8 @@ ssh_rsa_generate(u_int bits, RSA + goto out; + + if (EVP_PKEY_keygen(ctx, &res) <= 0) { ++ if (FIPS_mode()) ++ logit_f("the key length might be unsupported by FIPS mode approved key generation method"); + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c +--- openssh-8.7p1/kexgen.c.fips3 2022-07-11 16:11:21.973519913 +0200 ++++ openssh-8.7p1/kexgen.c 2022-07-11 16:25:31.172187365 +0200 +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "sshkey.h" + #include "kex.h" +@@ -115,10 +116,20 @@ kex_gen_client(struct ssh *ssh) + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_keypair(kex); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_keypair(kex); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_keypair(kex); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_keypair(kex); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +@@ -186,11 +197,21 @@ input_kex_gen_reply(int type, u_int32_t + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_dec(kex, server_blob, +- &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_dec(kex, server_blob, ++ &shared_secret); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +@@ -285,12 +306,22 @@ input_kex_gen_init(int type, u_int32_t s + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, +- &server_pubkey, &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, ++ &server_pubkey, &shared_secret); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +diff -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c +--- openssh-8.7p1/ssh-ed25519.c.fips3 2022-07-11 16:53:41.428343304 +0200 ++++ openssh-8.7p1/ssh-ed25519.c 2022-07-11 16:56:09.284663661 +0200 +@@ -24,6 +24,7 @@ + + #include + #include ++#include + + #include "log.h" + #include "sshbuf.h" +@@ -52,6 +53,10 @@ ssh_ed25519_sign(const struct sshkey *ke + key->ed25519_sk == NULL || + datalen >= INT_MAX - crypto_sign_ed25519_BYTES) + return SSH_ERR_INVALID_ARGUMENT; ++ if (FIPS_mode()) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } + smlen = slen = datalen + crypto_sign_ed25519_BYTES; + if ((sig = malloc(slen)) == NULL) + return SSH_ERR_ALLOC_FAIL; +@@ -108,6 +113,10 @@ ssh_ed25519_verify(const struct sshkey * + dlen >= INT_MAX - crypto_sign_ed25519_BYTES || + sig == NULL || siglen == 0) + return SSH_ERR_INVALID_ARGUMENT; ++ if (FIPS_mode()) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } + + if ((b = sshbuf_from(sig, siglen)) == NULL) + return SSH_ERR_ALLOC_FAIL; diff --git a/SOURCES/openssh-7.7p1-gssapi-new-unique.patch b/openssh-7.7p1-gssapi-new-unique.patch similarity index 76% rename from SOURCES/openssh-7.7p1-gssapi-new-unique.patch rename to openssh-7.7p1-gssapi-new-unique.patch index 2eea250..0b8ab02 100644 --- a/SOURCES/openssh-7.7p1-gssapi-new-unique.patch +++ b/openssh-7.7p1-gssapi-new-unique.patch @@ -1,7 +1,26 @@ -diff --git a/auth-krb5.c b/auth-krb5.c -index a5a81ed2..63f877f2 100644 ---- a/auth-krb5.c -+++ b/auth-krb5.c +diff -up openssh-8.6p1/auth.h.ccache_name openssh-8.6p1/auth.h +--- openssh-8.6p1/auth.h.ccache_name 2021-04-19 14:05:10.820744325 +0200 ++++ openssh-8.6p1/auth.h 2021-04-19 14:05:10.853744569 +0200 +@@ -83,6 +83,7 @@ struct Authctxt { + krb5_principal krb5_user; + char *krb5_ticket_file; + char *krb5_ccname; ++ int krb5_set_env; + #endif + struct sshbuf *loginmsg; + +@@ -231,7 +232,7 @@ struct passwd *fakepw(void); + int sys_auth_passwd(struct ssh *, const char *); + + #if defined(KRB5) && !defined(HEIMDAL) +-krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *); ++krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *); + #endif + + #endif /* AUTH_H */ +diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c +--- openssh-8.6p1/auth-krb5.c.ccache_name 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/auth-krb5.c 2021-04-19 14:40:55.142832954 +0200 @@ -51,6 +51,7 @@ #include #include @@ -10,7 +29,7 @@ index a5a81ed2..63f877f2 100644 extern ServerOptions options; -@@ -77,7 +78,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password) +@@ -77,7 +78,7 @@ auth_krb5_password(Authctxt *authctxt, c #endif krb5_error_code problem; krb5_ccache ccache = NULL; @@ -19,24 +38,18 @@ index a5a81ed2..63f877f2 100644 char *client, *platform_client; const char *errmsg; -@@ -163,7 +164,8 @@ auth_krb5_password(Authctxt *authctxt, const char *password) +@@ -163,8 +164,8 @@ auth_krb5_password(Authctxt *authctxt, c goto out; } -- problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache); +- problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, +- &authctxt->krb5_fwd_ccache); + problem = ssh_krb5_cc_new_unique(authctxt->krb5_ctx, + &authctxt->krb5_fwd_ccache, &authctxt->krb5_set_env); if (problem) goto out; -@@ -172,21 +174,20 @@ auth_krb5_password(Authctxt *authctxt, const char *password) - if (problem) - goto out; - -- problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, -+ problem = krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, - &creds); - if (problem) +@@ -179,15 +180,14 @@ auth_krb5_password(Authctxt *authctxt, c goto out; #endif @@ -57,7 +70,7 @@ index a5a81ed2..63f877f2 100644 do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname); #endif -@@ -222,11 +223,54 @@ auth_krb5_password(Authctxt *authctxt, const char *password) +@@ -223,11 +223,54 @@ auth_krb5_password(Authctxt *authctxt, c void krb5_cleanup_proc(Authctxt *authctxt) { @@ -113,7 +126,7 @@ index a5a81ed2..63f877f2 100644 if (authctxt->krb5_user) { krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); authctxt->krb5_user = NULL; -@@ -237,36 +281,188 @@ krb5_cleanup_proc(Authctxt *authctxt) +@@ -238,36 +281,188 @@ krb5_cleanup_proc(Authctxt *authctxt) } } @@ -151,7 +164,7 @@ index a5a81ed2..63f877f2 100644 +ssh_krb5_expand_template(char **result, const char *template) { + char *p_n, *p_o, *r, *tmp_template; + -+ debug3("%s: called, template = %s", __func__, template); ++ debug3_f("called, template = %s", template); + if (template == NULL) + return -1; + @@ -179,7 +192,7 @@ index a5a81ed2..63f877f2 100644 + } else { + p_o = strchr(p_n, '}') + 1; + *p_o = '\0'; -+ debug("%s: unsupported token %s in %s", __func__, p_n, template); ++ debug_f("unsupported token %s in %s", p_n, template); + /* unknown token, fallback to the default */ + goto cleanup; + } @@ -198,16 +211,13 @@ index a5a81ed2..63f877f2 100644 + return -1; +} + - krb5_error_code --ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { -- int tmpfd, ret, oerrno; -- char ccname[40]; ++krb5_error_code +ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) { + profile_t p; + int ret = 0; + char *value = NULL; + -+ debug3("%s: called", __func__); ++ debug3_f("called"); + ret = krb5_get_profile(ctx, &p); + if (ret) + return ret; @@ -218,11 +228,14 @@ index a5a81ed2..63f877f2 100644 + + ret = ssh_krb5_expand_template(ccname, value); + -+ debug3("%s: returning with ccname = %s", __func__, *ccname); ++ debug3_f("returning with ccname = %s", *ccname); + return ret; +} + -+krb5_error_code + krb5_error_code +-ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { +- int tmpfd, ret, oerrno; +- char ccname[40]; +ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environment) { + int tmpfd, ret, oerrno, type_len; + char *ccname = NULL; @@ -242,7 +255,7 @@ index a5a81ed2..63f877f2 100644 - logit("mkstemp(): %.100s", strerror(oerrno)); - return oerrno; - } -+ debug3("%s: called", __func__); ++ debug3_f("called"); + if (need_environment) + *need_environment = 0; + ret = ssh_krb5_get_cctemplate(ctx, &ccname); @@ -283,7 +296,7 @@ index a5a81ed2..63f877f2 100644 - close(tmpfd); - return (krb5_cc_resolve(ctx, ccname, ccache)); -+ debug3("%s: setting default ccname to %s", __func__, ccname); ++ debug3_f("setting default ccname to %s", ccname); + /* set the default with already expanded user IDs */ + ret = krb5_cc_set_default_name(ctx, ccname); + if (ret) @@ -304,13 +317,13 @@ index a5a81ed2..63f877f2 100644 + * a primary cache for this collection, if it supports that (non-FILE) + */ + if (krb5_cc_support_switch(ctx, type)) { -+ debug3("%s: calling cc_new_unique(%s)", __func__, ccname); ++ debug3_f("calling cc_new_unique(%s)", ccname); + ret = krb5_cc_new_unique(ctx, type, NULL, ccache); + free(type); + if (ret) + return ret; + -+ debug3("%s: calling cc_switch()", __func__); ++ debug3_f("calling cc_switch()"); + return krb5_cc_switch(ctx, *ccache); + } else { + /* Otherwise, we can not create a unique ccname here (either @@ -318,35 +331,47 @@ index a5a81ed2..63f877f2 100644 + * collections + */ + free(type); -+ debug3("%s: calling cc_resolve(%s)", __func__, ccname); ++ debug3_f("calling cc_resolve(%s)", ccname); + return (krb5_cc_resolve(ctx, ccname, ccache)); + } } #endif /* !HEIMDAL */ #endif /* KRB5 */ -diff --git a/auth.h b/auth.h -index 29491df9..fdab5040 100644 ---- a/auth.h -+++ b/auth.h -@@ -82,6 +82,7 @@ struct Authctxt { - krb5_principal krb5_user; - char *krb5_ticket_file; - char *krb5_ccname; -+ int krb5_set_env; - #endif - struct sshbuf *loginmsg; +diff -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c +--- openssh-8.6p1/gss-serv.c.ccache_name 2021-04-19 14:05:10.844744503 +0200 ++++ openssh-8.6p1/gss-serv.c 2021-04-19 14:05:10.854744577 +0200 +@@ -413,13 +413,15 @@ ssh_gssapi_cleanup_creds(void) + } -@@ -243,6 +244,6 @@ int sys_auth_passwd(struct ssh *, const char *); + /* As user */ +-void ++int + ssh_gssapi_storecreds(void) + { + if (gssapi_client.mech && gssapi_client.mech->storecreds) { +- (*gssapi_client.mech->storecreds)(&gssapi_client); ++ return (*gssapi_client.mech->storecreds)(&gssapi_client); + } else + debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); ++ ++ return 0; + } - #if defined(KRB5) && !defined(HEIMDAL) - #include --krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *); -+krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *); + /* This allows GSSAPI methods to do things to the child's environment based +@@ -499,9 +501,7 @@ ssh_gssapi_rekey_creds(void) { + char *envstr; #endif - #endif -diff -up openssh-7.9p1/gss-serv-krb5.c.ccache_name openssh-7.9p1/gss-serv-krb5.c ---- openssh-7.9p1/gss-serv-krb5.c.ccache_name 2019-03-01 15:17:42.708611802 +0100 -+++ openssh-7.9p1/gss-serv-krb5.c 2019-03-01 15:17:42.713611844 +0100 + +- if (gssapi_client.store.filename == NULL && +- gssapi_client.store.envval == NULL && +- gssapi_client.store.envvar == NULL) ++ if (gssapi_client.store.envval == NULL) + return; + + ok = mm_ssh_gssapi_update_creds(&gssapi_client.store); +diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c +--- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-04-19 14:05:10.852744562 +0200 ++++ openssh-8.6p1/gss-serv-krb5.c 2021-04-19 14:05:10.854744577 +0200 @@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ @@ -449,7 +474,7 @@ diff -up openssh-7.9p1/gss-serv-krb5.c.ccache_name openssh-7.9p1/gss-serv-krb5.c do_pam_putenv(client->store.envvar, client->store.envval); #endif -@@ -361,7 +355,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl +@@ -364,7 +354,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl client->store.data = krb_context; @@ -458,43 +483,10 @@ diff -up openssh-7.9p1/gss-serv-krb5.c.ccache_name openssh-7.9p1/gss-serv-krb5.c } int -diff --git a/gss-serv.c b/gss-serv.c -index 6cae720e..16e55cbc 100644 ---- a/gss-serv.c -+++ b/gss-serv.c -@@ -320,13 +320,15 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) - } - - /* As user */ --void -+int - ssh_gssapi_storecreds(void) - { - if (gssapi_client.mech && gssapi_client.mech->storecreds) { -- (*gssapi_client.mech->storecreds)(&gssapi_client); -+ return (*gssapi_client.mech->storecreds)(&gssapi_client); - } else - debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); -+ -+ return 0; - } - - /* This allows GSSAPI methods to do things to the childs environment based -@@ -498,9 +500,7 @@ ssh_gssapi_rekey_creds() { - char *envstr; - #endif - -- if (gssapi_client.store.filename == NULL && -- gssapi_client.store.envval == NULL && -- gssapi_client.store.envvar == NULL) -+ if (gssapi_client.store.envval == NULL) - return; - - ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); -diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c ---- openssh-7.9p1/servconf.c.ccache_name 2019-03-01 15:17:42.704611768 +0100 -+++ openssh-7.9p1/servconf.c 2019-03-01 15:17:42.713611844 +0100 -@@ -123,6 +123,7 @@ initialize_server_options(ServerOptions +diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c +--- openssh-8.6p1/servconf.c.ccache_name 2021-04-19 14:05:10.848744532 +0200 ++++ openssh-8.6p1/servconf.c 2021-04-19 14:05:10.854744577 +0200 +@@ -136,6 +136,7 @@ initialize_server_options(ServerOptions options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; @@ -502,7 +494,7 @@ diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c options->gss_authentication=-1; options->gss_keyex = -1; options->gss_cleanup_creds = -1; -@@ -315,6 +316,8 @@ fill_default_server_options(ServerOptions *options) +@@ -359,6 +360,8 @@ fill_default_server_options(ServerOption options->kerberos_ticket_cleanup = 1; if (options->kerberos_get_afs_token == -1) options->kerberos_get_afs_token = 0; @@ -511,17 +503,16 @@ diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_keyex == -1) -@@ -447,7 +450,8 @@ typedef enum { - sPermitRootLogin, sLogFacility, sLogLevel, - sRhostsRSAAuthentication, sRSAAuthentication, - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, -- sKerberosGetAFSToken, sChallengeResponseAuthentication, -+ sKerberosGetAFSToken, sKerberosUniqueCCache, -+ sChallengeResponseAuthentication, - sPasswordAuthentication, sKbdInteractiveAuthentication, - sListenAddress, sAddressFamily, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, -@@ -526,11 +530,13 @@ static struct { +@@ -506,7 +509,7 @@ typedef enum { + sPort, sHostKeyFile, sLoginGraceTime, + sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, +- sKerberosGetAFSToken, sPasswordAuthentication, ++ sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication, + sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, +@@ -593,11 +597,13 @@ static struct { #else { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif @@ -535,7 +526,7 @@ diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, -@@ -1437,6 +1443,10 @@ process_server_config_line(ServerOptions *options, char *line, +@@ -1573,6 +1579,10 @@ process_server_config_line_depth(ServerO intptr = &options->kerberos_get_afs_token; goto parse_flag; @@ -546,7 +537,7 @@ diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c case sGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; -@@ -2507,6 +2517,7 @@ dump_config(ServerOptions *o) +@@ -2891,6 +2901,7 @@ dump_config(ServerOptions *o) # ifdef USE_AFS dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif @@ -554,11 +545,10 @@ diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c #endif #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); -diff --git a/servconf.h b/servconf.h -index db8362c6..4fa42d64 100644 ---- a/servconf.h -+++ b/servconf.h -@@ -123,6 +123,8 @@ typedef struct { +diff -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h +--- openssh-8.6p1/servconf.h.ccache_name 2021-04-19 14:05:10.848744532 +0200 ++++ openssh-8.6p1/servconf.h 2021-04-19 14:05:10.855744584 +0200 +@@ -140,6 +140,8 @@ typedef struct { * file on logout. */ int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ @@ -567,13 +557,12 @@ index db8362c6..4fa42d64 100644 int gss_authentication; /* If true, permit GSSAPI authentication */ int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ -diff --git a/session.c b/session.c -index 85df6a27..480a5ead 100644 ---- a/session.c -+++ b/session.c -@@ -1033,7 +1033,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) +diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c +--- openssh-8.6p1/session.c.ccache_name 2021-04-19 14:05:10.852744562 +0200 ++++ openssh-8.6p1/session.c 2021-04-19 14:05:10.855744584 +0200 +@@ -1038,7 +1038,8 @@ do_setup_env(struct ssh *ssh, Session *s /* Allow any GSSAPI methods that we've used to alter - * the childs environment as they see fit + * the child's environment as they see fit */ - ssh_gssapi_do_child(&env, &envsize); + if (s->authctxt->krb5_set_env) @@ -581,7 +570,7 @@ index 85df6a27..480a5ead 100644 #endif /* Set basic environment. */ -@@ -1105,7 +1106,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) +@@ -1114,7 +1115,7 @@ do_setup_env(struct ssh *ssh, Session *s } #endif #ifdef KRB5 @@ -590,33 +579,10 @@ index 85df6a27..480a5ead 100644 child_set_env(&env, &envsize, "KRB5CCNAME", s->authctxt->krb5_ccname); #endif -diff --git a/ssh-gss.h b/ssh-gss.h -index 6593e422..245178af 100644 ---- a/ssh-gss.h -+++ b/ssh-gss.h -@@ -83,7 +82,7 @@ typedef struct ssh_gssapi_mech_struct { - int (*dochild) (ssh_gssapi_client *); - int (*userok) (ssh_gssapi_client *, char *); - int (*localname) (ssh_gssapi_client *, char **); -- void (*storecreds) (ssh_gssapi_client *); -+ int (*storecreds) (ssh_gssapi_client *); - int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - -@@ -127,7 +126,7 @@ int ssh_gssapi_userok(char *name); - 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); -+int ssh_gssapi_storecreds(void); - const char *ssh_gssapi_displayname(void); - - char *ssh_gssapi_server_mechanisms(void); -diff --git a/sshd.c b/sshd.c -index edbe815c..89514e8a 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -2162,7 +2162,7 @@ main(int ac, char **av) +diff -up openssh-8.6p1/sshd-session.c.ccache_name openssh-8.6p1/sshd-session.c +--- openssh-8.6p1/sshd-session.c.ccache_name 2021-04-19 14:05:10.849744540 +0200 ++++ openssh-8.6p1/sshd-session.c 2021-04-19 14:05:10.855744584 +0200 +@@ -2284,7 +2284,7 @@ main(int ac, char **av) #ifdef GSSAPI if (options.gss_authentication) { temporarily_use_uid(authctxt->pw); @@ -625,11 +591,10 @@ index edbe815c..89514e8a 100644 restore_uid(); } #endif -diff --git a/sshd_config.5 b/sshd_config.5 -index c0683d4a..2349f477 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -860,6 +860,14 @@ Specifies whether to automatically destroy the user's ticket cache +diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5 +--- openssh-8.6p1/sshd_config.5.ccache_name 2021-04-19 14:05:10.849744540 +0200 ++++ openssh-8.6p1/sshd_config.5 2021-04-19 14:05:10.856744592 +0200 +@@ -939,6 +939,14 @@ Specifies whether to automatically destr file on logout. The default is .Cm yes . @@ -642,5 +607,26 @@ index c0683d4a..2349f477 100644 +can lead to overwriting previous tickets by subseqent connections to the same +user account. .It Cm KexAlgorithms - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. + Specifies the permitted KEX (Key Exchange) algorithms that the server will + offer to clients. +diff -up openssh-8.6p1/ssh-gss.h.ccache_name openssh-8.6p1/ssh-gss.h +--- openssh-8.6p1/ssh-gss.h.ccache_name 2021-04-19 14:05:10.852744562 +0200 ++++ openssh-8.6p1/ssh-gss.h 2021-04-19 14:05:10.855744584 +0200 +@@ -114,7 +114,7 @@ typedef struct ssh_gssapi_mech_struct { + int (*dochild) (ssh_gssapi_client *); + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); +- void (*storecreds) (ssh_gssapi_client *); ++ int (*storecreds) (ssh_gssapi_client *); + int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + +@@ -175,7 +175,7 @@ int ssh_gssapi_userok(char *name, struct + 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); ++int ssh_gssapi_storecreds(void); + const char *ssh_gssapi_displayname(void); + + char *ssh_gssapi_server_mechanisms(void); diff --git a/openssh-7.7p1-redhat.patch b/openssh-7.7p1-redhat.patch new file mode 100644 index 0000000..1d77f90 --- /dev/null +++ b/openssh-7.7p1-redhat.patch @@ -0,0 +1,109 @@ +diff -up openssh/ssh_config.redhat openssh/ssh_config +--- openssh/ssh_config.redhat 2020-02-11 23:28:35.000000000 +0100 ++++ openssh/ssh_config 2020-02-13 18:13:39.180641839 +0100 +@@ -43,3 +43,10 @@ + # ProxyCommand ssh -q -W %h:%p gateway.example.com + # RekeyLimit 1G 1h + # UserKnownHostsFile ~/.ssh/known_hosts.d/%k ++# ++# This system is following system-wide crypto policy. ++# To modify the crypto properties (Ciphers, MACs, ...), create a *.conf ++# file under /etc/ssh/ssh_config.d/ which will be automatically ++# included below. For more information, see manual page for ++# update-crypto-policies(8) and ssh_config(5). ++Include /etc/ssh/ssh_config.d/*.conf +diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat +--- openssh/ssh_config_redhat.redhat 2020-02-13 18:13:39.180641839 +0100 ++++ openssh/ssh_config_redhat 2020-02-13 18:13:39.180641839 +0100 +@@ -0,0 +1,15 @@ ++# The options here are in the "Match final block" to be applied as the last ++# options and could be potentially overwritten by the user configuration ++Match final all ++ # Follow system-wide Crypto Policy, if defined: ++ Include /etc/crypto-policies/back-ends/openssh.config ++ ++ GSSAPIAuthentication yes ++ ++# If this option is set to yes then remote X11 clients will have full access ++# to the original X11 display. As virtually no X11 client supports the untrusted ++# mode correctly we set this to yes. ++ ForwardX11Trusted yes ++ ++# Uncomment this if you want to use .local domain ++# Host *.local +diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0 +--- openssh/sshd_config.0.redhat 2020-02-12 14:30:04.000000000 +0100 ++++ openssh/sshd_config.0 2020-02-13 18:13:39.181641855 +0100 +@@ -970,9 +970,9 @@ DESCRIPTION + + SyslogFacility + Gives the facility code that is used when logging messages from +- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, +- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The +- default is AUTH. ++ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV, ++ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. ++ The default is AUTH. + + TCPKeepAlive + Specifies whether the system should send TCP keepalive messages +diff -up openssh/sshd_config.5.redhat openssh/sshd_config.5 +--- openssh/sshd_config.5.redhat 2020-02-11 23:28:35.000000000 +0100 ++++ openssh/sshd_config.5 2020-02-13 18:13:39.181641855 +0100 +@@ -1614,7 +1614,7 @@ By default no subsystems are defined. + .It Cm SyslogFacility + Gives the facility code that is used when logging messages from + .Xr sshd 8 . +-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, ++The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2, + LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. + The default is AUTH. + .It Cm TCPKeepAlive +diff -up openssh/sshd_config.redhat openssh/sshd_config +--- openssh/sshd_config.redhat 2020-02-11 23:28:35.000000000 +0100 ++++ openssh/sshd_config 2020-02-13 18:20:16.349913681 +0100 +@@ -10,6 +10,14 @@ + # possible, but leave them commented. Uncommented options override the + # default value. + ++# To modify the system-wide sshd configuration, create a *.conf file under ++# /etc/ssh/sshd_config.d/ which will be automatically included below ++Include /etc/ssh/sshd_config.d/*.conf ++ ++# If you want to change the port on a SELinux system, you have to tell ++# SELinux about this change. ++# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER ++# + #Port 22 + #AddressFamily any + #ListenAddress 0.0.0.0 +diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat +--- openssh/sshd_config_redhat.redhat 2020-02-13 18:14:02.268006439 +0100 ++++ openssh/sshd_config_redhat 2020-02-13 18:19:20.765035947 +0100 +@@ -0,0 +1,15 @@ ++SyslogFacility AUTHPRIV ++ ++ChallengeResponseAuthentication no ++ ++GSSAPIAuthentication yes ++GSSAPICleanupCredentials no ++ ++UsePAM yes ++ ++X11Forwarding yes ++ ++# It is recommended to use pam_motd in /etc/pam.d/sshd instead of PrintMotd, ++# as it is more configurable and versatile than the built-in version. ++PrintMotd no ++ +diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat +--- openssh/sshd_config_redhat_cp.redhat 2020-02-13 18:14:02.268006439 +0100 ++++ openssh/sshd_config_redhat_cp 2020-02-13 18:19:20.765035947 +0100 +@@ -0,0 +1,7 @@ ++# This system is following system-wide crypto policy. The changes to ++# crypto properties (Ciphers, MACs, ...) will not have any effect in ++# this or following included files. To override some configuration option, ++# write it before this block or include it before this file. ++# Please, see manual pages for update-crypto-policies(8) and sshd_config(5). ++Include /etc/crypto-policies/back-ends/opensshserver.config ++ diff --git a/openssh-7.8p1-UsePAM-warning.patch b/openssh-7.8p1-UsePAM-warning.patch new file mode 100644 index 0000000..f8d7042 --- /dev/null +++ b/openssh-7.8p1-UsePAM-warning.patch @@ -0,0 +1,26 @@ +diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c +--- openssh-8.6p1/sshd-session.c.log-usepam-no 2021-04-19 14:00:45.099735129 +0200 ++++ openssh-8.6p1/sshd-session.c 2021-04-19 14:03:21.140920974 +0200 +@@ -1749,6 +1749,10 @@ main(int ac, char **av) + "enabled authentication methods"); + } + ++ /* 'UsePAM no' is not supported in our builds */ ++ if (! options.use_pam) ++ logit("WARNING: 'UsePAM no' is not supported in this build and may cause several problems."); ++ + #ifdef WITH_OPENSSL + if (options.moduli_file != NULL) + dh_set_moduli_file(options.moduli_file); +diff -up openssh-8.6p1/sshd_config.log-usepam-no openssh-8.6p1/sshd_config +--- openssh-8.6p1/sshd_config.log-usepam-no 2021-04-19 14:00:45.098735121 +0200 ++++ openssh-8.6p1/sshd_config 2021-04-19 14:00:45.099735129 +0200 +@@ -87,6 +87,8 @@ AuthorizedKeysFile .ssh/authorized_keys + # If you just want the PAM account and session checks to run without + # PAM authentication, then enable this but set PasswordAuthentication + # and KbdInteractiveAuthentication to 'no'. ++# WARNING: 'UsePAM no' is not supported in this build and may cause several ++# problems. + #UsePAM no + + #AllowAgentForwarding yes diff --git a/SOURCES/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch similarity index 86% rename from SOURCES/openssh-7.8p1-role-mls.patch rename to openssh-7.8p1-role-mls.patch index c3bec2a..7c6d0ca 100644 --- a/SOURCES/openssh-7.8p1-role-mls.patch +++ b/openssh-7.8p1-role-mls.patch @@ -23,23 +23,20 @@ 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 - use_privsep ? " [net]" : ""); +@@ -314,7 +314,13 @@ input_userauth_request(int type, u_int32 + setproctitle("%s [net]", authctxt->valid ? user : "unknown"); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; -- if (use_privsep) +#ifdef WITH_SELINUX + authctxt->role = role ? xstrdup(role) : NULL; +#endif -+ if (use_privsep) { - mm_inform_authserv(service, style); + 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 @@ -50,9 +47,9 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c + char *micuser; struct sshbuf *b; gss_buffer_desc mic, gssbuf; - const char *displayname; + u_char *p; @@ -298,7 +299,13 @@ input_gssapi_mic(int type, u_int32_t ple - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mic.value = p; mic.length = len; - ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, @@ -63,7 +60,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c +#endif + micuser = authctxt->user; + ssh_gssapi_buildmic(b, micuser, authctxt->service, - "gssapi-with-mic"); + "gssapi-with-mic", ssh->kex->session_id); if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) @@ -311,6 +318,8 @@ input_gssapi_mic(int type, u_int32_t ple @@ -74,13 +71,13 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c + free(micuser); free(mic.value); - if ((!use_privsep || mm_is_monitor()) && + authctxt->postponed = 0; diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c --- openssh/auth2-hostbased.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/auth2-hostbased.c 2018-08-22 11:14:56.816430924 +0200 @@ -123,7 +123,16 @@ userauth_hostbased(struct ssh *ssh) /* reconstruct packet */ - if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || + if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || +#ifdef WITH_SELINUX + (authctxt->role @@ -93,7 +90,7 @@ diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c (r = sshbuf_put_cstring(b, authctxt->user)) != 0 || +#endif (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || - (r = sshbuf_put_cstring(b, "hostbased")) != 0 || + (r = sshbuf_put_cstring(b, method)) != 0 || (r = sshbuf_put_string(b, pkalg, alen)) != 0 || diff -up openssh/auth2-pubkey.c.role-mls openssh/auth2-pubkey.c --- openssh/auth2-pubkey.c.role-mls 2018-08-22 11:14:56.816430924 +0200 @@ -141,33 +138,19 @@ diff -up openssh/auth-pam.c.role-mls openssh/auth-pam.c +do_pam_putenv(char *name, const char *value) { int ret = 1; - #ifdef HAVE_PAM_PUTENV + char *compound; diff -up openssh/auth-pam.h.role-mls openssh/auth-pam.h --- openssh/auth-pam.h.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/auth-pam.h 2018-08-22 11:14:56.817430932 +0200 @@ -33,7 +33,7 @@ u_int do_pam_account(void); void do_pam_session(struct ssh *); - void do_pam_setcred(int ); + void do_pam_setcred(void); void do_pam_chauthtok(void); -int do_pam_putenv(char *, char *); +int do_pam_putenv(char *, const char *); char ** fetch_pam_environment(void); char ** fetch_pam_child_environment(void); void free_pam_environment(char **); -diff -up openssh/configure.ac.role-mls openssh/configure.ac ---- openssh/configure.ac.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/configure.ac 2018-08-22 11:14:56.820430957 +0200 -@@ -4241,10 +4241,7 @@ AC_ARG_WITH([selinux], - LIBS="$LIBS -lselinux" - ], - AC_MSG_ERROR([SELinux support requires libselinux library])) -- SSHLIBS="$SSHLIBS $LIBSELINUX" -- SSHDLIBS="$SSHDLIBS $LIBSELINUX" - AC_CHECK_FUNCS([getseuserbyname get_default_context_with_level]) -- LIBS="$save_LIBS" - fi ] - ) - AC_SUBST([SSHLIBS]) diff -up openssh/misc.c.role-mls openssh/misc.c --- openssh/misc.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/misc.c 2018-08-22 11:14:56.817430932 +0200 @@ -193,10 +176,10 @@ diff -up openssh/misc.c.role-mls openssh/misc.c } return NULL; } -diff -up openssh/monitor.c.role-mls openssh/monitor.c ---- openssh/monitor.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/monitor.c 2018-08-22 11:19:56.006844867 +0200 -@@ -115,6 +115,9 @@ int mm_answer_sign(int, struct sshbuf *) +diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c +--- openssh-8.6p1/monitor.c.role-mls 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/monitor.c 2021-05-21 14:21:56.719414087 +0200 +@@ -117,6 +117,9 @@ int mm_answer_sign(struct ssh *, int, st int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); int mm_answer_authserv(struct ssh *, int, struct sshbuf *); @@ -206,7 +189,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); -@@ -189,6 +192,9 @@ struct mon_table mon_dispatch_proto20[] +@@ -195,6 +198,9 @@ struct mon_table mon_dispatch_proto20[] {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, @@ -216,7 +199,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM -@@ -796,6 +802,9 @@ mm_answer_pwnamallow(int sock, struct ss +@@ -803,6 +809,9 @@ mm_answer_pwnamallow(struct ssh *ssh, in /* Allow service/style information on the auth context */ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); @@ -226,7 +209,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); #ifdef USE_PAM -@@ -842,6 +851,26 @@ mm_answer_authserv(int sock, struct sshb +@@ -877,6 +886,26 @@ key_base_type_match(const char *method, return found; } @@ -238,8 +221,8 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c + monitor_permit_authentications(1); + + if ((r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ debug3("%s: role=%s", __func__, authctxt->role); ++ fatal_f("buffer error: %s", ssh_err(r)); ++ debug3_f("role=%s", authctxt->role); + + if (strlen(authctxt->role) == 0) { + free(authctxt->role); @@ -253,25 +236,25 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c int mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) { -@@ -1218,7 +1247,7 @@ monitor_valid_userblob(u_char *data, u_i - { +@@ -1251,7 +1280,7 @@ monitor_valid_userblob(struct ssh *ssh, struct sshbuf *b; + struct sshkey *hostkey = NULL; const u_char *p; - char *userstyle, *cp; + char *userstyle, *s, *cp; size_t len; u_char type; - int r, fail = 0; -@@ -1251,6 +1280,8 @@ monitor_valid_userblob(u_char *data, u_i + int hostbound = 0, r, fail = 0; +@@ -1282,6 +1311,8 @@ monitor_valid_userblob(struct ssh *ssh, fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse userstyle"); + if ((s = strchr(cp, '/')) != NULL) + *s = '\0'; xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); -@@ -1286,7 +1317,7 @@ monitor_valid_hostbasedblob(u_char *data +@@ -1317,7 +1348,7 @@ monitor_valid_hostbasedblob(const u_char { struct sshbuf *b; const u_char *p; @@ -280,10 +263,10 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c size_t len; int r, fail = 0; u_char type; -@@ -1308,6 +1339,8 @@ monitor_valid_hostbasedblob(u_char *data +@@ -1338,6 +1370,8 @@ monitor_valid_hostbasedblob(const u_char fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse userstyle"); + if ((s = strchr(cp, '/')) != NULL) + *s = '\0'; xasprintf(&userstyle, "%s%s%s", authctxt->user, @@ -319,12 +302,12 @@ diff -up openssh/monitor_wrap.c.role-mls openssh/monitor_wrap.c + int r; + struct sshbuf *m; + -+ debug3("%s entering", __func__); ++ debug3_f("entering"); + + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_cstring(m, role ? role : "")) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_f("buffer error: %s", ssh_err(r)); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, m); + + sshbuf_free(m); @@ -338,8 +321,8 @@ diff -up openssh/monitor_wrap.h.role-mls openssh/monitor_wrap.h --- openssh/monitor_wrap.h.role-mls 2018-08-22 11:14:56.818430941 +0200 +++ openssh/monitor_wrap.h 2018-08-22 11:22:10.439929513 +0200 @@ -44,6 +44,9 @@ DH *mm_choose_dh(int, int, int); - int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int compat); + const u_char *, size_t, const char *, const char *, + const char *, u_int compat); void mm_inform_authserv(char *, char *); +#ifdef WITH_SELINUX +void mm_inform_authrole(char *); @@ -351,7 +334,7 @@ diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Make --- openssh/openbsd-compat/Makefile.in.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/openbsd-compat/Makefile.in 2018-08-22 11:14:56.819430949 +0200 @@ -92,7 +92,8 @@ PORTS= port-aix.o \ - port-linux.o \ + port-prngd.o \ port-solaris.o \ port-net.o \ - port-uw.o @@ -359,7 +342,7 @@ diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Make + port-linux-sshd.o .c.o: - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< + $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< diff -up openssh/openbsd-compat/port-linux.c.role-mls openssh/openbsd-compat/port-linux.c --- openssh/openbsd-compat/port-linux.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/openbsd-compat/port-linux.c 2018-08-22 11:14:56.819430949 +0200 @@ -371,7 +354,7 @@ diff -up openssh/openbsd-compat/port-linux.c.role-mls openssh/openbsd-compat/por -void -ssh_selinux_setup_exec_context(char *pwname) -{ -- security_context_t user_ctx = NULL; +- char *user_ctx = NULL; - - if (!ssh_selinux_enabled()) - return; @@ -407,7 +390,7 @@ diff -up openssh/openbsd-compat/port-linux.c.role-mls openssh/openbsd-compat/por - user_ctx = ssh_selinux_getctxbyname(pwname); + if (getexeccon(&user_ctx) != 0) { -+ error("%s: getexeccon: %s", __func__, strerror(errno)); ++ error_f("getexeccon: %s", strerror(errno)); + goto out; + } + @@ -432,7 +415,7 @@ diff -up openssh/openbsd-compat/port-linux.h.role-mls openssh/openbsd-compat/por diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compat/port-linux-sshd.c --- openssh/openbsd-compat/port-linux-sshd.c.role-mls 2018-08-22 11:14:56.819430949 +0200 +++ openssh/openbsd-compat/port-linux-sshd.c 2018-08-22 11:14:56.819430949 +0200 -@@ -0,0 +1,425 @@ +@@ -0,0 +1,420 @@ +/* + * Copyright (c) 2005 Daniel Walsh + * Copyright (c) 2014 Petr Lautrbach @@ -486,7 +469,6 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa +extern ServerOptions options; +extern Authctxt *the_authctxt; +extern int inetd_flag; -+extern int rexeced_flag; + +/* Send audit message */ +static int @@ -544,7 +526,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + access_vector_t bit; + security_class_t class; + -+ debug("%s: src:%s dst:%s", __func__, src, dst); ++ debug_f("src:%s dst:%s", src, dst); + class = string_to_security_class("context"); + if (!class) { + error("string_to_security_class failed to translate security class context"); @@ -692,7 +674,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + + if (r == 0) { + /* If launched from xinetd, we must use current level */ -+ if (inetd_flag && !rexeced_flag) { ++ if (inetd_flag) { + security_context_t sshdsc=NULL; + + if (getcon_raw(&sshdsc) < 0) @@ -706,7 +688,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + /* we actually don't change level */ + reqlvl = ""; + -+ debug("%s: current connection level '%s'", __func__, reqlvl); ++ debug_f("current connection level '%s'", reqlvl); + + } + @@ -734,8 +716,8 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + } + } + if (r != 0) { -+ error("%s: Failed to get default SELinux security " -+ "context for %s", __func__, pwname); ++ error_f("Failed to get default SELinux security " ++ "context for %s", pwname); + } + +#ifdef HAVE_GETSEUSERBYNAME @@ -760,13 +742,13 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + char *use_current; + int rv; + -+ debug3("%s: setting execution context", __func__); ++ debug3_f("setting execution context"); + + ssh_selinux_get_role_level(&role, &reqlvl); + + rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); + -+ if (inetd_flag && !rexeced_flag) { ++ if (inetd_flag) { + use_current = "1"; + } else { + use_current = ""; @@ -797,32 +779,30 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + if (sshd_selinux_setup_pam_variables()) { + switch (security_getenforce()) { + case -1: -+ fatal("%s: security_getenforce() failed", __func__); ++ fatal_f("security_getenforce() failed"); + case 0: -+ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.", -+ __func__); ++ error_f("SELinux PAM variable setup failure. Continuing in permissive mode."); + break; + default: -+ fatal("%s: SELinux PAM variable setup failure. Aborting connection.", -+ __func__); ++ fatal_f("SELinux PAM variable setup failure. Aborting connection."); + } + } + return; + } + -+ debug3("%s: setting execution context", __func__); ++ debug3_f("setting execution context"); + + r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); + if (r >= 0) { + r = setexeccon(user_ctx); + if (r < 0) { -+ error("%s: Failed to set SELinux execution context %s for %s", -+ __func__, user_ctx, pwname); ++ error_f("Failed to set SELinux execution context %s for %s", ++ user_ctx, pwname); + } +#ifdef HAVE_SETKEYCREATECON + else if (setkeycreatecon(user_ctx) < 0) { -+ error("%s: Failed to set SELinux keyring creation context %s for %s", -+ __func__, user_ctx, pwname); ++ error_f("Failed to set SELinux keyring creation context %s for %s", ++ user_ctx, pwname); + } +#endif + } @@ -837,14 +817,12 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + if (r < 0) { + switch (security_getenforce()) { + case -1: -+ fatal("%s: security_getenforce() failed", __func__); ++ fatal_f("security_getenforce() failed"); + case 0: -+ error("%s: SELinux failure. Continuing in permissive mode.", -+ __func__); ++ error_f("ELinux failure. Continuing in permissive mode."); + break; + default: -+ fatal("%s: SELinux failure. Aborting connection.", -+ __func__); ++ fatal_f("SELinux failure. Aborting connection."); + } + } + if (user_ctx != NULL && user_ctx != default_ctx) @@ -852,7 +830,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + if (default_ctx != NULL) + freecon(default_ctx); + -+ debug3("%s: done", __func__); ++ debug3_f("done"); +} + +#endif @@ -871,8 +849,8 @@ diff -up openssh/platform.c.role-mls openssh/platform.c } diff -up openssh/sshd.c.role-mls openssh/sshd.c ---- openssh/sshd.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/sshd.c 2018-08-22 11:14:56.820430957 +0200 +--- openssh/sshd-session.c.role-mls 2018-08-20 07:57:29.000000000 +0200 ++++ openssh/sshd-session.c 2018-08-22 11:14:56.820430957 +0200 @@ -2186,6 +2186,9 @@ main(int ac, char **av) restore_uid(); } @@ -882,4 +860,4 @@ diff -up openssh/sshd.c.role-mls openssh/sshd.c +#endif #ifdef USE_PAM if (options.use_pam) { - do_pam_setcred(1); + do_pam_setcred(); diff --git a/SOURCES/openssh-7.8p1-scp-ipv6.patch b/openssh-7.8p1-scp-ipv6.patch similarity index 100% rename from SOURCES/openssh-7.8p1-scp-ipv6.patch rename to openssh-7.8p1-scp-ipv6.patch diff --git a/openssh-8.0p1-crypto-policies.patch b/openssh-8.0p1-crypto-policies.patch new file mode 100644 index 0000000..fd1e59d --- /dev/null +++ b/openssh-8.0p1-crypto-policies.patch @@ -0,0 +1,640 @@ +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_config.5 openssh-9.3p1-patched/ssh_config.5 +--- openssh-9.3p1/ssh_config.5 2023-06-07 10:26:48.284590156 +0200 ++++ openssh-9.3p1-patched/ssh_config.5 2023-06-07 10:26:00.623052194 +0200 +@@ -378,17 +378,13 @@ + causes no CNAMEs to be considered for canonicalization. + This is the default behaviour. + .It Cm CASignatureAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies which algorithms are allowed for signing of certificates + by certificate authorities (CAs). +-The default is: +-.Bd -literal -offset indent +-ssh-ed25519,ecdsa-sha2-nistp256, +-ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 +-.Ed +-.Pp + If the specified list begins with a + .Sq + + character, then the specified algorithms will be appended to the default set +@@ -450,20 +446,25 @@ + (the default), + the check will not be executed. + .It Cm Ciphers ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the ciphers allowed and their order of preference. + Multiple ciphers must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified ciphers will be appended to the default set +-instead of replacing them. ++character, then the specified ciphers will be appended to the built-in ++openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified ciphers (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified ciphers will be placed at the head of the +-default set. ++built-in openssh default set. + .Pp + The supported ciphers are: + .Bd -literal -offset indent +@@ -479,13 +480,6 @@ + chacha20-poly1305@openssh.com + .Ed + .Pp +-The default is: +-.Bd -literal -offset indent +-chacha20-poly1305@openssh.com, +-aes128-ctr,aes192-ctr,aes256-ctr, +-aes128-gcm@openssh.com,aes256-gcm@openssh.com +-.Ed +-.Pp + The list of available ciphers may also be obtained using + .Qq ssh -Q cipher . + .It Cm ClearAllForwardings +@@ -885,6 +879,11 @@ + The default is + .Dq no . + .It Cm GSSAPIKexAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + The list of key exchange algorithms that are offered for GSSAPI + key exchange. Possible values are + .Bd -literal -offset 3n +@@ -897,10 +896,8 @@ + gss-curve25519-sha256- + .Ed + .Pp +-The default is +-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, +-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . + This option only applies to connections using GSSAPI. ++.Pp + .It Cm HashKnownHosts + Indicates that + .Xr ssh 1 +@@ -919,36 +916,25 @@ + but may be manually hashed using + .Xr ssh-keygen 1 . + .It Cm HostbasedAcceptedAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the signature algorithms that will be used for hostbased + authentication as a comma-separated list of patterns. + Alternately if the specified list begins with a + .Sq + + character, then the specified signature algorithms will be appended +-to the default set instead of replacing them. ++to the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified signature algorithms (including wildcards) +-will be removed from the default set instead of replacing them. ++will be removed from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified signature algorithms will be placed +-at the head of the default set. +-The default for this option is: +-.Bd -literal -offset 3n +-ssh-ed25519-cert-v01@openssh.com, +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-ed25519, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 +-.Ed ++at the head of the built-in openssh default set. + .Pp + The + .Fl Q +@@ -1001,6 +987,17 @@ + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q HostKeyAlgorithms . ++.Pp ++The proposed ++.Cm HostKeyAlgorithms ++during KEX are limited to the set of algorithms that is defined in ++.Cm PubkeyAcceptedAlgorithms ++and therefore they are indirectly affected by system-wide ++.Xr crypto_policies 7 . ++.Xr crypto_policies 7 can not handle the list of host key algorithms directly as doing so ++would break the order given by the ++.Pa known_hosts ++file. + .It Cm HostKeyAlias + Specifies an alias that should be used instead of the + real host name when looking up or saving the host key +@@ -1330,6 +1330,11 @@ it may be zero or more of: + and + .Cm pam . + .It Cm KexAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the permitted KEX (Key Exchange) algorithms that will be used and + their preference order. + The selected algorithm will the the first algorithm in this list that +@@ -1338,28 +1343,17 @@ Multiple algorithms must be comma-separa + .Pp + If the specified list begins with a + .Sq + +-character, then the specified algorithms will be appended to the default set +-instead of replacing them. ++character, then the specified methods will be appended to the built-in ++openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified algorithms (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified algorithms will be placed at the head of the +-default set. +-.Pp +-The default is: +-.Bd -literal -offset indent +-sntrup761x25519-sha512@openssh.com, +-curve25519-sha256,curve25519-sha256@libssh.org, +-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, +-diffie-hellman-group-exchange-sha256, +-diffie-hellman-group16-sha512, +-diffie-hellman-group18-sha512, +-diffie-hellman-group14-sha256 +-.Ed + .Pp ++built-in openssh default set. + The list of supported key exchange algorithms may also be obtained using + .Qq ssh -Q kex . + .It Cm KnownHostsCommand +@@ -1365,37 +1357,33 @@ + file. + This option is intended for debugging and no overrides are enabled by default. + .It Cm MACs ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the MAC (message authentication code) algorithms + in order of preference. + The MAC algorithm is used for data integrity protection. + Multiple algorithms must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified algorithms will be appended to the default set +-instead of replacing them. ++character, then the specified algorithms will be appended to the built-in ++openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified algorithms (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified algorithms will be placed at the head of the +-default set. ++built-in openssh default set. + .Pp + The algorithms that contain + .Qq -etm + calculate the MAC after encryption (encrypt-then-mac). + These are considered safer and their use recommended. + .Pp +-The default is: +-.Bd -literal -offset indent +-umac-64-etm@openssh.com,umac-128-etm@openssh.com, +-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, +-hmac-sha1-etm@openssh.com, +-umac-64@openssh.com,umac-128@openssh.com, +-hmac-sha2-256,hmac-sha2-512,hmac-sha1 +-.Ed +-.Pp + The list of available MAC algorithms may also be obtained using + .Qq ssh -Q mac . + .It Cm NoHostAuthenticationForLocalhost +@@ -1567,39 +1555,31 @@ + The default is + .Cm no . + .It Cm PubkeyAcceptedAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the signature algorithms that will be used for public key + authentication as a comma-separated list of patterns. + If the specified list begins with a + .Sq + +-character, then the algorithms after it will be appended to the default +-instead of replacing it. ++character, then the algorithms after it will be appended to the built-in ++openssh default instead of replacing it. + If the specified list begins with a + .Sq - + character, then the specified algorithms (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified algorithms will be placed at the head of the +-default set. +-The default for this option is: +-.Bd -literal -offset 3n +-ssh-ed25519-cert-v01@openssh.com, +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-ed25519, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 +-.Ed ++built-in openssh default set. + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q PubkeyAcceptedAlgorithms . ++.Pp ++This option affects also ++.Cm HostKeyAlgorithms + .It Cm PubkeyAuthentication + Specifies whether to try public key authentication. + The argument to this keyword must be +@@ -2265,7 +2245,9 @@ + This file must be world-readable. + .El + .Sh SEE ALSO +-.Xr ssh 1 ++.Xr ssh 1 , ++.Xr crypto-policies 7 , ++.Xr update-crypto-policies 8 + .Sh AUTHORS + .An -nosplit + OpenSSH is a derivative of the original and free +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/sshd_config.5 openssh-9.3p1-patched/sshd_config.5 +--- openssh-9.3p1/sshd_config.5 2023-06-07 10:26:48.277590077 +0200 ++++ openssh-9.3p1-patched/sshd_config.5 2023-06-07 10:26:00.592051845 +0200 +@@ -379,17 +379,13 @@ + then no banner is displayed. + By default, no banner is displayed. + .It Cm CASignatureAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies which algorithms are allowed for signing of certificates + by certificate authorities (CAs). +-The default is: +-.Bd -literal -offset indent +-ssh-ed25519,ecdsa-sha2-nistp256, +-ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 +-.Ed +-.Pp + If the specified list begins with a + .Sq + + character, then the specified algorithms will be appended to the default set +@@ -525,20 +521,25 @@ + indicating not to + .Xr chroot 2 . + .It Cm Ciphers ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the ciphers allowed. + Multiple ciphers must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified ciphers will be appended to the default set +-instead of replacing them. ++character, then the specified ciphers will be appended to the built-in ++openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified ciphers (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified ciphers will be placed at the head of the +-default set. ++built-in openssh default set. + .Pp + The supported ciphers are: + .Pp +@@ -565,13 +566,6 @@ + chacha20-poly1305@openssh.com + .El + .Pp +-The default is: +-.Bd -literal -offset indent +-chacha20-poly1305@openssh.com, +-aes128-ctr,aes192-ctr,aes256-ctr, +-aes128-gcm@openssh.com,aes256-gcm@openssh.com +-.Ed +-.Pp + The list of available ciphers may also be obtained using + .Qq ssh -Q cipher . + .It Cm ClientAliveCountMax +@@ -766,53 +760,43 @@ + .Cm GSSAPIKeyExchange + needs to be enabled in the server and also used by the client. + .It Cm GSSAPIKexAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + The list of key exchange algorithms that are accepted by GSSAPI + key exchange. Possible values are + .Bd -literal -offset 3n +-gss-gex-sha1-, +-gss-group1-sha1-, +-gss-group14-sha1-, +-gss-group14-sha256-, +-gss-group16-sha512-, +-gss-nistp256-sha256-, ++gss-gex-sha1- ++gss-group1-sha1- ++gss-group14-sha1- ++gss-group14-sha256- ++gss-group16-sha512- ++gss-nistp256-sha256- + gss-curve25519-sha256- + .Ed +-.Pp +-The default is +-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, +-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . + This option only applies to connections using GSSAPI. + .It Cm HostbasedAcceptedAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the signature algorithms that will be accepted for hostbased + authentication as a list of comma-separated patterns. + Alternately if the specified list begins with a + .Sq + + character, then the specified signature algorithms will be appended to +-the default set instead of replacing them. ++the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified signature algorithms (including wildcards) +-will be removed from the default set instead of replacing them. ++will be removed from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified signature algorithms will be placed at +-the head of the default set. +-The default for this option is: +-.Bd -literal -offset 3n +-ssh-ed25519-cert-v01@openssh.com, +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-ed25519, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 +-.Ed ++the head of the built-in openssh default set. + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q HostbasedAcceptedAlgorithms . +@@ -879,25 +863,14 @@ + .Ev SSH_AUTH_SOCK + environment variable. + .It Cm HostKeyAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the host key signature algorithms + that the server offers. + The default for this option is: +-.Bd -literal -offset 3n +-ssh-ed25519-cert-v01@openssh.com, +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-ed25519, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 +-.Ed +-.Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q HostKeyAlgorithms . + .It Cm IgnoreRhosts +@@ -1025,6 +1025,11 @@ Specifies whether to look at .k5login fi + The default is + .Cm yes . + .It Cm KexAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the permitted KEX (Key Exchange) algorithms that the server will + offer to clients. + The ordering of this list is not important, as the client specifies the +@@ -1033,16 +1038,16 @@ Multiple algorithms must be comma-separa + .Pp + If the specified list begins with a + .Sq + +-character, then the specified algorithms will be appended to the default set +-instead of replacing them. ++character, then the specified methods will be appended to the built-in ++openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified algorithms (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified algorithms will be placed at the head of the +-default set. ++built-in openssh default set. + .Pp + The supported algorithms are: + .Pp +@@ -1075,16 +1080,6 @@ ecdh-sha2-nistp521 + sntrup761x25519-sha512@openssh.com + .El + .Pp +-The default is: +-.Bd -literal -offset indent +-sntrup761x25519-sha512@openssh.com, +-curve25519-sha256,curve25519-sha256@libssh.org, +-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, +-diffie-hellman-group-exchange-sha256, +-diffie-hellman-group16-sha512,diffie-hellman-group18-sha512, +-diffie-hellman-group14-sha256 +-.Ed +-.Pp + The list of supported key exchange algorithms may also be obtained using + .Qq ssh -Q KexAlgorithms . + .It Cm ListenAddress +@@ -1184,21 +1152,26 @@ + file. + This option is intended for debugging and no overrides are enabled by default. + .It Cm MACs ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the available MAC (message authentication code) algorithms. + The MAC algorithm is used for data integrity protection. + Multiple algorithms must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified algorithms will be appended to the default set +-instead of replacing them. ++character, then the specified algorithms will be appended to the built-in ++openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified algorithms (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified algorithms will be placed at the head of the +-default set. ++built-in openssh default set. + .Pp + The algorithms that contain + .Qq -etm +@@ -1241,15 +1214,6 @@ + umac-128-etm@openssh.com + .El + .Pp +-The default is: +-.Bd -literal -offset indent +-umac-64-etm@openssh.com,umac-128-etm@openssh.com, +-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, +-hmac-sha1-etm@openssh.com, +-umac-64@openssh.com,umac-128@openssh.com, +-hmac-sha2-256,hmac-sha2-512,hmac-sha1 +-.Ed +-.Pp + The list of available MAC algorithms may also be obtained using + .Qq ssh -Q mac . + .It Cm Match +@@ -1633,36 +1597,25 @@ + The default is + .Cm yes . + .It Cm PubkeyAcceptedAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the signature algorithms that will be accepted for public key + authentication as a list of comma-separated patterns. + Alternately if the specified list begins with a + .Sq + +-character, then the specified algorithms will be appended to the default set +-instead of replacing them. ++character, then the specified algorithms will be appended to the built-in ++openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified algorithms (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified algorithms will be placed at the head of the +-default set. +-The default for this option is: +-.Bd -literal -offset 3n +-ssh-ed25519-cert-v01@openssh.com, +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-ed25519, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 +-.Ed ++built-in openssh default set. + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q PubkeyAcceptedAlgorithms . +@@ -2131,7 +2084,9 @@ + .El + .Sh SEE ALSO + .Xr sftp-server 8 , +-.Xr sshd 8 ++.Xr sshd 8 , ++.Xr crypto-policies 7 , ++.Xr update-crypto-policies 8 + .Sh AUTHORS + .An -nosplit + OpenSSH is a derivative of the original and free diff --git a/SOURCES/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch similarity index 78% rename from SOURCES/openssh-8.0p1-gssapi-keyex.patch rename to openssh-8.0p1-gssapi-keyex.patch index 2182c49..82b2bfe 100644 --- a/SOURCES/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -1,160 +1,41 @@ -diff --git a/Makefile.in b/Makefile.in -index 6f001bb3..c31821ac 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -100,6 +100,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexgexc.o kexgexs.o \ - sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ -+ kexgssc.o \ - platform-pledge.o platform-tracing.o platform-misc.o +diff --color -ruNp a/auth2.c b/auth2.c +--- a/auth2.c 2024-08-28 12:35:01.189659493 +0200 ++++ b/auth2.c 2024-08-28 12:35:41.246432045 +0200 +@@ -71,6 +71,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif +@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + &method_passwd, +diff --color -ruNp a/auth2-gss.c b/auth2-gss.c +--- a/auth2-gss.c 2024-08-28 12:35:01.189659493 +0200 ++++ b/auth2-gss.c 2024-08-28 12:35:41.265432411 +0200 +@@ -51,6 +51,7 @@ + #define SSH_GSSAPI_MAX_MECHS 2048 -@@ -114,7 +115,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 \ - 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 md5crypt.o \ - sftp-server.o sftp-common.o \ - sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ -diff --git a/auth.c b/auth.c -index 332b6220..7664aaac 100644 ---- a/auth.c -+++ b/auth.c -@@ -399,7 +399,8 @@ auth_root_allowed(struct ssh *ssh, const char *method) - case PERMIT_NO_PASSWD: - if (strcmp(method, "publickey") == 0 || - strcmp(method, "hostbased") == 0 || -- strcmp(method, "gssapi-with-mic") == 0) -+ strcmp(method, "gssapi-with-mic") == 0 || -+ strcmp(method, "gssapi-keyex") == 0) - return 1; - break; - case PERMIT_FORCED_ONLY: -@@ -723,99 +724,6 @@ fakepw(void) - return (&fake); - } + extern ServerOptions options; ++extern struct authmethod_cfg methodcfg_gsskeyex; + extern struct authmethod_cfg methodcfg_gssapi; --/* -- * Returns the remote DNS hostname as a string. The returned string must not -- * be freed. NB. this will usually trigger a DNS query the first time it is -- * called. -- * This function does additional checks on the hostname to mitigate some -- * attacks on legacy rhosts-style authentication. -- * XXX is RhostsRSAAuthentication vulnerable to these? -- * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?) -- */ -- --static char * --remote_hostname(struct ssh *ssh) --{ -- struct sockaddr_storage from; -- socklen_t fromlen; -- struct addrinfo hints, *ai, *aitop; -- char name[NI_MAXHOST], ntop2[NI_MAXHOST]; -- const char *ntop = ssh_remote_ipaddr(ssh); -- -- /* Get IP address of client. */ -- fromlen = sizeof(from); -- memset(&from, 0, sizeof(from)); -- if (getpeername(ssh_packet_get_connection_in(ssh), -- (struct sockaddr *)&from, &fromlen) < 0) { -- debug("getpeername failed: %.100s", strerror(errno)); -- return strdup(ntop); -- } -- -- ipv64_normalise_mapped(&from, &fromlen); -- if (from.ss_family == AF_INET6) -- fromlen = sizeof(struct sockaddr_in6); -- -- debug3("Trying to reverse map address %.100s.", ntop); -- /* Map the IP address to a host name. */ -- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), -- NULL, 0, NI_NAMEREQD) != 0) { -- /* Host name not found. Use ip address. */ -- return strdup(ntop); -- } -- -- /* -- * if reverse lookup result looks like a numeric hostname, -- * someone is trying to trick us by PTR record like following: -- * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 -- */ -- memset(&hints, 0, sizeof(hints)); -- hints.ai_socktype = SOCK_DGRAM; /*dummy*/ -- hints.ai_flags = AI_NUMERICHOST; -- if (getaddrinfo(name, NULL, &hints, &ai) == 0) { -- logit("Nasty PTR record \"%s\" is set up for %s, ignoring", -- name, ntop); -- freeaddrinfo(ai); -- return strdup(ntop); -- } -- -- /* Names are stored in lowercase. */ -- lowercase(name); -- -- /* -- * Map it back to an IP address and check that the given -- * address actually is an address of this host. This is -- * necessary because anyone with access to a name server can -- * define arbitrary names for an IP address. Mapping from -- * name to IP address can be trusted better (but can still be -- * fooled if the intruder has access to the name server of -- * the domain). -- */ -- memset(&hints, 0, sizeof(hints)); -- hints.ai_family = from.ss_family; -- hints.ai_socktype = SOCK_STREAM; -- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { -- logit("reverse mapping checking getaddrinfo for %.700s " -- "[%s] failed.", name, ntop); -- return strdup(ntop); -- } -- /* Look for the address from the list of addresses. */ -- for (ai = aitop; ai; ai = ai->ai_next) { -- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, -- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && -- (strcmp(ntop, ntop2) == 0)) -- break; -- } -- freeaddrinfo(aitop); -- /* If we reached the end of the list, the address was not there. */ -- if (ai == NULL) { -- /* Address not found for the host name. */ -- logit("Address %.100s maps to %.600s, but this does not " -- "map back to the address.", ntop, name); -- return strdup(ntop); -- } -- return strdup(name); --} -- - /* - * 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 -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.29 2018/07/31 03:10:27 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_token(int type, u_int32_t plen, struct ssh *ssh); +@@ -59,6 +60,48 @@ static int input_gssapi_exchange_complet static int input_gssapi_errtok(int, u_int32_t, struct ssh *); -+/* + /* + * The 'gssapi_keyex' userauth mechanism. + */ +static int -+userauth_gsskeyex(struct ssh *ssh) ++userauth_gsskeyex(struct ssh *ssh, const char *method) +{ + Authctxt *authctxt = ssh->authctxt; + int r, authenticated = 0; @@ -165,26 +46,26 @@ index 9351e042..d6446c0c 100644 + + if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) -+ fatal("%s: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "parsing"); + + if ((b = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + + mic.value = p; + mic.length = len; + + ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, -+ "gssapi-keyex"); ++ "gssapi-keyex", ssh->kex->session_id); + + if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) -+ fatal("%s: sshbuf_mutable_ptr failed", __func__); ++ 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)); ++ if (!GSS_ERROR(mm_ssh_gssapi_checkmic(gss_kex_context, ++ &gssbuf, &mic))) ++ authenticated = mm_ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 1); + + sshbuf_free(b); + free(mic.value); @@ -192,66 +73,79 @@ index 9351e042..d6446c0c 100644 + 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) + */ +@@ -267,7 +310,7 @@ input_gssapi_exchange_complete(int type, if ((r = sshpkt_get_end(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw, 1)); +- authenticated = mm_ssh_gssapi_userok(authctxt->user); ++ authenticated = mm_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) + authctxt->postponed = 0; + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); +@@ -315,7 +358,7 @@ input_gssapi_mic(int type, u_int32_t ple 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)); + if (!GSS_ERROR(mm_ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))) +- authenticated = mm_ssh_gssapi_userok(authctxt->user); ++ authenticated = mm_ssh_gssapi_userok(authctxt->user, authctxt->pw, 0); else logit("GSSAPI MIC check failed"); -@@ -326,6 +370,12 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) +@@ -333,6 +376,11 @@ input_gssapi_mic(int type, u_int32_t ple return 0; } +Authmethod method_gsskeyex = { -+ "gssapi-keyex", ++ &methodcfg_gsskeyex, + userauth_gsskeyex, -+ &options.gss_authentication +}; + Authmethod method_gssapi = { - "gssapi-with-mic", + &methodcfg_gssapi, userauth_gssapi, -diff --git a/auth2.c b/auth2.c -index 16ae1a36..7417eafa 100644 ---- a/auth2.c -+++ b/auth2.c -@@ -75,6 +75,7 @@ extern Authmethod method_passwd; - extern Authmethod method_kbdint; - extern Authmethod method_hostbased; +diff --color -ruNp a/auth2-methods.c b/auth2-methods.c +--- a/auth2-methods.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/auth2-methods.c 2024-08-28 12:35:41.265432411 +0200 +@@ -50,6 +50,11 @@ struct authmethod_cfg methodcfg_pubkey = + &options.pubkey_authentication + }; #ifdef GSSAPI -+extern Authmethod method_gsskeyex; - extern Authmethod method_gssapi; - #endif - -@@ -82,6 +83,7 @@ Authmethod *authmethods[] = { - &method_none, - &method_pubkey, ++struct authmethod_cfg methodcfg_gsskeyex = { ++ "gssapi-keyex", ++ NULL, ++ &options.gss_authentication ++}; + struct authmethod_cfg methodcfg_gssapi = { + "gssapi-with-mic", + NULL, +@@ -76,6 +81,7 @@ static struct authmethod_cfg *authmethod + &methodcfg_none, + &methodcfg_pubkey, #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, ++ &methodcfg_gsskeyex, + &methodcfg_gssapi, #endif - &method_passwd, -diff --git a/canohost.c b/canohost.c -index f71a0856..404731d2 100644 ---- a/canohost.c -+++ b/canohost.c + &methodcfg_passwd, +diff --color -ruNp a/auth.c b/auth.c +--- a/auth.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/auth.c 2024-08-28 12:35:41.245432026 +0200 +@@ -356,7 +356,8 @@ auth_root_allowed(struct ssh *ssh, const + case PERMIT_NO_PASSWD: + if (strcmp(method, "publickey") == 0 || + strcmp(method, "hostbased") == 0 || +- strcmp(method, "gssapi-with-mic") == 0) ++ strcmp(method, "gssapi-with-mic") == 0 || ++ strcmp(method, "gssapi-keyex") == 0) + return 1; + break; + case PERMIT_FORCED_ONLY: +diff --color -ruNp a/canohost.c b/canohost.c +--- a/canohost.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/canohost.c 2024-08-28 12:35:41.246432045 +0200 @@ -35,6 +35,99 @@ #include "canohost.h" #include "misc.h" @@ -279,9 +173,9 @@ index f71a0856..404731d2 100644 + fromlen = sizeof(from); + memset(&from, 0, sizeof(from)); + if (getpeername(ssh_packet_get_connection_in(ssh), -+ (struct sockaddr *)&from, &fromlen) < 0) { ++ (struct sockaddr *)&from, &fromlen) == -1) { + debug("getpeername failed: %.100s", strerror(errno)); -+ return strdup(ntop); ++ return xstrdup(ntop); + } + + ipv64_normalise_mapped(&from, &fromlen); @@ -293,7 +187,7 @@ index f71a0856..404731d2 100644 + if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), + NULL, 0, NI_NAMEREQD) != 0) { + /* Host name not found. Use ip address. */ -+ return strdup(ntop); ++ return xstrdup(ntop); + } + + /* @@ -308,7 +202,7 @@ index f71a0856..404731d2 100644 + logit("Nasty PTR record \"%s\" is set up for %s, ignoring", + name, ntop); + freeaddrinfo(ai); -+ return strdup(ntop); ++ return xstrdup(ntop); + } + + /* Names are stored in lowercase. */ @@ -329,7 +223,7 @@ index f71a0856..404731d2 100644 + if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { + logit("reverse mapping checking getaddrinfo for %.700s " + "[%s] failed.", name, ntop); -+ return strdup(ntop); ++ return xstrdup(ntop); + } + /* Look for the address from the list of addresses. */ + for (ai = aitop; ai; ai = ai->ai_next) { @@ -344,18 +238,17 @@ index f71a0856..404731d2 100644 + /* Address not found for the host name. */ + logit("Address %.100s maps to %.600s, but this does not " + "map back to the address.", ntop, name); -+ return strdup(ntop); ++ return xstrdup(ntop); + } -+ return strdup(name); ++ return xstrdup(name); +} + 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 --color -ruNp a/canohost.h b/canohost.h +--- a/canohost.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/canohost.h 2024-08-28 12:35:41.246432045 +0200 @@ -15,6 +15,9 @@ #ifndef _CANOHOST_H #define _CANOHOST_H @@ -366,11 +259,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 521467bd..a0578e9d 100644 ---- a/clientloop.c -+++ b/clientloop.c -@@ -112,6 +112,10 @@ +diff --color -ruNp a/clientloop.c b/clientloop.c +--- a/clientloop.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/clientloop.c 2024-08-28 12:35:41.246432045 +0200 +@@ -115,6 +115,10 @@ #include "ssherr.h" #include "hostfile.h" @@ -378,16 +270,12 @@ index 521467bd..a0578e9d 100644 +#include "ssh-gss.h" +#endif + - /* import options */ - extern Options options; + /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ + #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" -@@ -1374,9 +1378,18 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, - break; - - /* Do channel operations unless rekeying in progress. */ -- if (!ssh_packet_is_rekeying(ssh)) -+ if (!ssh_packet_is_rekeying(ssh)) { - channel_after_select(ssh, readset, writeset); +@@ -1590,6 +1594,14 @@ client_loop(struct ssh *ssh, int have_pt + /* Do channel operations. */ + channel_after_poll(ssh, pfd, npfd_active); +#ifdef GSSAPI + if (options.gss_renewal_rekey && @@ -396,16 +284,14 @@ index 521467bd..a0578e9d 100644 + need_rekeying = 1; + } +#endif -+ } + /* Buffer input from the connection. */ - client_process_net_input(ssh, readset); - -diff --git a/configure.ac b/configure.ac -index 30be6c18..2869f704 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -665,6 +665,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) + if (conn_in_ready) + client_process_net_input(ssh); +diff --color -ruNp a/configure.ac b/configure.ac +--- a/configure.ac 2024-08-28 12:35:01.202659743 +0200 ++++ b/configure.ac 2024-08-28 12:35:41.247432064 +0200 +@@ -774,6 +774,30 @@ int main(void) { if (NSVersionOfRunTimeL [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) @@ -436,20 +322,10 @@ index 30be6c18..2869f704 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..3eaa5fa5 100644 ---- a/gss-genr.c -+++ b/gss-genr.c -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-genr.c,v 1.26 2018/07/10 09:13:30 djm Exp $ */ - - /* -- * Copyright (c) 2001-2007 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 -@@ -41,12 +41,36 @@ +diff --color -ruNp a/gss-genr.c b/gss-genr.c +--- a/gss-genr.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/gss-genr.c 2024-08-28 12:35:41.248432084 +0200 +@@ -42,9 +42,33 @@ #include "sshbuf.h" #include "log.h" #include "ssh2.h" @@ -461,9 +337,6 @@ index d56257b4..3eaa5fa5 100644 #include "ssh-gss.h" - extern u_char *session_id2; - extern u_int session_id2_len; - +typedef struct { + char *encoded; + gss_OID oid; @@ -486,7 +359,7 @@ index d56257b4..3eaa5fa5 100644 /* sshbuf_get for gss_buffer_desc */ int ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) -@@ -62,6 +86,161 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) +@@ -60,6 +84,159 @@ ssh_gssapi_get_buffer_desc(struct sshbuf return 0; } @@ -530,7 +403,8 @@ index d56257b4..3eaa5fa5 100644 + const char *host, const char *client, const char *kex) { + struct sshbuf *buf = NULL; + size_t i; -+ int r, oidpos, enclen; ++ int r = SSH_ERR_ALLOC_FAIL; ++ int oidpos, enclen; + char *mechs, *encoded; + u_char digest[SSH_DIGEST_MAX_LENGTH]; + char deroid[2]; @@ -547,7 +421,7 @@ index d56257b4..3eaa5fa5 100644 + (gss_supported->count + 1)); + + if ((buf = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + + oidpos = 0; + s = cp = xstrdup(kex); @@ -564,8 +438,7 @@ index d56257b4..3eaa5fa5 100644 + gss_supported->elements[i].elements, + gss_supported->elements[i].length)) != 0 || + (r = ssh_digest_final(md, digest, sizeof(digest))) != 0) -+ fatal("%s: digest failed: %s", __func__, -+ ssh_err(r)); ++ fatal_fr(r, "digest failed"); + ssh_digest_free(md); + md = NULL; + @@ -580,12 +453,10 @@ index d56257b4..3eaa5fa5 100644 + (p = strsep(&cp, ","))) { + if (sshbuf_len(buf) != 0 && + (r = sshbuf_put_u8(buf, ',')) != 0) -+ fatal("%s: sshbuf_put_u8 error: %s", -+ __func__, ssh_err(r)); ++ fatal_fr(r, "sshbuf_put_u8 error"); + if ((r = sshbuf_put(buf, p, strlen(p))) != 0 || + (r = sshbuf_put(buf, encoded, enclen)) != 0) -+ fatal("%s: sshbuf_put error: %s", -+ __func__, ssh_err(r)); ++ fatal_fr(r, "sshbuf_put error"); + } + + gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); @@ -598,7 +469,7 @@ index d56257b4..3eaa5fa5 100644 + gss_enc2oid[oidpos].encoded = NULL; + + if ((mechs = sshbuf_dup_string(buf)) == NULL) -+ fatal("%s: sshbuf_dup_string failed", __func__); ++ fatal_f("sshbuf_dup_string failed"); + + sshbuf_free(buf); + @@ -648,7 +519,7 @@ index d56257b4..3eaa5fa5 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 +397,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, +@@ -216,7 +393,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de } ctx->major = gss_init_sec_context(&ctx->minor, @@ -657,11 +528,10 @@ index d56257b4..3eaa5fa5 100644 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -247,9 +426,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) - return (ctx->major); +@@ -246,8 +423,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con } -+OM_uint32 + OM_uint32 +ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) +{ + gss_buffer_desc gssbuf; @@ -692,7 +562,7 @@ index d56257b4..3eaa5fa5 100644 + return(ctx->major); +} + - OM_uint32 ++OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { + if (ctx == NULL) @@ -701,7 +571,7 @@ index d56257b4..3eaa5fa5 100644 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); -@@ -257,6 +470,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) +@@ -255,6 +466,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer return (ctx->major); } @@ -720,8 +590,8 @@ index d56257b4..3eaa5fa5 100644 + void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, - const char *context) -@@ -273,11 +499,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, + const char *context, const struct sshbuf *session_id) +@@ -271,11 +495,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, co } int @@ -738,8 +608,8 @@ index d56257b4..3eaa5fa5 100644 + ctx = &intctx; /* RFC 4462 says we MUST NOT do SPNEGO */ - if (oid->length == spnego_oid.length && -@@ -287,6 +518,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_check_mechanism(Gssctxt **ctx ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); @@ -748,13 +618,13 @@ index d56257b4..3eaa5fa5 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 +531,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +@@ -294,10 +527,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx GSS_C_NO_BUFFER); } -- if (GSS_ERROR(major)) +- if (GSS_ERROR(major)) + if (GSS_ERROR(major) || intctx != NULL) ssh_gssapi_delete_ctx(ctx); @@ -818,10 +688,303 @@ index d56257b4..3eaa5fa5 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 +diff --color -ruNp a/gss-serv.c b/gss-serv.c +--- a/gss-serv.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/gss-serv.c 2024-08-28 12:35:41.248432084 +0200 +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 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 +@@ -44,17 +44,19 @@ + #include "session.h" + #include "misc.h" + #include "servconf.h" ++#include "uidswap.h" + + #include "ssh-gss.h" ++#include "monitor_wrap.h" + + extern ServerOptions options; + + static ssh_gssapi_client gssapi_client = +- { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, +- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; ++ { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL, ++ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0}; + + ssh_gssapi_mech gssapi_null_mech = +- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; ++ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; + + #ifdef KRB5 + extern ssh_gssapi_mech gssapi_kerberos_mech; +@@ -141,6 +143,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss + } + + /* Unprivileged */ ++char * ++ssh_gssapi_server_mechanisms(void) { ++ if (supported_oids == NULL) ++ ssh_gssapi_prepare_supported_oids(); ++ return (ssh_gssapi_kex_mechs(supported_oids, ++ &ssh_gssapi_server_check_mech, NULL, NULL, ++ options.gss_kex_algorithms)); ++} ++ ++/* Unprivileged */ ++int ++ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, ++ const char *dummy) { ++ Gssctxt *ctx = NULL; ++ int res; ++ ++ res = !GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctx, oid)); ++ ssh_gssapi_delete_ctx(&ctx); ++ ++ return (res); ++} ++ ++/* Unprivileged */ + void + ssh_gssapi_supported_oids(gss_OID_set *oidset) + { +@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o + gss_OID_set supported; + + gss_create_empty_oid_set(&min_status, oidset); +- gss_indicate_mechs(&min_status, &supported); ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) ++ return; + + while (supported_mechs[i]->name != NULL) { + if (GSS_ERROR(gss_test_oid_set_member(&min_status, +@@ -276,8 +303,48 @@ OM_uint32 + ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) + { + int i = 0; ++ int equal = 0; ++ gss_name_t new_name = GSS_C_NO_NAME; ++ gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; ++ ++ if (options.gss_store_rekey && client->used && ctx->client_creds) { ++ if (client->mech->oid.length != ctx->oid->length || ++ (memcmp(client->mech->oid.elements, ++ ctx->oid->elements, ctx->oid->length) !=0)) { ++ debug("Rekeyed credentials have different mechanism"); ++ return GSS_S_COMPLETE; ++ } + +- gss_buffer_desc ename; ++ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &new_name, ++ NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ ++ ctx->major = gss_compare_name(&ctx->minor, client->name, ++ new_name, &equal); ++ ++ if (GSS_ERROR(ctx->major)) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ ++ if (!equal) { ++ debug("Rekeyed credentials have different name"); ++ return GSS_S_COMPLETE; ++ } ++ ++ debug("Marking rekeyed credentials for export"); ++ ++ gss_release_name(&ctx->minor, &client->name); ++ gss_release_cred(&ctx->minor, &client->creds); ++ client->name = new_name; ++ client->creds = ctx->client_creds; ++ ctx->client_creds = GSS_C_NO_CREDENTIAL; ++ client->updated = 1; ++ return GSS_S_COMPLETE; ++ } + + client->mech = NULL; + +@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + if (client->mech == NULL) + return GSS_S_FAILURE; + ++ if (ctx->client_creds && ++ (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ + 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_g + return (ctx->major); + } + ++ gss_release_buffer(&ctx->minor, &ename); ++ + /* 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_g + void + ssh_gssapi_cleanup_creds(void) + { +- if (gssapi_client.store.filename != NULL) { +- /* Unlink probably isn't sufficient */ +- debug("removing gssapi cred file\"%s\"", +- gssapi_client.store.filename); +- unlink(gssapi_client.store.filename); ++ krb5_ccache ccache = NULL; ++ krb5_error_code problem; ++ ++ if (gssapi_client.store.data != NULL) { ++ if ((problem = krb5_cc_resolve(gssapi_client.store.data, gssapi_client.store.envval, &ccache))) { ++ debug_f("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(gssapi_client.store.data, problem)); ++ } else if ((problem = krb5_cc_destroy(gssapi_client.store.data, ccache))) { ++ debug_f("krb5_cc_destroy(): %.100s", ++ krb5_get_err_text(gssapi_client.store.data, problem)); ++ } else { ++ krb5_free_context(gssapi_client.store.data); ++ gssapi_client.store.data = NULL; ++ } + } + } + +@@ -356,19 +441,23 @@ ssh_gssapi_do_child(char ***envp, u_int + + /* Privileged */ + int +-ssh_gssapi_userok(char *user) ++ssh_gssapi_userok(char *user, struct passwd *pw, int kex) + { + OM_uint32 lmin; + ++ (void) kex; /* used in privilege separation */ ++ + if (gssapi_client.exportedname.length == 0 || + gssapi_client.exportedname.value == NULL) { + debug("No suitable client data"); + return 0; + } + if (gssapi_client.mech && gssapi_client.mech->userok) +- if ((*gssapi_client.mech->userok)(&gssapi_client, user)) ++ if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { ++ gssapi_client.used = 1; ++ gssapi_client.store.owner = pw; + return 1; +- else { ++ } else { + /* Destroy delegated credentials if userok fails */ + gss_release_buffer(&lmin, &gssapi_client.displayname); + gss_release_buffer(&lmin, &gssapi_client.exportedname); +@@ -382,14 +471,85 @@ ssh_gssapi_userok(char *user) + return (0); + } + +-/* Privileged */ +-OM_uint32 +-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) ++/* These bits are only used for rekeying. The unpriviledged child is running ++ * as the user, the monitor is root. ++ * ++ * In the child, we want to : ++ * *) Ask the monitor to store our credentials into the store we specify ++ * *) If it succeeds, maybe do a PAM update ++ */ ++ ++/* Stuff for PAM */ ++ ++#ifdef USE_PAM ++static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, ++ struct pam_response **resp, void *data) + { +- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, +- gssbuf, gssmic, NULL); ++ return (PAM_CONV_ERR); ++} ++#endif + +- return (ctx->major); ++void ++ssh_gssapi_rekey_creds(void) { ++ int ok; ++#ifdef USE_PAM ++ int ret; ++ pam_handle_t *pamh = NULL; ++ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; ++ char *envstr; ++#endif ++ ++ if (gssapi_client.store.filename == NULL && ++ gssapi_client.store.envval == NULL && ++ gssapi_client.store.envvar == NULL) ++ return; ++ ++ ok = mm_ssh_gssapi_update_creds(&gssapi_client.store); ++ ++ if (!ok) ++ return; ++ ++ debug("Rekeyed credentials stored successfully"); ++ ++ /* Actually managing to play with the ssh pam stack from here will ++ * be next to impossible. In any case, we may want different options ++ * for rekeying. So, use our own :) ++ */ ++#ifdef USE_PAM ++ ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, ++ &pamconv, &pamh); ++ if (ret) ++ return; ++ ++ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, ++ gssapi_client.store.envval); ++ ++ ret = pam_putenv(pamh, envstr); ++ if (!ret) ++ pam_setcred(pamh, PAM_REINITIALIZE_CRED); ++ pam_end(pamh, PAM_SUCCESS); ++#endif ++} ++ ++int ++ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { ++ int ok = 0; ++ ++ /* Check we've got credentials to store */ ++ if (!gssapi_client.updated) ++ return 0; ++ ++ gssapi_client.updated = 0; ++ ++ temporarily_use_uid(gssapi_client.store.owner); ++ if (gssapi_client.mech && gssapi_client.mech->updatecreds) ++ ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); ++ else ++ debug("No update function for this mechanism"); ++ ++ restore_uid(); ++ ++ return ok; + } + + /* Privileged */ +diff --color -ruNp a/gss-serv-krb5.c b/gss-serv-krb5.c +--- a/gss-serv-krb5.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/gss-serv-krb5.c 2024-08-28 12:35:41.248432084 +0200 @@ -1,7 +1,7 @@ /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ @@ -831,7 +994,7 @@ index a151bc1e..8d2b677f 100644 * * 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) +@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl krb5_error_code problem; krb5_principal princ; OM_uint32 maj_status, min_status; @@ -840,7 +1003,7 @@ index a151bc1e..8d2b677f 100644 const char *errmsg; if (client->creds == NULL) { -@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) +@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl return; } @@ -871,7 +1034,7 @@ index a151bc1e..8d2b677f 100644 #ifdef USE_PAM if (options.use_pam) -@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) +@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl krb5_cc_close(krb_context, ccache); @@ -958,516 +1121,67 @@ index a151bc1e..8d2b677f 100644 }; #endif /* KRB5 */ -diff --git a/gss-serv.c b/gss-serv.c -index ab3a15f0..6ce56e92 100644 ---- a/gss-serv.c -+++ b/gss-serv.c -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-serv.c,v 1.31 2018/07/09 21:37:55 markus 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 -@@ -44,17 +44,19 @@ - #include "session.h" - #include "misc.h" - #include "servconf.h" -+#include "uidswap.h" - - #include "ssh-gss.h" -+#include "monitor_wrap.h" - - extern ServerOptions options; - - static ssh_gssapi_client gssapi_client = -- { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, -- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; -+ { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL, -+ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0}; - - ssh_gssapi_mech gssapi_null_mech = -- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; -+ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; - - #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)); - } - -+/* Unprivileged */ -+char * -+ssh_gssapi_server_mechanisms(void) { -+ if (supported_oids == NULL) -+ ssh_gssapi_prepare_supported_oids(); -+ return (ssh_gssapi_kex_mechs(supported_oids, -+ &ssh_gssapi_server_check_mech, NULL, NULL, -+ options.gss_kex_algorithms)); -+} -+ -+/* Unprivileged */ -+int -+ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, -+ const char *dummy) { -+ Gssctxt *ctx = NULL; -+ int res; -+ -+ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); -+ ssh_gssapi_delete_ctx(&ctx); -+ -+ return (res); -+} -+ - /* Unprivileged */ - void - ssh_gssapi_supported_oids(gss_OID_set *oidset) -@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset) - gss_OID_set supported; - - gss_create_empty_oid_set(&min_status, oidset); -- gss_indicate_mechs(&min_status, &supported); -+ -+ if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) -+ return; - - while (supported_mechs[i]->name != NULL) { - if (GSS_ERROR(gss_test_oid_set_member(&min_status, -@@ -276,8 +303,48 @@ OM_uint32 - ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) +diff --color -ruNp a/kex.c b/kex.c +--- a/kex.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/kex.c 2024-08-28 12:35:41.249432103 +0200 +@@ -303,17 +303,37 @@ static int + kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m) { - int i = 0; -+ int equal = 0; -+ gss_name_t new_name = GSS_C_NO_NAME; -+ gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; + int r; ++ int have_key = 0; ++ int ext_count = 2; + -+ if (options.gss_store_rekey && client->used && ctx->client_creds) { -+ if (client->mech->oid.length != ctx->oid->length || -+ (memcmp(client->mech->oid.elements, -+ ctx->oid->elements, ctx->oid->length) !=0)) { -+ debug("Rekeyed credentials have different mechanism"); -+ return GSS_S_COMPLETE; -+ } -+ -+ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, -+ ctx->client_creds, ctx->oid, &new_name, -+ NULL, NULL, NULL))) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } - -- gss_buffer_desc ename; -+ ctx->major = gss_compare_name(&ctx->minor, client->name, -+ new_name, &equal); -+ -+ if (GSS_ERROR(ctx->major)) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } -+ -+ if (!equal) { -+ debug("Rekeyed credentials have different name"); -+ return GSS_S_COMPLETE; -+ } -+ -+ debug("Marking rekeyed credentials for export"); -+ -+ gss_release_name(&ctx->minor, &client->name); -+ gss_release_cred(&ctx->minor, &client->creds); -+ client->name = new_name; -+ client->creds = ctx->client_creds; -+ ctx->client_creds = GSS_C_NO_CREDENTIAL; -+ client->updated = 1; -+ return GSS_S_COMPLETE; -+ } - - client->mech = NULL; - -@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) - if (client->mech == NULL) - return GSS_S_FAILURE; - -+ if (ctx->client_creds && -+ (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, -+ ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } -+ - 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) - return (ctx->major); - } - -+ gss_release_buffer(&ctx->minor, &ename); -+ - /* 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) - void - ssh_gssapi_cleanup_creds(void) - { -- if (gssapi_client.store.filename != NULL) { -- /* Unlink probably isn't sufficient */ -- debug("removing gssapi cred file\"%s\"", -- gssapi_client.store.filename); -- unlink(gssapi_client.store.filename); -+ krb5_ccache ccache = NULL; -+ krb5_error_code problem; -+ -+ if (gssapi_client.store.data != NULL) { -+ if ((problem = krb5_cc_resolve(gssapi_client.store.data, gssapi_client.store.envval, &ccache))) { -+ debug("%s: krb5_cc_resolve(): %.100s", __func__, -+ krb5_get_err_text(gssapi_client.store.data, problem)); -+ } else if ((problem = krb5_cc_destroy(gssapi_client.store.data, ccache))) { -+ debug("%s: krb5_cc_destroy(): %.100s", __func__, -+ krb5_get_err_text(gssapi_client.store.data, problem)); -+ } else { -+ krb5_free_context(gssapi_client.store.data); -+ gssapi_client.store.data = NULL; -+ } - } - } - -@@ -356,19 +441,23 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep) - - /* Privileged */ - int --ssh_gssapi_userok(char *user) -+ssh_gssapi_userok(char *user, struct passwd *pw, int kex) - { - OM_uint32 lmin; - -+ (void) kex; /* used in privilege separation */ -+ - if (gssapi_client.exportedname.length == 0 || - gssapi_client.exportedname.value == NULL) { - debug("No suitable client data"); - return 0; - } - if (gssapi_client.mech && gssapi_client.mech->userok) -- if ((*gssapi_client.mech->userok)(&gssapi_client, user)) -+ if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { -+ gssapi_client.used = 1; -+ gssapi_client.store.owner = pw; - return 1; -- else { -+ } else { - /* 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) - return (0); - } - --/* Privileged */ --OM_uint32 --ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) -+/* These bits are only used for rekeying. The unpriviledged child is running -+ * as the user, the monitor is root. -+ * -+ * In the child, we want to : -+ * *) Ask the monitor to store our credentials into the store we specify -+ * *) If it succeeds, maybe do a PAM update -+ */ -+ -+/* Stuff for PAM */ -+ -+#ifdef USE_PAM -+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, -+ struct pam_response **resp, void *data) - { -- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, -- gssbuf, gssmic, NULL); -+ return (PAM_CONV_ERR); -+} -+#endif - -- return (ctx->major); -+void -+ssh_gssapi_rekey_creds(void) { -+ int ok; -+#ifdef USE_PAM -+ int ret; -+ pam_handle_t *pamh = NULL; -+ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; -+ char *envstr; -+#endif -+ -+ if (gssapi_client.store.filename == NULL && -+ gssapi_client.store.envval == NULL && -+ gssapi_client.store.envvar == NULL) -+ return; -+ -+ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); -+ -+ if (!ok) -+ return; -+ -+ debug("Rekeyed credentials stored successfully"); -+ -+ /* Actually managing to play with the ssh pam stack from here will -+ * be next to impossible. In any case, we may want different options -+ * for rekeying. So, use our own :) ++#ifdef GSSAPI ++ /* ++ * Currently GSS KEX don't provide host keys as optional message, so ++ * no reasons to announce the publickey-hostbound extension + */ -+#ifdef USE_PAM -+ if (!use_privsep) { -+ debug("Not even going to try and do PAM with privsep disabled"); -+ return; ++ if (ssh->kex->gss == NULL) ++ have_key = 1; ++#endif ++ ext_count += have_key; ++ + + if (ssh->kex->server_sig_algs == NULL && + (ssh->kex->server_sig_algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) + return SSH_ERR_ALLOC_FAIL; +- if ((r = sshbuf_put_u32(m, 3)) != 0 || ++ if ((r = sshbuf_put_u32(m, ext_count)) != 0 || + (r = sshbuf_put_cstring(m, "server-sig-algs")) != 0 || +- (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0 || +- (r = sshbuf_put_cstring(m, +- "publickey-hostbound@openssh.com")) != 0 || +- (r = sshbuf_put_cstring(m, "0")) != 0 || +- (r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 || ++ (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0) { ++ error_fr(r, "compose"); ++ return r; + } -+ -+ ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, -+ &pamconv, &pamh); -+ if (ret) -+ return; -+ -+ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, -+ gssapi_client.store.envval); -+ -+ ret = pam_putenv(pamh, envstr); -+ if (!ret) -+ pam_setcred(pamh, PAM_REINITIALIZE_CRED); -+ pam_end(pamh, PAM_SUCCESS); -+#endif -+} -+ -+int -+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { -+ int ok = 0; -+ -+ /* Check we've got credentials to store */ -+ if (!gssapi_client.updated) -+ return 0; -+ -+ gssapi_client.updated = 0; -+ -+ temporarily_use_uid(gssapi_client.store.owner); -+ if (gssapi_client.mech && gssapi_client.mech->updatecreds) -+ ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); -+ else -+ debug("No update function for this mechanism"); -+ -+ restore_uid(); -+ -+ return ok; - } - - /* Privileged */ -diff --git a/hmac.c b/hmac.c -index 1c879640..a29f32c5 100644 ---- a/hmac.c -+++ b/hmac.c -@@ -19,6 +19,7 @@ - - #include - #include -+#include - - #include "sshbuf.h" - #include "digest.h" -diff --git a/kex.c b/kex.c -index 34808b5c..a2a4794e 100644 ---- a/kex.c -+++ b/kex.c -@@ -55,11 +55,16 @@ - #include "misc.h" - #include "dispatch.h" - #include "monitor.h" -+#include "xmalloc.h" - - #include "ssherr.h" - #include "sshbuf.h" - #include "digest.h" - -+#ifdef GSSAPI -+#include "ssh-gss.h" -+#endif -+ - /* prototype */ - static int kex_choose_conf(struct ssh *); - static int kex_input_newkeys(int, u_int32_t, struct ssh *); -@@ -113,15 +118,28 @@ static const struct kexalg kexalgs[] = { - #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ - { NULL, -1, -1, -1}, - }; -+static const struct kexalg gss_kexalgs[] = { -+#ifdef GSSAPI -+ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, -+ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, -+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, -+#endif -+ { NULL, -1, -1, -1 }, -+}; - --char * --kex_alg_list(char sep) -+static char * -+kex_alg_list_internal(char sep, const struct kexalg *algs) - { - char *ret = NULL, *tmp; - size_t nlen, rlen = 0; - const struct kexalg *k; - -- for (k = kexalgs; k->name != NULL; k++) { -+ for (k = algs; k->name != NULL; k++) { - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(k->name); -@@ -136,6 +154,18 @@ kex_alg_list(char sep) - return ret; - } - -+char * -+kex_alg_list(char sep) -+{ -+ return kex_alg_list_internal(sep, kexalgs); -+} -+ -+char * -+kex_gss_alg_list(char sep) -+{ -+ return kex_alg_list_internal(sep, gss_kexalgs); -+} -+ - static const struct kexalg * - kex_alg_by_name(const char *name) - { -@@ -145,6 +175,10 @@ kex_alg_by_name(const char *name) - if (strcmp(k->name, name) == 0) - return k; - } -+ for (k = gss_kexalgs; k->name != NULL; k++) { -+ if (strncmp(k->name, name, strlen(k->name)) == 0) -+ return k; -+ } - return NULL; - } - -@@ -301,6 +335,29 @@ kex_assemble_names(char **listp, const char *def, const char *all) - return r; - } - -+/* Validate GSS KEX method name list */ -+int -+kex_gss_names_valid(const char *names) -+{ -+ char *s, *cp, *p; -+ -+ if (names == NULL || *names == '\0') -+ return 0; -+ s = cp = xstrdup(names); -+ for ((p = strsep(&cp, ",")); p && *p != '\0'; -+ (p = strsep(&cp, ","))) { -+ if (strncmp(p, "gss-", 4) != 0 -+ || kex_alg_by_name(p) == NULL) { -+ error("Unsupported KEX algorithm \"%.100s\"", p); -+ free(s); -+ return 0; ++ if (have_key) { ++ if ((r = sshbuf_put_cstring(m, "publickey-hostbound@openssh.com")) != 0 || ++ (r = sshbuf_put_cstring(m, "0")) != 0) { ++ error_fr(r, "compose"); ++ return r; + } + } -+ debug3("gss kex names ok: [%s]", names); -+ free(s); -+ return 1; -+} -+ - /* put algorithm proposal into buffer */ - int - kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) -@@ -657,6 +714,9 @@ kex_free(struct kex *kex) ++ if ((r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 || + (r = sshbuf_put_cstring(m, "0")) != 0) { + error_fr(r, "compose"); + return r; +@@ -737,6 +737,9 @@ kex_free(struct kex *kex) sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); - free(kex->session_id); + sshbuf_free(kex->session_id); +#ifdef GSSAPI + free(kex->gss_host); +#endif /* GSSAPI */ + sshbuf_free(kex->initial_sig); + sshkey_free(kex->initial_hostkey); free(kex->failed_choice); - free(kex->hostkey_alg); - free(kex->name); -diff --git a/kex.h b/kex.h -index 6d446d1c..f95dc02c 100644 ---- a/kex.h -+++ b/kex.h -@@ -103,6 +103,15 @@ enum kex_exchange { - KEX_ECDH_SHA2, - KEX_C25519_SHA256, - KEX_KEM_SNTRUP4591761X25519_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 - }; - -@@ -154,6 +163,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 *); -@@ -175,8 +190,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 *); - - int kex_exchange_identification(struct ssh *, int, const char *); - -@@ -203,6 +220,12 @@ int kexgex_client(struct ssh *); - int kexgex_server(struct ssh *); - int kex_gen_client(struct ssh *); - int kex_gen_server(struct ssh *); -+#ifdef GSSAPI -+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 **, -@@ -235,6 +258,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 --color -ruNp a/kexdh.c b/kexdh.c +--- a/kexdh.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/kexdh.c 2024-08-28 12:35:41.249432103 +0200 +@@ -49,13 +49,23 @@ kex_dh_keygen(struct kex *kex) { switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: @@ -1491,11 +1205,10 @@ index 67133e33..edaa4676 100644 kex->dh = dh_new_group16(); break; case KEX_DH_GRP18_SHA512: -diff --git a/kexgen.c b/kexgen.c -index 2abbb9ef..569dc83f 100644 ---- a/kexgen.c -+++ b/kexgen.c -@@ -43,7 +43,7 @@ +diff --color -ruNp a/kexgen.c b/kexgen.c +--- a/kexgen.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/kexgen.c 2024-08-28 12:35:41.249432103 +0200 +@@ -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); @@ -1504,12 +1217,10 @@ index 2abbb9ef..569dc83f 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..0b2f6a56 ---- /dev/null -+++ b/kexgssc.c -@@ -0,0 +1,618 @@ +diff --color -ruNp a/kexgssc.c b/kexgssc.c +--- a/kexgssc.c 1970-01-01 01:00:00.000000000 +0100 ++++ b/kexgssc.c 2024-08-28 12:35:41.250432122 +0200 +@@ -0,0 +1,612 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1608,7 +1319,7 @@ index 00000000..0b2f6a56 + r = kex_c25519_keypair(kex); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ fatal_f("Unexpected KEX type %d", kex->kex_type); + } + if (r != 0) { + ssh_gssapi_delete_ctx(&ctxt); @@ -1676,7 +1387,7 @@ index 00000000..0b2f6a56 + do { + type = ssh_packet_read(ssh); + if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -+ char *tmp = NULL; ++ u_char *tmp = NULL; + size_t tmp_len = 0; + + debug("Received KEXGSS_HOSTKEY"); @@ -1803,7 +1514,7 @@ index 00000000..0b2f6a56 + server_blob, + shared_secret, + hash, &hashlen)) != 0) -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ fatal_f("Unexpected KEX type %d", kex->kex_type); + + gssbuf.value = hash; + gssbuf.length = hashlen; @@ -1972,7 +1683,7 @@ index 00000000..0b2f6a56 + do { + type = ssh_packet_read(ssh); + if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -+ char *tmp = NULL; ++ u_char *tmp = NULL; + size_t tmp_len = 0; + + debug("Received KEXGSS_HOSTKEY"); @@ -2097,13 +1808,6 @@ index 00000000..0b2f6a56 + + gss_release_buffer(&min_status, &msg_tok); + -+ /* save session id */ -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); -+ } -+ + if (kex->gss_deleg_creds) + ssh_gssapi_credentials_updated(ctxt); + @@ -2127,12 +1831,11 @@ index 00000000..0b2f6a56 + sshbuf_free(server_host_key_blob); + return r; +} ++ +#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 +diff --color -ruNp a/kexgsss.c b/kexgsss.c +--- a/kexgsss.c 1970-01-01 01:00:00.000000000 +0100 ++++ b/kexgsss.c 2024-08-28 12:35:41.250432122 +0200 @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. @@ -2225,14 +1928,14 @@ index 00000000..60bc02de + free(mechs); + } + -+ debug2("%s: Identifying %s", __func__, kex->name); ++ debug2_f("Identifying %s", kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) + fatal("Unknown gssapi mechanism"); + -+ debug2("%s: Acquiring credentials", __func__); ++ debug2_f("Acquiring credentials"); + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) + fatal("Unable to acquire credentials for the server"); + + do { @@ -2265,7 +1968,7 @@ index 00000000..60bc02de + &shared_secret); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ fatal_f("Unexpected KEX type %d", kex->kex_type); + } + if (r != 0) + goto out; @@ -2309,8 +2012,8 @@ index 00000000..60bc02de + type); + } + -+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags)); ++ maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags); + + gss_release_buffer(&min_status, &recv_tok); + @@ -2346,7 +2049,7 @@ index 00000000..60bc02de + if (!(ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || @@ -2429,14 +2132,14 @@ index 00000000..60bc02de + if ((mechs = ssh_gssapi_server_mechanisms())) + free(mechs); + -+ debug2("%s: Identifying %s", __func__, kex->name); ++ debug2_f("Identifying %s", kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) + fatal("Unknown gssapi mechanism"); + -+ debug2("%s: Acquiring credentials", __func__); ++ debug2_f("Acquiring credentials"); + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) + fatal("Unable to acquire credentials for the server"); + + /* 5. S generates an ephemeral key pair (do the allocations early) */ @@ -2458,7 +2161,7 @@ index 00000000..60bc02de + if (max < min || nbits < min || max < nbits) + fatal("GSS_GEX, bad parameters: %d !< %d !< %d", + min, nbits, max); -+ kex->dh = PRIVSEP(choose_dh(min, nbits, max)); ++ kex->dh = mm_choose_dh(min, nbits, max); + if (kex->dh == NULL) { + sshpkt_disconnect(ssh, "Protocol error: no matching group found"); + fatal("Protocol error: no matching group found"); @@ -2505,8 +2208,8 @@ index 00000000..60bc02de + type); + } + -+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags)); ++ maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags); + + gss_release_buffer(&min_status, &recv_tok); + @@ -2571,7 +2274,7 @@ index 00000000..60bc02de + gssbuf.value = hash; + gssbuf.length = hashlen; + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || @@ -2616,32 +2319,220 @@ index 00000000..60bc02de + return r; +} +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --git a/mac.c b/mac.c -index 51dc11d7..3d11eba6 100644 ---- a/mac.c -+++ b/mac.c -@@ -29,6 +29,7 @@ +diff --color -ruNp a/kex.h b/kex.h +--- a/kex.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/kex.h 2024-08-28 12:35:41.249432103 +0200 +@@ -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 + }; - #include - #include -+#include +@@ -164,6 +173,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 *); +@@ -189,8 +204,10 @@ int kex_hash_from_name(const char *); + int kex_nid_from_name(const char *); + 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_has_any_alg(const char *, const char *); ++int kex_gss_names_valid(const char *); + int kex_assemble_names(char **, const char *, const char *); + void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], + const char *, const char *, const char *, const char *, const char *); +@@ -224,6 +241,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 - #include "digest.h" - #include "hmac.h" -diff --git a/monitor.c b/monitor.c -index 60e52944..669cdb4a 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -147,6 +147,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); + int kex_dh_keypair(struct kex *); + int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, +@@ -256,6 +279,12 @@ int kexgex_hash(int, const struct sshbu + 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 --color -ruNp a/kex-names.c b/kex-names.c +--- a/kex-names.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/kex-names.c 2024-08-28 12:35:41.249432103 +0200 +@@ -45,6 +45,10 @@ + #include "ssherr.h" + #include "xmalloc.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + struct kexalg { + char *name; + u_int type; +@@ -83,15 +87,28 @@ static const struct kexalg kexalgs[] = { + #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ + { NULL, 0, -1, -1}, + }; ++static const struct kexalg gss_kexalgs[] = { ++#ifdef GSSAPI ++ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, ++ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, ++ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, ++#endif ++ { NULL, 0, -1, -1}, ++}; + +-char * +-kex_alg_list(char sep) ++static char * ++kex_alg_list_internal(char sep, const struct kexalg *algs) + { + char *ret = NULL, *tmp; + size_t nlen, rlen = 0; + const struct kexalg *k; + +- for (k = kexalgs; k->name != NULL; k++) { ++ for (k = algs; k->name != NULL; k++) { + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(k->name); +@@ -106,6 +123,18 @@ kex_alg_list(char sep) + return ret; + } + ++char * ++kex_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, kexalgs); ++} ++ ++char * ++kex_gss_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, gss_kexalgs); ++} ++ + static const struct kexalg * + kex_alg_by_name(const char *name) + { +@@ -115,6 +144,10 @@ kex_alg_by_name(const char *name) + if (strcmp(k->name, name) == 0) + return k; + } ++ for (k = gss_kexalgs; k->name != NULL; k++) { ++ if (strncmp(k->name, name, strlen(k->name)) == 0) ++ return k; ++ } + return NULL; + } + +@@ -328,3 +361,26 @@ kex_assemble_names(char **listp, const c + free(ret); + return r; + } ++ ++/* Validate GSS KEX method name list */ ++int ++kex_gss_names_valid(const char *names) ++{ ++ char *s, *cp, *p; ++ ++ if (names == NULL || *names == '\0') ++ return 0; ++ s = cp = xstrdup(names); ++ for ((p = strsep(&cp, ",")); p && *p != '\0'; ++ (p = strsep(&cp, ","))) { ++ if (strncmp(p, "gss-", 4) != 0 ++ || kex_alg_by_name(p) == NULL) { ++ error("Unsupported KEX algorithm \"%.100s\"", p); ++ free(s); ++ return 0; ++ } ++ } ++ debug3("gss kex names ok: [%s]", names); ++ free(s); ++ return 1; ++} +diff --color -ruNp a/Makefile.in b/Makefile.in +--- a/Makefile.in 2024-08-28 12:35:01.200659705 +0200 ++++ b/Makefile.in 2024-08-28 12:35:41.244432006 +0200 +@@ -114,6 +114,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kex.o kex-names.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 + +@@ -135,7 +136,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rh + auth2-chall.o groupaccess.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 \ ++ monitor.o monitor_wrap.o auth-krb5.o kexgsss.o \ + auth2-gss.o gss-serv.o gss-serv-krb5.o \ + loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ + sftp-server.o sftp-common.o \ +@@ -529,7 +530,7 @@ regress-prep: + 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 --color -ruNp a/monitor.c b/monitor.c +--- a/monitor.c 2024-08-28 12:35:01.192659551 +0200 ++++ b/monitor.c 2024-08-28 12:35:41.251432142 +0200 +@@ -143,6 +143,8 @@ int mm_answer_gss_setup_ctx(struct ssh * 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 *); -+int mm_answer_gss_sign(struct ssh*, int, struct sshbuf *); -+int mm_answer_gss_updatecreds(struct ssh*, int, struct sshbuf *); ++int mm_answer_gss_sign(struct ssh *, int, struct sshbuf *); ++int mm_answer_gss_updatecreds(struct ssh *, int, struct sshbuf *); #endif #ifdef SSH_AUDIT_EVENTS -@@ -219,11 +221,18 @@ struct mon_table mon_dispatch_proto20[] = { +@@ -219,11 +221,18 @@ struct mon_table mon_dispatch_proto20[] {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}, @@ -2660,7 +2551,7 @@ index 60e52944..669cdb4a 100644 #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, #endif -@@ -292,6 +301,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -292,6 +301,10 @@ monitor_child_preauth(struct ssh *ssh, s /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -2671,7 +2562,24 @@ index 60e52944..669cdb4a 100644 /* The first few requests do not require asynchronous access */ while (!authenticated) { -@@ -405,6 +418,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -344,8 +357,15 @@ monitor_child_preauth(struct ssh *ssh, s + if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { + auth_log(ssh, authenticated, partial, + auth_method, auth_submethod); +- if (!partial && !authenticated) ++ if (!partial && !authenticated) { ++#ifdef GSSAPI ++ /* If gssapi-with-mic failed, MONITOR_REQ_GSSCHECKMIC is disabled. ++ * We have to reenable it to try again for gssapi-keyex */ ++ if (strcmp(auth_method, "gssapi-with-mic") == 0 && options.gss_keyex) ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); ++#endif + authctxt->failures++; ++ } + if (authenticated || partial) { + auth2_update_session_info(authctxt, + auth_method, auth_submethod); +@@ -413,6 +433,10 @@ monitor_child_postauth(struct ssh *ssh, monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); @@ -2682,47 +2590,47 @@ index 60e52944..669cdb4a 100644 if (auth_opts->permit_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); -@@ -1687,6 +1704,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1793,6 +1817,17 @@ monitor_apply_keystate(struct ssh *ssh, # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_gen_server; + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif +# ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; -+ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; -+ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; -+ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; -+ } ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; ++ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; ++ } +# endif #endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kex_gen_server; - kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; -@@ -1780,8 +1808,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; +@@ -1885,8 +1920,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, u_char *p; int r; - if (!options.gss_authentication) -- fatal("%s: GSSAPI authentication not enabled", __func__); +- fatal_f("GSSAPI authentication not enabled"); + if (!options.gss_authentication && !options.gss_keyex) -+ fatal("%s: GSSAPI not enabled", __func__); ++ fatal_f("GSSAPI not enabled"); if ((r = sshbuf_get_string(m, &p, &len)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -@@ -1813,8 +1841,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) + fatal_fr(r, "parse"); +@@ -1918,8 +1953,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh OM_uint32 flags = 0; /* GSI needs this */ int r; - if (!options.gss_authentication) -- fatal("%s: GSSAPI authentication not enabled", __func__); +- fatal_f("GSSAPI authentication not enabled"); + if (!options.gss_authentication && !options.gss_keyex) -+ fatal("%s: GSSAPI not enabled", __func__); ++ fatal_f("GSSAPI not enabled"); if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -@@ -1834,6 +1862,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) + fatal_fr(r, "ssh_gssapi_get_buffer_desc"); +@@ -1939,6 +1974,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); @@ -2730,18 +2638,18 @@ index 60e52944..669cdb4a 100644 } return (0); } -@@ -1845,8 +1874,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1950,8 +1986,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, OM_uint32 ret; int r; - if (!options.gss_authentication) -- fatal("%s: GSSAPI authentication not enabled", __func__); +- fatal_f("GSSAPI authentication not enabled"); + if (!options.gss_authentication && !options.gss_keyex) -+ fatal("%s: GSSAPI not enabled", __func__); ++ fatal_f("GSSAPI not enabled"); if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) -@@ -1872,13 +1901,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1977,13 +2013,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -2750,21 +2658,21 @@ index 60e52944..669cdb4a 100644 const char *displayname; - if (!options.gss_authentication) -- fatal("%s: GSSAPI authentication not enabled", __func__); +- fatal_f("GSSAPI authentication not enabled"); + if (!options.gss_authentication && !options.gss_keyex) -+ fatal("%s: GSSAPI not enabled", __func__); ++ fatal_f("GSSAPI not enabled"); - authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); + if ((r = sshbuf_get_u32(m, &kex)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + authenticated = authctxt->valid && + ssh_gssapi_userok(authctxt->user, authctxt->pw, kex); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) -@@ -1887,7 +1920,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) - debug3("%s: sending result %d", __func__, authenticated); +@@ -1992,7 +2032,11 @@ mm_answer_gss_userok(struct ssh *ssh, in + debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); - auth_method = "gssapi-with-mic"; @@ -2776,7 +2684,7 @@ index 60e52944..669cdb4a 100644 if ((displayname = ssh_gssapi_displayname()) != NULL) auth2_record_info(authctxt, "%s", displayname); -@@ -1895,5 +1932,85 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -2000,5 +2044,84 @@ mm_answer_gss_userok(struct ssh *ssh, in /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -2792,16 +2700,15 @@ index 60e52944..669cdb4a 100644 + int r; + + if (!options.gss_authentication && !options.gss_keyex) -+ fatal("%s: GSSAPI not enabled", __func__); ++ fatal_f("GSSAPI not enabled"); + + if ((r = sshbuf_get_string(m, &p, &len)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + data.value = p; + data.length = len; + /* Lengths of SHA-1, SHA-256 and SHA-512 hashes that are used */ + if (data.length != 20 && data.length != 32 && data.length != 64) -+ fatal("%s: data length incorrect: %d", __func__, -+ (int) data.length); ++ fatal_f("data length incorrect: %d", (int) data.length); + + /* Save the session ID on the first time around */ + if (session_id2_len == 0) { @@ -2817,7 +2724,7 @@ index 60e52944..669cdb4a 100644 + + if ((r = sshbuf_put_u32(m, major)) != 0 || + (r = sshbuf_put_string(m, hash.value, hash.length)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); + @@ -2838,12 +2745,12 @@ index 60e52944..669cdb4a 100644 + int r, ok; + + if (!options.gss_authentication && !options.gss_keyex) -+ fatal("%s: GSSAPI not enabled", __func__); ++ fatal_f("GSSAPI not enabled"); + + if ((r = sshbuf_get_string(m, (u_char **)&store.filename, NULL)) != 0 || + (r = sshbuf_get_string(m, (u_char **)&store.envvar, NULL)) != 0 || + (r = sshbuf_get_string(m, (u_char **)&store.envval, NULL)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + ok = ssh_gssapi_update_creds(&store); + @@ -2853,7 +2760,7 @@ index 60e52944..669cdb4a 100644 + + sshbuf_reset(m); + if ((r = sshbuf_put_u32(m, ok)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); + @@ -2862,11 +2769,10 @@ index 60e52944..669cdb4a 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 --color -ruNp a/monitor.h b/monitor.h +--- a/monitor.h 2024-08-28 12:35:01.192659551 +0200 ++++ b/monitor.h 2024-08-28 12:35:41.251432142 +0200 +@@ -67,6 +67,8 @@ enum monitor_reqtype { MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, @@ -2875,11 +2781,10 @@ index 683e5e07..2b1a2d59 100644 }; struct ssh; -diff --git a/monitor_wrap.c b/monitor_wrap.c -index 186e8f02..8e4c1c1f 100644 ---- a/monitor_wrap.c -+++ b/monitor_wrap.c -@@ -978,13 +978,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +diff --color -ruNp a/monitor_wrap.c b/monitor_wrap.c +--- a/monitor_wrap.c 2024-08-28 12:35:01.192659551 +0200 ++++ b/monitor_wrap.c 2024-08-28 12:35:41.251432142 +0200 +@@ -1075,13 +1075,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss } int @@ -2890,14 +2795,14 @@ index 186e8f02..8e4c1c1f 100644 int r, authenticated = 0; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u32(m, kex)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, -@@ -997,4 +999,57 @@ mm_ssh_gssapi_userok(char *user) - debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); +@@ -1094,6 +1096,59 @@ mm_ssh_gssapi_userok(char *user) + debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } + @@ -2909,16 +2814,16 @@ index 186e8f02..8e4c1c1f 100644 + int r; + + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_string(m, data->value, data->length)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, m); + + if ((r = sshbuf_get_u32(m, &major)) != 0 || + (r = ssh_gssapi_get_buffer_desc(m, hash)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + sshbuf_free(m); + @@ -2932,7 +2837,7 @@ index 186e8f02..8e4c1c1f 100644 + int r, ok; + + if ((m = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + + if ((r = sshbuf_put_cstring(m, + store->filename ? store->filename : "")) != 0 || @@ -2940,13 +2845,13 @@ index 186e8f02..8e4c1c1f 100644 + store->envvar ? store->envvar : "")) != 0 || + (r = sshbuf_put_cstring(m, + store->envval ? store->envval : "")) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, m); + + if ((r = sshbuf_get_u32(m, &ok)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "buffer error"); + + sshbuf_free(m); + @@ -2954,11 +2859,12 @@ index 186e8f02..8e4c1c1f 100644 +} + #endif /* GSSAPI */ -diff --git a/monitor_wrap.h b/monitor_wrap.h -index fdebb3aa..69164a8c 100644 ---- a/monitor_wrap.h -+++ b/monitor_wrap.h -@@ -61,8 +61,10 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, + + /* +diff --color -ruNp a/monitor_wrap.h b/monitor_wrap.h +--- a/monitor_wrap.h 2024-08-28 12:35:01.193659570 +0200 ++++ b/monitor_wrap.h 2024-08-28 12:35:41.251432142 +0200 +@@ -67,8 +67,10 @@ void mm_decode_activate_server_options(s 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 *); @@ -2970,11 +2876,54 @@ index fdebb3aa..69164a8c 100644 #endif #ifdef USE_PAM -diff --git a/readconf.c b/readconf.c -index ec497e79..4d699e5f 100644 ---- a/readconf.c -+++ b/readconf.c -@@ -67,6 +67,7 @@ +diff --color -ruNp a/packet.c b/packet.c +--- a/packet.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/packet.c 2024-08-28 12:35:41.260432315 +0200 +@@ -1517,6 +1517,29 @@ ssh_packet_read(struct ssh *ssh) + 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 --color -ruNp a/packet.h b/packet.h +--- a/packet.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/packet.h 2024-08-28 12:35:41.260432315 +0200 +@@ -124,6 +124,7 @@ int ssh_packet_send2_wrapped(struct ssh + 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_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); + int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); + int ssh_packet_process_read(struct ssh *, int); +diff --color -ruNp a/readconf.c b/readconf.c +--- a/readconf.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/readconf.c 2024-08-28 12:35:41.253432180 +0200 +@@ -70,6 +70,7 @@ #include "uidswap.h" #include "myproposal.h" #include "digest.h" @@ -2982,7 +2931,7 @@ index ec497e79..4d699e5f 100644 /* Format of the configuration file: -@@ -162,6 +163,8 @@ typedef enum { +@@ -164,6 +165,8 @@ typedef enum { oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, @@ -2991,7 +2940,7 @@ index ec497e79..4d699e5f 100644 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, -@@ -202,10 +205,22 @@ static struct { +@@ -210,10 +213,22 @@ static struct { /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, @@ -3014,7 +2963,7 @@ index ec497e79..4d699e5f 100644 #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, -@@ -983,10 +998,42 @@ parse_time: +@@ -1227,10 +1242,42 @@ parse_time: intptr = &options->gss_authentication; goto parse_flag; @@ -3043,7 +2992,7 @@ index ec497e79..4d699e5f 100644 + goto parse_flag; + + case oGssKexAlgorithms: -+ arg = strdelim(&s); ++ arg = argv_next(&ac, &av); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", + filename, linenum); @@ -3057,9 +3006,9 @@ index ec497e79..4d699e5f 100644 case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -1854,7 +1901,13 @@ initialize_options(Options * options) +@@ -2542,7 +2589,13 @@ initialize_options(Options * options) + options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; - options->challenge_response_authentication = -1; options->gss_authentication = -1; + options->gss_keyex = -1; options->gss_deleg_creds = -1; @@ -3071,8 +3020,8 @@ index ec497e79..4d699e5f 100644 options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; -@@ -2000,8 +2053,18 @@ fill_default_options(Options * options) - options->challenge_response_authentication = 1; +@@ -2705,8 +2758,18 @@ fill_default_options(Options * options) + options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; + if (options->gss_keyex == -1) @@ -3090,7 +3039,7 @@ index ec497e79..4d699e5f 100644 if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -2616,7 +2679,14 @@ dump_client_config(Options *o, const char *host) +@@ -3533,7 +3596,14 @@ dump_client_config(Options *o, const cha dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); #ifdef GSSAPI dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); @@ -3105,13 +3054,12 @@ index ec497e79..4d699e5f 100644 #endif /* GSSAPI */ dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); -diff --git a/readconf.h b/readconf.h -index 8e36bf32..0bff6d80 100644 ---- a/readconf.h -+++ b/readconf.h +diff --color -ruNp a/readconf.h b/readconf.h +--- a/readconf.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/readconf.h 2024-08-28 12:35:41.254432199 +0200 @@ -40,7 +40,13 @@ typedef struct { - int challenge_response_authentication; - /* Try S/Key or TIS, authentication. */ + int pubkey_authentication; /* Try ssh2 pubkey authentication. */ + int hostbased_authentication; /* ssh2's rhosts_rsa */ int gss_authentication; /* Try GSS authentication */ + int gss_keyex; /* Try GSS key exchange */ int gss_deleg_creds; /* Delegate GSS credentials */ @@ -3123,19 +3071,18 @@ index 8e36bf32..0bff6d80 100644 int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff --git a/servconf.c b/servconf.c -index ffac5d2c..ffdad31e 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -64,6 +64,7 @@ +diff --color -ruNp a/servconf.c b/servconf.c +--- a/servconf.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/servconf.c 2024-08-28 12:35:41.255432218 +0200 +@@ -68,6 +68,7 @@ #include "auth.h" #include "myproposal.h" #include "digest.h" +#include "ssh-gss.h" - static void add_listen_addr(ServerOptions *, const char *, - const char *, int); -@@ -124,8 +125,11 @@ initialize_server_options(ServerOptions *options) + #if !defined(SSHD_PAM_SERVICE) + # define SSHD_PAM_SERVICE "sshd" +@@ -137,8 +138,11 @@ initialize_server_options(ServerOptions options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; @@ -3146,8 +3093,8 @@ index ffac5d2c..ffdad31e 100644 + options->gss_kex_algorithms = NULL; options->password_authentication = -1; options->kbd_interactive_authentication = -1; - options->challenge_response_authentication = -1; -@@ -351,10 +355,18 @@ fill_default_server_options(ServerOptions *options) + options->permit_empty_passwd = -1; +@@ -376,10 +380,18 @@ fill_default_server_options(ServerOption options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3166,15 +3113,15 @@ index ffac5d2c..ffdad31e 100644 if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -498,6 +510,7 @@ typedef enum { - sHostKeyAlgorithms, +@@ -558,6 +570,7 @@ typedef enum { + sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, + sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -572,12 +585,22 @@ static struct { +@@ -643,12 +656,22 @@ static struct { #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, @@ -3196,8 +3143,8 @@ index ffac5d2c..ffdad31e 100644 + { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, - { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, -@@ -1485,6 +1508,10 @@ process_server_config_line(ServerOptions *options, char *line, + { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ +@@ -1585,6 +1608,10 @@ process_server_config_line_depth(ServerO intptr = &options->gss_authentication; goto parse_flag; @@ -3208,7 +3155,7 @@ index ffac5d2c..ffdad31e 100644 case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1493,6 +1520,22 @@ process_server_config_line(ServerOptions *options, char *line, +@@ -1593,6 +1620,22 @@ process_server_config_line_depth(ServerO intptr = &options->gss_strict_acceptor; goto parse_flag; @@ -3217,7 +3164,7 @@ index ffac5d2c..ffdad31e 100644 + goto parse_flag; + + case sGssKexAlgorithms: -+ arg = strdelim(&cp); ++ arg = argv_next(&ac, &av); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", + filename, linenum); @@ -3231,7 +3178,7 @@ index ffac5d2c..ffdad31e 100644 case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -2579,6 +2622,10 @@ dump_config(ServerOptions *o) +@@ -3178,6 +3221,10 @@ dump_config(ServerOptions *o) #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); @@ -3242,11 +3189,10 @@ index ffac5d2c..ffdad31e 100644 #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, -diff --git a/servconf.h b/servconf.h -index 54e0a8d8..a476d522 100644 ---- a/servconf.h -+++ b/servconf.h -@@ -126,8 +126,11 @@ typedef struct { +diff --color -ruNp a/servconf.h b/servconf.h +--- a/servconf.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/servconf.h 2024-08-28 12:35:41.255432218 +0200 +@@ -149,8 +149,11 @@ typedef struct { int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ int gss_authentication; /* If true, permit GSSAPI authentication */ @@ -3258,11 +3204,10 @@ index 54e0a8d8..a476d522 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 48cfaafb..78cc8358 100644 ---- a/session.c -+++ b/session.c -@@ -2674,13 +2674,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +diff --color -ruNp a/session.c b/session.c +--- a/session.c 2024-08-28 12:35:01.197659647 +0200 ++++ b/session.c 2024-08-28 12:35:41.255432218 +0200 +@@ -2674,13 +2674,19 @@ do_cleanup(struct ssh *ssh, Authctxt *au #ifdef KRB5 if (options.kerberos_ticket_cleanup && @@ -3284,135 +3229,10 @@ index 48cfaafb..78cc8358 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.14 2018/07/10 09:13:30 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 *); --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 9480eba8..a1c7d230 100644 ---- a/ssh.1 -+++ b/ssh.1 -@@ -497,7 +497,13 @@ For full details of the options listed below, and their possible values, see +diff --color -ruNp a/ssh.1 b/ssh.1 +--- a/ssh.1 2024-08-28 12:35:01.207659840 +0200 ++++ b/ssh.1 2024-08-28 12:35:41.256432238 +0200 +@@ -536,7 +536,13 @@ For full details of the options listed b .It GatewayPorts .It GlobalKnownHostsFile .It GSSAPIAuthentication @@ -3425,8 +3245,8 @@ index 9480eba8..a1c7d230 100644 +.It GSSAPITrustDns .It HashKnownHosts .It Host - .It HostbasedAuthentication -@@ -573,6 +579,8 @@ flag), + .It HostbasedAcceptedAlgorithms +@@ -624,6 +630,8 @@ flag), (supported message integrity codes), .Ar kex (key exchange algorithms), @@ -3434,33 +3254,33 @@ index 9480eba8..a1c7d230 100644 +(GSSAPI key exchange algorithms), .Ar key (key types), - .Ar key-cert -diff --git a/ssh.c b/ssh.c -index 91e7c351..42be7d88 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -736,6 +736,8 @@ main(int ac, char **av) - cp = mac_alg_list('\n'); - else if (strcmp(optarg, "kex") == 0) + .Ar key-ca-sign +diff --color -ruNp a/ssh.c b/ssh.c +--- a/ssh.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/ssh.c 2024-08-28 12:35:41.256432238 +0200 +@@ -827,6 +827,8 @@ main(int ac, char **av) + else if (strcmp(optarg, "kex") == 0 || + strcasecmp(optarg, "KexAlgorithms") == 0) cp = kex_alg_list('\n'); + else if (strcmp(optarg, "kex-gss") == 0) + cp = kex_gss_alg_list('\n'); else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); else if (strcmp(optarg, "key-cert") == 0) -@@ -748,7 +750,7 @@ main(int ac, char **av) - cp = xstrdup("2"); - else if (strcmp(optarg, "help") == 0) { +@@ -857,8 +859,8 @@ main(int ac, char **av) + } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( -- "cipher\ncipher-auth\nkex\nkey\n" -+ "cipher\ncipher-auth\nkex\nkex-gss\nkey\n" - "key-cert\nkey-plain\nmac\n" - "protocol-version\nsig"); + "cipher\ncipher-auth\ncompression\nkex\n" +- "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" +- "protocol-version\nsig"); ++ "kex-gss\nkey\nkey-cert\nkey-plain\n" ++ "key-sig\nmac\nprotocol-version\nsig"); } -diff --git a/ssh_config b/ssh_config -index 5e8ef548..1ff999b6 100644 ---- a/ssh_config -+++ b/ssh_config + if (cp == NULL) + fatal("Unsupported query \"%s\"", optarg); +diff --color -ruNp a/ssh_config b/ssh_config +--- a/ssh_config 2024-08-28 12:35:01.216660014 +0200 ++++ b/ssh_config 2024-08-28 12:35:41.256432238 +0200 @@ -24,6 +24,8 @@ # HostbasedAuthentication no # GSSAPIAuthentication no @@ -3468,13 +3288,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 41262963..c3c8b274 100644 ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -754,10 +754,67 @@ The default is +diff --color -ruNp a/ssh_config.5 b/ssh_config.5 +--- a/ssh_config.5 2024-07-01 06:36:28.000000000 +0200 ++++ b/ssh_config.5 2024-08-28 12:35:41.257432257 +0200 +@@ -938,10 +938,68 @@ The default is Specifies whether user authentication based on GSSAPI is allowed. The default is .Cm no . @@ -3527,37 +3346,28 @@ index 41262963..c3c8b274 100644 +The list of key exchange algorithms that are offered for GSSAPI +key exchange. Possible values are +.Bd -literal -offset 3n -+gss-gex-sha1- -+gss-group1-sha1- -+gss-group14-sha1- -+gss-group14-sha256- -+gss-group16-sha512- -+gss-nistp256-sha256- ++gss-gex-sha1-, ++gss-group1-sha1-, ++gss-group14-sha1-, ++gss-group14-sha256-, ++gss-group16-sha512-, ++gss-nistp256-sha256-, +gss-curve25519-sha256- +.Ed +.Pp +The default is -+.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . ++.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, ++gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . +This option only applies to connections using GSSAPI. .It Cm HashKnownHosts Indicates that .Xr ssh 1 -diff --git a/sshconnect2.c b/sshconnect2.c -index dffee90b..0d0a6cb8 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -78,8 +78,6 @@ - #endif - - /* import */ --extern char *client_version_string; --extern char *server_version_string; - extern Options options; - - /* -@@ -161,6 +159,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) - char *s, *all_key; - int r; +diff --color -ruNp a/sshconnect2.c b/sshconnect2.c +--- a/sshconnect2.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/sshconnect2.c 2024-08-28 12:35:41.258432276 +0200 +@@ -222,6 +222,11 @@ ssh_kex2(struct ssh *ssh, char *host, st + char *all_key, *hkalgs = NULL; + int r, use_known_hosts_order = 0; +#if defined(GSSAPI) && defined(WITH_OPENSSL) + char *orig = NULL, *gss = NULL; @@ -3566,10 +3376,10 @@ index dffee90b..0d0a6cb8 100644 + xxx_host = host; xxx_hostaddr = hostaddr; - -@@ -193,6 +196,41 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) - order_hostkeyalgs(host, hostaddr, port)); - } + xxx_conn_info = cinfo; +@@ -255,6 +260,42 @@ ssh_kex2(struct ssh *ssh, char *host, st + compression_alg_list(options.compression), + hkalgs ? hkalgs : options.hostkeyalgorithms); +#if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { @@ -3584,6 +3394,7 @@ index dffee90b..0d0a6cb8 100644 + /* Fall back to specified host if we are using proxy command + * and can not use DNS on that socket */ + if (strcmp(gss_host, "UNKNOWN") == 0) { ++ free(gss_host); + gss_host = xstrdup(host); + } + } else { @@ -3606,10 +3417,10 @@ index dffee90b..0d0a6cb8 100644 + } +#endif + - if (options.rekey_limit || options.rekey_interval) - ssh_packet_set_rekey_limits(ssh, options.rekey_limit, - options.rekey_interval); -@@ -211,16 +243,46 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + free(hkalgs); + + /* start key exchange */ +@@ -271,14 +312,44 @@ ssh_kex2(struct ssh *ssh, char *host, st # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif @@ -3627,7 +3438,7 @@ index dffee90b..0d0a6cb8 100644 +# endif +#endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3640,10 +3451,8 @@ index dffee90b..0d0a6cb8 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 */ - myproposal[PROPOSAL_KEX_ALGS] = - compat_kex_proposal(options.kex_algorithms); +#if defined(GSSAPI) && defined(WITH_OPENSSL) + /* repair myproposal after it was crumpled by the */ + /* ext-info removal above */ @@ -3654,10 +3463,10 @@ index dffee90b..0d0a6cb8 100644 + free(gss); + } +#endif - if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) - fatal("kex_prop2buf: %s", ssh_err(r)); - -@@ -317,6 +379,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 || +@@ -368,6 +439,7 @@ static int input_gssapi_response(int typ 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 *); @@ -3665,7 +3474,7 @@ index dffee90b..0d0a6cb8 100644 #endif void userauth(struct ssh *, char *); -@@ -333,6 +396,11 @@ static char *authmethods_get(void); +@@ -384,6 +456,11 @@ static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI @@ -3677,7 +3486,7 @@ index dffee90b..0d0a6cb8 100644 {"gssapi-with-mic", userauth_gssapi, userauth_gssapi_cleanup, -@@ -698,12 +766,29 @@ userauth_gssapi(struct ssh *ssh) +@@ -755,12 +832,32 @@ userauth_gssapi(struct ssh *ssh) OM_uint32 min; int r, ok = 0; gss_OID mech = NULL; @@ -3690,6 +3499,7 @@ index dffee90b..0d0a6cb8 100644 + /* Fall back to specified host if we are using proxy command + * and can not use DNS on that socket */ + if (strcmp(gss_host, "UNKNOWN") == 0) { ++ free(gss_host); + gss_host = xstrdup(authctxt->host); + } + } else { @@ -3701,14 +3511,16 @@ index dffee90b..0d0a6cb8 100644 if (authctxt->gss_supported_mechs == NULL) - gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); -+ if (GSS_ERROR(gss_indicate_mechs(&min, &authctxt->gss_supported_mechs))) { ++ if (GSS_ERROR(gss_indicate_mechs(&min, ++ &authctxt->gss_supported_mechs))) { ++ authctxt->gss_supported_mechs = NULL; + free(gss_host); + return 0; + } /* Check to see whether the mechanism is usable before we offer it */ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && -@@ -712,13 +791,15 @@ userauth_gssapi(struct ssh *ssh) +@@ -769,13 +866,15 @@ userauth_gssapi(struct ssh *ssh) elements[authctxt->mech_tried]; /* My DER encoding requires length<128 */ if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, @@ -3725,7 +3537,7 @@ index dffee90b..0d0a6cb8 100644 if (!ok || mech == NULL) return 0; -@@ -958,6 +1039,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) +@@ -1009,6 +1108,55 @@ input_gssapi_error(int type, u_int32_t p free(lang); return r; } @@ -3750,13 +3562,13 @@ index dffee90b..0d0a6cb8 100644 + } + + if ((b = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); ++ fatal_f("sshbuf_new failed"); + + ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, -+ "gssapi-keyex"); ++ "gssapi-keyex", ssh->kex->session_id); + + if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) -+ fatal("%s: sshbuf_mutable_ptr failed", __func__); ++ fatal_f("sshbuf_mutable_ptr failed"); + gssbuf.length = sshbuf_len(b); + + if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { @@ -3770,7 +3582,7 @@ index dffee90b..0d0a6cb8 100644 + (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || + (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || + (r = sshpkt_send(ssh)) != 0) -+ fatal("%s: %s", __func__, ssh_err(r)); ++ fatal_fr(r, "parsing"); + + sshbuf_free(b); + gss_release_buffer(&ms, &mic); @@ -3781,22 +3593,10 @@ index dffee90b..0d0a6cb8 100644 #endif /* GSSAPI */ static int -diff --git a/sshd.c b/sshd.c -index cbd3bce9..8c223f6a 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -796,8 +796,8 @@ notify_hostkeys(struct ssh *ssh) - } - debug3("%s: sent %u hostkeys", __func__, nkeys); - if (nkeys == 0) -- fatal("%s: no hostkeys", __func__); -- if ((r = sshpkt_send(ssh)) != 0) -+ debug3("%s: no hostkeys", __func__); -+ else if ((r = sshpkt_send(ssh)) != 0) - sshpkt_fatal(ssh, r, "%s: send", __func__); - sshbuf_free(buf); - } -@@ -1769,7 +1769,8 @@ main(int ac, char **av) +diff --color -ruNp a/sshd.c b/sshd.c +--- a/sshd.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/sshd.c 2024-08-28 12:35:41.258432276 +0200 +@@ -1551,7 +1551,8 @@ main(int ac, char **av) free(fp); } accumulate_host_timing_secret(cfg, NULL); @@ -3806,9 +3606,95 @@ index cbd3bce9..8c223f6a 100644 logit("sshd: no hostkeys available -- exiting."); exit(1); } -@@ -2260,6 +2261,48 @@ do_ssh2_kex(struct ssh *ssh) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( - list_hostkey_types()); +diff --color -ruNp a/sshd_config b/sshd_config +--- a/sshd_config 2024-08-28 12:35:01.221660110 +0200 ++++ b/sshd_config 2024-08-28 12:35:41.259432296 +0200 +@@ -77,6 +77,8 @@ AuthorizedKeysFile .ssh/authorized_keys + # GSSAPI options + #GSSAPIAuthentication no + #GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will +diff --color -ruNp a/sshd_config.5 b/sshd_config.5 +--- a/sshd_config.5 2024-08-28 12:35:01.218660052 +0200 ++++ b/sshd_config.5 2024-08-28 12:35:41.259432296 +0200 +@@ -739,6 +739,11 @@ Specifies whether to automatically destr + on logout. + The default is + .Cm yes . ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange ++doesn't rely on ssh keys to verify host identity. ++The default is ++.Cm no . + .It Cm GSSAPIStrictAcceptorCheck + Determines whether to be strict about the identity of the GSSAPI acceptor + a client authenticates against. +@@ -753,6 +758,32 @@ machine's default store. + This facility is provided to assist with operation on multi homed machines. + The default is + .Cm yes . ++.It Cm GSSAPIStoreCredentialsOnRekey ++Controls whether the user's GSSAPI credentials should be updated following a ++successful connection rekeying. This option can be used to accepted renewed ++or updated credentials from a compatible client. The default is ++.Dq no . ++.Pp ++For this to work ++.Cm GSSAPIKeyExchange ++needs to be enabled in the server and also used by the client. ++.It Cm GSSAPIKexAlgorithms ++The list of key exchange algorithms that are accepted by GSSAPI ++key exchange. Possible values are ++.Bd -literal -offset 3n ++gss-gex-sha1-, ++gss-group1-sha1-, ++gss-group14-sha1-, ++gss-group14-sha256-, ++gss-group16-sha512-, ++gss-nistp256-sha256-, ++gss-curve25519-sha256- ++.Ed ++.Pp ++The default is ++.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, ++gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . ++This option only applies to connections using GSSAPI. + .It Cm HostbasedAcceptedAlgorithms + Specifies the signature algorithms that will be accepted for hostbased + authentication as a list of comma-separated patterns. +diff --color -ruNp a/sshd-session.c b/sshd-session.c +--- a/sshd-session.c 2024-08-28 12:35:01.221660110 +0200 ++++ b/sshd-session.c 2024-08-28 12:35:41.263432373 +0200 +@@ -660,8 +660,8 @@ notify_hostkeys(struct ssh *ssh) + } + debug3_f("sent %u hostkeys", nkeys); + if (nkeys == 0) +- fatal_f("no hostkeys"); +- if ((r = sshpkt_send(ssh)) != 0) ++ debug3_f("no hostkeys"); ++ else if ((r = sshpkt_send(ssh)) != 0) + sshpkt_fatal(ssh, r, "%s: send", __func__); + sshbuf_free(buf); + } +@@ -1180,8 +1180,9 @@ main(int ac, char **av) + break; + } + } +- if (!have_key) +- fatal("internal error: monitor received no hostkeys"); ++ /* The GSSAPI key exchange can run without a host key */ ++ if (!have_key && !options.gss_keyex) ++ fatal("internal error: monitor received no hostkeys and GSS KEX is not configured"); + + /* Ensure that umask disallows at least group and world write */ + new_umask = umask(0077) | 0022; +@@ -1462,6 +1463,48 @@ do_ssh2_kex(struct ssh *ssh) + + free(hkalgs); +#if defined(GSSAPI) && defined(WITH_OPENSSL) + { @@ -3833,7 +3719,7 @@ index cbd3bce9..8c223f6a 100644 + if (gss && orig) + xasprintf(&newstr, "%s,%s", gss, orig); + else if (gss) -+ newstr = gss; ++ xasprintf(&newstr, "%s,%s", gss, "kex-strict-s-v00@openssh.com"); + else if (orig) + newstr = orig; + @@ -3843,7 +3729,7 @@ index cbd3bce9..8c223f6a 100644 + * host key algorithm we support + */ + if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xstrdup("null"); + + if (newstr) + myproposal[PROPOSAL_KEX_ALGS] = newstr; @@ -3854,11 +3740,11 @@ index cbd3bce9..8c223f6a 100644 + /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) - fatal("kex_setup: %s", ssh_err(r)); -@@ -2275,7 +2318,18 @@ do_ssh2_kex(struct ssh *ssh) - # ifdef OPENSSL_HAS_ECC + fatal_r(r, "kex_setup"); +@@ -1479,7 +1522,18 @@ do_ssh2_kex(struct ssh *ssh) + #ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; - # endif + #endif -#endif +# ifdef GSSAPI + if (options.gss_keyex) { @@ -3873,98 +3759,226 @@ index cbd3bce9..8c223f6a 100644 +# endif +#endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; - kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = 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 - # GSSAPI options - GSSAPIAuthentication yes - GSSAPICleanupCredentials no -+#GSSAPIStrictAcceptorCheck yes -+#GSSAPIKeyExchange no +diff --color -ruNp a/ssh-gss.h b/ssh-gss.h +--- a/ssh-gss.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/ssh-gss.h 2024-08-28 12:35:41.256432238 +0200 +@@ -61,10 +61,34 @@ - # 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 b224f292..2baa6622 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -653,6 +653,11 @@ Specifies whether to automatically destroy the user's credentials cache - on logout. - The default is - .Cm yes . -+.It Cm GSSAPIKeyExchange -+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange -+doesn't rely on ssh keys to verify host identity. -+The default is -+.Cm no . - .It Cm GSSAPIStrictAcceptorCheck - Determines whether to be strict about the identity of the GSSAPI acceptor - a client authenticates against. -@@ -667,6 +672,31 @@ machine's default store. - This facility is provided to assist with operation on multi homed machines. - The default is - .Cm yes . -+.It Cm GSSAPIStoreCredentialsOnRekey -+Controls whether the user's GSSAPI credentials should be updated following a -+successful connection rekeying. This option can be used to accepted renewed -+or updated credentials from a compatible client. The default is -+.Dq no . -+.Pp -+For this to work -+.Cm GSSAPIKeyExchange -+needs to be enabled in the server and also used by the client. -+.It Cm GSSAPIKexAlgorithms -+The list of key exchange algorithms that are accepted by GSSAPI -+key exchange. Possible values are -+.Bd -literal -offset 3n -+gss-gex-sha1- -+gss-group1-sha1- -+gss-group14-sha1- -+gss-group14-sha256- -+gss-group16-sha512- -+gss-nistp256-sha256- -+gss-curve25519-sha256- -+.Ed -+.Pp -+The default is -+.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . -+This option only applies to connections using GSSAPI. - .It Cm HostbasedAcceptedKeyTypes - Specifies the key types that will be accepted for hostbased authentication - as a list of comma-separated patterns. -diff --git a/sshkey.c b/sshkey.c -index ad195776..789cd61e 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -135,6 +135,7 @@ static const struct keytype keytypes[] = { - # endif /* OPENSSL_HAS_NISTP521 */ - # endif /* OPENSSL_HAS_ECC */ - #endif /* WITH_OPENSSL */ -+ { "null", "null", NULL, KEY_NULL, 0, 0, 0 }, - { NULL, NULL, NULL, -1, -1, 0, 0 } + #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 +96,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 +111,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 +122,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); +@@ -108,6 +137,7 @@ OM_uint32 ssh_gssapi_test_oid_supported( + + 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, +@@ -122,17 +152,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 --color -ruNp a/sshkey.c b/sshkey.c +--- a/sshkey.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/sshkey.c 2024-08-28 12:35:41.260432315 +0200 +@@ -131,6 +131,75 @@ extern const struct sshkey_impl sshkey_x + extern const struct sshkey_impl sshkey_xmss_cert_impl; + #endif + ++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, ++ /* .type = */ KEY_NULL, ++ /* .nid = */ 0, ++ /* .cert = */ 0, ++ /* .sigonly = */ 0, ++ /* .keybits = */ 0, /* FIXME */ ++ /* .funcs = */ &sshkey_gss_funcs, ++}; ++ + const struct sshkey_impl * const keyimpls[] = { + &sshkey_ed25519_impl, + &sshkey_ed25519_cert_impl, +@@ -169,6 +238,7 @@ const struct sshkey_impl * const keyimpl + &sshkey_xmss_impl, + &sshkey_xmss_cert_impl, + #endif ++ &sshkey_gss_kex_impl, + NULL }; -@@ -223,7 +224,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) - const struct keytype *kt; +@@ -324,7 +394,7 @@ sshkey_alg_list(int certs_only, int plai - for (kt = keytypes; kt->type != -1; kt++) { -- if (kt->name == NULL) -+ if (kt->name == NULL || kt->type == KEY_NULL) + for (i = 0; keyimpls[i] != NULL; i++) { + impl = keyimpls[i]; +- if (impl->name == NULL) ++ if (impl->name == NULL || impl->type == KEY_NULL) continue; - if (!include_sigonly && kt->sigonly) + if (!include_sigonly && impl->sigonly) continue; -diff --git a/sshkey.h b/sshkey.h -index a91e6043..c11106c9 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -65,6 +65,7 @@ enum sshkey_types { - KEY_ED25519_CERT, - KEY_XMSS, - KEY_XMSS_CERT, +diff --color -ruNp a/sshkey.h b/sshkey.h +--- a/sshkey.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/sshkey.h 2024-08-28 12:35:41.260432315 +0200 +@@ -71,6 +71,7 @@ enum sshkey_types { + KEY_ECDSA_SK_CERT, + KEY_ED25519_SK, + KEY_ED25519_SK_CERT, + KEY_NULL, KEY_UNSPEC }; diff --git a/SOURCES/openssh-8.0p1-keygen-strip-doseol.patch b/openssh-8.0p1-keygen-strip-doseol.patch similarity index 100% rename from SOURCES/openssh-8.0p1-keygen-strip-doseol.patch rename to openssh-8.0p1-keygen-strip-doseol.patch diff --git a/SOURCES/openssh-8.0p1-openssl-kdf.patch b/openssh-8.0p1-openssl-kdf.patch similarity index 55% rename from SOURCES/openssh-8.0p1-openssl-kdf.patch rename to openssh-8.0p1-openssl-kdf.patch index 1db95c3..c22b210 100644 --- a/SOURCES/openssh-8.0p1-openssl-kdf.patch +++ b/openssh-8.0p1-openssl-kdf.patch @@ -12,7 +12,7 @@ index 2a455e4e..e01c3d43 100644 HMAC_CTX_init \ RSA_generate_key_ex \ RSA_get_default_method \ -+ EVP_KDF_CTX_new_id \ ++ EVP_KDF_CTX_new \ ]) # OpenSSL_add_all_algorithms may be a macro. @@ -20,33 +20,35 @@ diff --git a/kex.c b/kex.c index b6f041f4..1fbce2bb 100644 --- a/kex.c +++ b/kex.c -@@ -38,6 +38,9 @@ +@@ -38,6 +38,11 @@ #ifdef WITH_OPENSSL #include #include -+# ifdef HAVE_EVP_KDF_CTX_NEW_ID ++# ifdef HAVE_EVP_KDF_CTX_NEW +# include ++# include ++# include +# endif #endif #include "ssh.h" -@@ -942,6 +945,95 @@ kex_choose_conf(struct ssh *ssh) +@@ -942,6 +945,107 @@ kex_choose_conf(struct ssh *ssh) return r; } -+#ifdef HAVE_EVP_KDF_CTX_NEW_ID -+static const EVP_MD * ++#ifdef HAVE_EVP_KDF_CTX_NEW ++static const char * +digest_to_md(int digest_type) +{ + switch (digest_type) { + case SSH_DIGEST_SHA1: -+ return EVP_sha1(); ++ return SN_sha1; + case SSH_DIGEST_SHA256: -+ return EVP_sha256(); ++ return SN_sha256; + case SSH_DIGEST_SHA384: -+ return EVP_sha384(); ++ return SN_sha384; + case SSH_DIGEST_SHA512: -+ return EVP_sha512(); ++ return SN_sha512; + } + return NULL; +} @@ -56,52 +58,62 @@ index b6f041f4..1fbce2bb 100644 + const struct sshbuf *shared_secret, u_char **keyp) +{ + struct kex *kex = ssh->kex; -+ EVP_KDF_CTX *ctx = NULL; + u_char *key = NULL; + int r, key_len; + -+ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) -+ return SSH_ERR_INVALID_ARGUMENT; ++ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL); ++ EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf); ++ OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); ++ OSSL_PARAM *params = NULL; ++ const char *md = digest_to_md(kex->hash_alg); ++ char keytype = (char)id; ++ ++ EVP_KDF_free(kdf); ++ if (!ctx) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (md == NULL) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } ++ ++ if (param_bld == NULL) { ++ EVP_KDF_CTX_free(ctx); ++ return -1; ++ } ++ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } ++ + key_len = ROUNDUP(need, key_len); + if ((key = calloc(1, key_len)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + -+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF); -+ if (!ctx) { ++ r = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_DIGEST, ++ md, strlen(md)) && /* SN */ ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_KEY, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)) && ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_XCGHASH, ++ hash, hashlen) && ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_SESSION_ID, ++ sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id)) && ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_SSHKDF_TYPE, ++ &keytype, 1); ++ if (r != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest_to_md(kex->hash_alg)); -+ if (r != 1) { ++ params = OSSL_PARAM_BLD_to_param(param_bld); ++ if (params == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, -+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, hash, hashlen); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, id); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, -+ kex->session_id, kex->session_id_len); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_derive(ctx, key, key_len); ++ r = EVP_KDF_derive(ctx, key, key_len, params); + if (r != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; @@ -115,6 +127,8 @@ index b6f041f4..1fbce2bb 100644 + r = 0; + +out: ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); + free (key); + EVP_KDF_CTX_free(ctx); + if (r < 0) { @@ -130,7 +144,7 @@ index b6f041f4..1fbce2bb 100644 ssh_digest_free(hashctx); return r; } -+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */ ++#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW */ #define NKEYS 6 int diff --git a/SOURCES/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch similarity index 67% rename from SOURCES/openssh-8.0p1-pkcs11-uri.patch rename to openssh-8.0p1-pkcs11-uri.patch index 80af3e0..9931d92 100644 --- a/SOURCES/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -1,85 +1,7 @@ -diff --git a/Makefile.in b/Makefile.in -index 6f001bb3..c9424f1e 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -93,7 +93,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - atomicio.o dispatch.o mac.o uuencode.o misc.o utf8.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ - msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ -- ssh-pkcs11.o smult_curve25519_ref.o \ -+ ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ - poly1305.o chacha.o cipher-chachapoly.o \ - ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ - sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ -@@ -250,6 +250,8 @@ clean: regressclean - rm -f regress/unittests/match/test_match$(EXEEXT) - rm -f regress/unittests/utf8/*.o - rm -f regress/unittests/utf8/test_utf8$(EXEEXT) -+ rm -f regress/unittests/pkcs11/*.o -+ rm -f regress/unittests/pkcs11/test_pkcs11$(EXEEXT) - rm -f regress/misc/kexfuzz/*.o - rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) - (cd openbsd-compat && $(MAKE) clean) -@@ -280,6 +282,8 @@ distclean: regressclean - rm -f regress/unittests/match/test_match - rm -f regress/unittests/utf8/*.o - rm -f regress/unittests/utf8/test_utf8 -+ rm -f regress/unittests/pkcs11/*.o -+ rm -f regress/unittests/pkcs11/test_pkcs11 - rm -f regress/misc/kexfuzz/*.o - rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) - (cd openbsd-compat && $(MAKE) distclean) -@@ -442,6 +446,7 @@ regress-prep: - $(MKDIR_P) `pwd`/regress/unittests/kex - $(MKDIR_P) `pwd`/regress/unittests/match - $(MKDIR_P) `pwd`/regress/unittests/utf8 -+ $(MKDIR_P) `pwd`/regress/unittests/pkcs11 - $(MKDIR_P) `pwd`/regress/misc/kexfuzz - [ -f `pwd`/regress/Makefile ] || \ - ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile -@@ -565,6 +570,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \ - regress/unittests/test_helper/libtest_helper.a \ - -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) - -+UNITTESTS_TEST_PKCS11_OBJS=\ -+ regress/unittests/pkcs11/tests.o -+ -+regress/unittests/pkcs11/test_pkcs11$(EXEEXT): \ -+ ${UNITTESTS_TEST_PKCS11_OBJS} \ -+ regress/unittests/test_helper/libtest_helper.a libssh.a -+ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_PKCS11_OBJS) \ -+ regress/unittests/test_helper/libtest_helper.a \ -+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) -+ - MISC_KEX_FUZZ_OBJS=\ - regress/misc/kexfuzz/kexfuzz.o - -@@ -585,6 +600,7 @@ regress-binaries: regress/modpipe$(EXEEXT) \ - regress/unittests/kex/test_kex$(EXEEXT) \ - regress/unittests/match/test_match$(EXEEXT) \ - regress/unittests/utf8/test_utf8$(EXEEXT) \ -+ regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \ - regress/misc/kexfuzz/kexfuzz$(EXEEXT) - - tests interop-tests t-exec unit: regress-prep regress-binaries $(TARGETS) -diff --git a/authfd.c b/authfd.c -index 95348abf..5383df92 100644 ---- a/authfd.c -+++ b/authfd.c -@@ -312,6 +312,8 @@ ssh_free_identitylist(struct ssh_identitylist *idl) - if (idl->comments != NULL) - free(idl->comments[i]); - } -+ free(idl->keys); -+ free(idl->comments); - free(idl); - } - -diff --git a/configure.ac b/configure.ac -index 30be6c18..82459746 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1854,12 +1854,14 @@ AC_LINK_IFELSE( +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).]) ]) @@ -94,9 +16,9 @@ index 30be6c18..82459746 100644 fi ] ) -@@ -1875,6 +1877,40 @@ if test "x$openssl" = "xyes" && test "x$disable_pkcs11" = "x"; then - ) - fi +@@ -2095,6 +2097,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) + AC_CHECK_FUNCS([dlopen]) + AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) +# Check whether we have a p11-kit, we got default provider on command line +DEFAULT_PKCS11_PROVIDER_MSG="no" @@ -135,73 +57,108 @@ index 30be6c18..82459746 100644 # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5256,6 +5292,7 @@ echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" - echo " BSD Auth support: $BSD_AUTH_MSG" +@@ -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" +echo " Default PKCS#11 provider: $DEFAULT_PKCS11_PROVIDER_MSG" + echo " U2F/FIDO support: $enable_sk" echo "" +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 \ +- ssh-pkcs11.o smult_curve25519_ref.o \ ++ ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ + poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ + ssh-ed25519.o digest-openssl.o digest-libc.o \ + hmac.o ed25519.o hash.o \ +@@ -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) ++ rm -f regress/unittests/pkcs11/*.o ++ rm -f regress/unittests/pkcs11/test_pkcs11$(EXEEXT) + 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 @@ distclean: regressclean + rm -f regress/unittests/sshsig/test_sshsig + rm -f regress/unittests/utf8/*.o + rm -f regress/unittests/utf8/test_utf8 ++ rm -f regress/unittests/pkcs11/*.o ++ rm -f regress/unittests/pkcs11/test_pkcs11 + 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 @@ regress-prep: + $(MKDIR_P) `pwd`/regress/unittests/sshkey + $(MKDIR_P) `pwd`/regress/unittests/sshsig + $(MKDIR_P) `pwd`/regress/unittests/utf8 ++ $(MKDIR_P) `pwd`/regress/unittests/pkcs11 + $(MKDIR_P) `pwd`/regress/misc/sk-dummy + [ -f `pwd`/regress/Makefile ] || \ + ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile +@@ -685,6 +690,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT + regress/unittests/test_helper/libtest_helper.a \ + -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) -diff --git a/regress/Makefile b/regress/Makefile -index 925edf71..94bb25e9 100644 ---- a/regress/Makefile -+++ b/regress/Makefile -@@ -109,9 +109,11 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ ++UNITTESTS_TEST_PKCS11_OBJS=\ ++ regress/unittests/pkcs11/tests.o ++ ++regress/unittests/pkcs11/test_pkcs11$(EXEEXT): \ ++ ${UNITTESTS_TEST_PKCS11_OBJS} \ ++ regress/unittests/test_helper/libtest_helper.a libssh.a ++ $(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 +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) \ + + tests: file-tests t-exec interop-tests extra-tests unit + echo all tests passed +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 revoked-* rsa rsa-agent rsa-agent.pub rsa.pub \ -+ remote_pid revoked-* rsa rsa-agent rsa-agent.pub \ -+ rsa-agent-cert.pub rsa.pub \ - rsa1 rsa1-agent rsa1-agent.pub rsa1.pub rsa_ssh2_cr.prv \ -- rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ -+ pkcs11*.crt pkcs11*.key \ -+ pkcs11.info rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ + pidfile putty.rsa2 ready regress.log remote_pid \ +- revoked-* rsa rsa-agent rsa-agent.pub rsa.pub rsa_ssh2_cr.prv \ ++ revoked-* rsa rsa-agent rsa-agent.pub rsa-agent-cert.pub \ ++ rsa.pub rsa_ssh2_cr.prv pkcs11*.crt pkcs11*.key pkcs11.info \ + 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 \ - ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \ -@@ -231,6 +233,7 @@ unit: +@@ -273,8 +274,9 @@ unit: V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ +- $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ +- $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ + $$V ${.OBJDIR}/unittests/pkcs11/test_pkcs11 ; \ - $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ - $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ ++ $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ ++ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ -d ${.CURDIR}/unittests/sshkey/testdata ; \ -diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh -index 5205d906..5ca49be5 100644 ---- a/regress/agent-pkcs11.sh -+++ b/regress/agent-pkcs11.sh -@@ -29,6 +29,13 @@ fi - - test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist" - -+# requires ssh-agent built with correct path to ssh-pkcs11-helper -+# otherwise it fails to start the helper -+strings ${TEST_SSH_SSHAGENT} | grep "$TEST_SSH_SSHPKCS11HELPER" -+if [ $? -ne 0 ]; then -+ fatal "Needs to reconfigure with --libexecdir=\`pwd\` or so" -+fi -+ - # setup environment for softhsm2 token - DIR=$OBJ/SOFTHSM - rm -rf $DIR -@@ -113,7 +120,7 @@ else - 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 --git a/regress/pkcs11.sh b/regress/pkcs11.sh -new file mode 100644 -index 00000000..19fc8169 ---- /dev/null -+++ b/regress/pkcs11.sh -@@ -0,0 +1,352 @@ + $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ + -d ${.CURDIR}/unittests/sshsig/testdata ; \ +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 +# @@ -247,13 +204,6 @@ index 00000000..19fc8169 + +test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist" + -+# requires ssh-agent built with correct path to ssh-pkcs11-helper -+# otherwise it fails to start the helper -+strings ${TEST_SSH_SSHAGENT} | grep "$TEST_SSH_SSHPKCS11HELPER" -+if [ $? -ne 0 ]; then -+ fatal "Needs to reconfigure with --libexecdir=\`pwd\` or so" -+fi -+ +# setup environment for softhsm token +DIR=$OBJ/SOFTHSM +rm -rf $DIR @@ -308,130 +258,134 @@ index 00000000..19fc8169 +trace "List the keys in the ssh-keygen with PKCS#11 URIs" +${SSHKEYGEN} -D ${TEST_SSH_PKCS11} > $OBJ/token_keys +if [ $? -ne 0 ]; then -+ fail "keygen fails to enumerate keys on PKCS#11 token" ++ fail "FAIL: keygen fails to enumerate keys on PKCS#11 token" +fi +grep "pkcs11:" $OBJ/token_keys > /dev/null +if [ $? -ne 0 ]; then -+ fail "The keys from ssh-keygen do not contain PKCS#11 URI as a comment" ++ fail "FAIL: The keys from ssh-keygen do not contain PKCS#11 URI as a comment" +fi -+tail -n 1 $OBJ/token_keys > $OBJ/authorized_keys_$USER ++ ++# Set the ECDSA key to authorized keys ++grep "ECDSA" $OBJ/token_keys > $OBJ/authorized_keys_$USER + +trace "Simple connect with ssh (without PKCS#11 URI)" +echo ${TEST_SSH_PIN} | notty ${SSH} -I ${TEST_SSH_PKCS11} \ + -F $OBJ/ssh_proxy somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with pkcs11 failed (exit code $r)" ++ fail "FAIL: ssh connect with pkcs11 failed (exit code $r)" +fi + +trace "Connect with PKCS#11 URI" -+trace " (second key should succeed)" ++trace " (ECDSA key should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)" +fi + -+trace " (first key should fail)" ++trace " (RSA key should fail)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)" +fi + +trace "Connect with PKCS#11 URI including PIN should not prompt" -+trace " (second key should succeed)" ++trace " (ECDSA key should succeed)" +${SSH} -F $OBJ/ssh_proxy -i \ -+ "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}&pin-value=${TEST_SSH_PIN}" somehost exit 5 ++ "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}&pin-value=${TEST_SSH_PIN}" somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)" +fi + -+trace " (first key should fail)" ++trace " (RSA key should fail)" +${SSH} -F $OBJ/ssh_proxy -i \ -+ "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}&pin-value=${TEST_SSH_PIN}" somehost exit 5 ++ "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}&pin-value=${TEST_SSH_PIN}" somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)" +fi + +trace "Connect with various filtering options in PKCS#11 URI" -+trace " (by object label, second key should succeed)" ++trace " (by object label, ECDSA should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:object=SSH%20RSA%20Key%202?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:object=SSH%20ECDSA%20Key%2004?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)" +fi + -+trace " (by object label, first key should fail)" ++trace " (by object label, RSA key should fail)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:object=SSH%20RSA%20Key?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:object=SSH%20RSA%20Key%2002?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)" +fi + -+trace " (by token label, second key should succeed)" ++trace " (by token label, ECDSA key should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:id=${ID2};token=SoftToken%20(token)?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:id=%${ID2};token=token-slot-0?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)" +fi + +trace " (by wrong token label, should fail)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:token=SoftToken?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:token=token-slot-99?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)" +fi + + + + +trace "Test PKCS#11 URI specification in configuration files" -+echo "IdentityFile \"pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}\"" \ ++echo "IdentityFile \"pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}\"" \ + >> $OBJ/ssh_proxy -+trace " (second key should succeed)" ++trace " (ECDSA key should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI in config failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI in config failed (exit code $r)" +fi + -+trace " (first key should fail)" -+head -n 1 $OBJ/token_keys > $OBJ/authorized_keys_$USER ++# Set the RSA key as authorized ++grep "RSA" $OBJ/token_keys > $OBJ/authorized_keys_$USER ++ ++trace " (RSA key should fail)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI in config succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI in config succeeded (should fail)" +fi +sed -i -e "/IdentityFile/d" $OBJ/ssh_proxy + +trace "Test PKCS#11 URI specification in configuration files with bogus spaces" -+echo "IdentityFile \" pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11} \"" \ ++echo "IdentityFile \" pkcs11:?module-path=${TEST_SSH_PKCS11} \"" \ + >> $OBJ/ssh_proxy +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI with bogus spaces in config failed" \ ++ fail "FAIL: ssh connect with PKCS#11 URI with bogus spaces in config failed" \ + "(exit code $r)" +fi +sed -i -e "/IdentityFile/d" $OBJ/ssh_proxy + + +trace "Combination of PKCS11Provider and PKCS11URI on commandline" -+trace " (first key should succeed)" ++trace " (RSA key should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:id=${ID1}" -I ${TEST_SSH_PKCS11} somehost exit 5 ++ -i "pkcs11:id=%${ID1}" -I ${TEST_SSH_PKCS11} somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI and provider combination" \ ++ fail "FAIL: ssh connect with PKCS#11 URI and provider combination" \ + "failed (exit code $r)" +fi + @@ -440,14 +394,14 @@ index 00000000..19fc8169 + -o IdentityFile=\"pkcs11:token=segfault\" somehost exit 5 +r=$? +if [ $r -eq 139 ]; then -+ fail "ssh connect with missing provider_id from configuration option" \ ++ fail "FAIL: ssh connect with missing provider_id from configuration option" \ + "crashed (exit code $r)" +fi + + +trace "SSH Agent can work with PKCS#11 URI" +trace "start the agent" -+eval `${SSHAGENT} -s -P "${OBJ}/*"` > /dev/null ++eval `${SSHAGENT} -s` > /dev/null + +r=$? +if [ $r -ne 0 ]; then @@ -455,123 +409,120 @@ index 00000000..19fc8169 +else + trace "add whole provider to agent" + echo ${TEST_SSH_PIN} | notty ${SSHADD} \ -+ "pkcs11:?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 ++ "pkcs11:?module-path=${TEST_SSH_PKCS11}" #> /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add failed with whole provider: exit code $r" ++ fail "FAIL: ssh-add failed with whole provider: exit code $r" + fi + + trace " pkcs11 list via agent (all keys)" + ${SSHADD} -l > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add -l failed with whole provider: exit code $r" ++ fail "FAIL: ssh-add -l failed with whole provider: exit code $r" + fi + + trace " pkcs11 connect via agent (all keys)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -ne 5 ]; then -+ fail "ssh connect failed with whole provider (exit code $r)" ++ fail "FAIL: ssh connect failed with whole provider (exit code $r)" + fi + + trace " remove pkcs11 keys (all keys)" + ${SSHADD} -d "pkcs11:?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add -d failed with whole provider: exit code $r" ++ fail "FAIL: ssh-add -d failed with whole provider: exit code $r" + fi + -+ trace "add only first key to the agent" ++ trace "add only RSA key to the agent" + echo ${TEST_SSH_PIN} | notty ${SSHADD} \ -+ "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 ++ "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add failed with first key: exit code $r" ++ fail "FAIL ssh-add failed with RSA key: exit code $r" + fi + -+ trace " pkcs11 connect via agent (first key)" ++ trace " pkcs11 connect via agent (RSA key)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -ne 5 ]; then -+ fail "ssh connect failed with first key (exit code $r)" ++ fail "FAIL: ssh connect failed with RSA key (exit code $r)" + fi + -+ trace " remove first pkcs11 key" -+ ${SSHADD} -d "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" \ ++ trace " remove RSA pkcs11 key" ++ ${SSHADD} -d "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" \ + > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add -d failed with first key: exit code $r" ++ fail "FAIL: ssh-add -d failed with RSA key: exit code $r" + fi + -+ trace "add only second key to the agent" ++ trace "add only ECDSA key to the agent" + echo ${TEST_SSH_PIN} | notty ${SSHADD} \ -+ "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 ++ "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add failed with second key: exit code $r" ++ fail "FAIL: ssh-add failed with second key: exit code $r" + fi + -+ trace " pkcs11 connect via agent (second key should fail)" ++ trace " pkcs11 connect via agent (ECDSA key should fail)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -eq 5 ]; then -+ fail "ssh connect passed without key (should fail)" ++ fail "FAIL: ssh connect passed with ECDSA key (should fail)" + fi + -+ trace "add also the first key to the agent" ++ trace "add also the RSA key to the agent" + echo ${TEST_SSH_PIN} | notty ${SSHADD} \ -+ "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 ++ "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add failed with first key: exit code $r" ++ fail "FAIL: ssh-add failed with first key: exit code $r" + fi + -+ trace " remove second pkcs11 key" -+ ${SSHADD} -d "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" \ ++ trace " remove ECDSA pkcs11 key" ++ ${SSHADD} -d "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" \ + > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add -d failed with second key: exit code $r" ++ fail "ssh-add -d failed with ECDSA key: exit code $r" + fi + + trace " remove already-removed pkcs11 key should fail" -+ ${SSHADD} -d "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" \ ++ ${SSHADD} -d "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" \ + > /dev/null 2>&1 + r=$? + if [ $r -eq 0 ]; then -+ fail "ssh-add -d passed with non-existing key (should fail)" ++ fail "FAIL: ssh-add -d passed with non-existing key (should fail)" + fi + -+ trace " pkcs11 connect via agent (the first key should be still usable)" ++ trace " pkcs11 connect via agent (the RSA key should be still usable)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -ne 5 ]; then -+ fail "ssh connect failed with first key (after removing second): exit code $r" ++ fail "ssh connect failed with RSA key (after removing ECDSA): exit code $r" + fi + + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi -diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile -index e464b085..a0e5a37c 100644 ---- a/regress/unittests/Makefile -+++ b/regress/unittests/Makefile -@@ -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 -+SUBDIR+=pkcs11 authopt +-SUBDIR+=authopt misc sshsig ++SUBDIR+=authopt misc sshsig pkcs11 .include -diff --git a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c -new file mode 100644 -index 00000000..b637cb13 ---- /dev/null -+++ b/regress/unittests/pkcs11/tests.c -@@ -0,0 +1,337 @@ +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 + * @@ -600,7 +551,7 @@ index 00000000..b637cb13 +#include "sshbuf.h" +#include "ssh-pkcs11-uri.h" + -+#define EMPTY_URI compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL) ++#define EMPTY_URI compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL) + +/* prototypes are not public -- specify them here internally for tests */ +struct sshbuf *percent_encode(const char *, size_t, char *); @@ -633,6 +584,10 @@ index 00000000..b637cb13 + ASSERT_STRING_EQ(a->lib_manuf, b->lib_manuf); + else /* both should be null */ + ASSERT_PTR_EQ(a->lib_manuf, b->lib_manuf); ++ if (b->serial != NULL) ++ ASSERT_STRING_EQ(a->serial, b->serial); ++ else /* both should be null */ ++ ASSERT_PTR_EQ(a->serial, b->serial); +} + +void @@ -667,7 +622,7 @@ index 00000000..b637cb13 + +struct pkcs11_uri * +compose_uri(unsigned char *id, size_t id_len, char *token, char *lib_manuf, -+ char *manuf, char *module_path, char *object, char *pin) ++ char *manuf, char *serial, char *module_path, char *object, char *pin) +{ + struct pkcs11_uri *uri = pkcs11_uri_init(); + if (id_len > 0) { @@ -678,6 +633,7 @@ index 00000000..b637cb13 + uri->token = token; + uri->lib_manuf = lib_manuf; + uri->manuf = manuf; ++ uri->serial = serial; + uri->object = object; + uri->pin = pin; + return uri; @@ -688,47 +644,49 @@ index 00000000..b637cb13 +{ + /* path arguments */ + check_parse("pkcs11:id=%01", -+ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + check_parse("pkcs11:id=%00%01", -+ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + check_parse("pkcs11:token=SSH%20Keys", -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL, NULL)); + check_parse("pkcs11:library-manufacturer=OpenSC", -+ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL, NULL)); + check_parse("pkcs11:manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL)); ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL, NULL)); ++ check_parse("pkcs11:serial=IamSerial", ++ compose_uri(NULL, 0, NULL, NULL, NULL, "IamSerial", NULL, NULL, NULL)); + check_parse("pkcs11:object=SIGN%20Key", -+ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "SIGN Key", NULL)); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, "SIGN Key", NULL)); + /* query arguments */ + check_parse("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + check_parse("pkcs11:?pin-value=123456", -+ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, "123456")); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, "123456")); + + /* combinations */ + /* ID SHOULD be percent encoded */ + check_parse("pkcs11:token=SSH%20Key;id=0", -+ compose_uri("0", 1, "SSH Key", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("0", 1, "SSH Key", NULL, NULL, NULL, NULL, NULL, NULL)); + check_parse( + "pkcs11:manufacturer=CAC?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, "CAC", ++ compose_uri(NULL, 0, NULL, NULL, "CAC", NULL, + "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + check_parse( + "pkcs11:object=RSA%20Key?module-path=/usr/lib64/pkcs11/opencryptoki.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, + "/usr/lib64/pkcs11/opencryptoki.so", "RSA Key", NULL)); + check_parse("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so&pin-value=123456", -+ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, "123456")); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, "123456")); + + /* empty path component matches everything */ + check_parse("pkcs11:", EMPTY_URI); + + /* empty string is a valid to match against (and different from NULL) */ + check_parse("pkcs11:token=", -+ compose_uri(NULL, 0, "", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "", NULL, NULL, NULL, NULL, NULL, NULL)); + /* Percent character needs to be percent-encoded */ + check_parse("pkcs11:token=%25", -+ compose_uri(NULL, 0, "%", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "%", NULL, NULL, NULL, NULL, NULL, NULL)); +} + +static void @@ -740,7 +698,7 @@ index 00000000..b637cb13 + check_parse_rv("pkcs11:id=%ZZ", EMPTY_URI, -1); + /* Space MUST be percent encoded -- XXX not enforced yet */ + check_parse("pkcs11:token=SSH Keys", -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL, NULL)); + /* MUST NOT contain duplicate attributes of the same name */ + check_parse_rv("pkcs11:id=%01;id=%02", EMPTY_URI, -1); + /* MUST NOT contain duplicate attributes of the same name */ @@ -771,29 +729,31 @@ index 00000000..b637cb13 +{ + /* path arguments */ + check_gen("pkcs11:id=%01", -+ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + check_gen("pkcs11:id=%00%01", -+ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + check_gen("pkcs11:token=SSH%20Keys", /* space must be percent encoded */ -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL, NULL)); + /* library-manufacturer is not implmented now */ + /*check_gen("pkcs11:library-manufacturer=OpenSC", -+ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL));*/ ++ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL, NULL));*/ + check_gen("pkcs11:manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL)); ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL, NULL)); ++ check_gen("pkcs11:serial=IamSerial", ++ compose_uri(NULL, 0, NULL, NULL, NULL, "IamSerial", NULL, NULL, NULL)); + check_gen("pkcs11:object=RSA%20Key", -+ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "RSA Key", NULL)); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, "RSA Key", NULL)); + /* query arguments */ + check_gen("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + + /* combinations */ + check_gen("pkcs11:id=%02;token=SSH%20Keys", -+ compose_uri("\x02", 1, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x02", 1, "SSH Keys", NULL, NULL, NULL, NULL, NULL, NULL)); + check_gen("pkcs11:id=%EE%02?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri("\xEE\x02", 2, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ compose_uri("\xEE\x02", 2, NULL, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + check_gen("pkcs11:object=Encryption%20Key;manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, "Encryption Key", NULL)); ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, "Encryption Key", NULL)); + + /* empty path component matches everything */ + check_gen("pkcs11:", EMPTY_URI); @@ -801,7 +761,7 @@ index 00000000..b637cb13 +} + +void -+check_encode(char *source, size_t len, char *whitelist, char *expect) ++check_encode(char *source, size_t len, char *allow_list, char *expect) +{ + char *buf = NULL; + struct sshbuf *b; @@ -810,7 +770,7 @@ index 00000000..b637cb13 + TEST_START(buf); + free(buf); + -+ b = percent_encode(source, len, whitelist); ++ b = percent_encode(source, len, allow_list); + ASSERT_STRING_EQ(sshbuf_ptr(b), expect); + sshbuf_free(b); + TEST_DONE(); @@ -835,14 +795,14 @@ index 00000000..b637cb13 +static void +test_percent_encode(void) +{ -+ /* Without whitelist encodes everything (for CKA_ID) */ ++ /* Without allow list encodes everything (for CKA_ID) */ + check_encode("A*", 2, "", "%41%2A"); + check_encode("\x00", 1, "", "%00"); + check_encode("\x7F", 1, "", "%7F"); + check_encode("\x80", 1, "", "%80"); + check_encode("\xff", 1, "", "%FF"); + -+ /* Default whitelist encodes anything but safe letters */ ++ /* Default allow list encodes anything but safe letters */ + check_encode("test" "\x00" "0alpha", 11, PKCS11_URI_WHITELIST, + "test%000alpha"); + check_encode(" ", 1, PKCS11_URI_WHITELIST, @@ -909,65 +869,105 @@ index 00000000..b637cb13 + test_parse_invalid(); + test_generate_valid(); +} -diff --git a/ssh-add.c b/ssh-add.c -index ac9c808d..f039e00e 100644 ---- a/ssh-add.c -+++ b/ssh-add.c -@@ -64,6 +64,7 @@ - #include "misc.h" - #include "ssherr.h" - #include "digest.h" +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" + #include "hostfile.h" +#include "ssh-pkcs11-uri.h" /* argv0 */ extern char *__progname; -@@ -188,6 +189,24 @@ delete_all(int agent_fd, int qflag) +@@ -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); ++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) ++update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag, ++ struct dest_constraint **dest_constraints, size_t ndest_constraints) +{ ++ char *pin = NULL; + struct pkcs11_uri *uri; + + /* dry-run parse to make sure the URI is valid and to report errors */ + uri = pkcs11_uri_init(); + if (pkcs11_uri_parse((char *) pkcs11_uri, uri) != 0) + fatal("Failed to parse PKCS#11 URI"); ++ if (uri->pin != NULL) { ++ pin = strdup(uri->pin); ++ if (pin == NULL) { ++ fatal("Failed to dupplicate string"); ++ } ++ /* pin is freed in the update_card() */ ++ } + pkcs11_uri_cleanup(uri); + -+ return update_card(agent_fd, adding, pkcs11_uri, qflag); ++ 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) + 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, + 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) { -@@ -529,6 +548,13 @@ lock_agent(int agent_fd, int lock) - static int - do_file(int agent_fd, int deleting, int key_only, char *file, int qflag) +- 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; +@@ -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) && + strncmp(file, PKCS11_URI_SCHEME, + strlen(PKCS11_URI_SCHEME)) == 0) { -+ return update_pkcs11_uri(agent_fd, !deleting, file, qflag); ++ return update_pkcs11_uri(agent_fd, !deleting, file, qflag, ++ dest_constraints, ndest_constraints); + } +#endif if (deleting) { - if (delete_file(agent_fd, file, key_only, qflag) == -1) - return -1; -diff --git a/ssh-agent.c b/ssh-agent.c -index d06ecfd9..9c1b328f 100644 ---- a/ssh-agent.c -+++ b/ssh-agent.c -@@ -548,10 +548,72 @@ no_identities(SocketEntry *e) + 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, key_only, cert_only, + dest_constraints, ndest_constraints, +- certs, ncerts) == -1) ++ certs, ncerts, NULL) == -1) + ret = 1; + goto done; + } +diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c +--- openssh-9.6p1/ssh-agent.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-agent.c 2024-01-12 14:25:25.234942360 +0100 +@@ -1549,10 +1549,74 @@ add_p11_identity(struct sshkey *key, cha + idtab->nentries++; } - #ifdef ENABLE_PKCS11 +static char * +sanitize_pkcs11_provider(const char *provider) +{ @@ -978,13 +978,15 @@ index d06ecfd9..9c1b328f 100644 + if (provider == NULL) + return NULL; + ++ memset(canonical_provider, 0, sizeof(canonical_provider)); ++ + if (strlen(provider) >= strlen(PKCS11_URI_SCHEME) && + strncmp(provider, PKCS11_URI_SCHEME, + strlen(PKCS11_URI_SCHEME)) == 0) { + /* PKCS#11 URI */ + uri = pkcs11_uri_init(); + if (uri == NULL) { -+ error("Failed to init PCKS#11 URI"); ++ error("Failed to init PKCS#11 URI"); + return NULL; + } + @@ -1007,9 +1009,9 @@ index d06ecfd9..9c1b328f 100644 + return NULL; + } + free(module_path); -+ if (match_pattern_list(canonical_provider, pkcs11_whitelist, 0) != 1) { ++ if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { + verbose("refusing PKCS#11 provider \"%.100s\": " -+ "not whitelisted", canonical_provider); ++ "not allowed", canonical_provider); + pkcs11_uri_cleanup(uri); + return NULL; + } @@ -1035,55 +1037,65 @@ index d06ecfd9..9c1b328f 100644 { - char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; + char *provider = NULL, *pin = NULL, *sane_uri = NULL; + char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; - u_int seconds; - time_t death = 0; -@@ -587,28 +649,23 @@ process_add_smartcard_key(SocketEntry *e) - goto send; - } + u_int seconds = 0; +@@ -1581,25 +1643,18 @@ process_add_smartcard_key(SocketEntry *e + "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, pkcs11_whitelist, 0) != 1) { -- verbose("refusing PKCS#11 add of \"%.100s\": " -- "provider not whitelisted", canonical_provider); -+ + sane_uri = sanitize_pkcs11_provider(provider); + if (sane_uri == NULL) goto send; - } -- debug("%s: add %.100s", __func__, canonical_provider); -+ +- 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); -+ debug("%s: add %.100s", __func__, sane_uri); -+ count = pkcs11_add_provider(sane_uri, pin, &keys); +- 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; -- id->provider = xstrdup(canonical_provider); -- id->comment = xstrdup(canonical_provider); /* XXX */ -+ id->provider = xstrdup(sane_uri); -+ id->comment = xstrdup(sane_uri); - id->death = death; - id->confirm = confirm; - TAILQ_INSERT_TAIL(&idtab->idlist, id, next); -@@ -622,6 +679,7 @@ process_add_smartcard_key(SocketEntry *e) + 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])) +@@ -1609,13 +1664,13 @@ process_add_smartcard_key(SocketEntry *e + 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 */ +@@ -1628,6 +1683,7 @@ process_add_smartcard_key(SocketEntry *e send: free(pin); free(provider); + free(sane_uri); free(keys); - send_status(e, success); - } -@@ -629,7 +687,7 @@ send: + free(comments); + free_dest_constraints(dest_constraints, ndest_constraints); +@@ -1640,7 +1696,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { @@ -1092,7 +1104,7 @@ index d06ecfd9..9c1b328f 100644 int r, success = 0; Identity *id, *nxt; -@@ -640,30 +698,29 @@ process_remove_smartcard_key(SocketEntry *e) +@@ -1652,30 +1708,29 @@ process_remove_smartcard_key(SocketEntry } free(pin); @@ -1104,8 +1116,8 @@ index d06ecfd9..9c1b328f 100644 goto send; - } -- debug("%s: remove %.100s", __func__, canonical_provider); -+ debug("%s: remove %.100s", __func__, sane_uri); +- debug_f("remove %.100s", canonical_provider); ++ debug_f("remove %.100s", sane_uri); for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { nxt = TAILQ_NEXT(id, next); /* Skip file--based keys */ @@ -1122,52 +1134,1504 @@ index d06ecfd9..9c1b328f 100644 + if (pkcs11_del_provider(sane_uri) == 0) success = 1; else - error("%s: pkcs11_del_provider failed", __func__); + error_f("pkcs11_del_provider failed"); send: free(provider); + free(sane_uri); send_status(e, success); } #endif /* ENABLE_PKCS11 */ -diff --git a/ssh-keygen.c b/ssh-keygen.c -index 3898b281..91c43b14 100644 ---- a/ssh-keygen.c -+++ b/ssh-keygen.c -@@ -798,6 +798,7 @@ do_download(struct passwd *pw) +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': ++#ifdef ENABLE_PKCS11 ++ if (strlen(optarg) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(optarg, PKCS11_URI_SCHEME, ++ strlen(PKCS11_URI_SCHEME)) == 0) { ++ add_identity_file(&options, NULL, optarg, 1); ++ break; ++ } ++#endif + p = tilde_expand_filename(optarg, getuid()); + if (stat(p, &st) == -1) + fprintf(stderr, "Warning: Identity file %s " +@@ -1784,6 +1792,7 @@ main(int ac, char **av) + #ifdef ENABLE_PKCS11 + (void)pkcs11_del_provider(options.pkcs11_provider); + #endif ++ pkcs11_terminate(); + + skip_connect: + exit_status = ssh_session2(ssh, cinfo); +@@ -2307,6 +2316,45 @@ ssh_session2(struct ssh *ssh, const stru + options.escape_char : SSH_ESCAPECHAR_NONE, id); + } + ++#ifdef ENABLE_PKCS11 ++static void ++load_pkcs11_identity(char *pkcs11_uri, char *identity_files[], ++ struct sshkey *identity_keys[], int *n_ids) ++{ ++ int nkeys, i; ++ struct sshkey **keys; ++ struct pkcs11_uri *uri; ++ ++ debug("identity file '%s' from pkcs#11", pkcs11_uri); ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); ++ ++ if (pkcs11_uri_parse(pkcs11_uri, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri); ++ ++ /* we need to merge URI and provider together */ ++ if (options.pkcs11_provider != NULL && uri->module_path == NULL) ++ uri->module_path = strdup(options.pkcs11_provider); ++ ++ if (options.num_identity_files < SSH_MAX_IDENTITY_FILES && ++ (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys, NULL)) > 0) { ++ for (i = 0; i < nkeys; i++) { ++ if (*n_ids >= SSH_MAX_IDENTITY_FILES) { ++ sshkey_free(keys[i]); ++ continue; ++ } ++ identity_keys[*n_ids] = keys[i]; ++ identity_files[*n_ids] = pkcs11_uri_get(uri); ++ (*n_ids)++; ++ } ++ free(keys); ++ } ++ ++ pkcs11_uri_cleanup(uri); ++} ++#endif /* ENABLE_PKCS11 */ ++ + /* Loads all IdentityFile and CertificateFile keys */ + static void + load_public_identity_files(const struct ssh_conn_info *cinfo) +@@ -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]; +-#ifdef ENABLE_PKCS11 +- struct sshkey **keys = NULL; +- char **comments = NULL; +- int nkeys; +-#endif /* PKCS11 */ + + n_ids = n_certs = 0; + memset(identity_files, 0, sizeof(identity_files)); +@@ -2338,33 +2381,46 @@ load_public_identity_files(const struct + sizeof(certificate_file_userprovided)); + + #ifdef ENABLE_PKCS11 +- if (options.pkcs11_provider != NULL && +- options.num_identity_files < SSH_MAX_IDENTITY_FILES && +- (pkcs11_init(!options.batch_mode) == 0) && +- (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, +- &keys, &comments)) > 0) { +- for (i = 0; i < nkeys; i++) { +- if (n_ids >= SSH_MAX_IDENTITY_FILES) { +- sshkey_free(keys[i]); +- free(comments[i]); +- continue; +- } +- identity_keys[n_ids] = keys[i]; +- identity_files[n_ids] = comments[i]; /* transferred */ +- n_ids++; +- } +- free(keys); +- free(comments); ++ /* handle fallback from PKCS11Provider option */ ++ pkcs11_init(!options.batch_mode); ++ ++ if (options.pkcs11_provider != NULL) { ++ struct pkcs11_uri *uri; ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); ++ ++ /* Construct simple PKCS#11 URI to simplify access */ ++ uri->module_path = strdup(options.pkcs11_provider); ++ ++ /* Add it as any other IdentityFile */ ++ cp = pkcs11_uri_get(uri); ++ add_identity_file(&options, NULL, cp, 1); ++ free(cp); ++ ++ pkcs11_uri_cleanup(uri); + } + #endif /* ENABLE_PKCS11 */ + for (i = 0; i < options.num_identity_files; i++) { ++ char *name = options.identity_files[i]; + if (n_ids >= SSH_MAX_IDENTITY_FILES || +- strcasecmp(options.identity_files[i], "none") == 0) { ++ strcasecmp(name, "none") == 0) { + free(options.identity_files[i]); + options.identity_files[i] = NULL; + continue; + } +- cp = tilde_expand_filename(options.identity_files[i], getuid()); ++#ifdef ENABLE_PKCS11 ++ if (strlen(name) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(name, PKCS11_URI_SCHEME, ++ strlen(PKCS11_URI_SCHEME)) == 0) { ++ load_pkcs11_identity(name, identity_files, ++ identity_keys, &n_ids); ++ free(options.identity_files[i]); ++ continue; ++ } ++#endif /* ENABLE_PKCS11 */ ++ cp = tilde_expand_filename(name, getuid()); + filename = default_client_percent_dollar_expand(cp, cinfo); + free(cp); + check_load(sshkey_load_public(filename, &public, NULL), +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 */ +- fprintf(stdout, "%s%s\n", +- *(comments[i]) == '\0' ? "" : " ", comments[i]); ++ if (*(comments[i]) != '\0') { ++ fprintf(stdout, " %s", comments[i]); ++ } + (void) pkcs11_uri_write(keys[i], stdout); - fprintf(stdout, "\n"); ++ fprintf(stdout, "\n"); } + free(comments[i]); sshkey_free(keys[i]); -diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c -index e7860de8..7b2a9115 100644 ---- a/ssh-pkcs11-client.c -+++ b/ssh-pkcs11-client.c -@@ -321,6 +321,8 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) - u_int nkeys, i; +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("%s: called, name = %s", __func__, name); ++ debug_f("called, name = %s", name); + - if (fd < 0 && pkcs11_start_helper() < 0) - return (-1); - -@@ -338,6 +340,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) - if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + 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 *)); -+ debug("%s: nkeys = %u", __func__, nkeys); + 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 --git a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c -new file mode 100644 -index 00000000..e1a7b4e0 ---- /dev/null -+++ b/ssh-pkcs11-uri.c -@@ -0,0 +1,425 @@ +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; + }; + +-struct pkcs11_provider { +- char *name; ++struct pkcs11_module { ++ char *module_path; + void *handle; + CK_FUNCTION_LIST *function_list; + CK_INFO info; +@@ -65,6 +65,13 @@ struct pkcs11_provider { + struct pkcs11_slotinfo *slotinfo; + int valid; + int refcount; ++}; ++ ++struct pkcs11_provider { ++ char *name; ++ struct pkcs11_module *module; /* can be shared between various providers */ ++ int refcount; ++ int valid; + TAILQ_ENTRY(pkcs11_provider) next; + }; + +@@ -75,6 +82,7 @@ struct pkcs11_key { + CK_ULONG slotidx; + char *keyid; + int keyid_len; ++ char *label; + }; + + int pkcs11_interactive = 0; +@@ -106,26 +114,61 @@ pkcs11_init(int interactive) + * this is called when a provider gets unregistered. + */ + static void +-pkcs11_provider_finalize(struct pkcs11_provider *p) ++pkcs11_module_finalize(struct pkcs11_module *m) + { + CK_RV rv; + CK_ULONG i; + +- debug_f("provider \"%s\" refcount %d valid %d", +- p->name, p->refcount, p->valid); +- if (!p->valid) ++ debug_f("%p refcount %d valid %d", m, m->refcount, m->valid); ++ if (!m->valid) + return; +- for (i = 0; i < p->nslots; i++) { +- if (p->slotinfo[i].session && +- (rv = p->function_list->C_CloseSession( +- p->slotinfo[i].session)) != CKR_OK) ++ for (i = 0; i < m->nslots; i++) { ++ if (m->slotinfo[i].session && ++ (rv = m->function_list->C_CloseSession( ++ m->slotinfo[i].session)) != CKR_OK) + error("C_CloseSession failed: %lu", rv); + } +- 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); ++ m->valid = 0; ++ m->function_list = NULL; ++ dlclose(m->handle); ++} ++ ++/* ++ * remove a reference to the pkcs11 module. ++ * called when a provider is unregistered. ++ */ ++static void ++pkcs11_module_unref(struct pkcs11_module *m) ++{ ++ debug_f("%p refcount %d", m, m->refcount); ++ if (--m->refcount <= 0) { ++ pkcs11_module_finalize(m); ++ if (m->valid) ++ error_f("%p still valid", m); ++ free(m->slotlist); ++ free(m->slotinfo); ++ free(m->module_path); ++ free(m); ++ } ++} ++ ++/* ++ * finalize a provider shared library, it's no longer usable. ++ * however, there might still be keys referencing this provider, ++ * so the actual freeing of memory is handled by pkcs11_provider_unref(). ++ * this is called when a provider gets unregistered. ++ */ ++static void ++pkcs11_provider_finalize(struct pkcs11_provider *p) ++{ ++ debug_f("%p refcount %d valid %d", p, p->refcount, p->valid); ++ if (!p->valid) ++ return; ++ pkcs11_module_unref(p->module); ++ p->module = NULL; + p->valid = 0; +- p->function_list = NULL; +- dlclose(p->handle); + } + + /* +@@ -137,11 +180,9 @@ pkcs11_provider_unref(struct pkcs11_prov + { + debug_f("provider \"%s\" refcount %d", p->name, p->refcount); + if (--p->refcount <= 0) { +- if (p->valid) +- error_f("provider \"%s\" still valid", p->name); + free(p->name); +- free(p->slotlist); +- free(p->slotinfo); ++ if (p->module) ++ pkcs11_module_unref(p->module); + free(p); + } + } +@@ -159,6 +200,20 @@ pkcs11_terminate(void) + } + } + ++/* lookup provider by module path */ ++static struct pkcs11_module * ++pkcs11_provider_lookup_module(char *module_path) ++{ ++ struct pkcs11_provider *p; ++ ++ TAILQ_FOREACH(p, &pkcs11_providers, next) { ++ debug("check %p %s (%s)", p, p->name, p->module->module_path); ++ if (!strcmp(module_path, p->module->module_path)) ++ return (p->module); ++ } ++ return (NULL); ++} ++ + /* lookup provider by name */ + static struct pkcs11_provider * + pkcs11_provider_lookup(char *provider_id) +@@ -173,19 +228,55 @@ pkcs11_provider_lookup(char *provider_id + return (NULL); + } + ++int pkcs11_del_provider_by_uri(struct pkcs11_uri *); ++ + /* unregister provider by name */ + int + pkcs11_del_provider(char *provider_id) + { ++ int rv; ++ struct pkcs11_uri *uri; ++ ++ debug_f("called, provider_id = %s", provider_id); ++ ++ if (provider_id == NULL) ++ return 0; ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); ++ ++ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { ++ if (pkcs11_uri_parse(provider_id, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI"); ++ } else { ++ uri->module_path = strdup(provider_id); ++ } ++ ++ rv = pkcs11_del_provider_by_uri(uri); ++ pkcs11_uri_cleanup(uri); ++ return rv; ++} ++ ++/* unregister provider by PKCS#11 URI */ ++int ++pkcs11_del_provider_by_uri(struct pkcs11_uri *uri) ++{ + struct pkcs11_provider *p; ++ int rv = -1; ++ char *provider_uri = pkcs11_uri_get(uri); ++ ++ debug3_f("called with provider %s", provider_uri); + +- if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { ++ if ((p = pkcs11_provider_lookup(provider_uri)) != NULL) { + TAILQ_REMOVE(&pkcs11_providers, p, next); + pkcs11_provider_finalize(p); + pkcs11_provider_unref(p); +- return (0); ++ rv = 0; + } +- return (-1); ++ free(provider_uri); ++ return rv; + } + + static RSA_METHOD *rsa_method; +@@ -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 */ + ++/* ++ * This can't be in the ssh-pkcs11-uri, becase we can not depend on ++ * PKCS#11 structures in ssh-agent (using client-helper communication) ++ */ ++int ++pkcs11_uri_write(const struct sshkey *key, FILE *f) ++{ ++ char *p = NULL; ++ struct pkcs11_uri uri; ++ struct pkcs11_key *k11; ++ ++ /* sanity - is it a RSA key with associated app_data? */ ++ switch (key->type) { ++ case KEY_RSA: ++ k11 = RSA_get_ex_data(key->rsa, rsa_idx); ++ break; ++#ifdef HAVE_EC_KEY_METHOD_NEW ++ case KEY_ECDSA: ++ k11 = EC_KEY_get_ex_data(key->ecdsa, ec_key_idx); ++ break; ++#endif ++ default: ++ error("Unknown key type %d", key->type); ++ return -1; ++ } ++ if (k11 == NULL) { ++ error("Failed to get ex_data for key type %d", key->type); ++ return (-1); ++ } ++ ++ /* omit type -- we are looking for private-public or private-certificate pairs */ ++ uri.id = k11->keyid; ++ uri.id_len = k11->keyid_len; ++ uri.token = k11->provider->module->slotinfo[k11->slotidx].token.label; ++ uri.object = k11->label; ++ uri.module_path = k11->provider->module->module_path; ++ uri.lib_manuf = k11->provider->module->info.manufacturerID; ++ uri.manuf = k11->provider->module->slotinfo[k11->slotidx].token.manufacturerID; ++ uri.serial = k11->provider->module->slotinfo[k11->slotidx].token.serialNumber; ++ ++ p = pkcs11_uri_get(&uri); ++ /* do not cleanup -- we do not allocate here, only reference */ ++ if (p == NULL) ++ return -1; ++ ++ fprintf(f, " %s", p); ++ free(p); ++ return 0; ++} ++ + /* release a wrapped object */ + static void + pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, +@@ -208,6 +349,7 @@ pkcs11_k11_free(void *parent, void *ptr, + if (k11->provider) + pkcs11_provider_unref(k11->provider); + free(k11->keyid); ++ free(k11->label); + free(k11); + } + +@@ -222,8 +364,8 @@ pkcs11_find(struct pkcs11_provider *p, C + CK_RV rv; + int ret = -1; + +- f = p->function_list; +- session = p->slotinfo[slotidx].session; ++ f = p->module->function_list; ++ session = p->module->slotinfo[slotidx].session; + 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 @@ pkcs11_login_slot(struct pkcs11_provider + if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + verbose("Deferring PIN entry to reader keypad."); + else { +- snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", ++ snprintf(prompt, sizeof(prompt), "Enter PIN for '%.32s': ", + si->token.label); +- if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) { ++ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF|RP_ALLOW_STDIN)) == NULL) { + debug_f("no pin specified"); + return (-1); /* bail out */ + } + } +- rv = provider->function_list->C_Login(si->session, type, (u_char *)pin, ++ rv = provider->module->function_list->C_Login(si->session, type, (u_char *)pin, + (pin != NULL) ? strlen(pin) : 0); + if (pin != NULL) + freezero(pin, strlen(pin)); +@@ -297,13 +439,14 @@ pkcs11_login_slot(struct pkcs11_provider + static int + pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) + { +- if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) { ++ if (k11 == NULL || k11->provider == NULL || !k11->provider->valid || ++ k11->provider->module == NULL || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + + return pkcs11_login_slot(k11->provider, +- &k11->provider->slotinfo[k11->slotidx], type); ++ &k11->provider->module->slotinfo[k11->slotidx], type); + } + + +@@ -319,13 +462,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs + + *val = 0; + +- if (!k11->provider || !k11->provider->valid) { ++ if (!k11->provider || !k11->provider->valid || ++ !k11->provider->module || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + attr.type = type; + attr.pValue = &flag; +@@ -356,13 +500,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C + int always_auth = 0; + int did_login = 0; + +- if (!k11->provider || !k11->provider->valid) { ++ if (!k11->provider || !k11->provider->valid || ++ !k11->provider->module || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { + if (pkcs11_login(k11, CKU_USER) < 0) { +@@ -439,8 +584,8 @@ pkcs11_rsa_private_encrypt(int flen, con + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + tlen = RSA_size(rsa); + + /* XXX handle CKR_BUFFER_TOO_SMALL */ +@@ -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, +- CK_ATTRIBUTE *keyid_attrib, RSA *rsa) ++ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, RSA *rsa) + { + struct pkcs11_key *k11; + +@@ -502,6 +647,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + } + ++ if (label_attrib->ulValueLen > 0 ) { ++ k11->label = xmalloc(label_attrib->ulValueLen+1); ++ memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); ++ k11->label[label_attrib->ulValueLen] = 0; ++ } ++ + RSA_set_method(rsa, rsa_method); + RSA_set_ex_data(rsa, rsa_idx, k11); + return (0); +@@ -532,8 +683,8 @@ ecdsa_do_sign(const unsigned char *dgst, + return (NULL); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + siglen = ECDSA_size(ec); + sig = xmalloc(siglen); +@@ -598,7 +749,7 @@ pkcs11_ecdsa_start_wrapper(void) + + static int + pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, +- CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) ++ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ec) + { + struct pkcs11_key *k11; + +@@ -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); + } ++ if (label_attrib->ulValueLen > 0 ) { ++ k11->label = xmalloc(label_attrib->ulValueLen+1); ++ 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 +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 char * + rmspace(u_char *buf, size_t len) + { +@@ -654,8 +812,8 @@ pkcs11_open_session(struct pkcs11_provid + CK_SESSION_HANDLE session; + int login_required, ret; + +- f = p->function_list; +- si = &p->slotinfo[slotidx]; ++ f = p->module->function_list; ++ si = &p->module->slotinfo[slotidx]; + + login_required = si->token.flags & CKF_LOGIN_REQUIRED; + +@@ -665,9 +823,9 @@ pkcs11_open_session(struct pkcs11_provid + error("pin required"); + return (-SSH_PKCS11_ERR_PIN_REQUIRED); + } +- if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| ++ if ((rv = f->C_OpenSession(p->module->slotlist[slotidx], CKF_RW_SESSION| + CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { +- error("C_OpenSession failed: %lu", rv); ++ error("C_OpenSession failed for slot %lu: %lu", slotidx, rv); + return (-1); + } + if (login_required && pin != NULL && strlen(pin) != 0) { +@@ -703,7 +861,8 @@ static struct sshkey * + pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) + { +- CK_ATTRIBUTE key_attr[3]; ++ CK_ATTRIBUTE key_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -717,14 +876,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; +- key_attr[1].type = CKA_EC_POINT; +- key_attr[2].type = CKA_EC_PARAMS; ++ key_attr[1].type = CKA_LABEL; ++ key_attr[2].type = CKA_EC_POINT; ++ key_attr[3].type = CKA_EC_PARAMS; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); +@@ -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. + */ +- if (key_attr[1].ulValueLen == 0 || +- key_attr[2].ulValueLen == 0) { ++ if (key_attr[2].ulValueLen == 0 || ++ key_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (key_attr[i].ulValueLen > 0) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + + /* retrieve ID, public point and curve parameters of EC key */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; +@@ -759,8 +919,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ + goto fail; + } + +- attrp = key_attr[2].pValue; +- group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); ++ attrp = key_attr[3].pValue; ++ group = d2i_ECPKParameters(NULL, &attrp, key_attr[3].ulValueLen); + if (group == NULL) { + ossl_error("d2i_ECPKParameters failed"); + goto fail; +@@ -771,13 +931,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ + goto fail; + } + +- if (key_attr[1].ulValueLen <= 2) { ++ if (key_attr[2].ulValueLen <= 2) { + error("CKA_EC_POINT too small"); + goto fail; + } + +- attrp = key_attr[1].pValue; +- octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen); ++ attrp = key_attr[2].pValue; ++ octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[2].ulValueLen); + if (octet == NULL) { + ossl_error("d2i_ASN1_OCTET_STRING failed"); + goto fail; +@@ -794,7 +954,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ + goto fail; + } + +- if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) ++ if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], ec)) + goto fail; + + key = sshkey_new(KEY_UNSPEC); +@@ -810,7 +970,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ + ec = NULL; /* now owned by key */ + + fail: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(key_attr[i].pValue); + if (ec) + EC_KEY_free(ec); +@@ -827,7 +987,8 @@ static struct sshkey * + pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) + { +- CK_ATTRIBUTE key_attr[3]; ++ CK_ATTRIBUTE key_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -838,14 +999,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; +- key_attr[1].type = CKA_MODULUS; +- key_attr[2].type = CKA_PUBLIC_EXPONENT; ++ key_attr[1].type = CKA_LABEL; ++ key_attr[2].type = CKA_MODULUS; ++ key_attr[3].type = CKA_PUBLIC_EXPONENT; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); +@@ -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. + */ +- if (key_attr[1].ulValueLen == 0 || +- key_attr[2].ulValueLen == 0) { ++ if (key_attr[2].ulValueLen == 0 || ++ key_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (key_attr[i].ulValueLen > 0) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + + /* retrieve ID, modulus and public exponent of RSA key */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; +@@ -880,8 +1042,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr + goto fail; + } + +- rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); +- rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); ++ rsa_n = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); ++ rsa_e = BN_bin2bn(key_attr[3].pValue, key_attr[3].ulValueLen, NULL); + if (rsa_n == NULL || rsa_e == NULL) { + error("BN_bin2bn failed"); + goto fail; +@@ -890,7 +1052,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr + fatal_f("set key"); + rsa_n = rsa_e = NULL; /* transferred */ + +- if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) ++ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], rsa)) + goto fail; + + key = sshkey_new(KEY_UNSPEC); +@@ -905,7 +1067,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr + rsa = NULL; /* now owned by key */ + + fail: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(key_attr[i].pValue); + RSA_free(rsa); + +@@ -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) + { +- CK_ATTRIBUTE cert_attr[3]; ++ CK_ATTRIBUTE cert_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -940,14 +1103,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p + + memset(&cert_attr, 0, sizeof(cert_attr)); + cert_attr[0].type = CKA_ID; +- cert_attr[1].type = CKA_SUBJECT; +- cert_attr[2].type = CKA_VALUE; ++ cert_attr[1].type = CKA_LABEL; ++ cert_attr[2].type = CKA_SUBJECT; ++ cert_attr[3].type = CKA_VALUE; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return -1; +@@ -959,18 +1123,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p + * XXX assumes CKA_ID is always first. + */ + if (cert_attr[1].ulValueLen == 0 || +- cert_attr[2].ulValueLen == 0) { ++ cert_attr[2].ulValueLen == 0 || ++ cert_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return -1; + } + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (cert_attr[i].ulValueLen > 0) + cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); + + /* retrieve ID, subject and value of certificate */ +- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto out; +@@ -984,8 +1149,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p + subject = xstrdup("invalid subject"); + X509_NAME_free(x509_name); + +- cp = cert_attr[2].pValue; +- if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) { ++ cp = cert_attr[3].pValue; ++ if ((x509 = d2i_X509(NULL, &cp, cert_attr[3].ulValueLen)) == NULL) { + error("d2i_x509 failed"); + goto out; + } +@@ -1005,7 +1170,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p + goto out; + } + +- if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) ++ if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], rsa)) + goto out; + + key = sshkey_new(KEY_UNSPEC); +@@ -1035,7 +1200,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p + goto out; + } + +- if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) ++ if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], ec)) + goto out; + + key = sshkey_new(KEY_UNSPEC); +@@ -1055,7 +1220,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p + goto out; + } + out: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(cert_attr[i].pValue); + X509_free(x509); + RSA_free(rsa); +@@ -1106,11 +1271,12 @@ note_key(struct pkcs11_provider *p, CK_U + */ + static int + pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, +- struct sshkey ***keysp, char ***labelsp, int *nkeys) ++ struct sshkey ***keysp, char ***labelsp, int *nkeys, struct pkcs11_uri *uri) + { + struct sshkey *key = NULL; + CK_OBJECT_CLASS key_class; +- CK_ATTRIBUTE key_attr[1]; ++ CK_ATTRIBUTE key_attr[3]; ++ int nattr = 1; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -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; ++ key_attr[nattr].ulValueLen = uri->id_len; ++ nattr++; ++ } ++ if (uri->object != NULL) { ++ key_attr[nattr].type = CKA_LABEL; ++ key_attr[nattr].pValue = uri->object; ++ key_attr[nattr].ulValueLen = strlen(uri->object); ++ nattr++; ++ } + +- rv = f->C_FindObjectsInit(session, key_attr, 1); ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; ++ ++ rv = f->C_FindObjectsInit(session, key_attr, nattr); + if (rv != CKR_OK) { + error("C_FindObjectsInit failed: %lu", rv); + goto fail; +@@ -1211,11 +1390,12 @@ fail: + */ + static int + pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, +- struct sshkey ***keysp, char ***labelsp, int *nkeys) ++ struct sshkey ***keysp, char ***labelsp, int *nkeys, struct pkcs11_uri *uri) + { + struct sshkey *key = NULL; + CK_OBJECT_CLASS key_class; +- CK_ATTRIBUTE key_attr[2]; ++ CK_ATTRIBUTE key_attr[3]; ++ int nattr = 1; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -1231,10 +1411,23 @@ pkcs11_fetch_keys(struct pkcs11_provider + 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; ++ key_attr[nattr].ulValueLen = uri->id_len; ++ nattr++; ++ } ++ if (uri->object != NULL) { ++ key_attr[nattr].type = CKA_LABEL; ++ key_attr[nattr].pValue = uri->object; ++ key_attr[nattr].ulValueLen = strlen(uri->object); ++ nattr++; ++ } ++ ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + +- rv = f->C_FindObjectsInit(session, key_attr, 1); ++ rv = f->C_FindObjectsInit(session, key_attr, nattr); + if (rv != CKR_OK) { + error("C_FindObjectsInit failed: %lu", rv); + goto fail; +@@ -1503,16 +1696,10 @@ pkcs11_ecdsa_generate_private_key(struct + } + #endif /* WITH_PKCS11_KEYGEN */ + +-/* +- * register a new provider, fails if provider already exists. if +- * keyp is provided, fetch keys. +- */ + static int +-pkcs11_register_provider(char *provider_id, char *pin, +- struct sshkey ***keyp, char ***labelsp, +- struct pkcs11_provider **providerp, CK_ULONG user) ++pkcs11_initialize_provider(struct pkcs11_uri *uri, struct pkcs11_provider **providerp) + { +- int nkeys, need_finalize = 0; ++ int need_finalize = 0; + int ret = -1; + struct pkcs11_provider *p = NULL; + void *handle = NULL; +@@ -1521,162 +1708,309 @@ pkcs11_register_provider(char *provider_ + CK_FUNCTION_LIST *f = NULL; + CK_TOKEN_INFO *token; + CK_ULONG i; ++ char *provider_module = NULL; ++ 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; ++#endif ++ } else { ++ provider_module = strdup(uri->module_path); ++ } ++ 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) { ++ debug_f("provider module already initialized: %s", provider_module); ++ free(provider_module); ++ /* Skip the initialization of PKCS#11 module */ ++ m->refcount++; ++ p->module = m; ++ p->valid = 1; ++ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); ++ p->refcount++; /* add to provider list */ ++ *providerp = p; ++ return 0; ++ } else { ++ m = xcalloc(1, sizeof(*m)); ++ 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()); ++ if ((handle = dlopen(provider_module, RTLD_NOW)) == NULL) { ++ error("dlopen %s failed: %s", provider_module, dlerror()); + goto fail; + } + if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) + fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); +- 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) { + error("C_GetFunctionList for provider %s failed: %lu", +- provider_id, rv); ++ provider_module, rv); + goto fail; + } +- p->function_list = f; ++ m->function_list = f; + if ((rv = f->C_Initialize(NULL)) != CKR_OK) { + error("C_Initialize for provider %s failed: %lu", +- provider_id, rv); ++ provider_module, rv); + goto fail; + } + need_finalize = 1; +- if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) { ++ if ((rv = f->C_GetInfo(&m->info)) != CKR_OK) { + error("C_GetInfo for provider %s failed: %lu", +- provider_id, rv); ++ provider_module, rv); + goto fail; + } +- debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" +- " libraryDescription <%.*s> libraryVersion %d.%d", +- provider_id, +- RMSPACE(p->info.manufacturerID), +- p->info.cryptokiVersion.major, +- p->info.cryptokiVersion.minor, +- RMSPACE(p->info.libraryDescription), +- p->info.libraryVersion.major, +- p->info.libraryVersion.minor); +- if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { ++ rmspace(m->info.manufacturerID, sizeof(m->info.manufacturerID)); ++ if (uri->lib_manuf != NULL && ++ strncmp(uri->lib_manuf, m->info.manufacturerID, 32)) { ++ debug_f("Skipping provider %s not matching library_manufacturer", ++ m->info.manufacturerID); ++ goto fail; ++ } ++ rmspace(m->info.libraryDescription, sizeof(m->info.libraryDescription)); ++ debug("provider %s: manufacturerID <%.32s> cryptokiVersion %d.%d" ++ " libraryDescription <%.32s> libraryVersion %d.%d", ++ provider_module, ++ m->info.manufacturerID, ++ m->info.cryptokiVersion.major, ++ m->info.cryptokiVersion.minor, ++ m->info.libraryDescription, ++ m->info.libraryVersion.major, ++ m->info.libraryVersion.minor); ++ ++ if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &m->nslots)) != CKR_OK) { + error("C_GetSlotList failed: %lu", rv); + goto fail; + } +- if (p->nslots == 0) { +- debug_f("provider %s returned no slots", provider_id); ++ if (m->nslots == 0) { ++ debug_f("provider %s returned no slots", provider_module); + ret = -SSH_PKCS11_ERR_NO_SLOTS; + goto fail; + } +- p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); +- if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots)) ++ m->slotlist = xcalloc(m->nslots, sizeof(CK_SLOT_ID)); ++ if ((rv = f->C_GetSlotList(CK_TRUE, m->slotlist, &m->nslots)) + != CKR_OK) { + error("C_GetSlotList for provider %s failed: %lu", +- provider_id, rv); ++ provider_module, rv); + 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->valid = 1; ++ for (i = 0; i < m->nslots; i++) { ++ token = &m->slotinfo[i].token; ++ if ((rv = f->C_GetTokenInfo(m->slotlist[i], token)) + != CKR_OK) { + error("C_GetTokenInfo for provider %s slot %lu " +- "failed: %lu", provider_id, (u_long)i, rv); +- continue; +- } +- if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { +- debug2_f("ignoring uninitialised token in " +- "provider %s slot %lu", provider_id, (u_long)i); ++ "failed: %lu", provider_module, (u_long)i, rv); ++ token->flags = 0; + continue; + } + 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; ++ ++ /* now owned by caller */ ++ *providerp = p; ++ ++ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); ++ p->refcount++; /* add to provider list */ ++ ++ return 0; ++fail: ++ if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) ++ error("C_Finalize for provider %s failed: %lu", ++ provider_module, rv); ++ free(provider_module); ++ if (m) { ++ free(m->slotlist); ++ free(m); ++ } ++ if (p) { ++ free(p->name); ++ free(p); ++ } ++ if (handle) ++ dlclose(handle); ++ return (ret); ++} ++ ++/* ++ * register a new provider, fails if provider already exists. if ++ * keyp is provided, fetch keys. ++ */ ++static int ++pkcs11_register_provider_by_uri(struct pkcs11_uri *uri, char *pin, ++ struct sshkey ***keyp, char ***labelsp, struct pkcs11_provider **providerp, ++ CK_ULONG user) ++{ ++ int nkeys; ++ int ret = -1; ++ struct pkcs11_provider *p = NULL; ++ CK_ULONG i; ++ CK_TOKEN_INFO *token; ++ char *provider_uri = NULL; ++ ++ if (providerp == NULL) ++ goto fail; ++ *providerp = NULL; ++ ++ if (keyp != NULL) ++ *keyp = NULL; ++ ++ if ((ret = pkcs11_initialize_provider(uri, &p)) != 0) { ++ goto fail; ++ } ++ ++ provider_uri = pkcs11_uri_get(uri); ++ if (pin == NULL && uri->pin != NULL) { ++ pin = uri->pin; ++ } ++ nkeys = 0; ++ for (i = 0; i < p->module->nslots; i++) { ++ token = &p->module->slotinfo[i].token; ++ if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { ++ debug2_f("ignoring uninitialised token in " ++ "provider %s slot %lu", provider_uri, (u_long)i); ++ continue; ++ } ++ if (uri->token != NULL && ++ strncmp(token->label, uri->token, 32) != 0) { ++ debug2_f("ignoring token not matching label (%.32s) " ++ "specified by PKCS#11 URI in slot %lu", ++ token->label, (unsigned long)i); ++ continue; ++ } ++ if (uri->manuf != NULL && ++ strncmp(token->manufacturerID, uri->manuf, 32) != 0) { ++ debug2_f("ignoring token not matching requrested " ++ "manufacturerID (%.32s) specified by PKCS#11 URI in " ++ "slot %lu", token->manufacturerID, (unsigned long)i); ++ continue; ++ } ++ if (uri->serial != NULL && ++ strncmp(token->serialNumber, uri->serial, 16) != 0) { ++ debug2_f("ignoring token not matching requrested " ++ "serialNumber (%s) specified by PKCS#11 URI in " ++ "slot %lu", token->serialNumber, (unsigned long)i); ++ continue; ++ } ++ 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); + /* +- * open session, login with pin and retrieve public +- * keys (if keyp is provided) ++ * 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 || ++ if ((p->module->slotinfo[i].session != 0 || ++ (ret = pkcs11_open_session(p, i, pin, user)) != 0) && /* ??? */ + keyp == NULL) + continue; +- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); +- if (nkeys == 0 && !p->slotinfo[i].logged_in && ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ if (nkeys == 0 && !p->module->slotinfo[i].logged_in && + pkcs11_interactive) { + /* + * Some tokens require login before they will + * expose keys. + */ +- if (pkcs11_login_slot(p, &p->slotinfo[i], ++ debug3_f("Trying to login as there were no keys found"); ++ if (pkcs11_login_slot(p, &p->module->slotinfo[i], + CKU_USER) < 0) { + error("login failed"); + continue; + } +- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ } ++ if (nkeys == 0 && uri->object != NULL) { ++ debug3_f("No keys found. Retrying without label (%.32s) ", ++ uri->object); ++ /* Try once more without the label filter */ ++ char *label = uri->object; ++ uri->object = NULL; /* XXX clone uri? */ ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ uri->object = label; + } + } ++ pin = NULL; /* Will be cleaned up with URI */ + + /* now owned by caller */ + *providerp = p; + +- 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) +- error("C_Finalize for provider %s failed: %lu", +- provider_id, rv); + if (p) { +- free(p->name); +- free(p->slotlist); +- free(p->slotinfo); +- free(p); ++ TAILQ_REMOVE(&pkcs11_providers, p, next); ++ pkcs11_provider_unref(p); + } +- if (handle) +- dlclose(handle); + if (ret > 0) + ret = -1; + return (ret); + } + +-/* +- * register a new provider and get number of keys hold by the token, +- * fails if provider already exists +- */ ++static int ++pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, ++ char ***labelsp, struct pkcs11_provider **providerp, CK_ULONG user) ++{ ++ struct pkcs11_uri *uri = NULL; ++ int r; ++ ++ debug_f("called, provider_id = %s", provider_id); ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("failed to init PKCS#11 URI"); ++ ++ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { ++ if (pkcs11_uri_parse(provider_id, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI"); ++ } else { ++ uri->module_path = strdup(provider_id); ++ } ++ ++ r = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, providerp, user); ++ pkcs11_uri_cleanup(uri); ++ ++ return r; ++} ++ + int +-pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, +- char ***labelsp) ++pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin, ++ struct sshkey ***keyp, char ***labelsp) + { + struct pkcs11_provider *p = NULL; + int nkeys; ++ char *provider_uri = pkcs11_uri_get(uri); ++ ++ debug_f("called, provider_uri = %s", provider_uri); + +- nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp, +- &p, CKU_USER); ++ nkeys = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, &p, CKU_USER); + + /* no keys found or some other error, de-register provider */ + if (nkeys <= 0 && p != NULL) { +@@ -1685,7 +2019,37 @@ pkcs11_add_provider(char *provider_id, c + pkcs11_provider_unref(p); + } + if (nkeys == 0) +- debug_f("provider %s returned no keys", provider_id); ++ debug_f("provider %s returned no keys", provider_uri); ++ ++ free(provider_uri); ++ return nkeys; ++} ++ ++/* ++ * register a new provider and get number of keys hold by the token, ++ * fails if provider already exists ++ */ ++int ++pkcs11_add_provider(char *provider_id, char *pin, ++ struct sshkey ***keyp, char ***labelsp) ++{ ++ struct pkcs11_uri *uri; ++ int nkeys; ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); ++ ++ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { ++ if (pkcs11_uri_parse(provider_id, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI"); ++ } else { ++ uri->module_path = strdup(provider_id); ++ } ++ ++ nkeys = pkcs11_add_provider_by_uri(uri, pin, keyp, labelsp); ++ pkcs11_uri_cleanup(uri); + + return (nkeys); + } +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 + ++#include "ssh-pkcs11-uri.h" ++ + int pkcs11_init(int); + void pkcs11_terminate(void); + int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); ++int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***, char ***); + int pkcs11_del_provider(char *); ++int pkcs11_uri_write(const struct sshkey *, FILE *); + #ifdef WITH_PKCS11_KEYGEN + struct sshkey * + pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, +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 + * @@ -1210,13 +2674,14 @@ index 00000000..e1a7b4e0 +#define PKCS11_URI_OBJECT "object" +#define PKCS11_URI_LIB_MANUF "library-manufacturer" +#define PKCS11_URI_MANUF "manufacturer" ++#define PKCS11_URI_SERIAL "serial" +#define PKCS11_URI_MODULE_PATH "module-path" +#define PKCS11_URI_PIN_VALUE "pin-value" + +/* Keyword tokens. */ +typedef enum { -+ pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pModulePath, -+ pPinValue, pBadOption ++ pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pSerial, ++ pModulePath, pPinValue, pBadOption +} pkcs11uriOpCodes; + +/* Textual representation of the tokens. */ @@ -1229,6 +2694,7 @@ index 00000000..e1a7b4e0 + { PKCS11_URI_OBJECT, pObject }, + { PKCS11_URI_LIB_MANUF, pLibraryManufacturer }, + { PKCS11_URI_MANUF, pManufacturer }, ++ { PKCS11_URI_SERIAL, pSerial }, + { PKCS11_URI_MODULE_PATH, pModulePath }, + { PKCS11_URI_PIN_VALUE, pPinValue }, + { NULL, pBadOption } @@ -1293,7 +2759,7 @@ index 00000000..e1a7b4e0 +} + +struct sshbuf * -+percent_encode(const char *data, size_t length, const char *whitelist) ++percent_encode(const char *data, size_t length, const char *allow_list) +{ + struct sshbuf *b = NULL; + char tmp[4], *cp; @@ -1302,7 +2768,7 @@ index 00000000..e1a7b4e0 + if ((b = sshbuf_new()) == NULL) + return NULL; + for (i = 0; i < length; i++) { -+ cp = strchr(whitelist, data[i]); ++ cp = strchr(allow_list, data[i]); + /* if c is specified as '\0' pointer to terminator is returned !! */ + if (cp != NULL && *cp != '\0') { + if (sshbuf_put(b, &data[i], 1) != 0) @@ -1387,6 +2853,16 @@ index 00000000..e1a7b4e0 + goto err; + } + ++ /* Write serial */ ++ if (uri->serial) { ++ struct sshbuf *serial = percent_encode(uri->serial, ++ strlen(uri->serial), PKCS11_URI_WHITELIST); ++ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, ++ PKCS11_URI_SERIAL, serial); ++ if (path == NULL) ++ goto err; ++ } ++ + /* Write module_path */ + if (uri->module_path) { + struct sshbuf *module = percent_encode(uri->module_path, @@ -1429,6 +2905,7 @@ index 00000000..e1a7b4e0 + free(pkcs11->object); + free(pkcs11->lib_manuf); + free(pkcs11->manuf); ++ free(pkcs11->serial); + if (pkcs11->pin) + freezero(pkcs11->pin, strlen(pkcs11->pin)); + free(pkcs11); @@ -1444,13 +2921,12 @@ index 00000000..e1a7b4e0 + size_t scheme_len = strlen(PKCS11_URI_SCHEME); + if (strlen(uri) < scheme_len || /* empty URI matches everything */ + strncmp(uri, PKCS11_URI_SCHEME, scheme_len) != 0) { -+ error("%s: The '%s' does not look like PKCS#11 URI", -+ __func__, uri); ++ error_f("The '%s' does not look like PKCS#11 URI", uri); + return -1; + } + + if (pkcs11 == NULL) { -+ error("%s: Bad arguments. The pkcs11 can't be null", __func__); ++ error_f("Bad arguments. The pkcs11 can't be null"); + return -1; + } + @@ -1461,7 +2937,7 @@ index 00000000..e1a7b4e0 + /* everything before ? */ + tok = strtok_r(str1, "?", &saveptr1); + if (tok == NULL) { -+ error("%s: pk11-path expected, got EOF", __func__); ++ error_f("pk11-path expected, got EOF"); + rv = -1; + goto out; + } @@ -1487,35 +2963,32 @@ index 00000000..e1a7b4e0 + case pId: + /* CKA_ID */ + if (pkcs11->id != NULL) { -+ verbose("%s: The id already set in the PKCS#11 URI", -+ __func__); ++ verbose_f("The id already set in the PKCS#11 URI"); + rv = -1; + goto out; + } + len = percent_decode(arg, &pkcs11->id); + if (len <= 0) { -+ verbose("%s: Failed to percent-decode CKA_ID: %s", -+ __func__, arg); ++ verbose_f("Failed to percent-decode CKA_ID: %s", arg); + rv = -1; + goto out; + } else + pkcs11->id_len = len; -+ debug3("%s: Setting CKA_ID = %s from PKCS#11 URI", -+ __func__, arg); ++ debug3_f("Setting CKA_ID = %s from PKCS#11 URI", arg); + break; + case pToken: + /* CK_TOKEN_INFO -> label */ + charptr = &pkcs11->token; + parse_string: + if (*charptr != NULL) { -+ verbose("%s: The %s already set in the PKCS#11 URI", -+ keywords[opcode].name, __func__); ++ verbose_f("The %s already set in the PKCS#11 URI", ++ keywords[opcode].name); + rv = -1; + goto out; + } + percent_decode(arg, charptr); -+ debug3("%s: Setting %s = %s from PKCS#11 URI", -+ __func__, keywords[opcode].name, *charptr); ++ debug3_f("Setting %s = %s from PKCS#11 URI", ++ keywords[opcode].name, *charptr); + break; + + case pObject: @@ -1528,6 +3001,11 @@ index 00000000..e1a7b4e0 + charptr = &pkcs11->manuf; + goto parse_string; + ++ case pSerial: ++ /* CK_TOKEN_INFO -> serialNumber */ ++ charptr = &pkcs11->serial; ++ goto parse_string; ++ + case pLibraryManufacturer: + /* CK_INFO -> manufacturerID */ + charptr = &pkcs11->lib_manuf; @@ -1535,8 +3013,7 @@ index 00000000..e1a7b4e0 + + default: + /* Unrecognized attribute in the URI path SHOULD be error */ -+ verbose("%s: Unknown part of path in PKCS#11 URI: %s", -+ __func__, tok); ++ verbose_f("Unknown part of path in PKCS#11 URI: %s", tok); + } + } + @@ -1559,32 +3036,31 @@ index 00000000..e1a7b4e0 + case pModulePath: + /* module-path is PKCS11Provider */ + if (pkcs11->module_path != NULL) { -+ verbose("%s: Multiple module-path attributes are" -+ "not supported the PKCS#11 URI", __func__); ++ verbose_f("Multiple module-path attributes are" ++ "not supported the PKCS#11 URI"); + rv = -1; + goto out; + } + percent_decode(arg, &pkcs11->module_path); -+ debug3("%s: Setting PKCS11Provider = %s from PKCS#11 URI", -+ __func__, pkcs11->module_path); ++ debug3_f("Setting PKCS11Provider = %s from PKCS#11 URI", ++ pkcs11->module_path); + break; + + case pPinValue: + /* pin-value */ + if (pkcs11->pin != NULL) { -+ verbose("%s: Multiple pin-value attributes are" -+ "not supported the PKCS#11 URI", __func__); ++ verbose_f("Multiple pin-value attributes are" ++ "not supported the PKCS#11 URI"); + rv = -1; + goto out; + } + percent_decode(arg, &pkcs11->pin); -+ debug3("%s: Setting PIN from PKCS#11 URI", __func__); ++ debug3_f("Setting PIN from PKCS#11 URI"); + break; + + default: + /* Unrecognized attribute in the URI query SHOULD be ignored */ -+ verbose("%s: Unknown part of query in PKCS#11 URI: %s", -+ __func__, tok); ++ verbose_f("Unknown part of query in PKCS#11 URI: %s", tok); + } + } +out: @@ -1593,12 +3069,10 @@ index 00000000..e1a7b4e0 +} + +#endif /* ENABLE_PKCS11 */ -diff --git a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h -new file mode 100644 -index 00000000..942a5a5a ---- /dev/null -+++ b/ssh-pkcs11-uri.h -@@ -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 + * @@ -1630,6 +3104,7 @@ index 00000000..942a5a5a + char *object; + char *lib_manuf; + char *manuf; ++ char *serial; + /* query */ + char *module_path; + char *pin; /* Only parsed, but not printed */ @@ -1641,1500 +3116,3 @@ index 00000000..942a5a5a +struct pkcs11_uri *pkcs11_uri_init(); +char *pkcs11_uri_get(struct pkcs11_uri *uri); + -diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c -index 70f06bff..59332945 100644 ---- a/ssh-pkcs11.c -+++ b/ssh-pkcs11.c -@@ -54,8 +54,8 @@ struct pkcs11_slotinfo { - int logged_in; - }; - --struct pkcs11_provider { -- char *name; -+struct pkcs11_module { -+ char *module_path; - void *handle; - CK_FUNCTION_LIST *function_list; - CK_INFO info; -@@ -64,6 +64,13 @@ struct pkcs11_provider { - struct pkcs11_slotinfo *slotinfo; - int valid; - int refcount; -+}; -+ -+struct pkcs11_provider { -+ char *name; -+ struct pkcs11_module *module; /* can be shared between various providers */ -+ int refcount; -+ int valid; - TAILQ_ENTRY(pkcs11_provider) next; - }; - -@@ -74,6 +81,7 @@ struct pkcs11_key { - CK_ULONG slotidx; - char *keyid; - int keyid_len; -+ char *label; - }; - - int pkcs11_interactive = 0; -@@ -106,26 +114,63 @@ pkcs11_init(int interactive) - * this is called when a provider gets unregistered. - */ - static void --pkcs11_provider_finalize(struct pkcs11_provider *p) -+pkcs11_module_finalize(struct pkcs11_module *m) - { - CK_RV rv; - CK_ULONG i; - -- debug("pkcs11_provider_finalize: %p refcount %d valid %d", -- p, p->refcount, p->valid); -- if (!p->valid) -+ debug("%s: %p refcount %d valid %d", __func__, -+ m, m->refcount, m->valid); -+ if (!m->valid) - return; -- for (i = 0; i < p->nslots; i++) { -- if (p->slotinfo[i].session && -- (rv = p->function_list->C_CloseSession( -- p->slotinfo[i].session)) != CKR_OK) -+ for (i = 0; i < m->nslots; i++) { -+ if (m->slotinfo[i].session && -+ (rv = m->function_list->C_CloseSession( -+ m->slotinfo[i].session)) != CKR_OK) - error("C_CloseSession failed: %lu", rv); - } -- 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); -+ m->valid = 0; -+ m->function_list = NULL; -+ dlclose(m->handle); -+} -+ -+/* -+ * remove a reference to the pkcs11 module. -+ * called when a provider is unregistered. -+ */ -+static void -+pkcs11_module_unref(struct pkcs11_module *m) -+{ -+ debug("%s: %p refcount %d", __func__, m, m->refcount); -+ if (--m->refcount <= 0) { -+ pkcs11_module_finalize(m); -+ if (m->valid) -+ error("%s: %p still valid", __func__, m); -+ free(m->slotlist); -+ free(m->slotinfo); -+ free(m->module_path); -+ free(m); -+ } -+} -+ -+/* -+ * finalize a provider shared libarary, it's no longer usable. -+ * however, there might still be keys referencing this provider, -+ * so the actuall freeing of memory is handled by pkcs11_provider_unref(). -+ * this is called when a provider gets unregistered. -+ */ -+static void -+pkcs11_provider_finalize(struct pkcs11_provider *p) -+{ -+ debug("%s: %p refcount %d valid %d", __func__, -+ p, p->refcount, p->valid); -+ if (!p->valid) -+ return; -+ pkcs11_module_unref(p->module); -+ p->module = NULL; - p->valid = 0; -- p->function_list = NULL; -- dlclose(p->handle); - } - - /* -@@ -135,13 +180,11 @@ pkcs11_provider_finalize(struct pkcs11_provider *p) - static void - pkcs11_provider_unref(struct pkcs11_provider *p) - { -- debug("pkcs11_provider_unref: %p refcount %d", p, p->refcount); -+ debug("%s: %p refcount %d", __func__, p, p->refcount); - if (--p->refcount <= 0) { -- if (p->valid) -- error("pkcs11_provider_unref: %p still valid", p); - free(p->name); -- free(p->slotlist); -- free(p->slotinfo); -+ if (p->module) -+ pkcs11_module_unref(p->module); - free(p); - } - } -@@ -159,6 +202,20 @@ pkcs11_terminate(void) - } - } - -+/* lookup provider by module path */ -+static struct pkcs11_module * -+pkcs11_provider_lookup_module(char *module_path) -+{ -+ struct pkcs11_provider *p; -+ -+ TAILQ_FOREACH(p, &pkcs11_providers, next) { -+ debug("check %p %s (%s)", p, p->name, p->module->module_path); -+ if (!strcmp(module_path, p->module->module_path)) -+ return (p->module); -+ } -+ return (NULL); -+} -+ - /* lookup provider by name */ - static struct pkcs11_provider * - pkcs11_provider_lookup(char *provider_id) -@@ -173,19 +230,52 @@ pkcs11_provider_lookup(char *provider_id) - return (NULL); - } - -+int pkcs11_del_provider_by_uri(struct pkcs11_uri *); -+ - /* unregister provider by name */ - int - pkcs11_del_provider(char *provider_id) -+{ -+ int rv; -+ struct pkcs11_uri *uri; -+ -+ debug("%s: called, provider_id = %s", __func__, provider_id); -+ -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PCKS#11 URI"); -+ -+ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { -+ if (pkcs11_uri_parse(provider_id, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI"); -+ } else { -+ uri->module_path = strdup(provider_id); -+ } -+ -+ rv = pkcs11_del_provider_by_uri(uri); -+ pkcs11_uri_cleanup(uri); -+ return rv; -+} -+ -+/* unregister provider by PKCS#11 URI */ -+int -+pkcs11_del_provider_by_uri(struct pkcs11_uri *uri) - { - struct pkcs11_provider *p; -+ int rv = -1; -+ char *provider_uri = pkcs11_uri_get(uri); - -- if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { -+ debug3("%s(%s): called", __func__, provider_uri); -+ -+ if ((p = pkcs11_provider_lookup(provider_uri)) != NULL) { - TAILQ_REMOVE(&pkcs11_providers, p, next); - pkcs11_provider_finalize(p); - pkcs11_provider_unref(p); -- return (0); -+ rv = 0; - } -- return (-1); -+ free(provider_uri); -+ return rv; - } - - static RSA_METHOD *rsa_method; -@@ -195,6 +285,55 @@ static EC_KEY_METHOD *ec_key_method; - static int ec_key_idx = 0; - #endif - -+/* -+ * This can't be in the ssh-pkcs11-uri, becase we can not depend on -+ * PKCS#11 structures in ssh-agent (using client-helper communication) -+ */ -+int -+pkcs11_uri_write(const struct sshkey *key, FILE *f) -+{ -+ char *p = NULL; -+ struct pkcs11_uri uri; -+ struct pkcs11_key *k11; -+ -+ /* sanity - is it a RSA key with associated app_data? */ -+ switch (key->type) { -+ case KEY_RSA: -+ k11 = RSA_get_ex_data(key->rsa, rsa_idx); -+ break; -+#ifdef HAVE_EC_KEY_METHOD_NEW -+ case KEY_ECDSA: -+ k11 = EC_KEY_get_ex_data(key->ecdsa, ec_key_idx); -+ break; -+#endif -+ default: -+ error("Unknown key type %d", key->type); -+ return -1; -+ } -+ if (k11 == NULL) { -+ error("Failed to get ex_data for key type %d", key->type); -+ return (-1); -+ } -+ -+ /* omit type -- we are looking for private-public or private-certificate pairs */ -+ uri.id = k11->keyid; -+ uri.id_len = k11->keyid_len; -+ uri.token = k11->provider->module->slotinfo[k11->slotidx].token.label; -+ uri.object = k11->label; -+ uri.module_path = k11->provider->module->module_path; -+ uri.lib_manuf = k11->provider->module->info.manufacturerID; -+ uri.manuf = k11->provider->module->slotinfo[k11->slotidx].token.manufacturerID; -+ -+ p = pkcs11_uri_get(&uri); -+ /* do not cleanup -- we do not allocate here, only reference */ -+ if (p == NULL) -+ return -1; -+ -+ fprintf(f, " %s", p); -+ free(p); -+ return 0; -+} -+ - /* release a wrapped object */ - static void - pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, -@@ -208,6 +347,7 @@ pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, - if (k11->provider) - pkcs11_provider_unref(k11->provider); - free(k11->keyid); -+ free(k11->label); - free(k11); - } - -@@ -222,8 +362,8 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, - CK_RV rv; - int ret = -1; - -- f = p->function_list; -- session = p->slotinfo[slotidx].session; -+ f = p->module->function_list; -+ session = p->module->slotinfo[slotidx].session; - if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { - error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); - return (-1); -@@ -252,8 +392,8 @@ pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - if (!pkcs11_interactive) { - error("need pin entry%s", -@@ -300,8 +440,8 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - attr.type = type; - attr.pValue = &flag; -@@ -332,13 +472,14 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) - int always_auth = 0; - int did_login = 0; - -- if (!k11->provider || !k11->provider->valid) { -+ if (!k11->provider || !k11->provider->valid || !k11->provider->module -+ || !k11->provider->module->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { - if (pkcs11_login(k11, CKU_USER) < 0) { -@@ -415,8 +556,8 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - tlen = RSA_size(rsa); - - /* XXX handle CKR_BUFFER_TOO_SMALL */ -@@ -460,7 +601,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, -- CK_ATTRIBUTE *keyid_attrib, RSA *rsa) -+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, RSA *rsa) - { - struct pkcs11_key *k11; - -@@ -478,6 +619,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); - } - -+ if (label_attrib->ulValueLen > 0 ) { -+ k11->label = xmalloc(label_attrib->ulValueLen+1); -+ memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); -+ k11->label[label_attrib->ulValueLen] = 0; -+ } -+ - RSA_set_method(rsa, rsa_method); - RSA_set_ex_data(rsa, rsa_idx, k11); - return (0); -@@ -508,8 +655,8 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, - return (NULL); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - siglen = ECDSA_size(ec); - sig = xmalloc(siglen); -@@ -574,7 +721,7 @@ pkcs11_ecdsa_start_wrapper(void) - - static int - pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, -- CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) -+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ec) - { - struct pkcs11_key *k11; - -@@ -590,6 +737,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - k11->keyid = xmalloc(k11->keyid_len); - memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); - -+ if (label_attrib->ulValueLen > 0 ) { -+ k11->label = xmalloc(label_attrib->ulValueLen+1); -+ 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); - -@@ -624,47 +777,26 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, - CK_FUNCTION_LIST *f; - CK_RV rv; - CK_SESSION_HANDLE session; -- int login_required, have_pinpad, ret; -- char prompt[1024], *xpin = NULL; -+ int login_required, ret; - -- f = p->function_list; -- si = &p->slotinfo[slotidx]; -+ f = p->module->function_list; -+ si = &p->module->slotinfo[slotidx]; - -- have_pinpad = si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH; - login_required = si->token.flags & CKF_LOGIN_REQUIRED; - - /* fail early before opening session */ -- if (login_required && !have_pinpad && !pkcs11_interactive && -+ if (login_required && !pkcs11_interactive && - (pin == NULL || strlen(pin) == 0)) { - error("pin required"); - return (-SSH_PKCS11_ERR_PIN_REQUIRED); - } -- if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| -+ if ((rv = f->C_OpenSession(p->module->slotlist[slotidx], CKF_RW_SESSION| - CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { -- error("C_OpenSession failed: %lu", rv); -+ error("C_OpenSession failed for slot %lu: %lu", slotidx, rv); - return (-1); - } -- if (login_required) { -- if (have_pinpad && (pin == NULL || strlen(pin) == 0)) { -- /* defer PIN entry to the reader keypad */ -- rv = f->C_Login(session, CKU_USER, NULL_PTR, 0); -- } else { -- if (pkcs11_interactive) { -- snprintf(prompt, sizeof(prompt), -- "Enter PIN for '%s': ", si->token.label); -- if ((xpin = read_passphrase(prompt, -- RP_ALLOW_EOF)) == NULL) { -- debug("%s: no pin specified", -- __func__); -- return (-SSH_PKCS11_ERR_PIN_REQUIRED); -- } -- pin = xpin; -- } -- rv = f->C_Login(session, CKU_USER, -- (u_char *)pin, strlen(pin)); -- if (xpin != NULL) -- freezero(xpin, strlen(xpin)); -- } -+ if (login_required && pin != NULL && strlen(pin) != 0) { -+ rv = f->C_Login(session, user, (u_char *)pin, strlen(pin)); - if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { - error("C_Login failed: %lu", rv); - ret = (rv == CKR_PIN_LOCKED) ? -@@ -696,7 +828,8 @@ static struct sshkey * - pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj) - { -- CK_ATTRIBUTE key_attr[3]; -+ CK_ATTRIBUTE key_attr[4]; -+ int nattr = 4; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -710,14 +843,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - - memset(&key_attr, 0, sizeof(key_attr)); - key_attr[0].type = CKA_ID; -- key_attr[1].type = CKA_EC_POINT; -- key_attr[2].type = CKA_EC_PARAMS; -+ key_attr[1].type = CKA_LABEL; -+ key_attr[2].type = CKA_EC_POINT; -+ key_attr[3].type = CKA_EC_PARAMS; - -- session = p->slotinfo[slotidx].session; -- f = p->function_list; -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - - /* figure out size of the attributes */ -- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return (NULL); -@@ -730,19 +863,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - * ensure that none of the others are zero length. - * XXX assumes CKA_ID is always first. - */ -- if (key_attr[1].ulValueLen == 0 || -- key_attr[2].ulValueLen == 0) { -+ if (key_attr[2].ulValueLen == 0 || -+ key_attr[3].ulValueLen == 0) { - error("invalid attribute length"); - return (NULL); - } - - /* allocate buffers for attributes */ -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - if (key_attr[i].ulValueLen > 0) - key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); - - /* retrieve ID, public point and curve parameters of EC key */ -- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto fail; -@@ -752,8 +887,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto fail; - } - -- attrp = key_attr[2].pValue; -- group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); -+ attrp = key_attr[3].pValue; -+ group = d2i_ECPKParameters(NULL, &attrp, key_attr[3].ulValueLen); - if (group == NULL) { - ossl_error("d2i_ECPKParameters failed"); - goto fail; -@@ -764,13 +899,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto fail; - } - -- if (key_attr[1].ulValueLen <= 2) { -+ if (key_attr[2].ulValueLen <= 2) { - error("CKA_EC_POINT too small"); - goto fail; - } - -- attrp = key_attr[1].pValue; -- octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen); -+ attrp = key_attr[2].pValue; -+ octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[2].ulValueLen); - if (octet == NULL) { - ossl_error("d2i_ASN1_OCTET_STRING failed"); - goto fail; -@@ -787,7 +922,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto fail; - } - -- if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) -+ if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], ec)) - goto fail; - - key = sshkey_new(KEY_UNSPEC); -@@ -803,7 +938,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - ec = NULL; /* now owned by key */ - - fail: -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - free(key_attr[i].pValue); - if (ec) - EC_KEY_free(ec); -@@ -820,7 +955,8 @@ static struct sshkey * - pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj) - { -- CK_ATTRIBUTE key_attr[3]; -+ CK_ATTRIBUTE key_attr[4]; -+ int nattr = 4; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -831,14 +967,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - - memset(&key_attr, 0, sizeof(key_attr)); - key_attr[0].type = CKA_ID; -- key_attr[1].type = CKA_MODULUS; -- key_attr[2].type = CKA_PUBLIC_EXPONENT; -+ key_attr[1].type = CKA_LABEL; -+ key_attr[2].type = CKA_MODULUS; -+ key_attr[3].type = CKA_PUBLIC_EXPONENT; - -- session = p->slotinfo[slotidx].session; -- f = p->function_list; -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - - /* figure out size of the attributes */ -- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return (NULL); -@@ -850,19 +987,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - * ensure that none of the others are zero length. - * XXX assumes CKA_ID is always first. - */ -- if (key_attr[1].ulValueLen == 0 || -- key_attr[2].ulValueLen == 0) { -+ if (key_attr[2].ulValueLen == 0 || -+ key_attr[3].ulValueLen == 0) { - error("invalid attribute length"); - return (NULL); - } - - /* allocate buffers for attributes */ -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - if (key_attr[i].ulValueLen > 0) - key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); - - /* retrieve ID, modulus and public exponent of RSA key */ -- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto fail; -@@ -873,8 +1011,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto fail; - } - -- rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); -- rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); -+ rsa_n = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); -+ rsa_e = BN_bin2bn(key_attr[3].pValue, key_attr[3].ulValueLen, NULL); - if (rsa_n == NULL || rsa_e == NULL) { - error("BN_bin2bn failed"); - goto fail; -@@ -883,7 +1021,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - fatal("%s: set key", __func__); - rsa_n = rsa_e = NULL; /* transferred */ - -- if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) -+ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], rsa)) - goto fail; - - key = sshkey_new(KEY_UNSPEC); -@@ -898,7 +1036,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - rsa = NULL; /* now owned by key */ - - fail: -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - free(key_attr[i].pValue); - RSA_free(rsa); - -@@ -909,7 +1047,8 @@ static struct sshkey * - pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj) - { -- CK_ATTRIBUTE cert_attr[3]; -+ CK_ATTRIBUTE cert_attr[4]; -+ int nattr = 4; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -926,14 +1065,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - - memset(&cert_attr, 0, sizeof(cert_attr)); - cert_attr[0].type = CKA_ID; -- cert_attr[1].type = CKA_SUBJECT; -- cert_attr[2].type = CKA_VALUE; -+ cert_attr[1].type = CKA_LABEL; -+ cert_attr[2].type = CKA_SUBJECT; -+ cert_attr[3].type = CKA_VALUE; - -- session = p->slotinfo[slotidx].session; -- f = p->function_list; -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - - /* figure out size of the attributes */ -- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return (NULL); -@@ -945,18 +1085,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - * XXX assumes CKA_ID is always first. - */ - if (cert_attr[1].ulValueLen == 0 || -- cert_attr[2].ulValueLen == 0) { -+ cert_attr[2].ulValueLen == 0 || -+ cert_attr[3].ulValueLen == 0) { - error("invalid attribute length"); - return (NULL); - } - - /* allocate buffers for attributes */ -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - if (cert_attr[i].ulValueLen > 0) - cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); - - /* retrieve ID, subject and value of certificate */ -- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto fail; -@@ -968,8 +1109,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto fail; - } - -- cp = cert_attr[2].pValue; -- if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) { -+ cp = cert_attr[3].pValue; -+ if (d2i_X509(&x509, &cp, cert_attr[3].ulValueLen) == NULL) { - error("d2i_x509 failed"); - goto fail; - } -@@ -990,7 +1131,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto fail; - } - -- if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) -+ if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], rsa)) - goto fail; - - key = sshkey_new(KEY_UNSPEC); -@@ -1020,7 +1161,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto fail; - } - -- if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) -+ if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], ec)) - goto fail; - - key = sshkey_new(KEY_UNSPEC); -@@ -1039,7 +1180,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - error("unknown certificate key type"); - - fail: -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - free(cert_attr[i].pValue); - X509_free(x509); - RSA_free(rsa); -@@ -1066,11 +1207,12 @@ have_rsa_key(const RSA *rsa) - */ - static int - pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, -- struct sshkey ***keysp, int *nkeys) -+ struct sshkey ***keysp, int *nkeys, struct pkcs11_uri *uri) - { - struct sshkey *key = NULL; - CK_OBJECT_CLASS key_class; -- CK_ATTRIBUTE key_attr[1]; -+ CK_ATTRIBUTE key_attr[3]; -+ int nattr = 1; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -1086,10 +1228,23 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, - 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; -+ key_attr[nattr].ulValueLen = uri->id_len; -+ nattr++; -+ } -+ if (uri->object != NULL) { -+ key_attr[nattr].type = CKA_LABEL; -+ key_attr[nattr].pValue = uri->object; -+ key_attr[nattr].ulValueLen = strlen(uri->object); -+ nattr++; -+ } - -- rv = f->C_FindObjectsInit(session, key_attr, 1); -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; -+ -+ rv = f->C_FindObjectsInit(session, key_attr, nattr); - if (rv != CKR_OK) { - error("C_FindObjectsInit failed: %lu", rv); - goto fail; -@@ -1163,11 +1318,12 @@ fail: - */ - static int - pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, -- struct sshkey ***keysp, int *nkeys) -+ struct sshkey ***keysp, int *nkeys, struct pkcs11_uri *uri) - { - struct sshkey *key = NULL; - CK_OBJECT_CLASS key_class; -- CK_ATTRIBUTE key_attr[1]; -+ CK_ATTRIBUTE key_attr[3]; -+ int nattr = 1; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -1183,10 +1339,23 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, - 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; -+ key_attr[nattr].ulValueLen = uri->id_len; -+ nattr++; -+ } -+ if (uri->object != NULL) { -+ key_attr[nattr].type = CKA_LABEL; -+ key_attr[nattr].pValue = uri->object; -+ key_attr[nattr].ulValueLen = strlen(uri->object); -+ nattr++; -+ } - -- rv = f->C_FindObjectsInit(session, key_attr, 1); -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; -+ -+ rv = f->C_FindObjectsInit(session, key_attr, nattr); - if (rv != CKR_OK) { - error("C_FindObjectsInit failed: %lu", rv); - goto fail; -@@ -1443,15 +1612,10 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, - } - #endif /* WITH_PKCS11_KEYGEN */ - --/* -- * register a new provider, fails if provider already exists. if -- * keyp is provided, fetch keys. -- */ - static int --pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, -- struct pkcs11_provider **providerp, CK_ULONG user) -+pkcs11_initialize_provider(struct pkcs11_uri *uri, struct pkcs11_provider **providerp) - { -- int nkeys, need_finalize = 0; -+ int need_finalize = 0; - int ret = -1; - struct pkcs11_provider *p = NULL; - void *handle = NULL; -@@ -1460,148 +1624,285 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, - CK_FUNCTION_LIST *f = NULL; - CK_TOKEN_INFO *token; - CK_ULONG i; -- -- if (providerp == NULL) -+ char *provider_module = NULL; -+ struct pkcs11_module *m = 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("%s: No module path provided", __func__); - goto fail; -- *providerp = NULL; -- -- if (keyp != NULL) -- *keyp = NULL; -+#endif -+ } else { -+ provider_module = strdup(uri->module_path); -+ } - -- if (pkcs11_provider_lookup(provider_id) != NULL) { -- debug("%s: provider already registered: %s", -- __func__, provider_id); -- goto fail; -+ p = xcalloc(1, sizeof(*p)); -+ p->name = pkcs11_uri_get(uri); -+ -+ if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL -+ && m->valid) { -+ debug("%s: provider module already initialized: %s", -+ __func__, provider_module); -+ free(provider_module); -+ /* Skip the initialization of PKCS#11 module */ -+ m->refcount++; -+ p->module = m; -+ p->valid = 1; -+ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -+ p->refcount++; /* add to provider list */ -+ *providerp = p; -+ return 0; -+ } else { -+ m = xcalloc(1, sizeof(*m)); -+ 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()); -+ if ((handle = dlopen(provider_module, RTLD_NOW)) == NULL) { -+ error("dlopen %s failed: %s", provider_module, dlerror()); - goto fail; - } - if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) { - error("dlsym(C_GetFunctionList) failed: %s", dlerror()); - goto fail; - } -- 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) { - error("C_GetFunctionList for provider %s failed: %lu", -- provider_id, rv); -+ provider_module, rv); - goto fail; - } -- p->function_list = f; -+ m->function_list = f; - if ((rv = f->C_Initialize(NULL)) != CKR_OK) { - error("C_Initialize for provider %s failed: %lu", -- provider_id, rv); -+ provider_module, rv); - goto fail; - } - need_finalize = 1; -- if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) { -+ if ((rv = f->C_GetInfo(&m->info)) != CKR_OK) { - error("C_GetInfo for provider %s failed: %lu", -- provider_id, rv); -+ provider_module, rv); - goto fail; - } -- rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID)); -- rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription)); -+ rmspace(m->info.manufacturerID, sizeof(m->info.manufacturerID)); -+ if (uri->lib_manuf != NULL && -+ strcmp(uri->lib_manuf, m->info.manufacturerID)) { -+ debug("%s: Skipping provider %s not matching library_manufacturer", -+ __func__, m->info.manufacturerID); -+ goto fail; -+ } -+ rmspace(m->info.libraryDescription, sizeof(m->info.libraryDescription)); - debug("provider %s: manufacturerID <%s> cryptokiVersion %d.%d" - " libraryDescription <%s> libraryVersion %d.%d", -- provider_id, -- p->info.manufacturerID, -- p->info.cryptokiVersion.major, -- p->info.cryptokiVersion.minor, -- p->info.libraryDescription, -- p->info.libraryVersion.major, -- p->info.libraryVersion.minor); -- if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { -+ provider_module, -+ m->info.manufacturerID, -+ m->info.cryptokiVersion.major, -+ m->info.cryptokiVersion.minor, -+ m->info.libraryDescription, -+ m->info.libraryVersion.major, -+ m->info.libraryVersion.minor); -+ -+ if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &m->nslots)) != CKR_OK) { - error("C_GetSlotList failed: %lu", rv); - goto fail; - } -- if (p->nslots == 0) { -+ if (m->nslots == 0) { -- error("%s: provider %s returned no slots", __func__, -+ debug("%s: provider %s returned no slots", __func__, -- provider_id); -+ provider_module); - ret = -SSH_PKCS11_ERR_NO_SLOTS; - goto fail; - } -- p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); -- if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots)) -+ m->slotlist = xcalloc(m->nslots, sizeof(CK_SLOT_ID)); -+ if ((rv = f->C_GetSlotList(CK_TRUE, m->slotlist, &m->nslots)) - != CKR_OK) { - error("C_GetSlotList for provider %s failed: %lu", -- provider_id, rv); -+ provider_module, rv); - goto fail; - } -- p->slotinfo = xcalloc(p->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; -+ if ((rv = f->C_GetTokenInfo(m->slotlist[i], token)) - != CKR_OK) { - error("C_GetTokenInfo for provider %s slot %lu " -- "failed: %lu", provider_id, (unsigned long)i, rv); -+ "failed: %lu", provider_module, (unsigned long)i, rv); -+ 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)); -+ } -+ m->module_path = provider_module; -+ provider_module = NULL; -+ -+ /* insert unconditionally -- remove if there will be no keys later */ -+ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -+ p->refcount++; /* add to provider list */ -+ *providerp = p; -+ return 0; -+ -+fail: -+ if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) -+ error("C_Finalize for provider %s failed: %lu", -+ provider_module, rv); -+ free(provider_module); -+ if (m) { -+ free(m->slotlist); -+ free(m); -+ } -+ if (p) { -+ free(p->name); -+ free(p); -+ } -+ if (handle) -+ dlclose(handle); -+ return ret; -+} -+ -+/* -+ * register a new provider, fails if provider already exists. if -+ * keyp is provided, fetch keys. -+ */ -+static int -+pkcs11_register_provider_by_uri(struct pkcs11_uri *uri, char *pin, -+ struct sshkey ***keyp, struct pkcs11_provider **providerp, CK_ULONG user) -+{ -+ int nkeys; -+ int ret = -1; -+ struct pkcs11_provider *p = NULL; -+ CK_ULONG i; -+ CK_TOKEN_INFO *token; -+ char *provider_uri = NULL; -+ -+ if (providerp == NULL) -+ goto fail; -+ *providerp = NULL; -+ -+ if (keyp != NULL) -+ *keyp = NULL; -+ -+ if ((ret = pkcs11_initialize_provider(uri, &p)) != 0) { -+ goto fail; -+ } -+ -+ provider_uri = pkcs11_uri_get(uri); -+ if (pin == NULL && uri->pin != NULL) { -+ pin = uri->pin; -+ } -+ nkeys = 0; -+ for (i = 0; i < p->module->nslots; i++) { -+ token = &p->module->slotinfo[i].token; - if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { - debug2("%s: ignoring uninitialised token in " - "provider %s slot %lu", __func__, -- provider_id, (unsigned long)i); -+ provider_uri, (unsigned long)i); -+ continue; -+ } -+ if (uri->token != NULL && -+ strcmp(token->label, uri->token) != 0) { -+ debug2("%s: ignoring token not matching label (%s) " -+ "specified by PKCS#11 URI in slot %lu", __func__, -+ token->label, (unsigned long)i); -+ continue; -+ } -+ if (uri->manuf != NULL && -+ strcmp(token->manufacturerID, uri->manuf) != 0) { -+ debug2("%s: ignoring token not matching requrested " -+ "manufacturerID (%s) specified by PKCS#11 URI in " -+ "slot %lu", __func__, -+ token->manufacturerID, (unsigned long)i); - 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", -- provider_id, (unsigned long)i, -+ provider_uri, (unsigned long)i, - 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 -+ * retrieve public keys (if keyp is provided) - */ -- if ((ret = pkcs11_open_session(p, i, pin, user)) == 0) { -+ if (p->module->slotinfo[i].session != 0 || -+ (ret = pkcs11_open_session(p, i, pin, user)) == 0) { - if (keyp == NULL) - continue; -- pkcs11_fetch_keys(p, i, keyp, &nkeys); -- pkcs11_fetch_certs(p, i, keyp, &nkeys); -+ pkcs11_fetch_keys(p, i, keyp, &nkeys, uri); -+ pkcs11_fetch_certs(p, i, keyp, &nkeys, uri); -+ if (nkeys == 0 && uri->object != NULL) { -+ debug3("%s: No keys found. Retrying without label (%s) ", -+ __func__, token->label); -+ /* Try once more without the label filter */ -+ char *label = uri->object; -+ uri->object = NULL; /* XXX clone uri? */ -+ pkcs11_fetch_keys(p, i, keyp, &nkeys, uri); -+ pkcs11_fetch_certs(p, i, keyp, &nkeys, uri); -+ uri->object = label; -+ } - } - } -+ pin = NULL; /* Will be cleaned up with URI */ - - /* now owned by caller */ - *providerp = p; - -- 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) -- error("C_Finalize for provider %s failed: %lu", -- provider_id, rv); - if (p) { -- free(p->name); -- free(p->slotlist); -- free(p->slotinfo); -- free(p); -+ TAILQ_REMOVE(&pkcs11_providers, p, next); -+ pkcs11_provider_unref(p); - } -- if (handle) -- dlclose(handle); - return (ret); - } - --/* -- * register a new provider and get number of keys hold by the token, -- * fails if provider already exists -- */ -+static int -+pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, -+ struct pkcs11_provider **providerp, CK_ULONG user) -+{ -+ struct pkcs11_uri *uri = NULL; -+ int r; -+ -+ debug("%s: called, provider_id = %s", __func__, provider_id); -+ -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("failed to init PKCS#11 URI"); -+ -+ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { -+ if (pkcs11_uri_parse(provider_id, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI"); -+ } else { -+ uri->module_path = strdup(provider_id); -+ } -+ -+ r = pkcs11_register_provider_by_uri(uri, pin, keyp, providerp, user); -+ pkcs11_uri_cleanup(uri); -+ -+ return r; -+} -+ - int --pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) -+pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin, -+ struct sshkey ***keyp) - { -- struct pkcs11_provider *p = NULL; - int nkeys; -+ struct pkcs11_provider *p = NULL; -+ char *provider_uri = pkcs11_uri_get(uri); - -- nkeys = pkcs11_register_provider(provider_id, pin, keyp, &p, CKU_USER); -+ debug("%s: called, provider_uri = %s", __func__, provider_uri); -+ -+ nkeys = pkcs11_register_provider_by_uri(uri, pin, keyp, &p, CKU_USER); - - /* no keys found or some other error, de-register provider */ - if (nkeys <= 0 && p != NULL) { -@@ -1611,7 +1912,36 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) - } - if (nkeys == 0) - debug("%s: provider %s returned no keys", __func__, -- provider_id); -+ provider_uri); -+ -+ free(provider_uri); -+ return nkeys; -+} -+ -+/* -+ * register a new provider and get number of keys hold by the token, -+ * fails if provider already exists -+ */ -+int -+pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) -+{ -+ struct pkcs11_uri *uri; -+ int nkeys; -+ -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PCKS#11 URI"); -+ -+ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { -+ if (pkcs11_uri_parse(provider_id, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI"); -+ } else { -+ uri->module_path = strdup(provider_id); -+ } -+ -+ nkeys = pkcs11_add_provider_by_uri(uri, pin, keyp); -+ pkcs11_uri_cleanup(uri); - - return (nkeys); - } -@@ -1633,8 +1963,7 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, - - if ((p = pkcs11_provider_lookup(provider_id)) != NULL) - debug("%s: provider \"%s\" available", __func__, provider_id); -- else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, &p, -- CKU_SO)) < 0) { -+ else if ((rv = pkcs11_register_provider(provider_id, pin, NULL, &p, CKU_SO)) != 0) { - debug("%s: could not register provider %s", __func__, - provider_id); - goto out; -@@ -1705,8 +2034,7 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, - - if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { - debug("%s: using provider \"%s\"", __func__, provider_id); -- } else if (pkcs11_register_provider(provider_id, pin, NULL, &p, -- CKU_SO) < 0) { -+ } else if ((rv = pkcs11_register_provider(provider_id, pin, NULL, &p, CKU_SO)) != 0) { - debug("%s: could not register provider %s", __func__, - provider_id); - goto out; -diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h -index b9038450..5a855338 100644 ---- a/ssh-pkcs11.h -+++ b/ssh-pkcs11.h -@@ -22,10 +22,14 @@ - #define SSH_PKCS11_ERR_PIN_REQUIRED 4 - #define SSH_PKCS11_ERR_PIN_LOCKED 5 - -+#include "ssh-pkcs11-uri.h" -+ - int pkcs11_init(int); - void pkcs11_terminate(void); - int pkcs11_add_provider(char *, char *, struct sshkey ***); -+int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***); - int pkcs11_del_provider(char *); -+int pkcs11_uri_write(const struct sshkey *, FILE *); - #ifdef WITH_PKCS11_KEYGEN - struct sshkey * - pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, -diff --git a/ssh.c b/ssh.c -index 91e7c351..47f4f299 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -772,6 +772,14 @@ main(int ac, char **av) - options.gss_deleg_creds = 1; - break; - case 'i': -+#ifdef ENABLE_PKCS11 -+ if (strlen(optarg) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(optarg, PKCS11_URI_SCHEME, -+ strlen(PKCS11_URI_SCHEME)) == 0) { -+ add_identity_file(&options, NULL, optarg, 1); -+ break; -+ } -+#endif - p = tilde_expand_filename(optarg, getuid()); - if (stat(p, &st) < 0) - fprintf(stderr, "Warning: Identity file %s " -@@ -1521,6 +1529,7 @@ main(int ac, char **av) - free(options.certificate_files[i]); - options.certificate_files[i] = NULL; - } -+ pkcs11_terminate(); - - skip_connect: - exit_status = ssh_session2(ssh, pw); -@@ -1994,6 +2003,45 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) - options.escape_char : SSH_ESCAPECHAR_NONE, id); - } - -+#ifdef ENABLE_PKCS11 -+static void -+load_pkcs11_identity(char *pkcs11_uri, char *identity_files[], -+ struct sshkey *identity_keys[], int *n_ids) -+{ -+ int nkeys, i; -+ struct sshkey **keys; -+ struct pkcs11_uri *uri; -+ -+ debug("identity file '%s' from pkcs#11", pkcs11_uri); -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PCKS#11 URI"); -+ -+ if (pkcs11_uri_parse(pkcs11_uri, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri); -+ -+ /* we need to merge URI and provider together */ -+ if (options.pkcs11_provider != NULL && uri->module_path == NULL) -+ uri->module_path = strdup(options.pkcs11_provider); -+ -+ if (options.num_identity_files < SSH_MAX_IDENTITY_FILES && -+ (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys)) > 0) { -+ for (i = 0; i < nkeys; i++) { -+ if (*n_ids >= SSH_MAX_IDENTITY_FILES) { -+ sshkey_free(keys[i]); -+ continue; -+ } -+ identity_keys[*n_ids] = keys[i]; -+ identity_files[*n_ids] = pkcs11_uri_get(uri); -+ (*n_ids)++; -+ } -+ free(keys); -+ } -+ -+ pkcs11_uri_cleanup(uri); -+} -+#endif /* ENABLE_PKCS11 */ -+ - /* Loads all IdentityFile and CertificateFile keys */ - static void - load_public_identity_files(struct passwd *pw) -@@ -2008,10 +2056,6 @@ load_public_identity_files(struct passwd *pw) - char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; - struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; - int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; --#ifdef ENABLE_PKCS11 -- struct sshkey **keys; -- int nkeys; --#endif /* PKCS11 */ - - n_ids = n_certs = 0; - memset(identity_files, 0, sizeof(identity_files)); -@@ -2024,32 +2068,46 @@ load_public_identity_files(struct passwd *pw) - sizeof(certificate_file_userprovided)); - - #ifdef ENABLE_PKCS11 -- if (options.pkcs11_provider != NULL && -- options.num_identity_files < SSH_MAX_IDENTITY_FILES && -- (pkcs11_init(!options.batch_mode) == 0) && -- (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, -- &keys)) > 0) { -- for (i = 0; i < nkeys; i++) { -- if (n_ids >= SSH_MAX_IDENTITY_FILES) { -- sshkey_free(keys[i]); -- continue; -- } -- identity_keys[n_ids] = keys[i]; -- identity_files[n_ids] = -- xstrdup(options.pkcs11_provider); /* XXX */ -- n_ids++; -- } -- free(keys); -+ /* handle fallback from PKCS11Provider option */ -+ pkcs11_init(!options.batch_mode); -+ -+ if (options.pkcs11_provider != NULL) { -+ struct pkcs11_uri *uri; -+ -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PCKS#11 URI"); -+ -+ /* Construct simple PKCS#11 URI to simplify access */ -+ uri->module_path = strdup(options.pkcs11_provider); -+ -+ /* Add it as any other IdentityFile */ -+ cp = pkcs11_uri_get(uri); -+ add_identity_file(&options, NULL, cp, 1); -+ free(cp); -+ -+ pkcs11_uri_cleanup(uri); - } - #endif /* ENABLE_PKCS11 */ - for (i = 0; i < options.num_identity_files; i++) { -+ char *name = options.identity_files[i]; - if (n_ids >= SSH_MAX_IDENTITY_FILES || -- strcasecmp(options.identity_files[i], "none") == 0) { -+ strcasecmp(name, "none") == 0) { - free(options.identity_files[i]); - options.identity_files[i] = NULL; - continue; - } -- cp = tilde_expand_filename(options.identity_files[i], getuid()); -+#ifdef ENABLE_PKCS11 -+ if (strlen(name) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(name, PKCS11_URI_SCHEME, -+ strlen(PKCS11_URI_SCHEME)) == 0) { -+ load_pkcs11_identity(name, identity_files, -+ identity_keys, &n_ids); -+ free(options.identity_files[i]); -+ continue; -+ } -+#endif /* ENABLE_PKCS11 */ -+ cp = tilde_expand_filename(name, getuid()); - filename = percent_expand(cp, "d", pw->pw_dir, - "u", pw->pw_name, "l", thishost, "h", host, - "r", options.user, (char *)NULL); -diff --git a/ssh_config.5 b/ssh_config.5 -index 41262963..a211034e 100644 ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -952,6 +952,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. -commit 1efe98998408593861fdcd4da392dd10820f0fde -Author: Jakub Jelen -Date: Wed Jun 12 14:30:30 2019 +0200 - - Allow to specify the pin also for the ssh-add - -diff --git a/ssh-add.c b/ssh-add.c -index f039e00e..adc4e5c9 100644 ---- a/ssh-add.c -+++ b/ssh-add.c -@@ -190,20 +190,28 @@ delete_all(int agent_fd, int qflag) - } - - #ifdef ENABLE_PKCS11 --static int update_card(int, int, const char *, int); -+static int update_card(int, int, const char *, int, char *); - - int - update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag) - { -+ char *pin = NULL; - struct pkcs11_uri *uri; - - /* dry-run parse to make sure the URI is valid and to report errors */ - uri = pkcs11_uri_init(); - if (pkcs11_uri_parse((char *) pkcs11_uri, uri) != 0) - fatal("Failed to parse PKCS#11 URI"); -+ if (uri->pin != NULL) { -+ pin = strdup(uri->pin); -+ if (pin == NULL) { -+ fatal("Failed to dupplicate string"); -+ } -+ /* pin is freed in the update_card() */ -+ } - pkcs11_uri_cleanup(uri); - -- return update_card(agent_fd, adding, pkcs11_uri, qflag); -+ return update_card(agent_fd, adding, pkcs11_uri, qflag, pin); - } - #endif - -@@ -409,12 +417,11 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag) - } - - static int --update_card(int agent_fd, int add, const char *id, int qflag) -+update_card(int agent_fd, int add, const char *id, int qflag, char *pin) - { -- char *pin = NULL; - int r, ret = -1; - -- if (add) { -+ if (add && pin == NULL) { - if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", - RP_ALLOW_STDIN)) == NULL) - return -1; -@@ -734,7 +741,7 @@ main(int argc, char **argv) - } - if (pkcs11provider != NULL) { - if (update_card(agent_fd, !deleting, pkcs11provider, -- qflag) == -1) -+ qflag, NULL) == -1) - ret = 1; - goto done; - } diff --git a/SOURCES/openssh-8.0p1-preserve-pam-errors.patch b/openssh-8.0p1-preserve-pam-errors.patch similarity index 95% rename from SOURCES/openssh-8.0p1-preserve-pam-errors.patch rename to openssh-8.0p1-preserve-pam-errors.patch index dbdbe93..b7ab965 100644 --- a/SOURCES/openssh-8.0p1-preserve-pam-errors.patch +++ b/openssh-8.0p1-preserve-pam-errors.patch @@ -27,16 +27,15 @@ diff -up openssh-8.0p1/auth-pam.c.preserve-pam-errors openssh-8.0p1/auth-pam.c else if (sshpam_maxtries_reached) ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer); else -@@ -856,10 +862,12 @@ sshpam_query(void *ctx, char **name, cha - plen++; +@@ -856,9 +862,11 @@ sshpam_query(void *ctx, char **name, cha free(msg); break; -+ case PAM_USER_UNKNOWN: -+ case PAM_PERM_DENIED: case PAM_ACCT_EXPIRED: + sshpam_account_status = 0; + /* FALLTHROUGH */ case PAM_MAXTRIES: ++ case PAM_USER_UNKNOWN: ++ case PAM_PERM_DENIED: - if (type == PAM_ACCT_EXPIRED) - sshpam_account_status = 0; if (type == PAM_MAXTRIES) diff --git a/openssh-8.2p1-visibility.patch b/openssh-8.2p1-visibility.patch new file mode 100644 index 0000000..89c35ef --- /dev/null +++ b/openssh-8.2p1-visibility.patch @@ -0,0 +1,40 @@ +diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c +index dca158de..afdcb1d2 100644 +--- a/regress/misc/sk-dummy/sk-dummy.c ++++ b/regress/misc/sk-dummy/sk-dummy.c +@@ -71,7 +71,7 @@ skdebug(const char *func, const char *fmt, ...) + #endif + } + +-uint32_t ++uint32_t __attribute__((visibility("default"))) + sk_api_version(void) + { + return SSH_SK_VERSION_MAJOR; +@@ -220,7 +220,7 @@ check_options(struct sk_option **options) + return 0; + } + +-int ++int __attribute__((visibility("default"))) + sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, + const char *application, uint8_t flags, const char *pin, + struct sk_option **options, struct sk_enroll_response **enroll_response) +@@ -467,7 +467,7 @@ sig_ed25519(const uint8_t *message, size_t message_len, + return ret; + } + +-int ++int __attribute__((visibility("default"))) + sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, + const char *application, const uint8_t *key_handle, size_t key_handle_len, + uint8_t flags, const char *pin, struct sk_option **options, +@@ -518,7 +518,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len, + return ret; + } + +-int ++int __attribute__((visibility("default"))) + sk_load_resident_keys(const char *pin, struct sk_option **options, + struct sk_resident_key ***rks, size_t *nrks) + { diff --git a/SOURCES/openssh-8.0p1-x11-without-ipv6.patch b/openssh-8.2p1-x11-without-ipv6.patch similarity index 83% rename from SOURCES/openssh-8.0p1-x11-without-ipv6.patch rename to openssh-8.2p1-x11-without-ipv6.patch index 0623b47..8b83bc3 100644 --- a/SOURCES/openssh-8.0p1-x11-without-ipv6.patch +++ b/openssh-8.2p1-x11-without-ipv6.patch @@ -6,9 +6,9 @@ diff --git a/channels.c b/channels.c sock_set_v6only(sock); if (x11_use_localhost) set_reuseaddr(sock); - if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { - debug2("%s: bind port %d: %.100s", __func__, - port, strerror(errno)); + if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { + debug2_f("bind port %d: %.100s", port, + strerror(errno)); close(sock); + + /* do not remove successfully opened diff --git a/openssh-8.7p1-audit-hostname.patch b/openssh-8.7p1-audit-hostname.patch new file mode 100644 index 0000000..e450c00 --- /dev/null +++ b/openssh-8.7p1-audit-hostname.patch @@ -0,0 +1,106 @@ +diff --color -ruNp a/audit-linux.c b/audit-linux.c +--- a/audit-linux.c 2024-05-09 12:38:08.843017319 +0200 ++++ b/audit-linux.c 2024-05-09 12:47:05.162267634 +0200 +@@ -52,7 +52,7 @@ extern u_int utmp_len; + const char *audit_username(void); + + static void +-linux_audit_user_logxxx(int uid, const char *username, ++linux_audit_user_logxxx(int uid, const char *username, const char *hostname, + const char *ip, const char *ttyn, int success, int event) + { + int audit_fd, rc, saved_errno; +@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const c + } + rc = audit_log_acct_message(audit_fd, event, + NULL, "login", username ? username : "(unknown)", +- username == NULL ? uid : -1, NULL, ip, ttyn, success); ++ username == NULL ? uid : -1, hostname, ip, ttyn, success); + saved_errno = errno; + close(audit_fd); + +@@ -181,9 +181,11 @@ audit_run_command(struct ssh *ssh, const + { + if (!user_login_count++) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGIN); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_START); + return 0; +@@ -193,10 +195,12 @@ void + audit_end_command(struct ssh *ssh, int handle, const char *command) + { + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); + } +@@ -211,19 +215,27 @@ void + audit_session_open(struct logininfo *li) + { + if (!user_login_count++) +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_LOGIN); +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_START); + } + + void + audit_session_close(struct logininfo *li) + { +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_LOGOUT); + } + +@@ -236,6 +248,7 @@ audit_event(struct ssh *ssh, ssh_audit_e + linux_audit_user_auth(-1, audit_username(), + ssh_remote_ipaddr(ssh), "ssh", 0, event); + linux_audit_user_logxxx(-1, audit_username(), ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + case SSH_AUTH_FAIL_PASSWD: +@@ -254,9 +267,11 @@ audit_event(struct ssh *ssh, ssh_audit_e + if (user_login_count) { + while (user_login_count--) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); + } +@@ -265,6 +280,7 @@ audit_event(struct ssh *ssh, ssh_audit_e + case SSH_CONNECTION_ABANDON: + case SSH_INVALID_USER: + linux_audit_user_logxxx(-1, audit_username(), ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + default: diff --git a/openssh-8.7p1-ibmca.patch b/openssh-8.7p1-ibmca.patch new file mode 100644 index 0000000..88914bf --- /dev/null +++ b/openssh-8.7p1-ibmca.patch @@ -0,0 +1,11 @@ +--- openssh-8.7p1/openbsd-compat/bsd-closefrom.c.orig 2022-04-12 15:47:03.815044607 +0200 ++++ openssh-8.7p1/openbsd-compat/bsd-closefrom.c 2022-04-12 15:48:12.464963511 +0200 +@@ -16,7 +16,7 @@ + + #include "includes.h" + +-#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) ++#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) || (defined __s390__) + + #include + #include diff --git a/openssh-8.7p1-minrsabits.patch b/openssh-8.7p1-minrsabits.patch new file mode 100644 index 0000000..d8577d2 --- /dev/null +++ b/openssh-8.7p1-minrsabits.patch @@ -0,0 +1,22 @@ +diff --git a/readconf.c b/readconf.c +--- a/readconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/readconf.c (date 1703169891147) +@@ -326,6 +326,7 @@ + { "securitykeyprovider", oSecurityKeyProvider }, + { "knownhostscommand", oKnownHostsCommand }, + { "requiredrsasize", oRequiredRSASize }, ++ { "rsaminsize", oRequiredRSASize }, /* alias */ + { "enableescapecommandline", oEnableEscapeCommandline }, + { "obscurekeystroketiming", oObscureKeystrokeTiming }, + { "channeltimeout", oChannelTimeout }, +diff --git a/servconf.c b/servconf.c +--- 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 }, ++ { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */ + { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, + { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, + { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, diff --git a/openssh-8.7p1-negotiate-supported-algs.patch b/openssh-8.7p1-negotiate-supported-algs.patch new file mode 100644 index 0000000..c4d86e7 --- /dev/null +++ b/openssh-8.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 @@ ssh_kex2(struct ssh *ssh, char *host, st + const struct ssh_conn_info *cinfo) + { + char *myproposal[PROPOSAL_MAX]; +- char *all_key, *hkalgs = NULL; ++ char *all_key, *hkalgs = NULL, *filtered_algs = NULL; + int r, use_known_hosts_order = 0; + + #if defined(GSSAPI) && defined(WITH_OPENSSL) +@@ -260,10 +260,22 @@ ssh_kex2(struct ssh *ssh, char *host, st + 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) { +@@ -303,6 +315,7 @@ ssh_kex2(struct ssh *ssh, char *host, st + #endif + + free(hkalgs); ++ free(filtered_algs); + + /* start key exchange */ + if ((r = kex_setup(ssh, myproposal)) != 0) diff --git a/openssh-8.7p1-nohostsha1proof.patch b/openssh-8.7p1-nohostsha1proof.patch new file mode 100644 index 0000000..abc6aa4 --- /dev/null +++ b/openssh-8.7p1-nohostsha1proof.patch @@ -0,0 +1,338 @@ +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 +@@ -43,6 +43,7 @@ void + compat_banner(struct ssh *ssh, const char *version) + { + int i; ++ int forbid_ssh_rsa = 0; + static struct { + char *pat; + int bugs; +@@ -145,16 +146,21 @@ compat_banner(struct ssh *ssh, const cha + }; + + /* process table, return first match */ ++ forbid_ssh_rsa = (ssh->compat & SSH_RH_RSASIGSHA); + ssh->compat = 0; + for (i = 0; check[i].pat; i++) { + if (match_pattern_list(version, check[i].pat, 0) == 1) { + debug_f("match: %s pat %s compat 0x%08x", + version, check[i].pat, check[i].bugs); + ssh->compat = check[i].bugs; ++ if (forbid_ssh_rsa) ++ ssh->compat |= SSH_RH_RSASIGSHA; + return; + } + } + debug_f("no match: %s", version); ++ if (forbid_ssh_rsa) ++ ssh->compat |= SSH_RH_RSASIGSHA; + } + + /* 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 +@@ -30,7 +30,7 @@ + #define SSH_BUG_UTF8TTYMODE 0x00000001 + #define SSH_BUG_SIGTYPE 0x00000002 + #define SSH_BUG_SIGTYPE74 0x00000004 +-/* #define unused 0x00000008 */ ++#define SSH_RH_RSASIGSHA 0x00000008 + #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 +@@ -660,11 +660,12 @@ mm_answer_sign(struct ssh *ssh, int sock + struct sshkey *key; + struct sshbuf *sigbuf = NULL; + u_char *p = NULL, *signature = NULL; +- char *alg = NULL; ++ char *alg = NULL, *effective_alg; + size_t datlen, siglen, alglen; + int r, is_proof = 0; + u_int keyid, compat; + const char proof_req[] = "hostkeys-prove-00@openssh.com"; ++ const char safe_rsa[] = "rsa-sha2-256"; + + debug3_f("entering"); + +@@ -719,18 +720,30 @@ mm_answer_sign(struct ssh *ssh, int sock + } + + if ((key = get_hostkey_by_index(keyid)) != NULL) { +- if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, ++ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0 ++ && (sshkey_type_plain(key->type) == KEY_RSA)) { ++ effective_alg = safe_rsa; ++ } else { ++ effective_alg = alg; ++ } ++ if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, effective_alg, + options.sk_provider, NULL, compat)) != 0) + fatal_fr(r, "sign"); + } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && + auth_sock > 0) { ++ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0 ++ && (sshkey_type_plain(key->type) == KEY_RSA)) { ++ effective_alg = safe_rsa; ++ } else { ++ effective_alg = alg; ++ } + if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, +- p, datlen, alg, compat)) != 0) ++ p, datlen, effective_alg, compat)) != 0) + fatal_fr(r, "agent sign"); + } else + fatal_f("no hostkey from index %d", keyid); + +- debug3_f("%s %s signature len=%zu", alg, ++ debug3_f("%s (effective: %s) %s signature len=%zu", alg, effective_alg, + 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 +@@ -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 + +-PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` ++#ssh-dss keys are incompatible with DEFAULT crypto policy ++PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss' | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` + 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 +@@ -2,7 +2,8 @@ + + tests: prep file-tests t-exec unit + +-REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 ++#ssh-dss tests will not pass on DEFAULT crypto-policy because of SHA1, skipping ++REGRESS_TARGETS= t1 t2 t3 t4 t5 t7 t8 t9 t10 t11 t12 + + # 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 +@@ -581,8 +581,9 @@ maybe_filter_sk() { + fi + } + +-SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk` +-SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk` ++#ssh-dss keys are incompatible with DEFAULT crypto policy ++SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'` ++SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'` + + 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, + memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); + if (kex != NULL) + kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; +- keyname = strdup(sshkey_ssh_name(private)); ++ keyname = (strcmp(sshkey_ssh_name(private), "ssh-rsa")) ? ++ strdup(sshkey_ssh_name(private)) : strdup("rsa-sha2-256"); + ASSERT_PTR_NE(keyname, NULL); + kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; + ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); +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 +@@ -110,6 +110,7 @@ sshkey_file_tests(void) + sshkey_free(k2); + TEST_DONE(); + ++ /* Skip this test, SHA1 signatures are not supported + TEST_START("load RSA cert with SHA1 signature"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); +@@ -117,7 +118,7 @@ sshkey_file_tests(void) + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa"); + sshkey_free(k2); +- TEST_DONE(); ++ TEST_DONE(); */ + + 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) + TEST_DONE(); + + #ifdef WITH_OPENSSL ++ /* Skip this test, SHA1 signatures are not supported + TEST_START("fuzz RSA sig"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, "ssh-rsa"); + sshkey_free(k1); +- TEST_DONE(); ++ TEST_DONE();*/ + + TEST_START("fuzz RSA SHA256 sig"); + buf = load_file("rsa_1"); +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 +@@ -60,6 +60,9 @@ build_cert(struct sshbuf *b, struct sshk + u_char *sigblob; + size_t siglen; + ++ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */ ++ int expected = (sig_alg == NULL || strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0; ++ + ca_buf = sshbuf_new(); + ASSERT_PTR_NE(ca_buf, NULL); + ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0); +@@ -101,8 +104,9 @@ build_cert(struct sshbuf *b, struct sshk + ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ + ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, +- sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0); +- ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ ++ sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), expected); ++ if (expected == 0) ++ ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ + + free(sigblob); + sshbuf_free(ca_buf); +@@ -119,16 +123,22 @@ signature_test(struct sshkey *k, struct + { + size_t len; + u_char *sig; ++ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp in RHEL, permitted in Fedora */ ++ int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0) : 0; ++ if (k && (sshkey_type_plain(k->type) == KEY_DSA || sshkey_type_plain(k->type) == KEY_DSA_CERT)) ++ expected = sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0); + + ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, +- NULL, NULL, 0), 0); +- ASSERT_SIZE_T_GT(len, 8); +- ASSERT_PTR_NE(sig, NULL); +- ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); +- ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); +- /* Fuzz test is more comprehensive, this is just a smoke test */ +- sig[len - 5] ^= 0x10; +- ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ NULL, NULL, 0), expected); ++ if (expected == 0) { ++ ASSERT_SIZE_T_GT(len, 8); ++ ASSERT_PTR_NE(sig, NULL); ++ ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); ++ /* Fuzz test is more comprehensive, this is just a smoke test */ ++ sig[len - 5] ^= 0x10; ++ ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ } + free(sig); + } + +@@ -514,7 +524,7 @@ sshkey_tests(void) + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, + NULL), 0); + k3 = get_private("rsa_1"); +- build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, NULL); ++ build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, "rsa-sha2-256"); + 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/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 +@@ -80,6 +80,7 @@ + #include "auth-options.h" + #include "serverloop.h" + #include "ssherr.h" ++#include "compat.h" + + extern ServerOptions options; + +@@ -737,6 +737,10 @@ server_input_hostkeys_prove(struct ssh * + else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) + sigalg = "rsa-sha2-256"; + } ++ if (ssh->compat & SSH_RH_RSASIGSHA && sigalg == NULL) { ++ sigalg = "rsa-sha2-512"; ++ debug3_f("SHA1 signature is not supported, falling back to %s", sigalg); ++ } + 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 +@@ -1461,6 +1464,14 @@ identity_sign(struct identity *id, u_cha + retried = 1; + goto retry_pin; + } ++ if ((r == SSH_ERR_LIBCRYPTO_ERROR) && strcmp("ssh-rsa", alg)) { ++ char rsa_safe_alg[] = "rsa-sha2-512"; ++ debug3_f("trying to fallback to algorithm %s", rsa_safe_alg); ++ ++ if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, ++ rsa_safe_alg, options.sk_provider, pin, compat)) != 0) ++ debug_fr(r, "sshkey_sign - RSA fallback"); ++ } + goto out; + } + +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 +@@ -254,7 +254,8 @@ ssh_rsa_verify(const struct sshkey *key, + ret = SSH_ERR_INVALID_ARGUMENT; + goto out; + } +- if (hash_alg != want_alg) { ++ if (hash_alg != want_alg && want_alg != SSH_DIGEST_SHA1) { ++ debug_f("Unexpected digest algorithm: got %d, wanted %d", hash_alg, want_alg); + ret = SSH_ERR_SIGNATURE_INVALID; + goto out; + } +diff -up openssh-9.8p1/sshd-session.c.xxx openssh-9.8p1/sshd-session.c +--- openssh-9.8p1/sshd-session.c.xxx 2024-07-23 15:08:14.794350818 +0200 ++++ openssh-9.8p1/sshd-session.c 2024-07-23 15:40:21.658456636 +0200 +@@ -1305,6 +1305,27 @@ main(int ac, char **av) + + check_ip_options(ssh); + ++ { ++ struct sshkey *rsakey = NULL; ++ rsakey = get_hostkey_private_by_type(KEY_RSA, 0, ssh); ++ if (rsakey == NULL) ++ rsakey = get_hostkey_private_by_type(KEY_RSA_CERT, 0, ssh); ++ ++ if (rsakey != NULL) { ++ size_t sign_size = 0; ++ u_char *tmp = NULL; ++ u_char data[] = "Test SHA1 vector"; ++ int res; ++ ++ res = sshkey_sign(rsakey, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0); ++ free(tmp); ++ if (res == SSH_ERR_LIBCRYPTO_ERROR) { ++ verbose_f("SHA1 in signatures is disabled for RSA keys"); ++ ssh->compat |= SSH_RH_RSASIGSHA; ++ } ++ } ++ } ++ + /* Prepare the channels layer */ + channel_init_channels(ssh); + channel_set_af(ssh, options.address_family); diff --git a/openssh-8.7p1-recursive-scp.patch b/openssh-8.7p1-recursive-scp.patch new file mode 100644 index 0000000..17c340e --- /dev/null +++ b/openssh-8.7p1-recursive-scp.patch @@ -0,0 +1,182 @@ +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 (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 --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 * +-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; +@@ -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"); +- error("%s %s: %s", expand ? "expand" : "realpath", +- path, *errmsg == '\0' ? fx2txt(status) : errmsg); +- free(errmsg); +- sshbuf_free(msg); +- return NULL; ++ if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) { ++ memset(&a, '\0', sizeof(a)); ++ if ((r = sftp_mkdir(conn, path, &a, 0)) != 0) { ++ sshbuf_free(msg); ++ return NULL; ++ } ++ debug2("Sending SSH2_FXP_REALPATH \"%s\" - create dir", path); ++ send_string_request(conn, id, SSH2_FXP_REALPATH, ++ path, strlen(path)); ++ ++ get_msg(conn, msg); ++ if ((r = sshbuf_get_u8(msg, &type)) != 0 || ++ (r = sshbuf_get_u32(msg, &id)) != 0) ++ fatal_fr(r, "parse"); ++ ++ if (id != expected_id) ++ fatal("ID mismatch (%u != %u)", id, expected_id); ++ ++ if (type == SSH2_FXP_STATUS) { ++ free(errmsg); ++ ++ if ((r = sshbuf_get_u32(msg, &status)) != 0 || ++ (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) ++ fatal_fr(r, "parse status"); ++ error("%s %s: %s", expand ? "expand" : "realpath", ++ path, *errmsg == '\0' ? fx2txt(status) : errmsg); ++ free(errmsg); ++ sshbuf_free(msg); ++ return NULL; ++ } ++ } else { ++ error("%s %s: %s", expand ? "expand" : "realpath", ++ path, *errmsg == '\0' ? fx2txt(status) : errmsg); ++ free(errmsg); ++ sshbuf_free(msg); ++ return NULL; ++ } + } else if (type != SSH2_FXP_NAME) + fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", + SSH2_FXP_NAME, type); +@@ -1078,9 +1110,9 @@ + } + + char * +-sftp_realpath(struct sftp_conn *conn, const char *path) ++sftp_realpath(struct sftp_conn *conn, const char *path, int create_dir) + { +- return sftp_realpath_expand(conn, path, 0); ++ return sftp_realpath_expand(conn, path, 0, create_dir); + } + + int +@@ -1094,9 +1126,9 @@ + { + if (!sftp_can_expand_path(conn)) { + debug3_f("no server support, fallback to realpath"); +- return sftp_realpath_expand(conn, path, 0); ++ return sftp_realpath_expand(conn, path, 0, 0); + } +- return sftp_realpath_expand(conn, path, 1); ++ return sftp_realpath_expand(conn, path, 1, 0); + } + + int +@@ -2016,7 +2048,7 @@ + char *src_canon; + int ret; + +- 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 + 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 = 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 = 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 *sftp_realpath(struct sftp_conn *, const char *); ++char *sftp_realpath(struct sftp_conn *, const char *, int); + + /* Canonicalisation with tilde expansion (requires server extension) */ + char *sftp_expand_path(struct sftp_conn *, const char *); +@@ -163,7 +163,7 @@ + * times if 'pflag' is set + */ + 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 --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 (sftp_upload(conn, g.gl_pathv[i], abs_dst, +@@ -1642,7 +1642,7 @@ + if (path1 == NULL || *path1 == '\0') + path1 = xstrdup(startdir); + path1 = sftp_make_absolute(path1, *pwd); +- if ((tmp = sftp_realpath(conn, path1)) == NULL) { ++ if ((tmp = sftp_realpath(conn, path1, 0)) == NULL) { + err = 1; + break; + } +@@ -2247,7 +2247,7 @@ + } + #endif /* USE_LIBEDIT */ + +- 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/SOURCES/openssh-8.7p1-scp-kill-switch.patch b/openssh-8.7p1-scp-kill-switch.patch similarity index 92% rename from SOURCES/openssh-8.7p1-scp-kill-switch.patch rename to openssh-8.7p1-scp-kill-switch.patch index cbfbf56..161ab2d 100644 --- a/SOURCES/openssh-8.7p1-scp-kill-switch.patch +++ b/openssh-8.7p1-scp-kill-switch.patch @@ -13,8 +13,8 @@ diff -up openssh-8.7p1/scp.1.kill-scp openssh-8.7p1/scp.1 --- openssh-8.7p1/scp.1.kill-scp 2021-09-16 12:09:02.646714578 +0200 +++ openssh-8.7p1/scp.1 2021-09-16 12:26:49.978628226 +0200 @@ -278,6 +278,13 @@ to print debugging messages about their - This is helpful in - debugging connection, authentication, and configuration problems. + By default a 32KB buffer is used. + .El .El +.Pp +Usage of SCP protocol can be blocked by creating a world-readable @@ -30,10 +30,10 @@ diff -up openssh-8.7p1/scp.c.kill-scp openssh-8.7p1/scp.c --- openssh-8.7p1/scp.c.kill-scp 2021-09-16 11:42:56.013650519 +0200 +++ openssh-8.7p1/scp.c 2021-09-16 11:53:03.249713836 +0200 @@ -596,6 +596,14 @@ main(int argc, char **argv) - argc -= optind; - argv += optind; + if (iamremote) + mode = MODE_SCP; -+ { ++ if (mode == MODE_SCP) { + FILE *f = fopen(_PATH_SCP_KILL_SWITCH, "r"); + if (f != NULL) { + fclose(f); diff --git a/openssh-8.7p1-ssh-manpage.patch b/openssh-8.7p1-ssh-manpage.patch new file mode 100644 index 0000000..c7f6f1e --- /dev/null +++ b/openssh-8.7p1-ssh-manpage.patch @@ -0,0 +1,53 @@ +diff --color -ru a/ssh.1 b/ssh.1 +--- a/ssh.1 2022-07-12 11:47:51.307295880 +0200 ++++ b/ssh.1 2022-07-12 11:50:28.793363263 +0200 +@@ -493,6 +493,7 @@ + .It AddressFamily + .It BatchMode + .It BindAddress ++.It BindInterface + .It CanonicalDomains + .It CanonicalizeFallbackLocal + .It CanonicalizeHostname +@@ -510,6 +511,7 @@ + .It ControlPath + .It ControlPersist + .It DynamicForward ++.It EnableSSHKeysign + .It EnableEscapeCommandline + .It EscapeChar + .It ExitOnForwardFailure +@@ -538,6 +540,8 @@ + .It IdentitiesOnly + .It IdentityAgent + .It IdentityFile ++.It IgnoreUnknown ++.It Include + .It IPQoS + .It KbdInteractiveAuthentication + .It KbdInteractiveDevices +@@ -546,6 +550,7 @@ + .It LocalCommand + .It LocalForward + .It LogLevel ++.It LogVerbose + .It MACs + .It Match + .It NoHostAuthenticationForLocalhost +@@ -566,6 +571,8 @@ + .It RemoteCommand + .It RemoteForward + .It RequestTTY ++.It RevokedHostKeys ++.It SecurityKeyProvider + .It RequiredRSASize + .It SendEnv + .It ServerAliveInterval +@@ -575,6 +582,7 @@ + .It StreamLocalBindMask + .It StreamLocalBindUnlink + .It StrictHostKeyChecking ++.It SyslogFacility + .It TCPKeepAlive + .It Tunnel + .It TunnelDevice diff --git a/openssh-9.0p1-audit-log.patch b/openssh-9.0p1-audit-log.patch new file mode 100644 index 0000000..fbf5094 --- /dev/null +++ b/openssh-9.0p1-audit-log.patch @@ -0,0 +1,119 @@ +diff -up openssh-9.0p1/audit-bsm.c.patch openssh-9.0p1/audit-bsm.c +--- openssh-9.0p1/audit-bsm.c.patch 2022-10-24 15:02:16.544858331 +0200 ++++ openssh-9.0p1/audit-bsm.c 2022-10-24 14:51:43.685766639 +0200 +@@ -405,7 +405,7 @@ audit_session_close(struct logininfo *li + } + + int +-audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) ++audit_keyusage(struct ssh *ssh, int host_user, char *key_fp, const struct sshkey_cert *cert, const char *issuer_fp, int rv) + { + /* not implemented */ + } +diff -up openssh-9.0p1/audit.c.patch openssh-9.0p1/audit.c +--- openssh-9.0p1/audit.c.patch 2022-10-24 15:02:16.544858331 +0200 ++++ openssh-9.0p1/audit.c 2022-10-24 15:20:38.854548226 +0200 +@@ -116,12 +116,22 @@ audit_event_lookup(ssh_audit_event_t ev) + void + audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key) + { +- char *fp; ++ char *key_fp = NULL; ++ char *issuer_fp = NULL; ++ struct sshkey_cert *cert = NULL; + +- fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); +- if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0) ++ key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); ++ if (sshkey_is_cert(key) && key->cert != NULL && key->cert->signature_key != NULL) { ++ cert = key->cert; ++ issuer_fp = sshkey_fingerprint(cert->signature_key, ++ options.fingerprint_hash, SSH_FP_DEFAULT); ++ } ++ if (audit_keyusage(ssh, host_user, key_fp, cert, issuer_fp, (*rv == 0)) == 0) + *rv = -SSH_ERR_INTERNAL_ERROR; +- free(fp); ++ if (key_fp) ++ free(key_fp); ++ if (issuer_fp) ++ free(issuer_fp); + } + + void +diff -up openssh-9.0p1/audit.h.patch openssh-9.0p1/audit.h +--- openssh-9.0p1/audit.h.patch 2022-10-24 15:02:16.544858331 +0200 ++++ openssh-9.0p1/audit.h 2022-10-24 14:58:20.887565518 +0200 +@@ -64,7 +64,7 @@ void audit_session_close(struct logininf + int audit_run_command(struct ssh *, const char *); + void audit_end_command(struct ssh *, int, const char *); + ssh_audit_event_t audit_classify_auth(const char *); +-int audit_keyusage(struct ssh *, int, char *, int); ++int audit_keyusage(struct ssh *, int, const char *, const struct sshkey_cert *, const char *, int); + void audit_key(struct ssh *, int, int *, const struct sshkey *); + void audit_unsupported(struct ssh *, int); + void audit_kex(struct ssh *, int, char *, char *, char *, char *); +diff -up openssh-9.0p1/audit-linux.c.patch openssh-9.0p1/audit-linux.c +--- openssh-9.0p1/audit-linux.c.patch 2022-10-24 15:02:16.544858331 +0200 ++++ openssh-9.0p1/audit-linux.c 2022-10-24 15:21:58.165303951 +0200 +@@ -137,10 +137,12 @@ fatal_report: + } + + int +-audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) ++audit_keyusage(struct ssh *ssh, int host_user, const char *key_fp, const struct sshkey_cert *cert, const char *issuer_fp, int rv) + { + char buf[AUDIT_LOG_SIZE]; + int audit_fd, rc, saved_errno; ++ const char *rip; ++ u_int i; + + audit_fd = audit_open(); + if (audit_fd < 0) { +@@ -150,14 +152,44 @@ audit_keyusage(struct ssh *ssh, int host + else + return 0; /* Must prevent login */ + } ++ rip = ssh_remote_ipaddr(ssh); + snprintf(buf, sizeof(buf), "%s_auth grantors=auth-key", host_user ? "pubkey" : "hostbased"); + rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, +- buf, audit_username(), -1, NULL, ssh_remote_ipaddr(ssh), NULL, rv); ++ buf, audit_username(), -1, NULL, rip, NULL, rv); + if ((rc < 0) && ((rc != -1) || (getuid() == 0))) + goto out; +- snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", fp); ++ snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", key_fp); + rc = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, buf, NULL, +- ssh_remote_ipaddr(ssh), NULL, rv); ++ rip, NULL, rv); ++ if ((rc < 0) && ((rc != -1) || (getuid() == 0))) ++ goto out; ++ ++ if (cert) { ++ char *pbuf; ++ ++ pbuf = audit_encode_nv_string("key_id", cert->key_id, 0); ++ if (pbuf == NULL) ++ goto out; ++ snprintf(buf, sizeof(buf), "cert %s cert_serial=%llu cert_issuer_alg=\"%s\" cert_issuer_fp=\"%s\"", ++ pbuf, (unsigned long long)cert->serial, sshkey_type(cert->signature_key), issuer_fp); ++ free(pbuf); ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, ++ buf, audit_username(), -1, NULL, rip, NULL, rv); ++ if ((rc < 0) && ((rc != -1) || (getuid() == 0))) ++ goto out; ++ ++ for (i = 0; cert->principals != NULL && i < cert->nprincipals; i++) { ++ pbuf = audit_encode_nv_string("cert_principal", cert->principals[i], 0); ++ if (pbuf == NULL) ++ goto out; ++ snprintf(buf, sizeof(buf), "principal %s", pbuf); ++ free(pbuf); ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, ++ buf, audit_username(), -1, NULL, rip, NULL, rv); ++ if ((rc < 0) && ((rc != -1) || (getuid() == 0))) ++ goto out; ++ } ++ } + out: + saved_errno = errno; + audit_close(audit_fd); diff --git a/openssh-9.0p1-evp-fips-dh.patch b/openssh-9.0p1-evp-fips-dh.patch new file mode 100644 index 0000000..8c70197 --- /dev/null +++ b/openssh-9.0p1-evp-fips-dh.patch @@ -0,0 +1,292 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/dh.c openssh-9.0p1-patched/dh.c +--- openssh-9.0p1/dh.c 2023-05-25 09:24:28.730868316 +0200 ++++ openssh-9.0p1-patched/dh.c 2023-05-25 09:23:44.841379532 +0200 +@@ -37,6 +37,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #include "dh.h" + #include "pathnames.h" +@@ -290,10 +293,15 @@ + int + dh_gen_key(DH *dh, int need) + { +- int pbits; +- const BIGNUM *dh_p, *pub_key; ++ const BIGNUM *dh_p, *dh_g; ++ BIGNUM *pub_key = NULL, *priv_key = NULL; ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ int pbits, r = 0; + +- DH_get0_pqg(dh, &dh_p, NULL, NULL); ++ DH_get0_pqg(dh, &dh_p, NULL, &dh_g); + + if (need < 0 || dh_p == NULL || + (pbits = BN_num_bits(dh_p)) <= 0 || +@@ -301,19 +309,85 @@ + return SSH_ERR_INVALID_ARGUMENT; + if (need < 256) + need = 256; ++ ++ if ((param_bld = OSSL_PARAM_BLD_new()) == NULL || ++ (ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL) { ++ OSSL_PARAM_BLD_free(param_bld); ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ if (OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_FFC_P, dh_p) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_FFC_G, dh_g) != 1) { ++ error_f("Could not set p,q,g parameters"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + /* + * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), + * so double requested need here. + */ +- if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1))) +- return SSH_ERR_LIBCRYPTO_ERROR; +- +- if (DH_generate_key(dh) == 0) +- return SSH_ERR_LIBCRYPTO_ERROR; +- DH_get0_key(dh, &pub_key, NULL); +- if (!dh_pub_is_valid(dh, pub_key)) +- return SSH_ERR_INVALID_FORMAT; +- return 0; ++ if (OSSL_PARAM_BLD_push_int(param_bld, ++ OSSL_PKEY_PARAM_DH_PRIV_LEN, ++ MINIMUM(need * 2, pbits - 1)) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata(ctx, &pkey, ++ EVP_PKEY_KEY_PARAMETERS, params) != 1) { ++ error_f("Failed key generation"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* reuse context for key generation */ ++ EVP_PKEY_CTX_free(ctx); ++ ctx = NULL; ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ EVP_PKEY_keygen_init(ctx) != 1) { ++ error_f("Could not create or init context"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_generate(ctx, &pkey) != 1) { ++ error_f("Could not generate keys"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_public_check(ctx) != 1) { ++ error_f("The public key is incorrect"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, ++ &pub_key) != 1 || ++ EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, ++ &priv_key) != 1 || ++ DH_set0_key(dh, pub_key, priv_key) != 1) { ++ error_f("Could not set pub/priv keys to DH struct"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* transferred */ ++ pub_key = NULL; ++ priv_key = NULL; ++out: ++ OSSL_PARAM_free(params); ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(pkey); ++ BN_clear_free(pub_key); ++ BN_clear_free(priv_key); ++ return r; + } + + DH * +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.c openssh-9.0p1-patched/kex.c +--- openssh-9.0p1/kex.c 2023-05-25 09:24:28.731868327 +0200 ++++ openssh-9.0p1-patched/kex.c 2023-05-25 09:23:44.841379532 +0200 +@@ -1623,3 +1623,47 @@ + return r; + } + ++#ifdef WITH_OPENSSL ++/* ++ * Creates an EVP_PKEY from the given parameters and keys. ++ * The private key can be omitted. ++ */ ++int ++kex_create_evp_dh(EVP_PKEY **pkey, const BIGNUM *p, const BIGNUM *q, ++ const BIGNUM *g, const BIGNUM *pub, const BIGNUM *priv) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ int r = 0; ++ ++ /* create EVP_PKEY-DH key */ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ error_f("EVP_PKEY_CTX or PARAM_BLD init failed"); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, pub) != 1) { ++ error_f("Failed pushing params to OSSL_PARAM_BLD"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (priv != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) { ++ error_f("Failed pushing private key to OSSL_PARAM_BLD"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ return r; ++} ++#endif /* WITH_OPENSSL */ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kexdh.c openssh-9.0p1-patched/kexdh.c +--- openssh-9.0p1/kexdh.c 2023-05-25 09:24:28.674867692 +0200 ++++ openssh-9.0p1-patched/kexdh.c 2023-05-25 09:25:28.494533889 +0200 +@@ -35,6 +35,10 @@ + + #include "openbsd-compat/openssl-compat.h" + #include ++#include ++#include ++#include ++#include + + #include "sshkey.h" + #include "kex.h" +@@ -83,9 +87,12 @@ + kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) + { + BIGNUM *shared_secret = NULL; ++ const BIGNUM *pub, *priv, *p, *q, *g; ++ EVP_PKEY *pkey = NULL, *dh_pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; + u_char *kbuf = NULL; + size_t klen = 0; +- int kout, r; ++ int r = 0; + + #ifdef DEBUG_KEXDH + fprintf(stderr, "dh_pub= "); +@@ -100,24 +107,59 @@ + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } +- klen = DH_size(kex->dh); ++ ++ DH_get0_key(kex->dh, &pub, &priv); ++ DH_get0_pqg(kex->dh, &p, &q, &g); ++ /* import key */ ++ r = kex_create_evp_dh(&pkey, p, q, g, pub, priv); ++ if (r != 0) { ++ error_f("Could not create EVP_PKEY for dh"); ++ ERR_print_errors_fp(stderr); ++ goto out; ++ } ++ /* import peer key ++ * the parameters should be the same as with pkey ++ */ ++ r = kex_create_evp_dh(&dh_pkey, p, q, g, dh_pub, NULL); ++ if (r != 0) { ++ error_f("Could not import peer key for dh"); ++ ERR_print_errors_fp(stderr); ++ goto out; ++ } ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL) { ++ error_f("Could not init EVP_PKEY_CTX for dh"); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (EVP_PKEY_derive_init(ctx) != 1 || ++ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 || ++ EVP_PKEY_derive(ctx, NULL, &klen) != 1) { ++ error_f("Could not get key size"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 || +- BN_bin2bn(kbuf, kout, shared_secret) == NULL) { ++ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1 || ++ BN_bin2bn(kbuf, klen, shared_secret) == NULL) { ++ error_f("Could not derive key"); + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + #ifdef DEBUG_KEXDH +- dump_digest("shared secret", kbuf, kout); ++ dump_digest("shared secret", kbuf, klen); + #endif + r = sshbuf_put_bignum2(out, shared_secret); + out: + freezero(kbuf, klen); + BN_clear_free(shared_secret); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_free(dh_pkey); ++ EVP_PKEY_CTX_free(ctx); + return r; + } + +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.h openssh-9.0p1-patched/kex.h +--- openssh-9.0p1/kex.h 2023-05-25 09:24:28.725868260 +0200 ++++ openssh-9.0p1-patched/kex.h 2023-05-25 09:23:44.841379532 +0200 +@@ -33,6 +33,9 @@ + # include + # include + # include ++# include ++# include ++# include + # ifdef OPENSSL_HAS_ECC + # include + # else /* OPENSSL_HAS_ECC */ +@@ -283,6 +286,8 @@ + const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); ++int kex_create_evp_dh(EVP_PKEY **, const BIGNUM *, const BIGNUM *, ++ const BIGNUM *, const BIGNUM *, const BIGNUM *); + + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) + void dump_digest(const char *, const u_char *, int); diff --git a/openssh-9.0p1-evp-fips-ecdh.patch b/openssh-9.0p1-evp-fips-ecdh.patch new file mode 100644 index 0000000..0313c6f --- /dev/null +++ b/openssh-9.0p1-evp-fips-ecdh.patch @@ -0,0 +1,207 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../openssh-8.7p1/kexecdh.c ./kexecdh.c +--- ../openssh-8.7p1/kexecdh.c 2021-08-20 06:03:49.000000000 +0200 ++++ ./kexecdh.c 2023-04-13 14:30:14.882449593 +0200 +@@ -35,17 +35,57 @@ + #include + + #include ++#include ++#include ++#include ++#include + + #include "sshkey.h" + #include "kex.h" + #include "sshbuf.h" + #include "digest.h" + #include "ssherr.h" ++#include "log.h" + + static int + kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key, + const EC_GROUP *, struct sshbuf **); + ++static EC_KEY * ++generate_ec_keys(int ec_nid) ++{ ++ EC_KEY *client_key = NULL; ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ const char *group_name; ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) ++ goto out; ++ if ((group_name = OSSL_EC_curve_nid2name(ec_nid)) == NULL || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ error_f("Could not create OSSL_PARAM"); ++ goto out; ++ } ++ if (EVP_PKEY_keygen_init(ctx) != 1 || ++ EVP_PKEY_CTX_set_params(ctx, params) != 1 || ++ EVP_PKEY_generate(ctx, &pkey) != 1 || ++ (client_key = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) { ++ error_f("Could not generate ec keys"); ++ goto out; ++ } ++out: ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(ctx); ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); ++ return client_key; ++} ++ + int + kex_ecdh_keypair(struct kex *kex) + { +@@ -55,11 +95,7 @@ + struct sshbuf *buf = NULL; + int r; + +- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if (EC_KEY_generate_key(client_key) != 1) { ++ if ((client_key = generate_ec_keys(kex->ec_nid)) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +@@ -101,11 +137,7 @@ + *server_blobp = NULL; + *shared_secretp = NULL; + +- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if (EC_KEY_generate_key(server_key) != 1) { ++ if ((server_key = generate_ec_keys(kex->ec_nid)) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +@@ -140,11 +172,21 @@ + { + struct sshbuf *buf = NULL; + BIGNUM *shared_secret = NULL; +- EC_POINT *dh_pub = NULL; +- u_char *kbuf = NULL; +- size_t klen = 0; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *pkey = NULL, *dh_pkey = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ u_char *kbuf = NULL, *pub = NULL; ++ size_t klen = 0, publen; ++ const char *group_name; + int r; + ++ /* import EC_KEY to EVP_PKEY */ ++ if ((r = ssh_create_evp_ec(key, kex->ec_nid, &pkey)) != 0) { ++ error_f("Could not create EVP_PKEY"); ++ goto out; ++ } ++ + *shared_secretp = NULL; + + if ((buf = sshbuf_new()) == NULL) { +@@ -153,45 +195,82 @@ + } + if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0) + goto out; +- if ((dh_pub = EC_POINT_new(group)) == NULL) { ++ ++ /* the public key is in the buffer in octet string UNCOMPRESSED ++ * format. See sshbuf_put_ec */ ++ if ((r = sshbuf_get_string(buf, &pub, &publen)) != 0) ++ goto out; ++ sshbuf_reset(buf); ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) { ++ if ((group_name = OSSL_EC_curve_nid2name(kex->ec_nid)) == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (OSSL_PARAM_BLD_push_octet_string(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, pub, publen) != 1 || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ error_f("Failed to set params for dh_pkey"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1 || ++ EVP_PKEY_fromdata(ctx, &dh_pkey, ++ EVP_PKEY_PUBLIC_KEY, params) != 1 || ++ EVP_PKEY_public_check(ctx) != 1) { ++ error_f("Peer public key import failed"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- sshbuf_reset(buf); + + #ifdef DEBUG_KEXECDH + fputs("public key:\n", stderr); +- sshkey_dump_ec_point(group, dh_pub); ++ EVP_PKEY_print_public_fp(stderr, dh_pkey, 0, NULL); + #endif +- if (sshkey_ec_validate_public(group, dh_pub) != 0) { +- r = SSH_ERR_MESSAGE_INCOMPLETE; ++ EVP_PKEY_CTX_free(ctx); ++ ctx = NULL; ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ EVP_PKEY_derive_init(ctx) != 1 || ++ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 || ++ EVP_PKEY_derive(ctx, NULL, &klen) != 1) { ++ error_f("Failed to get derive information"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- klen = (EC_GROUP_get_degree(group) + 7) / 8; +- if ((kbuf = malloc(klen)) == NULL || +- (shared_secret = BN_new()) == NULL) { ++ if ((kbuf = malloc(klen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen || +- BN_bin2bn(kbuf, klen, shared_secret) == NULL) { ++ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + #ifdef DEBUG_KEXECDH + dump_digest("shared secret", kbuf, klen); + #endif ++ if ((shared_secret = BN_new()) == NULL || ++ (BN_bin2bn(kbuf, klen, shared_secret) == NULL)) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0) + goto out; + *shared_secretp = buf; + buf = NULL; + out: +- EC_POINT_clear_free(dh_pub); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_free(dh_pkey); ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); + BN_clear_free(shared_secret); + freezero(kbuf, klen); ++ freezero(pub, publen); + sshbuf_free(buf); + return r; + } diff --git a/openssh-9.3p1-merged-openssl-evp.patch b/openssh-9.3p1-merged-openssl-evp.patch new file mode 100644 index 0000000..6a30485 --- /dev/null +++ b/openssh-9.3p1-merged-openssl-evp.patch @@ -0,0 +1,1237 @@ +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/digest.h openssh-9.3p1-patched/digest.h +--- openssh-9.3p1/digest.h 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/digest.h 2023-06-06 15:52:25.602551466 +0200 +@@ -32,6 +32,12 @@ + struct sshbuf; + struct ssh_digest_ctx; + ++#ifdef WITH_OPENSSL ++#include ++/* Converts internal digest representation to the OpenSSL one */ ++const EVP_MD *ssh_digest_to_md(int digest_type); ++#endif ++ + /* Looks up a digest algorithm by name */ + int ssh_digest_alg_by_name(const char *name); + +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/digest-openssl.c openssh-9.3p1-patched/digest-openssl.c +--- openssh-9.3p1/digest-openssl.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/digest-openssl.c 2023-06-06 15:52:25.601551454 +0200 +@@ -64,6 +64,22 @@ + { -1, NULL, 0, NULL }, + }; + ++const EVP_MD * ++ssh_digest_to_md(int digest_type) ++{ ++ switch (digest_type) { ++ case SSH_DIGEST_SHA1: ++ return EVP_sha1(); ++ case SSH_DIGEST_SHA256: ++ return EVP_sha256(); ++ case SSH_DIGEST_SHA384: ++ return EVP_sha384(); ++ case SSH_DIGEST_SHA512: ++ return EVP_sha512(); ++ } ++ return NULL; ++} ++ + static const struct ssh_digest * + ssh_digest_by_alg(int alg) + { +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-dss.c openssh-9.3p1-patched/ssh-dss.c +--- openssh-9.3p1/ssh-dss.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/ssh-dss.c 2023-06-06 15:52:25.624551743 +0200 +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -261,11 +263,15 @@ + const u_char *data, size_t datalen, + const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) + { ++ EVP_PKEY *pkey = NULL; + DSA_SIG *sig = NULL; + const BIGNUM *sig_r, *sig_s; +- u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; +- size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); ++ u_char sigblob[SIGBLOB_LEN]; ++ size_t rlen, slen; ++ int len; + struct sshbuf *b = NULL; ++ u_char *sigb = NULL; ++ const u_char *psig = NULL; + int ret = SSH_ERR_INVALID_ARGUMENT; + + if (lenp != NULL) +@@ -276,17 +282,23 @@ + if (key == NULL || key->dsa == NULL || + sshkey_type_plain(key->type) != KEY_DSA) + return SSH_ERR_INVALID_ARGUMENT; +- if (dlen == 0) +- return SSH_ERR_INTERNAL_ERROR; + +- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, +- digest, sizeof(digest))) != 0) ++ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0) ++ return ret; ++ ret = sshkey_calculate_signature(pkey, SSH_DIGEST_SHA1, &sigb, &len, ++ data, datalen); ++ EVP_PKEY_free(pkey); ++ if (ret < 0) { + goto out; ++ } + +- if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { ++ psig = sigb; ++ if ((sig = d2i_DSA_SIG(NULL, &psig, len)) == NULL) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } ++ free(sigb); ++ sigb = NULL; + + DSA_SIG_get0(sig, &sig_r, &sig_s); + rlen = BN_num_bytes(sig_r); +@@ -319,7 +331,7 @@ + *lenp = len; + ret = 0; + out: +- explicit_bzero(digest, sizeof(digest)); ++ free(sigb); + DSA_SIG_free(sig); + sshbuf_free(b); + return ret; +@@ -331,20 +343,20 @@ + const u_char *data, size_t dlen, const char *alg, u_int compat, + struct sshkey_sig_details **detailsp) + { ++ EVP_PKEY *pkey = NULL; + DSA_SIG *dsig = NULL; + BIGNUM *sig_r = NULL, *sig_s = NULL; +- u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; +- size_t len, hlen = ssh_digest_bytes(SSH_DIGEST_SHA1); ++ u_char *sigblob = NULL; ++ size_t len, slen; + int ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; + char *ktype = NULL; ++ u_char *sigb = NULL, *psig = NULL; + + if (key == NULL || key->dsa == NULL || + sshkey_type_plain(key->type) != KEY_DSA || + sig == NULL || siglen == 0) + return SSH_ERR_INVALID_ARGUMENT; +- if (hlen == 0) +- return SSH_ERR_INTERNAL_ERROR; + + /* fetch signature */ + if ((b = sshbuf_from(sig, siglen)) == NULL) +@@ -386,25 +398,28 @@ + } + sig_r = sig_s = NULL; /* transferred */ + +- /* sha1 the data */ +- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, dlen, +- digest, sizeof(digest))) != 0) ++ if ((slen = i2d_DSA_SIG(dsig, NULL)) == 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; +- +- switch (DSA_do_verify(digest, hlen, dsig, key->dsa)) { +- case 1: +- ret = 0; +- break; +- case 0: +- ret = SSH_ERR_SIGNATURE_INVALID; ++ } ++ if ((sigb = malloc(slen)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; + goto out; +- default: ++ } ++ psig = sigb; ++ if ((slen = i2d_DSA_SIG(dsig, &psig)) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + ++ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0) ++ goto out; ++ ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, dlen, ++ sigb, slen); ++ EVP_PKEY_free(pkey); ++ + out: +- explicit_bzero(digest, sizeof(digest)); ++ free(sigb); + DSA_SIG_free(dsig); + BN_clear_free(sig_r); + BN_clear_free(sig_s); +@@ -415,6 +430,65 @@ + return ret; + } + ++int ++ssh_create_evp_dss(const struct sshkey *k, EVP_PKEY **pkey) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ const BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub = NULL, *priv = NULL; ++ int ret = 0; ++ ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ DSA_get0_pqg(k->dsa, &p, &q, &g); ++ DSA_get0_key(k->dsa, &pub, &priv); ++ ++ if (p != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (q != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (g != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (pub != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, ++ pub) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (priv != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, ++ priv) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ return ret; ++} ++ + static const struct sshkey_impl_funcs sshkey_dss_funcs = { + /* .size = */ ssh_dss_size, + /* .alloc = */ ssh_dss_alloc, +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-ecdsa.c openssh-9.3p1-patched/ssh-ecdsa.c +--- openssh-9.3p1/ssh-ecdsa.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/ssh-ecdsa.c 2023-06-06 15:52:25.626551768 +0200 +@@ -34,6 +34,8 @@ + #include + #include + #include ++#include ++#include + + #include + +@@ -44,6 +44,9 @@ + #include "digest.h" + #define SSHKEY_INTERNAL + #include "sshkey.h" ++#ifdef ENABLE_PKCS11 ++#include "ssh-pkcs11.h" ++#endif + + #include "openbsd-compat/openssl-compat.h" + +@@ -126,19 +128,29 @@ + static int + ssh_ecdsa_generate(struct sshkey *k, int bits) + { +- EC_KEY *private; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *res = NULL; + + if ((k->ecdsa_nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) + return SSH_ERR_KEY_LENGTH; +- if ((private = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL) + return SSH_ERR_ALLOC_FAIL; +- if (EC_KEY_generate_key(private) != 1) { +- EC_KEY_free(private); ++ ++ if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_CTX_set_group_name(ctx, OBJ_nid2sn(k->ecdsa_nid)) <= 0 ++ || EVP_PKEY_keygen(ctx, &res) <= 0) { ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(res); + return SSH_ERR_LIBCRYPTO_ERROR; + } +- EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); +- k->ecdsa = private; +- return 0; ++ /* This function is deprecated in OpenSSL 3.0 but OpenSSH doesn't worry about it*/ ++ k->ecdsa = EVP_PKEY_get1_EC_KEY(res); ++ if (k->ecdsa) ++ EC_KEY_set_asn1_flag(k->ecdsa, OPENSSL_EC_NAMED_CURVE); ++ ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(res); ++ return (k->ecdsa) ? 0 : SSH_ERR_LIBCRYPTO_ERROR; + } + + static int +@@ -228,11 +240,13 @@ + const u_char *data, size_t dlen, + const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) + { ++ EVP_PKEY *pkey = NULL; + ECDSA_SIG *esig = NULL; ++ unsigned char *sigb = NULL; ++ const unsigned char *psig; + const BIGNUM *sig_r, *sig_s; + int hash_alg; +- u_char digest[SSH_DIGEST_MAX_LENGTH]; +- size_t len, hlen; ++ int len; + struct sshbuf *b = NULL, *bb = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + +@@ -245,18 +259,33 @@ + sshkey_type_plain(key->type) != KEY_ECDSA) + return SSH_ERR_INVALID_ARGUMENT; + +- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || +- (hlen = ssh_digest_bytes(hash_alg)) == 0) ++ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) + return SSH_ERR_INTERNAL_ERROR; +- if ((ret = ssh_digest_memory(hash_alg, data, dlen, +- digest, sizeof(digest))) != 0) ++ ++#ifdef ENABLE_PKCS11 ++ if (is_ecdsa_pkcs11(key->ecdsa)) { ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ } else { ++#endif ++ if ((ret = ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey)) != 0) ++ return ret; ++#ifdef ENABLE_PKCS11 ++ } ++#endif ++ ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data, ++ dlen); ++ EVP_PKEY_free(pkey); ++ if (ret < 0) { + goto out; ++ } + +- if ((esig = ECDSA_do_sign(digest, hlen, key->ecdsa)) == NULL) { ++ psig = sigb; ++ if (d2i_ECDSA_SIG(&esig, &psig, len) == NULL) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- + if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; +@@ -280,7 +309,7 @@ + *lenp = len; + ret = 0; + out: +- explicit_bzero(digest, sizeof(digest)); ++ free(sigb); + sshbuf_free(b); + sshbuf_free(bb); + ECDSA_SIG_free(esig); +@@ -293,22 +322,21 @@ + const u_char *data, size_t dlen, const char *alg, u_int compat, + struct sshkey_sig_details **detailsp) + { ++ EVP_PKEY *pkey = NULL; + ECDSA_SIG *esig = NULL; + BIGNUM *sig_r = NULL, *sig_s = NULL; +- int hash_alg; +- u_char digest[SSH_DIGEST_MAX_LENGTH]; +- size_t hlen; ++ int hash_alg, len; + int ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL, *sigbuf = NULL; + char *ktype = NULL; ++ unsigned char *sigb = NULL, *psig = NULL; + + if (key == NULL || key->ecdsa == NULL || + sshkey_type_plain(key->type) != KEY_ECDSA || + sig == NULL || siglen == 0) + return SSH_ERR_INVALID_ARGUMENT; + +- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || +- (hlen = ssh_digest_bytes(hash_alg)) == 0) ++ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) + return SSH_ERR_INTERNAL_ERROR; + + /* fetch signature */ +@@ -344,28 +372,33 @@ + } + sig_r = sig_s = NULL; /* transferred */ + +- if (sshbuf_len(sigbuf) != 0) { +- ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; ++ /* Figure out the length */ ++ if ((len = i2d_ECDSA_SIG(esig, NULL)) == 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- if ((ret = ssh_digest_memory(hash_alg, data, dlen, +- digest, sizeof(digest))) != 0) +- goto out; +- +- switch (ECDSA_do_verify(digest, hlen, esig, key->ecdsa)) { +- case 1: +- ret = 0; +- break; +- case 0: +- ret = SSH_ERR_SIGNATURE_INVALID; ++ if ((sigb = malloc(len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; + goto out; +- default: ++ } ++ psig = sigb; ++ if ((len = i2d_ECDSA_SIG(esig, &psig)) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + ++ if (sshbuf_len(sigbuf) != 0) { ++ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; ++ goto out; ++ } ++ ++ if (ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey) != 0) ++ goto out; ++ ret = sshkey_verify_signature(pkey, hash_alg, data, dlen, sigb, len); ++ EVP_PKEY_free(pkey); ++ + out: +- explicit_bzero(digest, sizeof(digest)); ++ free(sigb); + sshbuf_free(sigbuf); + sshbuf_free(b); + ECDSA_SIG_free(esig); +@@ -375,6 +408,79 @@ + return ret; + } + ++int ++ssh_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ BN_CTX *bn_ctx = NULL; ++ uint8_t *pub_ser = NULL; ++ const char *group_name; ++ const EC_POINT *pub = NULL; ++ const BIGNUM *priv = NULL; ++ int ret = 0; ++ ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL || ++ (bn_ctx = BN_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if ((group_name = OSSL_EC_curve_nid2name(ecdsa_nid)) == NULL || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, ++ group_name, ++ strlen(group_name)) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((pub = EC_KEY_get0_public_key(k)) != NULL) { ++ const EC_GROUP *group; ++ size_t len; ++ ++ group = EC_KEY_get0_group(k); ++ len = EC_POINT_point2oct(group, pub, ++ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); ++ if ((pub_ser = malloc(len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ EC_POINT_point2oct(group, ++ pub, ++ POINT_CONVERSION_UNCOMPRESSED, ++ pub_ser, ++ len, ++ bn_ctx); ++ if (OSSL_PARAM_BLD_push_octet_string(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, ++ pub_ser, ++ len) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ } ++ if ((priv = EC_KEY_get0_private_key(k)) != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ BN_CTX_free(bn_ctx); ++ free(pub_ser); ++ return ret; ++} ++ + /* NB. not static; used by ECDSA-SK */ + const struct sshkey_impl_funcs sshkey_ecdsa_funcs = { + /* .size = */ ssh_ecdsa_size, +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/sshkey.c openssh-9.3p1-patched/sshkey.c +--- openssh-9.3p1/sshkey.c 2023-06-06 15:53:36.608444190 +0200 ++++ openssh-9.3p1-patched/sshkey.c 2023-06-06 15:52:25.625551756 +0200 +@@ -34,6 +34,8 @@ + #include + #include + #include ++#include ++#include + #endif + + #include "crypto_api.h" +@@ -575,6 +577,86 @@ + } + + #ifdef WITH_OPENSSL ++int ++sshkey_calculate_signature(EVP_PKEY *pkey, int hash_alg, u_char **sigp, ++ int *lenp, const u_char *data, size_t datalen) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ u_char *sig = NULL; ++ int ret, slen; ++ size_t len; ++ ++ if (sigp == NULL || lenp == NULL) { ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ ++ slen = EVP_PKEY_get_size(pkey); ++ if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) ++ return SSH_ERR_INVALID_ARGUMENT; ++ ++ len = slen; ++ if ((sig = malloc(slen)) == NULL) { ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ if ((ctx = EVP_MD_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto error; ++ } ++ if (EVP_DigestSignInit(ctx, NULL, ssh_digest_to_md(hash_alg), ++ NULL, pkey) != 1 || ++ EVP_DigestSignUpdate(ctx, data, datalen) != 1 || ++ EVP_DigestSignFinal(ctx, sig, &len) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto error; ++ } ++ ++ *sigp = sig; ++ *lenp = len; ++ /* Now owned by the caller */ ++ sig = NULL; ++ ret = 0; ++ ++error: ++ EVP_MD_CTX_free(ctx); ++ free(sig); ++ return ret; ++} ++ ++int ++sshkey_verify_signature(EVP_PKEY *pkey, int hash_alg, const u_char *data, ++ size_t datalen, u_char *sigbuf, int siglen) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ int ret; ++ ++ if ((ctx = EVP_MD_CTX_new()) == NULL) { ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ if (EVP_DigestVerifyInit(ctx, NULL, ssh_digest_to_md(hash_alg), ++ NULL, pkey) != 1 || ++ EVP_DigestVerifyUpdate(ctx, data, datalen) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto done; ++ } ++ ret = EVP_DigestVerifyFinal(ctx, sigbuf, siglen); ++ switch (ret) { ++ case 1: ++ ret = 0; ++ break; ++ case 0: ++ ret = SSH_ERR_SIGNATURE_INVALID; ++ break; ++ default: ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ break; ++ } ++ ++done: ++ EVP_MD_CTX_free(ctx); ++ return ret; ++} ++ + /* XXX: these are really begging for a table-driven approach */ + int + sshkey_curve_name_to_nid(const char *name) +@@ -3763,3 +3845,27 @@ + return 0; + } + #endif /* WITH_XMSS */ ++ ++#ifdef WITH_OPENSSL ++EVP_PKEY * ++sshkey_create_evp(OSSL_PARAM_BLD *param_bld, EVP_PKEY_CTX *ctx) ++{ ++ EVP_PKEY *ret = NULL; ++ OSSL_PARAM *params = NULL; ++ if (param_bld == NULL || ctx == NULL) { ++ debug2_f("param_bld or ctx is NULL"); ++ return NULL; ++ } ++ if ((params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ debug2_f("Could not build param list"); ++ return NULL; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1 || ++ EVP_PKEY_fromdata(ctx, &ret, EVP_PKEY_KEYPAIR, params) != 1) { ++ debug2_f("EVP_PKEY_fromdata failed"); ++ OSSL_PARAM_free(params); ++ return NULL; ++ } ++ return ret; ++} ++#endif /* WITH_OPENSSL */ +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/sshkey.h openssh-9.3p1-patched/sshkey.h +--- openssh-9.3p1/sshkey.h 2023-06-06 15:53:36.608444190 +0200 ++++ openssh-9.3p1-patched/sshkey.h 2023-06-06 15:52:25.626551768 +0200 +@@ -31,6 +31,9 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include ++#include ++#include + # ifdef OPENSSL_HAS_ECC + # include + # include +@@ -266,6 +266,10 @@ + const char *sshkey_ssh_name_plain(const struct sshkey *); + int sshkey_names_valid2(const char *, int, int); + char *sshkey_alg_list(int, int, int, char); ++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 @@ + + void sshkey_sig_details_free(struct sshkey_sig_details *); + ++#ifdef WITH_OPENSSL ++EVP_PKEY *sshkey_create_evp(OSSL_PARAM_BLD *, EVP_PKEY_CTX *); ++int ssh_create_evp_dss(const struct sshkey *, EVP_PKEY **); ++int ssh_create_evp_rsa(const struct sshkey *, EVP_PKEY **); ++int ssh_create_evp_ec(EC_KEY *, int, EVP_PKEY **); ++#endif /* WITH_OPENSSL */ ++ + #ifdef SSHKEY_INTERNAL + int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b); + void sshkey_sk_cleanup(struct sshkey *k); +@@ -338,6 +352,10 @@ + #endif + #endif + ++#ifdef ENABLE_PKCS11 ++int pkcs11_get_ecdsa_idx(void); ++#endif ++ + #if !defined(WITH_OPENSSL) + # undef RSA + # undef DSA +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); + } ++ ++int ++is_ecdsa_pkcs11(EC_KEY *ecdsa) ++{ ++ if (EC_KEY_get_ex_data(ecdsa, ec_key_idx) != NULL) ++ return 1; ++ return 0; ++} + #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + ++int ++is_rsa_pkcs11(RSA *rsa) ++{ ++ if (RSA_get_ex_data(rsa, rsa_idx) != NULL) ++ return 1; ++ return 0; ++} ++ + /* remove trailing spaces. Note, that this does NOT guarantee the buffer + * will be null terminated if there are no trailing spaces! */ + 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) ++{ ++ const EC_KEY_METHOD *meth; ++ ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgstlen, ++ const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey) = NULL; ++ ++ meth = EC_KEY_get_method(ecdsa); ++ EC_KEY_METHOD_get_sign(meth, NULL, NULL, &sign_sig); ++ if (sign_sig == ecdsa_do_sign) ++ return 1; ++ return 0; ++} + #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ + ++int ++is_rsa_pkcs11(RSA *rsa) ++{ ++ const RSA_METHOD *meth; ++ int (*priv_enc)(int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa, int padding) = NULL; ++ ++ meth = RSA_get_method(rsa); ++ priv_enc = RSA_meth_get_priv_enc(meth); ++ if (priv_enc == rsa_encrypt) ++ return 1; ++ return 0; ++} ++ + /* redirect private key crypto operations to the ssh-pkcs11-helper */ + static void + 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 ++int is_rsa_pkcs11(RSA *rsa); ++ + #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) + #undef ENABLE_PKCS11 + #endif +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-rsa.c openssh-9.3p1-patched/ssh-rsa.c +--- openssh-9.3p1/ssh-rsa.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/ssh-rsa.c 2023-06-06 15:52:25.627551781 +0200 +@@ -23,6 +23,8 @@ + + #include + #include ++#include ++#include + + #include + #include +@@ -36,10 +36,13 @@ + #include "sshkey.h" + #include "digest.h" + #include "log.h" ++#ifdef ENABLE_PKCS11 ++#include "ssh-pkcs11.h" ++#endif + + #include "openbsd-compat/openssl-compat.h" + +-static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); ++static int openssh_RSA_verify(int, const u_char *, size_t, u_char *, size_t, EVP_PKEY *); + + static u_int + ssh_rsa_size(const struct sshkey *key) +@@ -131,27 +133,50 @@ + static int + ssh_rsa_generate(struct sshkey *k, int bits) + { +- RSA *private = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *res = NULL; + BIGNUM *f4 = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || + bits > SSHBUF_MAX_BIGNUM * 8) + return SSH_ERR_KEY_LENGTH; +- if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL ++ || (f4 = BN_new()) == NULL || !BN_set_word(f4, RSA_F4)) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (!BN_set_word(f4, RSA_F4) || +- !RSA_generate_key_ex(private, bits, f4, NULL)) { ++ ++ if (EVP_PKEY_keygen_init(ctx) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) { ++ ret = SSH_ERR_KEY_LENGTH; ++ goto out; ++ } ++ ++ if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, f4) <= 0) ++ goto out; ++ ++ if (EVP_PKEY_keygen(ctx, &res) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* This function is deprecated in OpenSSL 3.0 but OpenSSH doesn't worry about it*/ ++ k->rsa = EVP_PKEY_get1_RSA(res); ++ if (k->rsa) { ++ ret = 0; ++ } else { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- k->rsa = private; +- private = NULL; +- ret = 0; + out: +- RSA_free(private); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(res); + BN_free(f4); + return ret; + } +@@ -317,21 +342,6 @@ + return -1; + } + +-static int +-rsa_hash_alg_nid(int type) +-{ +- switch (type) { +- case SSH_DIGEST_SHA1: +- return NID_sha1; +- case SSH_DIGEST_SHA256: +- return NID_sha256; +- case SSH_DIGEST_SHA512: +- return NID_sha512; +- default: +- return -1; +- } +-} +- + int + ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp) + { +@@ -393,11 +403,10 @@ + const u_char *data, size_t datalen, + const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) + { +- const BIGNUM *rsa_n; +- u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; +- size_t slen = 0; +- u_int hlen, len; +- int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; ++ EVP_PKEY *pkey = NULL; ++ u_char *sig = NULL; ++ int len, slen = 0; ++ int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; + + if (lenp != NULL) +@@ -409,33 +418,33 @@ + hash_alg = SSH_DIGEST_SHA1; + else + hash_alg = rsa_hash_id_from_keyname(alg); ++ + if (key == NULL || key->rsa == NULL || hash_alg == -1 || + sshkey_type_plain(key->type) != KEY_RSA) + return SSH_ERR_INVALID_ARGUMENT; +- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); +- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) +- return SSH_ERR_KEY_LENGTH; + slen = RSA_size(key->rsa); +- if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) +- return SSH_ERR_INVALID_ARGUMENT; +- +- /* hash the data */ +- nid = rsa_hash_alg_nid(hash_alg); +- if ((hlen = ssh_digest_bytes(hash_alg)) == 0) +- return SSH_ERR_INTERNAL_ERROR; +- if ((ret = ssh_digest_memory(hash_alg, data, datalen, +- digest, sizeof(digest))) != 0) +- goto out; ++ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) ++ return SSH_ERR_KEY_LENGTH; + +- if ((sig = malloc(slen)) == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; +- goto out; ++#ifdef ENABLE_PKCS11 ++ if (is_rsa_pkcs11(key->rsa)) { ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ } else { ++#endif ++ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) ++ return ret; ++#ifdef ENABLE_PKCS11 + } +- +- if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) { +- ret = SSH_ERR_LIBCRYPTO_ERROR; ++#endif ++ ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data, ++ datalen); ++ EVP_PKEY_free(pkey); ++ if (ret < 0) { + goto out; + } ++ + if (len < slen) { + size_t diff = slen - len; + memmove(sig + diff, sig, len); +@@ -444,6 +453,7 @@ + ret = SSH_ERR_INTERNAL_ERROR; + goto out; + } ++ + /* encode signature */ + if ((b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; +@@ -464,7 +474,6 @@ + *lenp = len; + ret = 0; + out: +- explicit_bzero(digest, sizeof(digest)); + freezero(sig, slen); + sshbuf_free(b); + return ret; +@@ -476,10 +485,10 @@ + const u_char *data, size_t dlen, const char *alg, u_int compat, + struct sshkey_sig_details **detailsp) + { +- const BIGNUM *rsa_n; ++ EVP_PKEY *pkey = NULL; + char *sigtype = NULL; + int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; +- size_t len = 0, diff, modlen, hlen; ++ size_t len = 0, diff, modlen; + struct sshbuf *b = NULL; + u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; + +@@ -487,8 +496,7 @@ + sshkey_type_plain(key->type) != KEY_RSA || + sig == NULL || siglen == 0) + return SSH_ERR_INVALID_ARGUMENT; +- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); +- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) ++ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_KEY_LENGTH; + + if ((b = sshbuf_from(sig, siglen)) == NULL) +@@ -540,16 +548,13 @@ + explicit_bzero(sigblob, diff); + len = modlen; + } +- if ((hlen = ssh_digest_bytes(hash_alg)) == 0) { +- ret = SSH_ERR_INTERNAL_ERROR; +- goto out; +- } +- if ((ret = ssh_digest_memory(hash_alg, data, dlen, +- digest, sizeof(digest))) != 0) ++ ++ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) + goto out; + +- ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len, +- key->rsa); ++ ret = openssh_RSA_verify(hash_alg, data, dlen, sigblob, len, pkey); ++ EVP_PKEY_free(pkey); ++ + out: + freezero(sigblob, len); + free(sigtype); +@@ -558,125 +563,110 @@ + return ret; + } + +-/* +- * See: +- * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ +- * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn +- */ +- +-/* +- * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) +- * oiw(14) secsig(3) algorithms(2) 26 } +- */ +-static const u_char id_sha1[] = { +- 0x30, 0x21, /* type Sequence, length 0x21 (33) */ +- 0x30, 0x09, /* type Sequence, length 0x09 */ +- 0x06, 0x05, /* type OID, length 0x05 */ +- 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ +- 0x05, 0x00, /* NULL */ +- 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ +-}; +- +-/* +- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html +- * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) +- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) +- * id-sha256(1) } +- */ +-static const u_char id_sha256[] = { +- 0x30, 0x31, /* type Sequence, length 0x31 (49) */ +- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ +- 0x06, 0x09, /* type OID, length 0x09 */ +- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ +- 0x05, 0x00, /* NULL */ +- 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ +-}; +- +-/* +- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html +- * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) +- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) +- * id-sha256(3) } +- */ +-static const u_char id_sha512[] = { +- 0x30, 0x51, /* type Sequence, length 0x51 (81) */ +- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ +- 0x06, 0x09, /* type OID, length 0x09 */ +- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ +- 0x05, 0x00, /* NULL */ +- 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ +-}; +- + static int +-rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) ++openssh_RSA_verify(int hash_alg, const u_char *data, size_t datalen, ++ u_char *sigbuf, size_t siglen, EVP_PKEY *pkey) + { +- switch (hash_alg) { +- case SSH_DIGEST_SHA1: +- *oidp = id_sha1; +- *oidlenp = sizeof(id_sha1); +- break; +- case SSH_DIGEST_SHA256: +- *oidp = id_sha256; +- *oidlenp = sizeof(id_sha256); +- break; +- case SSH_DIGEST_SHA512: +- *oidp = id_sha512; +- *oidlenp = sizeof(id_sha512); +- break; +- default: +- return SSH_ERR_INVALID_ARGUMENT; +- } +- return 0; +-} ++ size_t rsasize = 0; ++ int ret; + +-static int +-openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, +- u_char *sigbuf, size_t siglen, RSA *rsa) +-{ +- size_t rsasize = 0, oidlen = 0, hlen = 0; +- int ret, len, oidmatch, hashmatch; +- const u_char *oid = NULL; +- u_char *decrypted = NULL; +- +- if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) +- return ret; +- ret = SSH_ERR_INTERNAL_ERROR; +- hlen = ssh_digest_bytes(hash_alg); +- if (hashlen != hlen) { +- ret = SSH_ERR_INVALID_ARGUMENT; +- goto done; +- } +- rsasize = RSA_size(rsa); ++ rsasize = EVP_PKEY_get_size(pkey); + if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || + siglen == 0 || siglen > rsasize) { + ret = SSH_ERR_INVALID_ARGUMENT; + goto done; + } +- if ((decrypted = malloc(rsasize)) == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; +- goto done; +- } +- if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, +- RSA_PKCS1_PADDING)) < 0) { +- ret = SSH_ERR_LIBCRYPTO_ERROR; +- goto done; +- } +- if (len < 0 || (size_t)len != hlen + oidlen) { +- ret = SSH_ERR_INVALID_FORMAT; +- goto done; +- } +- oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; +- hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; +- if (!oidmatch || !hashmatch) { +- ret = SSH_ERR_SIGNATURE_INVALID; +- goto done; +- } +- ret = 0; ++ ++ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, ++ sigbuf, siglen); ++ + done: +- freezero(decrypted, rsasize); + return ret; + } + ++int ++ssh_create_evp_rsa(const struct sshkey *k, EVP_PKEY **pkey) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ int ret = 0; ++ const BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; ++ const BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; ++ ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ RSA_get0_key(k->rsa, &n, &e, &d); ++ RSA_get0_factors(k->rsa, &p, &q); ++ RSA_get0_crt_params(k->rsa, &dmp1, &dmq1, &iqmp); ++ ++ if (n != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, n) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (e != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, e) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (d != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_D, d) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* setting this to param_build makes the creation process fail */ ++ if (p != NULL && ++ EVP_PKEY_set_bn_param(*pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, p) != 1) { ++ debug2_f("failed to add 'p' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (q != NULL && ++ EVP_PKEY_set_bn_param(*pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, q) != 1) { ++ debug2_f("failed to add 'q' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (dmp1 != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_EXPONENT1, dmp1) != 1) { ++ debug2_f("failed to add 'dmp1' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (dmq1 != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_EXPONENT2, dmq1) != 1) { ++ debug2_f("failed to add 'dmq1' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (iqmp != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_COEFFICIENT1, iqmp) != 1) { ++ debug2_f("failed to add 'iqmp' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ return ret; ++} ++ + static const struct sshkey_impl_funcs sshkey_rsa_funcs = { + /* .size = */ ssh_rsa_size, + /* .alloc = */ ssh_rsa_alloc, diff --git a/openssh-9.6p1-gsskex-new-api.patch b/openssh-9.6p1-gsskex-new-api.patch new file mode 100644 index 0000000..0f2eabb --- /dev/null +++ b/openssh-9.6p1-gsskex-new-api.patch @@ -0,0 +1,1965 @@ +diff --color -ruNp a/gss-genr.c b/gss-genr.c +--- a/gss-genr.c 2024-05-16 15:49:43.999411060 +0200 ++++ b/gss-genr.c 2024-06-26 12:17:55.586856954 +0200 +@@ -346,6 +346,7 @@ ssh_gssapi_build_ctx(Gssctxt **ctx) + (*ctx)->creds = GSS_C_NO_CREDENTIAL; + (*ctx)->client = GSS_C_NO_NAME; + (*ctx)->client_creds = GSS_C_NO_CREDENTIAL; ++ (*ctx)->first = 1; + } + + /* Delete our context, providing it has been built correctly */ +@@ -371,6 +372,12 @@ ssh_gssapi_delete_ctx(Gssctxt **ctx) + gss_release_name(&ms, &(*ctx)->client); + if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) + gss_release_cred(&ms, &(*ctx)->client_creds); ++ sshbuf_free((*ctx)->shared_secret); ++ sshbuf_free((*ctx)->server_pubkey); ++ sshbuf_free((*ctx)->server_host_key_blob); ++ sshbuf_free((*ctx)->server_blob); ++ explicit_bzero((*ctx)->hash, sizeof((*ctx)->hash)); ++ BN_clear_free((*ctx)->dh_client_pub); + + free(*ctx); + *ctx = NULL; +diff --color -ruNp a/kexgssc.c b/kexgssc.c +--- a/kexgssc.c 2024-05-16 15:49:43.820407648 +0200 ++++ b/kexgssc.c 2024-07-02 16:26:25.628746744 +0200 +@@ -47,566 +47,658 @@ + + #include "ssh-gss.h" + +-int +-kexgss_client(struct ssh *ssh) ++static int input_kexgss_hostkey(int, u_int32_t, struct ssh *); ++static int input_kexgss_continue(int, u_int32_t, struct ssh *); ++static int input_kexgss_complete(int, u_int32_t, struct ssh *); ++static int input_kexgss_error(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_group(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_continue(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_complete(int, u_int32_t, struct ssh *); ++ ++static int ++kexgss_final(struct ssh *ssh) + { + struct kex *kex = ssh->kex; +- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, +- recv_tok = GSS_C_EMPTY_BUFFER, +- gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; +- Gssctxt *ctxt; +- OM_uint32 maj_status, min_status, ret_flags; +- struct sshbuf *server_blob = NULL; +- struct sshbuf *shared_secret = NULL; +- struct sshbuf *server_host_key_blob = NULL; ++ Gssctxt *gss = kex->gss; + struct sshbuf *empty = NULL; +- u_char *msg; +- int type = 0; +- int first = 1; ++ struct sshbuf *shared_secret = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t hashlen; +- u_char c; + int r; + +- /* Initialise our GSSAPI world */ +- ssh_gssapi_build_ctx(&ctxt); +- if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) +- == GSS_C_NO_OID) +- fatal("Couldn't identify host exchange"); +- +- if (ssh_gssapi_import_name(ctxt, kex->gss_host)) +- fatal("Couldn't import hostname"); +- +- if (kex->gss_client && +- ssh_gssapi_client_identity(ctxt, kex->gss_client)) +- fatal("Couldn't acquire client credentials"); +- +- /* Step 1 */ +- switch (kex->kex_type) { +- case KEX_GSS_GRP1_SHA1: +- case KEX_GSS_GRP14_SHA1: +- case KEX_GSS_GRP14_SHA256: +- case KEX_GSS_GRP16_SHA512: +- r = kex_dh_keypair(kex); +- break; +- case KEX_GSS_NISTP256_SHA256: +- r = kex_ecdh_keypair(kex); +- break; +- case KEX_GSS_C25519_SHA256: +- r = kex_c25519_keypair(kex); +- break; +- default: +- fatal_f("Unexpected KEX type %d", kex->kex_type); +- } +- if (r != 0) { +- ssh_gssapi_delete_ctx(&ctxt); +- return r; +- } +- +- token_ptr = GSS_C_NO_BUFFER; +- +- do { +- debug("Calling gss_init_sec_context"); +- +- maj_status = ssh_gssapi_init_ctx(ctxt, +- kex->gss_deleg_creds, token_ptr, &send_tok, +- &ret_flags); +- +- if (GSS_ERROR(maj_status)) { +- /* XXX Useles code: Missing send? */ +- if (send_tok.length != 0) { +- if ((r = sshpkt_start(ssh, +- SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- } +- fatal("gss_init_context failed"); +- } +- +- /* If we've got an old receive buffer get rid of it */ +- if (token_ptr != GSS_C_NO_BUFFER) +- gss_release_buffer(&min_status, &recv_tok); +- +- if (maj_status == GSS_S_COMPLETE) { +- /* If mutual state flag is not true, kex fails */ +- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) +- fatal("Mutual authentication failed"); +- +- /* If integ avail flag is not true kex fails */ +- if (!(ret_flags & GSS_C_INTEG_FLAG)) +- fatal("Integrity check failed"); +- } +- +- /* +- * If we have data to send, then the last message that we +- * received cannot have been a 'complete'. +- */ +- if (send_tok.length != 0) { +- if (first) { +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0 || +- (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) +- fatal("failed to construct packet: %s", ssh_err(r)); +- first = 0; +- } else { +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0) +- fatal("failed to construct packet: %s", ssh_err(r)); +- } +- if ((r = sshpkt_send(ssh)) != 0) +- fatal("failed to send packet: %s", ssh_err(r)); +- gss_release_buffer(&min_status, &send_tok); +- +- /* If we've sent them data, they should reply */ +- 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_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); +- +- switch (type) { +- case SSH2_MSG_KEXGSS_CONTINUE: +- debug("Received GSSAPI_CONTINUE"); +- if (maj_status == GSS_S_COMPLETE) +- fatal("GSSAPI Continue received from server when complete"); +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("Failed to read token: %s", ssh_err(r)); +- break; +- case SSH2_MSG_KEXGSS_COMPLETE: +- debug("Received GSSAPI_COMPLETE"); +- if (msg_tok.value != NULL) +- fatal("Received GSSAPI_COMPLETE twice?"); +- if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || +- (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &msg_tok)) != 0) +- fatal("Failed to read message: %s", ssh_err(r)); +- +- /* Is there a token included? */ +- if ((r = sshpkt_get_u8(ssh, &c)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- if (c) { +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc( +- ssh, &recv_tok)) != 0) +- fatal("Failed to read token: %s", ssh_err(r)); +- /* If we're already complete - protocol error */ +- if (maj_status == GSS_S_COMPLETE) +- sshpkt_disconnect(ssh, "Protocol error: received token when complete"); +- } else { +- /* No token included */ +- if (maj_status != GSS_S_COMPLETE) +- sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); +- } +- if ((r = sshpkt_get_end(ssh)) != 0) { +- fatal("Expecting end of packet."); +- } +- break; +- case SSH2_MSG_KEXGSS_ERROR: +- debug("Received Error"); +- if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || +- (r = sshpkt_get_u32(ssh, &min_status)) != 0 || +- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || +- (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt_get failed: %s", ssh_err(r)); +- fatal("GSSAPI Error: \n%.400s", msg); +- default: +- sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", +- type); +- } +- token_ptr = &recv_tok; +- } else { +- /* No data, and not complete */ +- if (maj_status != GSS_S_COMPLETE) +- fatal("Not complete, and no token output"); +- } +- } while (maj_status & GSS_S_CONTINUE_NEEDED); +- + /* + * We _must_ have received a COMPLETE message in reply from the + * server, which will have set server_blob and msg_tok + */ + +- if (type != SSH2_MSG_KEXGSS_COMPLETE) +- fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); +- + /* compute shared secret */ + switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + case KEX_GSS_GRP14_SHA1: + case KEX_GSS_GRP14_SHA256: + case KEX_GSS_GRP16_SHA512: +- r = kex_dh_dec(kex, server_blob, &shared_secret); ++ r = kex_dh_dec(kex, gss->server_blob, &shared_secret); + break; + case KEX_GSS_C25519_SHA256: +- if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80) ++ if (sshbuf_ptr(gss->server_blob)[sshbuf_len(gss->server_blob)] & 0x80) + fatal("The received key has MSB of last octet set!"); +- r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ r = kex_c25519_dec(kex, gss->server_blob, &shared_secret); + break; + case KEX_GSS_NISTP256_SHA256: +- if (sshbuf_len(server_blob) != 65) +- fatal("The received NIST-P256 key did not match" +- "expected length (expected 65, got %zu)", sshbuf_len(server_blob)); ++ if (sshbuf_len(gss->server_blob) != 65) ++ fatal("The received NIST-P256 key did not match " ++ "expected length (expected 65, got %zu)", ++ sshbuf_len(gss->server_blob)); + +- if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) ++ if (sshbuf_ptr(gss->server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) + fatal("The received NIST-P256 key does not have first octet 0x04"); + +- r = kex_ecdh_dec(kex, server_blob, &shared_secret); ++ r = kex_ecdh_dec(kex, gss->server_blob, &shared_secret); + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; + } +- if (r != 0) ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } + + if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + hashlen = sizeof(hash); +- if ((r = kex_gen_hash( +- kex->hash_alg, +- kex->client_version, +- kex->server_version, +- kex->my, +- kex->peer, +- (server_host_key_blob ? server_host_key_blob : empty), +- kex->client_pub, +- server_blob, +- shared_secret, +- hash, &hashlen)) != 0) ++ r = kex_gen_hash(kex->hash_alg, kex->client_version, ++ kex->server_version, kex->my, kex->peer, ++ (gss->server_host_key_blob ? gss->server_host_key_blob : empty), ++ kex->client_pub, gss->server_blob, shared_secret, ++ hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) + fatal_f("Unexpected KEX type %d", kex->kex_type); + +- gssbuf.value = hash; +- gssbuf.length = hashlen; ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; + + /* Verify that the hash matches the MIC we just got. */ +- if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(ssh_gssapi_checkmic(gss, &gss->buf, &gss->msg_tok))) + sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); + +- gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, &gss->msg_tok); + + if (kex->gss_deleg_creds) +- ssh_gssapi_credentials_updated(ctxt); ++ ssh_gssapi_credentials_updated(gss); + + if (gss_kex_context == NULL) +- gss_kex_context = ctxt; ++ gss_kex_context = gss; + else +- ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + ++ if (kex->gss != NULL) { ++ sshbuf_free(gss->server_host_key_blob); ++ gss->server_host_key_blob = NULL; ++ sshbuf_free(gss->server_blob); ++ gss->server_blob = NULL; ++ } + out: +- explicit_bzero(hash, sizeof(hash)); + explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); +- sshbuf_free(empty); +- sshbuf_free(server_host_key_blob); +- sshbuf_free(server_blob); ++ explicit_bzero(hash, sizeof(hash)); + sshbuf_free(shared_secret); + sshbuf_free(kex->client_pub); + kex->client_pub = NULL; + return r; + } + ++static int ++kexgss_init_ctx(struct ssh *ssh, ++ gss_buffer_desc *token_ptr) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags; ++ int r; ++ ++ debug("Calling gss_init_sec_context"); ++ ++ gss->major = ssh_gssapi_init_ctx(gss, kex->gss_deleg_creds, ++ token_ptr, &send_tok, &ret_flags); ++ ++ if (GSS_ERROR(gss->major)) { ++ /* XXX Useless code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&gss->minor, token_ptr); ++ ++ if (gss->major == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (gss->first) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ gss->first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("failed to send packet: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, &input_kexgss_hostkey); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgss_continue); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, &input_kexgss_complete); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, &input_kexgss_error); ++ return 0; ++ } ++ /* No data, and not complete */ ++ if (gss->major != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgss_init_ctx(ssh, token_ptr); ++ ++ return kexgss_final(ssh); ++} ++ + int +-kexgssgex_client(struct ssh *ssh) ++kexgss_client(struct ssh *ssh) + { + struct kex *kex = ssh->kex; +- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, +- recv_tok = GSS_C_EMPTY_BUFFER, gssbuf, +- msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; +- Gssctxt *ctxt; +- OM_uint32 maj_status, min_status, ret_flags; +- struct sshbuf *shared_secret = NULL; +- BIGNUM *p = NULL; +- BIGNUM *g = NULL; +- struct sshbuf *buf = NULL; +- struct sshbuf *server_host_key_blob = NULL; +- struct sshbuf *server_blob = NULL; +- BIGNUM *dh_server_pub = NULL; +- u_char *msg; +- int type = 0; +- int first = 1; +- u_char hash[SSH_DIGEST_MAX_LENGTH]; +- size_t hashlen; +- const BIGNUM *pub_key, *dh_p, *dh_g; +- int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; +- struct sshbuf *empty = NULL; +- u_char c; + int r; + + /* Initialise our GSSAPI world */ +- ssh_gssapi_build_ctx(&ctxt); +- if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) +- == GSS_C_NO_OID) ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (ssh_gssapi_id_kex(kex->gss, kex->name, kex->kex_type) == GSS_C_NO_OID) + fatal("Couldn't identify host exchange"); + +- if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ if (ssh_gssapi_import_name(kex->gss, kex->gss_host)) + fatal("Couldn't import hostname"); + + if (kex->gss_client && +- ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ ssh_gssapi_client_identity(kex->gss, kex->gss_client)) + fatal("Couldn't acquire client credentials"); + +- debug("Doing group exchange"); +- nbits = dh_estimate(kex->dh_need * 8); ++ /* Step 1 */ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_keypair(kex); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_keypair(kex); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_keypair(kex); ++ break; ++ default: ++ fatal_f("Unexpected KEX type %d", kex->kex_type); ++ } ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return r; ++ } ++ return kexgss_init_ctx(ssh, GSS_C_NO_BUFFER); ++} + +- kex->min = DH_GRP_MIN; +- kex->max = DH_GRP_MAX; +- kex->nbits = nbits; +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || +- (r = sshpkt_put_u32(ssh, min)) != 0 || +- (r = sshpkt_put_u32(ssh, nbits)) != 0 || +- (r = sshpkt_put_u32(ssh, max)) != 0 || +- (r = sshpkt_send(ssh)) != 0) +- fatal("Failed to construct a packet: %s", ssh_err(r)); ++static int ++input_kexgss_hostkey(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ u_char *tmp = NULL; ++ size_t tmp_len = 0; ++ int r; ++ ++ debug("Received KEXGSS_HOSTKEY"); ++ if (gss->server_host_key_blob) ++ fatal("Server host key received more than once"); ++ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) ++ fatal("Failed to read server host key: %s", ssh_err(r)); ++ if ((gss->server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) ++ fatal("sshbuf_from failed"); ++ return 0; ++} + +- if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0) +- fatal("Error: %s", ssh_err(r)); ++static int ++input_kexgss_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ int r; + +- if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || +- (r = sshpkt_get_bignum2(ssh, &g)) != 0 || ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_CONTINUE"); ++ if (gss->major == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) +- fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); ++ fatal("Failed to read token: %s", ssh_err(r)); ++ if (!(gss->major & GSS_S_CONTINUE_NEEDED)) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ return kexgss_init_ctx(ssh, &recv_tok); ++} + +- if (BN_num_bits(p) < min || BN_num_bits(p) > max) +- fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", +- min, BN_num_bits(p), max); ++static int ++input_kexgss_complete(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ u_char c; ++ int r; + +- if ((kex->dh = dh_new_group(g, p)) == NULL) +- fatal("dn_new_group() failed"); +- p = g = NULL; /* belong to kex->dh now */ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_COMPLETE"); ++ if (gss->msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &gss->server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &gss->msg_tok)) != 0) ++ fatal("Failed to read message: %s", ssh_err(r)); ++ ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (gss->major == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ if (gss->major != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ if ((r = sshpkt_get_end(ssh)) != 0) ++ fatal("Expecting end of packet."); + +- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) +- goto out; +- DH_get0_key(kex->dh, &pub_key, NULL); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgss_init_ctx(ssh, &recv_tok); + +- token_ptr = GSS_C_NO_BUFFER; ++ return kexgss_final(ssh); ++} + +- do { +- /* Step 2 - call GSS_Init_sec_context() */ +- debug("Calling gss_init_sec_context"); +- +- maj_status = ssh_gssapi_init_ctx(ctxt, +- kex->gss_deleg_creds, token_ptr, &send_tok, +- &ret_flags); +- +- if (GSS_ERROR(maj_status)) { +- /* XXX Useles code: Missing send? */ +- if (send_tok.length != 0) { +- if ((r = sshpkt_start(ssh, +- SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- } +- fatal("gss_init_context failed"); +- } ++static int ++input_kexgss_error(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ u_char *msg; ++ int r; + +- /* If we've got an old receive buffer get rid of it */ +- if (token_ptr != GSS_C_NO_BUFFER) +- gss_release_buffer(&min_status, &recv_tok); +- +- if (maj_status == GSS_S_COMPLETE) { +- /* If mutual state flag is not true, kex fails */ +- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) +- fatal("Mutual authentication failed"); +- +- /* If integ avail flag is not true kex fails */ +- if (!(ret_flags & GSS_C_INTEG_FLAG)) +- fatal("Integrity check failed"); +- } ++ debug("Received Error"); ++ if ((r = sshpkt_get_u32(ssh, &gss->major)) != 0 || ++ (r = sshpkt_get_u32(ssh, &gss->minor)) != 0 || ++ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || ++ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt_get failed: %s", ssh_err(r)); ++ fatal("GSSAPI Error: \n%.400s", msg); ++ return 0; ++} + +- /* +- * If we have data to send, then the last message that we +- * received cannot have been a 'complete'. +- */ +- if (send_tok.length != 0) { +- if (first) { +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0 || +- (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- first = 0; +- } else { +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh,send_tok.value, +- send_tok.length)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- } +- if ((r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt_send failed: %s", ssh_err(r)); +- gss_release_buffer(&min_status, &send_tok); +- +- /* If we've sent them data, they should reply */ +- 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_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); +- +- switch (type) { +- case SSH2_MSG_KEXGSS_CONTINUE: +- debug("Received GSSAPI_CONTINUE"); +- if (maj_status == GSS_S_COMPLETE) +- fatal("GSSAPI Continue received from server when complete"); +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- break; +- case SSH2_MSG_KEXGSS_COMPLETE: +- debug("Received GSSAPI_COMPLETE"); +- if (msg_tok.value != NULL) +- fatal("Received GSSAPI_COMPLETE twice?"); +- if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || +- (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &msg_tok)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- +- /* Is there a token included? */ +- if ((r = sshpkt_get_u8(ssh, &c)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- if (c) { +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc( +- ssh, &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- /* If we're already complete - protocol error */ +- if (maj_status == GSS_S_COMPLETE) +- sshpkt_disconnect(ssh, "Protocol error: received token when complete"); +- } else { +- /* No token included */ +- if (maj_status != GSS_S_COMPLETE) +- sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); +- } +- break; +- case SSH2_MSG_KEXGSS_ERROR: +- debug("Received Error"); +- if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || +- (r = sshpkt_get_u32(ssh, &min_status)) != 0 || +- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || +- (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- fatal("GSSAPI Error: \n%.400s", msg); +- default: +- sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", +- type); +- } +- token_ptr = &recv_tok; +- } else { +- /* No data, and not complete */ +- if (maj_status != GSS_S_COMPLETE) +- fatal("Not complete, and no token output"); +- } +- } while (maj_status & GSS_S_CONTINUE_NEEDED); ++/*******************************************************/ ++/******************** KEXGSSGEX ************************/ ++/*******************************************************/ ++ ++int ++kexgssgex_client(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ int r; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (ssh_gssapi_id_kex(kex->gss, kex->name, kex->kex_type) == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ if (ssh_gssapi_import_name(kex->gss, kex->gss_host)) ++ fatal("Couldn't import hostname"); ++ ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(kex->gss, kex->gss_client)) ++ fatal("Couldn't acquire client credentials"); ++ ++ debug("Doing group exchange"); ++ kex->min = DH_GRP_MIN; ++ kex->max = DH_GRP_MAX; ++ kex->nbits = dh_estimate(kex->dh_need * 8); ++ ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->min)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->max)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("Failed to construct a packet: %s", ssh_err(r)); ++ ++ debug("Wait SSH2_MSG_KEXGSS_GROUP"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUP, &input_kexgssgex_group); ++ return 0; ++} ++ ++static int ++kexgssgex_final(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ struct sshbuf *buf = NULL; ++ struct sshbuf *empty = NULL; ++ struct sshbuf *shared_secret = NULL; ++ BIGNUM *dh_server_pub = NULL; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ int r = SSH_ERR_INTERNAL_ERROR; + + /* + * We _must_ have received a COMPLETE message in reply from the +- * server, which will have set dh_server_pub and msg_tok ++ * server, which will have set server_blob and msg_tok + */ + +- if (type != SSH2_MSG_KEXGSS_COMPLETE) +- fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); +- + /* 7. C verifies that the key Q_S is valid */ + /* 8. C computes shared secret */ + if ((buf = sshbuf_new()) == NULL || +- (r = sshbuf_put_stringb(buf, server_blob)) != 0 || +- (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) ++ (r = sshbuf_put_stringb(buf, gss->server_blob)) != 0 || ++ (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } + sshbuf_free(buf); + buf = NULL; + + if ((shared_secret = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + +- if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) ++ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } ++ + if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + ++ DH_get0_key(kex->dh, &pub_key, NULL); + DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); + hashlen = sizeof(hash); +- if ((r = kexgex_hash( +- kex->hash_alg, +- kex->client_version, +- kex->server_version, +- kex->my, +- kex->peer, +- (server_host_key_blob ? server_host_key_blob : empty), +- kex->min, kex->nbits, kex->max, +- dh_p, dh_g, +- pub_key, +- dh_server_pub, +- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), +- hash, &hashlen)) != 0) ++ r = kexgex_hash(kex->hash_alg, kex->client_version, ++ kex->server_version, kex->my, kex->peer, ++ (gss->server_host_key_blob ? gss->server_host_key_blob : empty), ++ kex->min, kex->nbits, kex->max, dh_p, dh_g, pub_key, ++ dh_server_pub, sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), ++ hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) + fatal("Failed to calculate hash: %s", ssh_err(r)); + +- gssbuf.value = hash; +- gssbuf.length = hashlen; ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; + + /* Verify that the hash matches the MIC we just got. */ +- if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(ssh_gssapi_checkmic(gss, &gss->buf, &gss->msg_tok))) + sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); + +- gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, &gss->msg_tok); + + if (kex->gss_deleg_creds) +- ssh_gssapi_credentials_updated(ctxt); ++ ssh_gssapi_credentials_updated(gss); + + if (gss_kex_context == NULL) +- gss_kex_context = ctxt; ++ gss_kex_context = gss; + else +- ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + + /* Finally derive the keys and send them */ + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); ++ ++ if (kex->gss != NULL) { ++ sshbuf_free(gss->server_host_key_blob); ++ gss->server_host_key_blob = NULL; ++ sshbuf_free(gss->server_blob); ++ gss->server_blob = NULL; ++ } + out: +- sshbuf_free(buf); +- sshbuf_free(server_blob); +- sshbuf_free(empty); + explicit_bzero(hash, sizeof(hash)); + DH_free(kex->dh); + kex->dh = NULL; + BN_clear_free(dh_server_pub); + sshbuf_free(shared_secret); +- sshbuf_free(server_host_key_blob); + return r; + } + ++static int ++kexgssgex_init_ctx(struct ssh *ssh, ++ gss_buffer_desc *token_ptr) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ const BIGNUM *pub_key; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags; ++ int r; ++ ++ /* Step 2 - call GSS_Init_sec_context() */ ++ debug("Calling gss_init_sec_context"); ++ ++ gss->major = ssh_gssapi_init_ctx(gss, kex->gss_deleg_creds, ++ token_ptr, &send_tok, &ret_flags); ++ ++ if (GSS_ERROR(gss->major)) { ++ /* XXX Useless code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&gss->minor, token_ptr); ++ ++ if (gss->major == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (gss->first) { ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ gss->first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("failed to send packet: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, &input_kexgss_hostkey); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgssgex_continue); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, &input_kexgssgex_complete); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, &input_kexgss_error); ++ return 0; ++ } ++ /* No data, and not complete */ ++ if (gss->major != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgssgex_init_ctx(ssh, token_ptr); ++ ++ return kexgssgex_final(ssh); ++} ++ ++static int ++input_kexgssgex_group(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ BIGNUM *p = NULL; ++ BIGNUM *g = NULL; ++ int r; ++ ++ debug("Received SSH2_MSG_KEXGSS_GROUP"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUP, NULL); ++ ++ if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &g)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); ++ ++ if (BN_num_bits(p) < kex->min || BN_num_bits(p) > kex->max) ++ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", ++ kex->min, BN_num_bits(p), kex->max); ++ ++ if ((kex->dh = dh_new_group(g, p)) == NULL) ++ fatal("dn_new_group() failed"); ++ p = g = NULL; /* belong to kex->dh now */ ++ ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ return r; ++ } ++ ++ return kexgssgex_init_ctx(ssh, GSS_C_NO_BUFFER); ++} ++ ++static int ++input_kexgssgex_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ int r; ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_CONTINUE"); ++ if (gss->major == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ if (!(gss->major & GSS_S_CONTINUE_NEEDED)) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ return kexgssgex_init_ctx(ssh, &recv_tok); ++} ++ ++static int ++input_kexgssgex_complete(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ u_char c; ++ int r; ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_COMPLETE"); ++ if (gss->msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &gss->server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &gss->msg_tok)) != 0) ++ fatal("Failed to read message: %s", ssh_err(r)); ++ ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (gss->major == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ if (gss->major != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ if ((r = sshpkt_get_end(ssh)) != 0) ++ fatal("Expecting end of packet."); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgssgex_init_ctx(ssh, &recv_tok); ++ ++ return kexgssgex_final(ssh); ++} ++ + #endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ +diff --color -ruNp a/kexgsss.c b/kexgsss.c +--- a/kexgsss.c 2024-05-16 15:49:43.820407648 +0200 ++++ b/kexgsss.c 2024-07-02 16:29:05.744790839 +0200 +@@ -50,33 +50,18 @@ + + extern ServerOptions options; + ++static int input_kexgss_init(int, u_int32_t, struct ssh *); ++static int input_kexgss_continue(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_groupreq(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_init(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_continue(int, u_int32_t, struct ssh *); ++ + int + kexgss_server(struct ssh *ssh) + { + struct kex *kex = ssh->kex; +- OM_uint32 maj_status, min_status; +- +- /* +- * Some GSSAPI implementations use the input value of ret_flags (an +- * output variable) as a means of triggering mechanism specific +- * features. Initializing it to zero avoids inadvertently +- * activating this non-standard behaviour. +- */ +- +- OM_uint32 ret_flags = 0; +- 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; +- struct sshbuf *client_pubkey = NULL; +- struct sshbuf *server_pubkey = NULL; +- struct sshbuf *empty = sshbuf_new(); +- int type = 0; + gss_OID oid; + char *mechs; +- u_char hash[SSH_DIGEST_MAX_LENGTH]; +- size_t hashlen; +- int r; + + /* Initialise GSSAPI */ + +@@ -92,135 +77,91 @@ kexgss_server(struct ssh *ssh) + debug2_f("Identifying %s", kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) +- fatal("Unknown gssapi mechanism"); ++ fatal("Unknown gssapi mechanism"); + + debug2_f("Acquiring credentials"); + +- if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&kex->gss, oid))) + fatal("Unable to acquire credentials for the server"); + +- do { +- debug("Wait SSH2_MSG_KEXGSS_INIT"); +- type = ssh_packet_read(ssh); +- switch(type) { +- case SSH2_MSG_KEXGSS_INIT: +- if (gssbuf.value != NULL) +- fatal("Received KEXGSS_INIT after initialising"); +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (kex->gss == NULL) ++ fatal("Unable to allocate memory for gss context"); ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, &input_kexgss_init); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgss_continue); ++ debug("Wait SSH2_MSG_KEXGSS_INIT"); ++ return 0; ++} + +- switch (kex->kex_type) { +- case KEX_GSS_GRP1_SHA1: +- case KEX_GSS_GRP14_SHA1: +- case KEX_GSS_GRP14_SHA256: +- case KEX_GSS_GRP16_SHA512: +- r = kex_dh_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); +- break; +- case KEX_GSS_NISTP256_SHA256: +- r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); +- break; +- case KEX_GSS_C25519_SHA256: +- r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); +- break; +- default: +- fatal_f("Unexpected KEX type %d", kex->kex_type); +- } +- if (r != 0) +- 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, +- &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- break; +- default: +- sshpkt_disconnect(ssh, +- "Protocol error: didn't expect packet type %d", +- type); +- } ++static inline void ++kexgss_accept_ctx(struct ssh *ssh, ++ gss_buffer_desc *recv_tok, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ int r; + +- maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, +- &send_tok, &ret_flags); ++ gss->major = mm_ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags); ++ gss_release_buffer(&gss->minor, recv_tok); + +- gss_release_buffer(&min_status, &recv_tok); ++ if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) ++ fatal("Zero length token output when incomplete"); + +- if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) +- fatal("Zero length token output when incomplete"); ++ if (gss->buf.value == NULL) ++ fatal("No client public key"); + +- if (gssbuf.value == NULL) +- fatal("No client public key"); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, send_tok); ++ } ++} + +- if (maj_status & GSS_S_CONTINUE_NEEDED) { +- debug("Sending GSSAPI_CONTINUE"); +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || +- (r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- gss_release_buffer(&min_status, &send_tok); +- } +- } while (maj_status & GSS_S_CONTINUE_NEEDED); ++static inline int ++kexgss_final(struct ssh *ssh, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc msg_tok; ++ int r; ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); + +- if (GSS_ERROR(maj_status)) { +- if (send_tok.length > 0) { ++ if (GSS_ERROR(gss->major)) { ++ if (send_tok->length > 0) { + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } + fatal("accept_ctx died"); + } + +- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ if (!(*ret_flags & GSS_C_MUTUAL_FLAG)) + fatal("Mutual Authentication flag wasn't set"); + +- if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ if (!(*ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + +- if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(gss, &gss->buf, &msg_tok))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || +- (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || ++ (r = sshpkt_put_stringb(ssh, gss->server_pubkey)) != 0 || + (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + +- if (send_tok.length != 0) { ++ if (send_tok->length != 0) { + if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } else { + if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ +@@ -229,59 +170,139 @@ kexgss_server(struct ssh *ssh) + if ((r = sshpkt_send(ssh)) != 0) + fatal("sshpkt_send failed: %s", ssh_err(r)); + +- gss_release_buffer(&min_status, &send_tok); +- gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, send_tok); ++ gss_release_buffer(&gss->minor, &msg_tok); + + if (gss_kex_context == NULL) +- gss_kex_context = ctxt; ++ gss_kex_context = gss; + else +- ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + +- if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ if ((r = kex_derive_keys(ssh, gss->hash, gss->hashlen, gss->shared_secret)) == 0) + r = kex_send_newkeys(ssh); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); +-out: +- sshbuf_free(empty); +- explicit_bzero(hash, sizeof(hash)); +- sshbuf_free(shared_secret); +- sshbuf_free(client_pubkey); +- sshbuf_free(server_pubkey); ++ ++ if (kex->gss != NULL) { ++ explicit_bzero(gss->hash, sizeof(gss->hash)); ++ sshbuf_free(gss->shared_secret); ++ gss->shared_secret = NULL; ++ sshbuf_free(gss->server_pubkey); ++ gss->server_pubkey = NULL; ++ } + return r; + } + +-int +-kexgssgex_server(struct ssh *ssh) ++static int ++input_kexgss_init(int type, ++ u_int32_t seq, ++ struct ssh *ssh) + { + struct kex *kex = ssh->kex; +- OM_uint32 maj_status, min_status; ++ Gssctxt *gss = kex->gss; ++ struct sshbuf *empty; ++ struct sshbuf *client_pubkey = NULL; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ debug("SSH2_MSG_KEXGSS_INIT received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); + +- /* +- * Some GSSAPI implementations use the input value of ret_flags (an +- * output variable) as a means of triggering mechanism specific +- * features. Initializing it to zero avoids inadvertently +- * activating this non-standard behaviour. ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ default: ++ fatal_f("Unexpected KEX type %d", kex->kex_type); ++ } ++ if (r != 0) { ++ sshbuf_free(client_pubkey); ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return r; ++ } ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ ++ if ((empty = sshbuf_new()) == NULL) { ++ sshbuf_free(client_pubkey); ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ /* Calculate the hash early so we can free the ++ * client_pubkey, which has reference to the parent ++ * buffer state->incoming_packet + */ ++ gss->hashlen = sizeof(gss->hash); ++ r = kex_gen_hash(kex->hash_alg, kex->client_version, kex->server_version, ++ kex->peer, kex->my, empty, client_pubkey, gss->server_pubkey, ++ gss->shared_secret, gss->hash, &gss->hashlen); ++ sshbuf_free(empty); ++ sshbuf_free(client_pubkey); ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return r; ++ } ++ ++ gss->buf.value = gss->hash; ++ gss->buf.length = gss->hashlen; ++ ++ kexgss_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; + ++ return kexgss_final(ssh, &send_tok, &ret_flags); ++} ++ ++static int ++input_kexgss_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; + OM_uint32 ret_flags = 0; +- gss_buffer_desc gssbuf, recv_tok, msg_tok; +- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; +- Gssctxt *ctxt = NULL; +- struct sshbuf *shared_secret = NULL; +- int type = 0; ++ int r; ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ kexgss_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgss_final(ssh, &send_tok, &ret_flags); ++} ++ ++/*******************************************************/ ++/******************** KEXGSSGEX ************************/ ++/*******************************************************/ ++ ++int ++kexgssgex_server(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; + gss_OID oid; + char *mechs; +- u_char hash[SSH_DIGEST_MAX_LENGTH]; +- size_t hashlen; +- BIGNUM *dh_client_pub = NULL; +- const BIGNUM *pub_key, *dh_p, *dh_g; +- int min = -1, max = -1, nbits = -1; +- int cmin = -1, cmax = -1; /* client proposal */ +- struct sshbuf *empty = sshbuf_new(); +- int r; + + /* Initialise GSSAPI */ + +@@ -289,153 +310,125 @@ kexgssgex_server(struct ssh *ssh) + * in the GSSAPI code are no longer available. This kludges them back + * into life + */ +- if (!ssh_gssapi_oid_table_ok()) +- if ((mechs = ssh_gssapi_server_mechanisms())) +- free(mechs); ++ if (!ssh_gssapi_oid_table_ok()) { ++ mechs = ssh_gssapi_server_mechanisms(); ++ free(mechs); ++ } + + debug2_f("Identifying %s", kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) +- fatal("Unknown gssapi mechanism"); ++ fatal("Unknown gssapi mechanism"); + + debug2_f("Acquiring credentials"); + +- if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&kex->gss, oid))) + fatal("Unable to acquire credentials for the server"); + +- /* 5. S generates an ephemeral key pair (do the allocations early) */ +- debug("Doing group exchange"); +- ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUPREQ); +- /* store client proposal to provide valid signature */ +- if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || +- (r = sshpkt_get_u32(ssh, &nbits)) != 0 || +- (r = sshpkt_get_u32(ssh, &cmax)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- kex->nbits = nbits; +- kex->min = cmin; +- kex->max = cmax; +- min = MAX(DH_GRP_MIN, cmin); +- max = MIN(DH_GRP_MAX, cmax); +- nbits = MAXIMUM(DH_GRP_MIN, nbits); +- nbits = MINIMUM(DH_GRP_MAX, nbits); +- if (max < min || nbits < min || max < nbits) +- fatal("GSS_GEX, bad parameters: %d !< %d !< %d", +- min, nbits, max); +- kex->dh = mm_choose_dh(min, nbits, max); +- if (kex->dh == NULL) { +- sshpkt_disconnect(ssh, "Protocol error: no matching group found"); +- fatal("Protocol error: no matching group found"); +- } ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (kex->gss == NULL) ++ fatal("Unable to allocate memory for gss context"); + +- DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 || +- (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || +- (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || +- (r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- +- if ((r = ssh_packet_write_wait(ssh)) != 0) +- fatal("ssh_packet_write_wait: %s", ssh_err(r)); +- +- /* Compute our exchange value in parallel with the client */ +- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) +- goto out; ++ debug("Doing group exchange"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUPREQ, &input_kexgssgex_groupreq); ++ return 0; ++} + +- do { +- debug("Wait SSH2_MSG_GSSAPI_INIT"); +- type = ssh_packet_read(ssh); +- switch(type) { +- case SSH2_MSG_KEXGSS_INIT: +- if (dh_client_pub != NULL) +- fatal("Received KEXGSS_INIT after initialising"); +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); ++static inline void ++kexgssgex_accept_ctx(struct ssh *ssh, ++ gss_buffer_desc *recv_tok, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ int r; + +- /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ +- break; +- case SSH2_MSG_KEXGSS_CONTINUE: +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- break; +- default: +- sshpkt_disconnect(ssh, +- "Protocol error: didn't expect packet type %d", +- type); +- } ++ gss->major = mm_ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags); ++ gss_release_buffer(&gss->minor, recv_tok); + +- maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, +- &send_tok, &ret_flags); ++ if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) ++ fatal("Zero length token output when incomplete"); + +- gss_release_buffer(&min_status, &recv_tok); ++ if (gss->dh_client_pub == NULL) ++ fatal("No client public key"); + +- if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) +- fatal("Zero length token output when incomplete"); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, send_tok); ++ } ++} + +- if (dh_client_pub == NULL) +- fatal("No client public key"); ++static inline int ++kexgssgex_final(struct ssh *ssh, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc msg_tok; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ struct sshbuf *shared_secret = NULL; ++ struct sshbuf *empty = NULL; ++ int r; + +- if (maj_status & GSS_S_CONTINUE_NEEDED) { +- debug("Sending GSSAPI_CONTINUE"); +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || +- (r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- gss_release_buffer(&min_status, &send_tok); +- } +- } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); + +- if (GSS_ERROR(maj_status)) { +- if (send_tok.length > 0) { ++ if (GSS_ERROR(gss->major)) { ++ if (send_tok->length > 0) { + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } + fatal("accept_ctx died"); + } + +- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ if (!(*ret_flags & GSS_C_MUTUAL_FLAG)) + fatal("Mutual Authentication flag wasn't set"); + +- if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ if (!(*ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + + /* calculate shared secret */ +- if ((shared_secret = sshbuf_new()) == NULL) { ++ shared_secret = sshbuf_new(); ++ if (shared_secret == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) ++ if ((r = kex_dh_compute_key(kex, gss->dh_client_pub, shared_secret)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } ++ ++ if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + + DH_get0_key(kex->dh, &pub_key, NULL); + DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); + hashlen = sizeof(hash); +- if ((r = kexgex_hash( +- kex->hash_alg, +- kex->client_version, +- kex->server_version, +- kex->peer, +- kex->my, +- empty, +- cmin, nbits, cmax, +- dh_p, dh_g, +- dh_client_pub, +- pub_key, +- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), +- hash, &hashlen)) != 0) ++ r = kexgex_hash(kex->hash_alg, kex->client_version, kex->server_version, ++ kex->peer, kex->my, empty, kex->min, kex->nbits, kex->max, dh_p, dh_g, ++ gss->dh_client_pub, pub_key, sshbuf_ptr(shared_secret), ++ sshbuf_len(shared_secret), hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) + fatal("kexgex_hash failed: %s", ssh_err(r)); + +- gssbuf.value = hash; +- gssbuf.length = hashlen; ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; + +- if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(gss, &gss->buf, &msg_tok))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || +@@ -443,24 +436,24 @@ kexgssgex_server(struct ssh *ssh) + (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + +- if (send_tok.length != 0) { ++ if (send_tok->length != 0) { + if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } else { + if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ + fatal("sshpkt failed: %s", ssh_err(r)); + } + if ((r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); ++ fatal("sshpkt_send failed: %s", ssh_err(r)); + +- gss_release_buffer(&min_status, &send_tok); +- gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, send_tok); ++ gss_release_buffer(&gss->minor, &msg_tok); + + if (gss_kex_context == NULL) +- gss_kex_context = ctxt; ++ gss_kex_context = gss; + else +- ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + + /* Finally derive the keys and send them */ + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) +@@ -470,13 +463,128 @@ kexgssgex_server(struct ssh *ssh) + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); ++ ++ if (kex->gss != NULL) ++ BN_clear_free(gss->dh_client_pub); ++ + out: +- sshbuf_free(empty); + explicit_bzero(hash, sizeof(hash)); + DH_free(kex->dh); + kex->dh = NULL; +- BN_clear_free(dh_client_pub); + sshbuf_free(shared_secret); + return r; + } ++ ++static int ++input_kexgssgex_groupreq(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ const BIGNUM *dh_p, *dh_g; ++ int min = -1, max = -1, nbits = -1; ++ int cmin = -1, cmax = -1; /* client proposal */ ++ int r; ++ ++ /* 5. S generates an ephemeral key pair (do the allocations early) */ ++ ++ debug("SSH2_MSG_KEXGSS_GROUPREQ received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUPREQ, NULL); ++ ++ /* store client proposal to provide valid signature */ ++ if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || ++ (r = sshpkt_get_u32(ssh, &nbits)) != 0 || ++ (r = sshpkt_get_u32(ssh, &cmax)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ kex->nbits = nbits; ++ kex->min = cmin; ++ kex->max = cmax; ++ min = MAX(DH_GRP_MIN, cmin); ++ max = MIN(DH_GRP_MAX, cmax); ++ nbits = MAXIMUM(DH_GRP_MIN, nbits); ++ nbits = MINIMUM(DH_GRP_MAX, nbits); ++ ++ if (max < min || nbits < min || max < nbits) ++ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", min, nbits, max); ++ ++ kex->dh = mm_choose_dh(min, nbits, max); ++ if (kex->dh == NULL) { ++ sshpkt_disconnect(ssh, "Protocol error: no matching group found"); ++ fatal("Protocol error: no matching group found"); ++ } ++ ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ if ((r = ssh_packet_write_wait(ssh)) != 0) ++ fatal("ssh_packet_write_wait: %s", ssh_err(r)); ++ ++ /* Compute our exchange value in parallel with the client */ ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ return r; ++ } ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, &input_kexgssgex_init); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgssgex_continue); ++ debug("Wait SSH2_MSG_KEXGSS_INIT"); ++ return 0; ++} ++ ++static int ++input_kexgssgex_init(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ debug("SSH2_MSG_KEXGSS_INIT received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &gss->dh_client_pub)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ ++ kexgssgex_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgssgex_final(ssh, &send_tok, &ret_flags); ++} ++ ++static int ++input_kexgssgex_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ kexgssgex_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgssgex_final(ssh, &send_tok, &ret_flags); ++} ++ + #endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ +diff --color -ruNp a/kex.h b/kex.h +--- a/kex.h 2024-05-16 15:49:43.986410812 +0200 ++++ b/kex.h 2024-06-18 12:19:48.580347469 +0200 +@@ -29,6 +29,10 @@ + #include "mac.h" + #include "crypto_api.h" + ++#ifdef GSSAPI ++# include "ssh-gss.h" /* Gssctxt */ ++#endif ++ + #ifdef WITH_OPENSSL + # include + # include +@@ -177,6 +181,7 @@ struct kex { + int hash_alg; + int ec_nid; + #ifdef GSSAPI ++ Gssctxt *gss; + int gss_deleg_creds; + int gss_trust_dns; + char *gss_host; +diff --color -ruNp a/ssh-gss.h b/ssh-gss.h +--- a/ssh-gss.h 2024-05-16 15:49:43.837407972 +0200 ++++ b/ssh-gss.h 2024-06-27 14:12:48.659866937 +0200 +@@ -88,6 +88,8 @@ extern char **k5users_allowed_cmds; + KEX_GSS_GRP14_SHA1_ID "," \ + KEX_GSS_GEX_SHA1_ID + ++#include "digest.h" /* SSH_DIGEST_MAX_LENGTH */ ++ + typedef struct { + char *filename; + char *envvar; +@@ -127,6 +129,16 @@ typedef struct { + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ + gss_cred_id_t client_creds; /* both */ ++ struct sshbuf *shared_secret; /* both */ ++ struct sshbuf *server_pubkey; /* server */ ++ struct sshbuf *server_blob; /* client */ ++ struct sshbuf *server_host_key_blob; /* client */ ++ gss_buffer_desc msg_tok; /* client */ ++ gss_buffer_desc buf; /* both */ ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; /* both */ ++ size_t hashlen; /* both */ ++ int first; /* client */ ++ BIGNUM *dh_client_pub; /* server (gex) */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; diff --git a/openssh-9.6p1-pam-rhost.patch b/openssh-9.6p1-pam-rhost.patch new file mode 100644 index 0000000..b1b0d04 --- /dev/null +++ b/openssh-9.6p1-pam-rhost.patch @@ -0,0 +1,32 @@ +From 26f366e263e575c4e1a18e2e64ba418f58878b37 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Mon, 20 Mar 2023 20:22:14 +0100 +Subject: [PATCH] Only set PAM_RHOST if the remote host is not "UNKNOWN" + +When using sshd's -i option with stdio that is not a AF_INET/AF_INET6 +socket, auth_get_canonical_hostname() returns "UNKNOWN" which is then +set as the value of PAM_RHOST, causing pam to try to do a reverse DNS +query of "UNKNOWN", which times out multiple times, causing a +substantial slowdown when logging in. + +To fix this, let's only set PAM_RHOST if the hostname is not "UNKNOWN". +--- + auth-pam.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/auth-pam.c b/auth-pam.c +index e143304e3..39b4e4563 100644 +--- a/auth-pam.c ++++ b/auth-pam.c +@@ -735,7 +735,7 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt) + sshpam_laddr = get_local_ipaddr( + ssh_packet_get_connection_in(ssh)); + } +- if (sshpam_rhost != NULL) { ++ if (sshpam_rhost != NULL && strcmp(sshpam_rhost, "UNKNOWN") != 0) { + debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost); + sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, + sshpam_rhost); +-- +2.44.0 + diff --git a/openssh-9.8p1.tar.gz.asc b/openssh-9.8p1.tar.gz.asc new file mode 100644 index 0000000..18dc27e --- /dev/null +++ b/openssh-9.8p1.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmaCMn0ACgkQKj9BTnNg +YLrjcBAAgO7xhKUXp8YxdqSZigDbcHu7T37bm1pRTKg2ihPepz+q6pV+DY8AHSRu +eyuOCOHYzjLyArFpiMX3z9iT2NqO+KNBvKQoh8loaxNrECmgRGk2jBEKiibFSP5M +i6CYkF3sET9xnVDkt4P6KievWXY1/Tl93qve3K2a/bvvgT8s2AaBMM8u4BMGNm3D +sc3A6euN0aiXRts2V6I885VyrQDMK++E7+eTHet0ex82KH4I+ceIOwB48hny4wpb +Zaqy9pTFisTmFNOF6d3TB58yMWoLQIbLuVrbbbcr7hFYCWsgj0yN5iYQNOR9pU4E +ooF+aC0kK9M4iUXthzjjgIjnMzsCmPeKisbwblsPSfSgccj/pCMzW8C3CMVL6AvG +slSSLK42qm3f38kx3sg2S8LDW0v+hoyvBmKNFMiBwsF2tWCXIG+oP1PDYpJUpaOJ +RFHG7JEPtY94UJGdo5C4YhqDWr3HOqEwuVIt1gWMMPs9IvDkDRo6emmDd64FFAKH +ss3hHixu6OHqU5iw6JIVVtYiur6s9m6N/Xxt5Ho6wuqnzUZ+Dwj3L6lF9IOJbJxU +Ufb70I1Uko9kXcoje9ONUsqr88wfQY+JZxxVTlzDUDadytCzmO3wXsz+cosMQ5Rw +aOZwXYyvmcoZuUQG8GIqRO1wfOcD7o7pI6IyVJQjOeG/rA0eu/4= +=Gj2n +-----END PGP SIGNATURE----- diff --git a/openssh-server-systemd-sysusers.conf b/openssh-server-systemd-sysusers.conf new file mode 100644 index 0000000..419c529 --- /dev/null +++ b/openssh-server-systemd-sysusers.conf @@ -0,0 +1,2 @@ +#Type Name ID GECOS Home directory Shell +u sshd 74 "Privilege-separated SSH" /usr/share/empty.sshd - diff --git a/SPECS/openssh.spec b/openssh.spec similarity index 78% rename from SPECS/openssh.spec rename to openssh.spec index a07dbd3..7bf36e2 100644 --- a/SPECS/openssh.spec +++ b/openssh.spec @@ -7,18 +7,14 @@ %global _hardened_build 1 -# OpenSSH privilege separation requires a user & group ID -%global sshd_uid 74 -%global sshd_gid 74 - # Do we want to disable building of gnome-askpass? (1=yes 0=no) %global no_gnome_askpass 0 # Do we want to link against a static libcrypto? (1=yes 0=no) %global static_libcrypto 0 -# Use GTK2 instead of GNOME in gnome-ssh-askpass -%global gtk2 1 +# Use GTK3 instead of GTK2 in gnome-ssh-askpass +%global gtk3 1 # Build position-independent executables (requires toolchain support)? %global pie 1 @@ -29,59 +25,31 @@ # Do we want libedit support %global libedit 1 -# Do we want LDAP support -%global ldap 1 - -# Whether to build pam_ssh_agent_auth -%if 0%{?!nopam:1} -%global pam_ssh_agent 1 -%else -%global pam_ssh_agent 0 -%endif - # Reserve options to override askpass settings with: # rpm -ba|--rebuild --define 'skip_xxx 1' %{?skip_gnome_askpass:%global no_gnome_askpass 1} # Add option to build without GTK2 for older platforms with only GTK+. # Red Hat Linux <= 7.2 and Red Hat Advanced Server 2.1 are examples. -# rpm -ba|--rebuild --define 'no_gtk2 1' -%{?no_gtk2:%global gtk2 0} +# rpm -ba|--rebuild --define 'no_gtk3 1' +%{?no_gtk3:%global gtk3 0} # Options for static OpenSSL link: # rpm -ba|--rebuild --define "static_openssl 1" %{?static_openssl:%global static_libcrypto 1} -# Is this a build for the rescue CD (without PAM, with MD5)? (1=yes 0=no) -%global rescue 0 -%{?build_rescue:%global rescue 1} -%{?build_rescue:%global rescue_rel rescue} - -# Turn off some stuff for resuce builds -%if %{rescue} -%global kerberos5 0 -%global libedit 0 -%global pam_ssh_agent 0 -%endif - -# Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%global openssh_ver 8.0p1 -%global openssh_rel 25 -%global pam_ssh_agent_ver 0.10.3 -%global pam_ssh_agent_rel 7 +%global openssh_ver 9.8p1 +%global openssh_rel 6 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}%{?rescue_rel} +Release: %{openssh_rel}%{?dist} URL: http://www.openssh.com/portable.html -#URL1: http://pamsshagentauth.sourceforge.net 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 Source2: sshd.pam -Source3: DJM-GPG-KEY.gpg -Source4: http://prdownloads.sourceforge.net/pamsshagentauth/pam_ssh_agent_auth/pam_ssh_agent_auth-%{pam_ssh_agent_ver}.tar.bz2 -Source5: pam_ssh_agent-rmheaders +Source3: gpgkey-736060BA.gpg Source6: ssh-keycat.pam Source7: sshd.sysconfig Source9: sshd@.service @@ -89,8 +57,14 @@ Source10: sshd.socket Source11: sshd.service Source12: sshd-keygen@.service Source13: sshd-keygen -Source14: sshd.tmpfiles Source15: sshd-keygen.target +Source16: ssh-agent.service +Source17: ssh-agent.socket +Source19: openssh-server-systemd-sysusers.conf +Source20: ssh-host-keys-migration.sh +Source21: ssh-host-keys-migration.service +Source22: parallel_test.sh +Source23: parallel_test.Makefile #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 Patch100: openssh-6.7p1-coverity.patch @@ -101,37 +75,20 @@ Patch100: openssh-6.7p1-coverity.patch Patch200: openssh-7.6p1-audit.patch # Audit race condition in forked child (#1310684) Patch201: openssh-7.1p2-audit-race-condition.patch - -# --- pam_ssh-agent --- -# make it build reusing the openssh sources -Patch300: pam_ssh_agent_auth-0.9.3-build.patch -# check return value of seteuid() -# https://sourceforge.net/p/pamsshagentauth/bugs/23/ -Patch301: pam_ssh_agent_auth-0.10.3-seteuid.patch -# explicitly make pam callbacks visible -Patch302: pam_ssh_agent_auth-0.9.2-visibility.patch -# update to current version of agent structure -Patch305: pam_ssh_agent_auth-0.9.3-agent_structure.patch -# remove prefixes to be able to build against current openssh library -Patch306: pam_ssh_agent_auth-0.10.2-compat.patch -# Fix NULL dereference from getpwuid() return value -# https://sourceforge.net/p/pamsshagentauth/bugs/22/ -Patch307: pam_ssh_agent_auth-0.10.2-dereference.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2049947 +Patch202: openssh-9.0p1-audit-log.patch +# Correctly audit hostname and IP address +Patch203: openssh-8.7p1-audit-hostname.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX) Patch400: openssh-7.8p1-role-mls.patch #https://bugzilla.redhat.com/show_bug.cgi?id=781634 Patch404: openssh-6.6p1-privsep-selinux.patch - -#?-- unwanted child :( -Patch501: openssh-6.7p1-ldap.patch #? Patch502: openssh-6.6p1-keycat.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1644 Patch601: openssh-6.6p1-allow-ip-opts.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1893 (WONTFIX) -Patch604: openssh-6.6p1-keyperm.patch #(drop?) https://bugzilla.mindrot.org/show_bug.cgi?id=1925 Patch606: openssh-5.9p1-ipv6man.patch #? @@ -149,15 +106,13 @@ Patch703: openssh-4.3p2-askpass-grab-info.patch Patch707: openssh-7.7p1-redhat.patch # warn users for unsupported UsePAM=no (#757545) Patch711: openssh-7.8p1-UsePAM-warning.patch -# make aes-ctr ciphers use EVP engines such as AES-NI from OpenSSL -Patch712: openssh-6.3p1-ctr-evp-fast.patch -# add cavs test binary for the aes-ctr -Patch713: openssh-6.6p1-ctr-cavstest.patch -# add SSH KDF CAVS test driver -Patch714: openssh-6.7p1-kdf-cavs.patch -# GSSAPI Key Exchange (RFC 4462 + draft-ietf-curdle-gss-keyex-sha2-08) +# GSSAPI Key Exchange (RFC 4462 + RFC 8732) # from https://github.com/openssh-gsskex/openssh-gsskex/tree/fedora/master +# and +# Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures +# upstream MR: +# https://github.com/openssh-gsskex/openssh-gsskex/pull/21 Patch800: openssh-8.0p1-gssapi-keyex.patch #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html Patch801: openssh-6.6p1-force_krb.patch @@ -169,7 +124,8 @@ Patch802: openssh-6.6p1-GSSAPIEnablek5users.patch Patch804: openssh-7.7p1-gssapi-new-unique.patch # Respect k5login_directory option in krk5.conf (#1328243) Patch805: openssh-7.2p2-k5login_directory.patch - +# Rewriting OpenSSH GSS KEX to use new packet API +Patch806: openssh-9.6p1-gsskex-new-api.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 Patch901: openssh-6.6p1-kuserok.patch @@ -185,134 +141,79 @@ Patch919: openssh-6.6.1p1-scp-non-existing-directory.patch Patch922: openssh-6.8p1-sshdT-output.patch # Add sftp option to force mode of created files (#1191055) Patch926: openssh-6.7p1-sftp-force-permission.patch -# Restore compatible default (#89216) -Patch929: openssh-6.9p1-permit-root-login.patch # make s390 use /dev/ crypto devices -- ignore closefrom Patch939: openssh-7.2p2-s390-closefrom.patch # Move MAX_DISPLAYS to a configuration option (#1341302) Patch944: openssh-7.3p1-x11-max-displays.patch -# Help systemd to track the running service -Patch948: openssh-7.4p1-systemd.patch # Pass inetd flags for SELinux down to openbsd compat level Patch949: openssh-7.6p1-cleanup-selinux.patch # Sandbox adjustments for s390 and audit 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-8.0p1-pkcs11-uri.patch # Unbreak scp between two IPv6 hosts (#1620333) Patch953: openssh-7.8p1-scp-ipv6.patch -# ssh-copy-id is unmaintained: Aggreagete patches -# - do not return 0 if the write fails (full disk) -# - shellcheck reports (upstream #2902) -Patch958: openssh-7.9p1-ssh-copy-id.patch -# Verify the SCP vulnerabilities are fixed in the package testsuite -# https://bugzilla.mindrot.org/show_bug.cgi?id=3007 -Patch961: openssh-8.0p1-scp-tests.patch # Mention crypto-policies in manual pages (#1668325) +# clarify rhbz#2068423 on the man page of ssh_config Patch962: openssh-8.0p1-crypto-policies.patch # Use OpenSSL high-level API to produce and verify signatures (#1707485) -Patch963: openssh-8.0p1-openssl-evp.patch +# TODO fix the comment above ^ +Patch963: openssh-9.3p1-merged-openssl-evp.patch # Use OpenSSL KDF (#1631761) Patch964: openssh-8.0p1-openssl-kdf.patch -# Use new OpenSSL for PEM export to avoid MD5 dependency (#1712436) -Patch965: openssh-8.0p1-openssl-pem.patch -# Seed from dev/random if requested (#1785655) -Patch966: openssh-8.0p1-entropy.patch -# Unbreak ssh-keyscan RSA keys without SHA1 (#1744108) -Patch967: openssh-8.0p1-keyscan-rsa-sha2.patch -# Detect proxyJump loops in configuration files (#1804099) -Patch968: openssh-8.0p1-proxyjump-loops.patch -# ssh-keygen should default to SHA2-based signature algorithm (#1790610) -Patch969: openssh-8.0p1-keygen-sha2.patch -# RDomain is not suported on non-OpenBSD (#1807686) -# https://bugzilla.mindrot.org/show_bug.cgi?id=3126 -Patch970: openssh-8.0p1-rdomain.patch -# Do not fail X11 forwarding if IPv6 is disabled (#1662189) -# https://bugzilla.mindrot.org/show_bug.cgi?id=2143 -Patch971: openssh-8.0p1-x11-without-ipv6.patch -# Client window fix (#1913041) -Patch972: openssh-8.0p1-channel-limits.patch -# SFTP sort upon the modification time (#1909988) -# https://bugzilla.mindrot.org/show_bug.cgi?id=3248 -Patch973: openssh-8.0p1-sftp-timespeccmp.patch +# sk-dummy.so built with -fvisibility=hidden does not work +Patch965: openssh-8.2p1-visibility.patch +# Do not break X11 without IPv6 +Patch966: openssh-8.2p1-x11-without-ipv6.patch # ssh-keygen printing fingerprint issue with Windows keys (#1901518) Patch974: openssh-8.0p1-keygen-strip-doseol.patch # sshd provides PAM an incorrect error code (#1879503) Patch975: openssh-8.0p1-preserve-pam-errors.patch -# ssh incorrectly restores the blocking mode on standard output (#1942901) -Patch976: openssh-8.0p1-restore-nonblock.patch -# CVE 2020-14145 -Patch977: openssh-8.0p1-cve-2020-14145.patch -# sshd -T requires -C when "Match" is used in sshd_config (#1836277) -Patch978: openssh-8.0p1-sshd_config.patch -# CVE-2021-41617 -Patch980: openssh-8.7p1-upstream-cve-2021-41617.patch -# support sshd Include directive -# upstream commits: -# c2bd7f74b0e0f3a3ee9d19ac549e6ba89013abaf~1..677d0ece67634262b3b96c3cd6410b19f3a603b7 -# 8bdc3bb7cf4c82c3344cfcb82495a43406e87e83 -# 47adfdc07f4f8ea0064a1495500244de08d311ed~1..7af1e92cd289b7eaa9a683e9a6f2fddd98f37a01 -# supplementary commit 612b1dd1ec91ffb1e01f58cca0c6eb1d47bf4423 -Patch981: openssh-8.0p1-sshd_include.patch -# Port upstream ClientAliveCountMax behaviour -# upstream commit: -# 69334996ae203c51c70bf01d414c918a44618f8e -Patch982: openssh-8.0p1-client_alive_count_max.patch -# add a local implementation of BSD realpath() for sftp-server -# use ahead of OpenBSD's realpath changing to match POSIX -# upstream commits: -# 569b650f93b561c09c655f83f128e1dfffe74101 -# 53a6ebf1445a857f5e487b18ee5e5830a9575149 -# 5428b0d239f6b516c81d1dd15aa9fe9e60af75d4 -Patch983: openssh-8.0p1-sftp-realpath.patch -# include caveat for crypto-policy in sshd manpage (#2044354) -Patch984: openssh-8.0p1-crypto-policy-doc.patch -# minimize the use of SHA1 as a proof of possession for RSA key (#2093897) -# upstream commits: -# 291721bc7c840d113a49518f3fca70e86248b8e8 -# 0fa33683223c76289470a954404047bc762be84c -# f8df0413f0a057b6a3d3dd7bd8bc7c5d80911d3a -Patch985: openssh-8.7p1-minimize-sha1-use.patch -# Upstream ff89b1bed80721295555bd083b173247a9c0484e -Patch986: openssh-9.1p1-sshbanner.patch -# Upstream 25e3bccbaa63d27b9d5e09c123f1eb28594d2bd6 -Patch987: openssh-8.0p1-ipv6-process.patch -# Upstream 4332b4fe49360679647a8705bc08f4e81323f6b4 -Patch988: openssh-8.0p1-avoidkillall.patch -# Upstream 89b54900ac61986760452f132bbe3fb7249cfdac -Patch989: openssh-8.0p1-bigsshdconfig.patch -# upsream commit -# b23fe83f06ee7e721033769cfa03ae840476d280 -Patch1015: openssh-9.3p1-upstream-cve-2023-38408.patch -#upstream commit 01dbf3d46651b7d6ddf5e45d233839bbfffaeaec -Patch1017: openssh-9.4p2-limit-delay.patch -#upstream commit 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5 -Patch1018: openssh-9.6p1-CVE-2023-48795.patch -#upstream commit 7ef3787c84b6b524501211b11a26c742f829af1a -Patch1019: openssh-9.6p1-CVE-2023-51385.patch -# SCP kill switch -Patch1020: openssh-8.7p1-scp-kill-switch.patch -#upstream commit 96faa0de6c673a2ce84736eba37fc9fb723d9e5c -Patch1021: openssh-8.0p1-upstream-ignore-SIGPIPE.patch -License: BSD -Group: Applications/Internet +# Implement kill switch for SCP protocol +Patch977: openssh-8.7p1-scp-kill-switch.patch + +# Workaround for lack of sftp_realpath in older versions of RHEL +# https://bugzilla.redhat.com/show_bug.cgi?id=2038854 +# https://github.com/openssh/openssh-portable/pull/299 +# downstream only +Patch981: openssh-8.7p1-recursive-scp.patch +# https://github.com/djmdjm/openssh-wip/pull/13 +Patch982: openssh-8.7p1-minrsabits.patch +# downstream only, IBMCA tentative fix +# From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14 +Patch984: openssh-8.7p1-ibmca.patch + +# Add missing options from ssh_config into ssh manpage +# upstream bug: +# https://bugzilla.mindrot.org/show_bug.cgi?id=3455 +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 + +Patch1012: openssh-9.0p1-evp-fips-dh.patch +Patch1013: openssh-9.0p1-evp-fips-ecdh.patch +Patch1014: openssh-8.7p1-nohostsha1proof.patch + +Patch1015: openssh-9.6p1-pam-rhost.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 -Obsoletes: openssh-clients-fips, openssh-server-fips -Obsoletes: openssh-server-sysvinit %if ! %{no_gnome_askpass} -%if %{gtk2} -BuildRequires: gtk2-devel BuildRequires: libX11-devel +%if %{gtk3} +BuildRequires: gtk3-devel %else -BuildRequires: gnome-libs-devel +BuildRequires: gtk2-devel %endif %endif -%if %{ldap} -BuildRequires: openldap-devel -%endif BuildRequires: autoconf, automake, perl-interpreter, perl-generators, zlib-devel BuildRequires: audit-libs-devel >= 2.0.5 BuildRequires: util-linux, groff @@ -320,9 +221,13 @@ BuildRequires: pam-devel BuildRequires: openssl-devel >= 0.9.8j BuildRequires: perl-podlators BuildRequires: systemd-devel -BuildRequires: gcc +BuildRequires: systemd-rpm-macros +BuildRequires: gcc make BuildRequires: p11-kit-devel +BuildRequires: libfido2-devel Recommends: p11-kit +Obsoletes: openssh-ldap < 8.3p1-4 +Obsoletes: openssh-cavs < 8.4p1-5 %if %{kerberos5} BuildRequires: krb5-devel @@ -345,49 +250,28 @@ BuildRequires: gnupg2 %package clients Summary: An open source SSH client applications -Group: Applications/Internet Requires: openssh = %{version}-%{release} -Requires: crypto-policies >= 20180306-1 +Requires: crypto-policies >= 20220824-1 %package server Summary: An open source SSH server daemon -Group: System Environment/Daemons Requires: openssh = %{version}-%{release} Requires(pre): /usr/sbin/useradd Requires: pam >= 1.0.1-3 -Requires: crypto-policies >= 20180306-1 +Requires: crypto-policies >= 20220824-1 %{?systemd_requires} -%if %{ldap} -%package ldap -Summary: A LDAP support for open source SSH server daemon -Requires: openssh = %{version}-%{release} -Group: System Environment/Daemons -%endif - %package keycat Summary: A mls keycat backend for openssh Requires: openssh = %{version}-%{release} -Group: System Environment/Daemons %package askpass Summary: A passphrase dialog for OpenSSH and X -Group: Applications/Internet -Requires: openssh = %{version}-%{release} -Obsoletes: openssh-askpass-gnome -Provides: openssh-askpass-gnome - -%package cavs -Summary: CAVS tests for FIPS validation -Group: Applications/Internet Requires: openssh = %{version}-%{release} -%package -n pam_ssh_agent_auth -Summary: PAM module for authentication with ssh-agent -Group: System Environment/Base -Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}%{?rescue_rel} -License: BSD +%package sk-dummy +Summary: OpenSSH SK driver for test purposes +Requires: openssh = %{version}-%{release} %description SSH (Secure SHell) is a program for logging into and executing @@ -414,12 +298,6 @@ into and executing commands on a remote machine. This package contains the secure shell daemon (sshd). The sshd daemon allows SSH clients to securely connect to your SSH server. -%if %{ldap} -%description ldap -OpenSSH LDAP backend is a way how to distribute the authorized tokens -among the servers in the network. -%endif - %description keycat OpenSSH mls keycat is backend for using the authorized keys in the openssh in the mls mode. @@ -429,132 +307,83 @@ OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains an X11 passphrase dialog for OpenSSH. -%description cavs -This package contains test binaries and scripts to make FIPS validation -easier. Now contains CTR and KDF CAVS test driver. - -%description -n pam_ssh_agent_auth -This package contains a PAM module which can be used to authenticate -users using ssh keys stored in a ssh-agent. Through the use of the -forwarding of ssh-agent connection it also allows to authenticate with -remote ssh-agent instance. - -The module is most useful for su and sudo service stacks. +%description sk-dummy +This package contains a test SK driver used for OpenSSH test purposes %prep gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} -%setup -q -a 4 +%setup -q -%if %{pam_ssh_agent} -pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} -%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 -# 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 -%if %{ldap} -%patch501 -p1 -b .ldap -%endif -%patch502 -p1 -b .keycat - -%patch601 -p1 -b .ip-opts -%patch604 -p1 -b .keyperm -%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 -%patch712 -p1 -b .evp-ctr -%patch713 -p1 -b .ctr-cavs -%patch714 -p1 -b .kdf-cavs +%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 # -%patch800 -p1 -b .gsskex -%patch801 -p1 -b .force_krb -%patch804 -p1 -b .ccache_name -%patch805 -p1 -b .k5login +%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 806 -p1 -b .gsskex-new-api # -%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 -%patch929 -p1 -b .root-login -%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 -%patch958 -p1 -b .ssh-copy-id -%patch961 -p1 -b .scp-tests -%patch962 -p1 -b .crypto-policies -%patch963 -p1 -b .openssl-evp -%patch964 -p1 -b .openssl-kdf -%patch965 -p1 -b .openssl-pem -%patch966 -p1 -b .entropy -%patch967 -p1 -b .keyscan -%patch968 -p1 -b .proxyjump-loops -%patch969 -p1 -b .keygen-sha2 -%patch970 -p1 -b .rdomain -%patch971 -p1 -b .x11-ipv6 -%patch972 -p1 -b .channel-limits -%patch973 -p1 -b .sftp-timespeccmp -%patch974 -p1 -b .keygen-strip-doseol -%patch975 -p1 -b .preserve-pam-errors -%patch976 -p1 -b .restore-nonblock -%patch977 -p1 -b .cve-2020-14145 -%patch978 -p1 -b .sshd_config -%patch980 -p1 -b .cve-2021-41617 -%patch981 -p1 -b .sshdinclude -%patch982 -p1 -b .client_alive_count_max -%patch983 -p1 -b .sftp-realpath -%patch984 -p1 -b .crypto-policy-doc -%patch985 -p1 -b .minimize-sha1-use -%patch986 -p1 -b .banner -%patch987 -p1 -b .sftp_ipv6 -%patch988 -p1 -b .killall -%patch989 -p1 -b .bigsshdconfig +%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 949 -p1 -b .refactor +%patch -P 950 -p1 -b .sandbox +%patch -P 951 -p1 -b .pkcs11-uri +%patch -P 953 -p1 -b .scp-ipv6 +%patch -P 962 -p1 -b .crypto-policies +%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 -%patch200 -p1 -b .audit -%patch201 -p1 -b .audit-race -%patch700 -p1 -b .fips +%patch -P 977 -p1 -b .kill-scp -%patch100 -p1 -b .coverity +%patch -P 981 -p1 -b .scp-sftpdirs +%patch -P 982 -p1 -b .minrsabits +%patch -P 984 -p1 -b .ibmca -%patch1015 -p1 -b .cve-2023-38408 -%patch1017 -p1 -b .limitdelay -%patch1018 -p1 -b .cve-2023-48795 -%patch1019 -p1 -b .cve-2023-51385 -%patch1020 -p1 -b .scp-kill-switch -%patch1021 -p1 -b .ignore-SIGPIPE +%patch -P 200 -p1 -b .audit +%patch -P 201 -p1 -b .audit-race +%patch -P 202 -p1 -b .audit-log +%patch -P 203 -p1 -b .audit-hostname +%patch -P 700 -p1 -b .fips + +%patch -P 1002 -p1 -b .ssh-manpage + +%patch -P 1006 -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 1015 -p1 -b .pam-rhost + +%patch -P 100 -p1 -b .coverity autoreconf -pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} -autoreconf -popd %build -# the -fvisibility=hidden is needed for clean build of the pam_ssh_agent_auth -# and it makes the ssh build more clean and even optimized better -CFLAGS="$RPM_OPT_FLAGS -fvisibility=hidden"; export CFLAGS -%if %{rescue} -CFLAGS="$CFLAGS -Os" -%endif +%set_build_flags +CFLAGS="$CFLAGS"; export CFLAGS %if %{pie} %ifarch s390 s390x sparc sparcv9 sparc64 CFLAGS="$CFLAGS -fPIC" @@ -590,23 +419,16 @@ fi --datadir=%{_datadir}/openssh \ --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=%{_var}/empty/sshd \ + --with-privsep-path=%{_datadir}/empty.sshd \ --disable-strip \ --without-zlib-version-check \ - --with-ssl-engine \ --with-ipaddr-display \ --with-pie=no \ --without-hardening `# The hardening flags are configured by system` \ --with-systemd \ --with-default-pkcs11-provider=yes \ -%if %{ldap} - --with-ldap \ -%endif -%if %{rescue} - --without-pam \ -%else + --with-security-key-builtin=yes \ --with-pam \ -%endif %if %{WITH_SELINUX} --with-selinux --with-audit=linux \ --with-sandbox=seccomp_filter \ @@ -626,55 +448,41 @@ fi perl -pi -e "s|-lcrypto|%{_libdir}/libcrypto.a|g" Makefile %endif -make +%make_build +make regress/misc/sk-dummy/sk-dummy.so -# Define a variable to toggle gnome1/gtk2 building. This is necessary +# Define a variable to toggle gtk2/gtk3 building. This is necessary # because RPM doesn't handle nested %%if statements. -%if %{gtk2} - gtk2=yes +%if %{gtk3} + gtk3=yes %else - gtk2=no + gtk3=no %endif %if ! %{no_gnome_askpass} pushd contrib -if [ $gtk2 = yes ] ; then +if [ $gtk3 = yes ] ; then + CFLAGS="$CFLAGS %{?__global_ldflags}" \ + make gnome-ssh-askpass3 + mv gnome-ssh-askpass3 gnome-ssh-askpass +else CFLAGS="$CFLAGS %{?__global_ldflags}" \ make gnome-ssh-askpass2 mv gnome-ssh-askpass2 gnome-ssh-askpass -else - CFLAGS="$CFLAGS %{?__global_ldflags}" - make gnome-ssh-askpass1 - mv gnome-ssh-askpass1 gnome-ssh-askpass fi popd %endif -%if %{pam_ssh_agent} -pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} -LDFLAGS="$SAVE_LDFLAGS" -%configure --with-selinux \ - --libexecdir=/%{_libdir}/security \ - --with-mantype=man \ - --without-openssl-header-check `# The check is broken` -make -popd -%endif - %check -#to run tests use "--with check" -%if %{?_with_check:1}%{!?_with_check:0} -make tests -%endif +%{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile %install rm -rf $RPM_BUILD_ROOT mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config.d +mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config.d mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/openssh -mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd -make install DESTDIR=$RPM_BUILD_ROOT -rm -f $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ldap.conf +%make_install install -d $RPM_BUILD_ROOT/etc/pam.d/ install -d $RPM_BUILD_ROOT/etc/sysconfig/ @@ -682,17 +490,30 @@ install -d $RPM_BUILD_ROOT%{_libexecdir}/openssh install -m644 %{SOURCE2} $RPM_BUILD_ROOT/etc/pam.d/sshd install -m644 %{SOURCE6} $RPM_BUILD_ROOT/etc/pam.d/ssh-keycat install -m644 %{SOURCE7} $RPM_BUILD_ROOT/etc/sysconfig/sshd -install -m644 ssh_config_redhat $RPM_BUILD_ROOT/etc/ssh/ssh_config.d/05-redhat.conf +install -m644 ssh_config_redhat $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config.d/50-redhat.conf +install -m644 sshd_config_redhat_cp $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config.d/40-redhat-crypto-policies.conf +install -m644 sshd_config_redhat $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config.d/50-redhat.conf 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 install -m644 %{SOURCE11} $RPM_BUILD_ROOT/%{_unitdir}/sshd.service install -m644 %{SOURCE12} $RPM_BUILD_ROOT/%{_unitdir}/sshd-keygen@.service install -m644 %{SOURCE15} $RPM_BUILD_ROOT/%{_unitdir}/sshd-keygen.target +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 -m644 -D %{SOURCE14} $RPM_BUILD_ROOT%{_tmpfilesdir}/%{name}.conf +install -d -m711 ${RPM_BUILD_ROOT}/%{_datadir}/empty.sshd +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 +install -m744 %{SOURCE20} $RPM_BUILD_ROOT/%{_libexecdir}/openssh/ssh-host-keys-migration.sh +# Pulled-in via a `Wants=` in `sshd.service` & `sshd@.service` +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 %if ! %{no_gnome_askpass} install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass @@ -711,22 +532,33 @@ rm -f $RPM_BUILD_ROOT/etc/profile.d/gnome-ssh-askpass.* perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* -%if %{pam_ssh_agent} -pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} -make install DESTDIR=$RPM_BUILD_ROOT -popd -%endif -%pre -getent group ssh_keys >/dev/null || groupadd -r ssh_keys || : +install -m 755 -d $RPM_BUILD_ROOT%{_libdir}/sshtest/ +install -m 755 regress/misc/sk-dummy/sk-dummy.so $RPM_BUILD_ROOT%{_libdir}/sshtest %pre server -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 /var/empty/sshd sshd 2> /dev/null || : +%sysusers_create_compat %{SOURCE19} %post server +if [ $1 -gt 1 ]; then + # In the case of an upgrade (never true on OSTree systems) run the migration + # script for Fedora 38 to remove group ownership for host keys. + %{_libexecdir}/openssh/ssh-host-keys-migration.sh + # Prevent the systemd unit that performs the same service (useful for + # OSTree systems) from running. + touch /var/lib/.ssh-host-keys-migration +fi %systemd_post sshd.service sshd.socket +# Migration scriptlet for Fedora 31 and 32 installations to sshd_config +# drop-in directory (in F32+). +# Do this only if the file generated by anaconda exists, contains our config +# directive and sshd_config contains include directive as shipped in our package +%global sysconfig_anaconda /etc/sysconfig/sshd-permitrootlogin +test -f %{sysconfig_anaconda} && \ + test ! -f /etc/ssh/sshd_config.d/01-permitrootlogin.conf && \ + grep -q '^PERMITROOTLOGIN="-oPermitRootLogin=yes"' %{sysconfig_anaconda} && \ + grep -q '^Include /etc/ssh/sshd_config.d/\*.conf' /etc/ssh/sshd_config && \ + echo "PermitRootLogin yes" >> /etc/ssh/sshd_config.d/25-permitrootlogin.conf && \ + rm %{sysconfig_anaconda} || : %preun server %systemd_preun sshd.service sshd.socket @@ -734,18 +566,24 @@ getent passwd sshd >/dev/null || \ %postun server %systemd_postun_with_restart sshd.service +%post clients +%systemd_user_post ssh-agent.service +%systemd_user_post ssh-agent.socket + +%preun clients +%systemd_user_preun ssh-agent.service +%systemd_user_preun ssh-agent.socket + %files %license LICENCE -%doc CREDITS ChangeLog INSTALL OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns TODO +%doc CREDITS ChangeLog OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns TODO %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli -%if ! %{rescue} %attr(0755,root,root) %{_bindir}/ssh-keygen %attr(0644,root,root) %{_mandir}/man1/ssh-keygen.1* %attr(0755,root,root) %dir %{_libexecdir}/openssh -%attr(2555,root,ssh_keys) %{_libexecdir}/openssh/ssh-keysign +%attr(4555,root,root) %{_libexecdir}/openssh/ssh-keysign %attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8* -%endif %files clients %attr(0755,root,root) %{_bindir}/ssh @@ -754,27 +592,29 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man1/scp.1* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config %dir %attr(0755,root,root) %{_sysconfdir}/ssh/ssh_config.d/ -%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config.d/05-redhat.conf +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config.d/50-redhat.conf %attr(0644,root,root) %{_mandir}/man5/ssh_config.5* -%if ! %{rescue} %attr(0755,root,root) %{_bindir}/ssh-agent %attr(0755,root,root) %{_bindir}/ssh-add %attr(0755,root,root) %{_bindir}/ssh-keyscan %attr(0755,root,root) %{_bindir}/sftp %attr(0755,root,root) %{_bindir}/ssh-copy-id %attr(0755,root,root) %{_libexecdir}/openssh/ssh-pkcs11-helper +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-sk-helper %attr(0644,root,root) %{_mandir}/man1/ssh-agent.1* %attr(0644,root,root) %{_mandir}/man1/ssh-add.1* %attr(0644,root,root) %{_mandir}/man1/ssh-keyscan.1* %attr(0644,root,root) %{_mandir}/man1/sftp.1* %attr(0644,root,root) %{_mandir}/man1/ssh-copy-id.1* %attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8* -%endif +%attr(0644,root,root) %{_mandir}/man8/ssh-sk-helper.8* +%attr(0644,root,root) %{_userunitdir}/ssh-agent.service +%attr(0644,root,root) %{_userunitdir}/ssh-agent.socket -%if ! %{rescue} %files server -%dir %attr(0711,root,root) %{_var}/empty/sshd +%dir %attr(0711,root,root) %{_datadir}/empty.sshd %attr(0755,root,root) %{_sbindir}/sshd +%attr(0755,root,root) %{_libexecdir}/openssh/sshd-session %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* @@ -782,6 +622,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sshd.8* %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config +%dir %attr(0700,root,root) %{_sysconfdir}/ssh/sshd_config.d/ +%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config.d/40-redhat-crypto-policies.conf +%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config.d/50-redhat.conf %attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0640,root,root) %config(noreplace) /etc/sysconfig/sshd %attr(0644,root,root) %{_unitdir}/sshd.service @@ -789,18 +632,10 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/sshd.socket %attr(0644,root,root) %{_unitdir}/sshd-keygen@.service %attr(0644,root,root) %{_unitdir}/sshd-keygen.target -%attr(0644,root,root) %{_tmpfilesdir}/openssh.conf -%endif - -%if %{ldap} -%files ldap -%doc HOWTO.ldap-keys openssh-lpk-openldap.schema openssh-lpk-sun.schema ldap.conf -%doc openssh-lpk-openldap.ldif openssh-lpk-sun.ldif -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-ldap-helper -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-ldap-wrapper -%attr(0644,root,root) %{_mandir}/man8/ssh-ldap-helper.8* -%attr(0644,root,root) %{_mandir}/man5/ssh-ldap.conf.5* -%endif +%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 +%ghost %attr(0644,root,root) %{_localstatedir}/lib/.ssh-host-keys-migration %files keycat %doc HOWTO.ssh-keycat @@ -814,174 +649,424 @@ getent passwd sshd >/dev/null || \ %attr(0755,root,root) %{_libexecdir}/openssh/ssh-askpass %endif -%files cavs -%attr(0755,root,root) %{_libexecdir}/openssh/ctr-cavstest -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-cavs -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-cavs_driver.pl - -%if %{pam_ssh_agent} -%files -n pam_ssh_agent_auth -%license pam_ssh_agent_auth-%{pam_ssh_agent_ver}/OPENSSH_LICENSE -%attr(0755,root,root) %{_libdir}/security/pam_ssh_agent_auth.so -%attr(0644,root,root) %{_mandir}/man8/pam_ssh_agent_auth.8* -%endif +%files sk-dummy +%attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog -* Tue Jun 25 2024 Stepan Broz - 8.0p1-25 -- Upstream: Ignore SIGPIPE earlier in main() - Resolves: RHEL-37743 - -* Tue Feb 06 2024 Dmitry Belyavskiy - 8.0p1-24 -- Providing a kill switch for scp to deal with CVE-2020-15778 - Resolves: RHEL-22870 - -* Fri Jan 05 2024 Dmitry Belyavskiy - 8.0p1-23 -- Fix Terrapin attack - Resolves: RHEL-19308 - -* Thu Dec 21 2023 Dmitry Belyavskiy - 8.0p1-22 -- Fix Terrapin attack - Resolves: RHEL-19308 -- Forbid shell metasymbols in username/hostname - Resolves: RHEL-19788 - -* Tue Nov 07 2023 Dmitry Belyavskiy - 8.0p1-21 -- Using DigestSign/DigestVerify functions for better FIPS compatibility - Resolves: RHEL-5217 - -* Mon Oct 30 2023 Dmitry Belyavskiy - 8.0p1-20 -- Limit artificial delays in sshd while login using AD user - Resolves: RHEL-1684 -- Add comment to OpenSSH server config about FIPS-incompatible key - Resolves: RHEL-5221 -- Avoid killing all processes on system in case of race condition - Resolves: RHEL-11548 -- Avoid sshd_config 256K limit - Resolves: RHEL-5279 -- Using DigestSign/DigestVerify functions for better FIPS compatibility - Resolves: RHEL-5217 -- Fix GSS KEX causing ssh failures when connecting to WinSSHD - Resolves: RHEL-5321 - -* Thu Aug 24 2023 Dmitry Belyavskiy - 8.0p1-19 +* Mon Sep 16 2024 Dmitry Belyavskiy - 9.8p1-6 - rebuilt - Related: CVE-2023-38408 + Related: RHEL-59024 -* Thu Jul 20 2023 Dmitry Belyavskiy - 8.0p1-18 -- Avoid remote code execution in ssh-agent PKCS#11 support +* Mon Aug 26 2024 Dmitry Belyavskiy - 9.8p1-5 +- Restore GSS connectivity when no hostkeys are present + Related: RHEL-42635 +- Add missing gsskeyex authentication method + Related: RHEL-42635 +- "publickey-hostbound@openssh.com" extension makes no sense with GSS + Related: RHEL-42635 + +* Fri Aug 16 2024 Dmitry Belyavskiy - 9.8p1-4 +- Address SAST scan issues + Resolves: RHEL-36766 +- Remove obsoleted patches + Related: RHEL-42635 + +* Mon Aug 05 2024 Dmitry Belyavskiy - 9.8p1-3 +- sshd doesn't propose to enter password again when a non-existing user is specified + Resolves: RHEL-11981 +- Reenabling self-test on rpm build + Related: RHEL-42635 + +* Fri Jul 26 2024 Dmitry Belyavskiy - 9.8p1-2.0 +- Temporary disabling self-test + Related: RHEL-42635 +- Change ssh-keygen defaults in FIPS mode + Resolves: RHEL-37324 +- Use FIPS-compatible API for key derivation RHEL-10 + Resolves: RHEL-43592 + +* Thu Jul 25 2024 Dmitry Belyavskiy - 9.8p1-1.0 +- Rebase OpenSSH to 9.8p1 + Resolves: RHEL-42635 + +* Fri Jul 12 2024 Zoltan Fridrich - 9.6p1-1.5 +- Build OpenSSH without ENGINE API + Resolves: RHEL-45507 +- Remove pam_ssh_agent_auth subpackage + Resolves: RHEL-45002 + +* Mon Jun 24 2024 Troy Dawson - 9.6p1-1.4 +- Bump release for June 2024 mass rebuild + +* Thu May 09 2024 Zoltan Fridrich - 9.6p1-1.3 +- Correctly audit hostname and IP address (RHEL-22316) +- Make default key sizes configurable in sshd-keygen (RHEL-26454) + +* Thu Jan 25 2024 Fedora Release Engineering - 9.6p1-1.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Sun Jan 21 2024 Fedora Release Engineering - 9.6p1-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Tue Dec 26 2023 Daniel Milnes - 9.6p1-1 +- Update to OpenSSH 9.6 + Original patches from https://src.fedoraproject.org/rpms/openssh/pull-request/63 + Tuned by Dmitry Belyavskiy for GSS and PKCS#11 URI processing + +* Fri Dec 22 2023 Florian Weimer - 9.3p1-13.1 +- Fix type errors in downstream gssapi-keyex patch + +* Mon Oct 16 2023 Mattias Ellert - 9.3p1-13 +- Fix issue with read-only ssh buffer during gssapi key exchange (rhbz#1938224) +- https://github.com/openssh-gsskex/openssh-gsskex/pull/19 + +* Sun Oct 15 2023 Mattias Ellert - 9.3p1-12 +- Fix FTBFS due to implicit declarations (rhbz#2241211) + +* Tue Sep 19 2023 Dmitry Belyavskiy - 9.3p1-11 +- migrated to SPDX license + +* Fri Sep 15 2023 Timothée Ravier - 9.3p1-10 +- Revert "Remove sshd.socket unit (rhbz#2025716)" + +* Thu Aug 03 2023 Norbert Pocs - 9.3p1-9 +- pkcs11: Add support for 'serial' in PKCS#11 URI +- Apply the upstream MR related to the previous pkcs11 issue +- https://github.com/openssh/openssh-portable/pull/406 + +* Thu Aug 03 2023 Dmitry Belyavskiy - 9.3p1-8 +- Split including crypto-policies to a separate config (rhbz#1970566) +- Disable forking of ssh-agent on startup (rhbz#2148555) +- Remove sshd.socket unit (rhbz#2025716) +- Minor optimization of ssh_krb5_kuserok (rhbz#2112501) + +* Tue Aug 01 2023 Dmitry Belyavskiy - 9.3p1-7 +- Relax checks of OpenSSL version + +* Wed Jul 26 2023 Mattias Ellert - 9.3p1-6 +- Update gssapi-keyex patch for OpenSSH 9.0+ + +* Fri Jul 21 2023 Dmitry Belyavskiy - 9.3p1-5 +- Fix remote code execution in ssh-agent PKCS#11 support Resolves: CVE-2023-38408 -* Tue Dec 20 2022 Dmitry Belyavskiy - 8.0p1-17 -- Fix parsing of IPv6 IPs in sftp client (#2151334) -- Avoid ssh banner one-byte overflow (#2138344) -- Avoid crash of sshd when Include folder does not exist (#2133087) +* Thu Jul 20 2023 Fedora Release Engineering - 9.3p1-3.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild -* Wed Jun 29 2022 Zoltan Fridrich - 8.0p1-16 -- Omit client side from minimize-sha1-use.patch to prevent regression (#2093897) +* Thu Jun 08 2023 Norbert Pocs - 9.3p1-4 +- Fix deprecated %patchN syntax +- Reduce the number of patches by merging related patches -* Thu Jun 23 2022 Zoltan Fridrich - 8.0p1-15 -- Fix new issues found by static analyzers +* Wed Jun 07 2023 Dmitry Belyavskiy - 9.3p1-3 +- Fix DSS verification problem + Resolves: rhbz#2212937 -* Wed Jun 01 2022 Zoltan Fridrich - 8.0p1-14 -- Upstream: add a local implementation of BSD realpath() for sftp-server (#2064249) -- Change product name from Fedora to RHEL in openssh-7.8p1-UsePAM-warning.patch (#1953807) -- Include caveat for crypto-policy in sshd manpage (#2044354) -- Change log level of FIPS specific log message to verbose (#2050511) -- Clarify force_file_perms (-m) documentation in sftp-server manpage (#1862504) -- Minimize the use of SHA1 as a proof of possession for RSA key (#2093897) +* Fri Jun 02 2023 Dmitry Belyavskiy - 9.3p1-2 +- Remove unused patch -* Tue Oct 26 2021 Dmitry Belyavskiy - 8.0p1-13 -- Upstream: ClientAliveCountMax=0 disable the connection killing behaviour (#2015828) +* Thu Jun 01 2023 Dmitry Belyavskiy - 9.3p1-1 + 0.10.4-9 +- Rebase OpenSSH to 9.3p1 -* Wed Oct 20 2021 Dmitry Belyavskiy - 8.0p1-12 -- Add support for "Include" directive in sshd_config file (#1926103) +* Wed May 24 2023 Norbert Pocs - 9.0p1-18 +- Fix pkcs11 issue with the recent changes +- Clarify HostKeyAlgorithms relation with crypto-policies -* Fri Oct 01 2021 Dmitry Belyavskiy - 8.0p1-11 -- CVE-2021-41617 upstream fix (#2008885) +* Fri Apr 14 2023 Dmitry Belyavskiy - 9.0p1-17 +- In case when sha1 signatures are not supported, fallback to sha2 in hostproof +- Audit logging patch was not applied (rhbz#2177471) -* Mon Jun 21 2021 Dmitry Belyavskiy - 8.0p1-10 -- sshd -T requires -C when "Match" is used in sshd_config (#1836277) +* Thu Apr 13 2023 Norbert Pocs - 9.0p1-16 +- Make the sign, dh, ecdh processes FIPS compliant by adopting to + openssl 3.0 -* Wed Jun 02 2021 Dmitry Belyavskiy - 8.0p1-9 -- CVE-2020-14145 openssh: Observable Discrepancy leading to an information - leak in the algorithm negotiation (#1882252) -- Hostbased ssh authentication fails if session ID contains a '/' (#1944125) +* Thu Apr 13 2023 Dmitry Belyavskiy - 9.0p1-15 +- Fix self-DoS + Resolves: CVE-2023-25136 +- Remove too aggressive coverity fix causing native tests failure -* Mon Apr 26 2021 Dmitry Belyavskiy - 8.0p1-8 -- ssh doesn't restore the blocking mode on standard output (#1942901) +* Wed Apr 12 2023 Florian Weimer - 9.0p1-14.2 +- C99 compatiblity fixes -* Fri Apr 09 2021 Dmitry Belyavskiy - 8.0p1-7 + 0.10.3-7 -- SFTP sort upon the modification time (#1909988) +* Tue Mar 14 2023 Timothée Ravier - 9.0p1-14 +- Make sshd & sshd@ units want ssh-host-keys-migration.service + +* Mon Mar 13 2023 Zoltan Fridrich - 9.0p1-13 +- Add sk-dummy subpackage for test purposes (rhbz#2176795) + +* Mon Mar 06 2023 Dusty Mabe - 9.0p1-12 +- Mark /var/lib/.ssh-host-keys-migration as %ghost file +- Make ssh-host key migration less conditional + +* Wed Mar 01 2023 Dusty Mabe - 9.0p1-11 +- Provide a systemd unit for restoring default host key permissions (rhbz#2172956) +- Co-Authored by Timothée Ravier + +* Mon Jan 23 2023 Dmitry Belyavskiy - 9.0p1-10 +- Restore upstream behaviour and default host key permissions (rhbz#2141272) + +* Thu Jan 19 2023 Fedora Release Engineering - 9.0p1-9.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Mon Jan 09 2023 Dmitry Belyavskiy - 9.0p1-9 +- Fix build against updated OpenSSL (rhbz#2158966) + +* Mon Oct 24 2022 Norbert Pocs - 9.0p1-8 +- Add additional audit logging about ssh key used to login (rhbz#2049947) + +* Fri Oct 21 2022 Dmitry Belyavskiy - 9.0p1-7 +- Check IP opts length (rhbz#1960015) + +* Wed Oct 5 2022 Anthony Rabbito - 9.0p1-6 +- Add a socket unit to ssh-agent user unit (rhbz#2125576) + +* Thu Sep 29 2022 Dmitry Belyavskiy - 9.0p1-5 +- RSAMinSize => RequiredRSASize + +* Fri Sep 02 2022 Luca BRUNO - 9.0p1-4 +- Move users/groups creation logic to sysusers.d fragments + +* Wed Aug 24 2022 Alexander Sosedkin - 9.0p1-3 +- State in manpages that HostbasedAcceptedAlgorithms is set by crypto-policies + +* Wed Aug 17 2022 Dmitry Belyavskiy - 9.0p1-2 +- Port patches from CentOS - RSAMinSize (rhbz#2117264) + +* Thu Aug 11 2022 Dmitry Belyavskiy - 9.0p1-1 + 0.10.4-7 +- Rebase OpenSSH to 9.0p1 (rhbz#2057466) + +* Wed Aug 10 2022 Dmitry Belyavskiy - 8.8p1-4 + 0.10.4-6 +- Port patches from CentOS (rhbz#2117264) + +* Mon Aug 01 2022 Luca BRUNO - 8.8p1-3 +- Use allocated static GID for 'ssh_keys' group (rhbz#2104595) + +* Fri Jul 22 2022 Fedora Release Engineering - 8.8p1-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Fri Apr 29 2022 Dmitry Belyavskiy - 8.8p1-2 +- Disable locale forwarding in OpenSSH (#2002739) + +* Thu Jan 20 2022 Fedora Release Engineering - 8.8p1-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Mon Nov 29 2021 Dmitry Belyavskiy - 8.8p1-1 + 0.10.4-5 +- New upstream release (#2007967) + +* Wed Sep 29 2021 Dmitry Belyavskiy - 8.7p1-3 +- CVE-2021-41617 fix (#2008292) + +* Thu Sep 16 2021 Dmitry Belyavskiy - 8.7p1-2 +- Use SFTP protocol for scp by default (#2004956) + +* Tue Sep 14 2021 Sahana Prasad - 8.7p1-1.1 +- Rebuilt with OpenSSL 3.0.0 + +* Wed Sep 01 2021 Dmitry Belyavskiy - 8.7p1-1 + 0.10.4-4 +- New upstream release (#1995893) + +* Thu Jul 22 2021 Fedora Release Engineering - 8.6p1-5.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Mon Jun 21 2021 Dmitry Belyavskiy - 8.6p1-5 +- restore the blocking mode on standard output (#1942901) - upstream + +* Tue May 25 2021 Timm Bäder - 8.6p1-4 +- Use %%set_build_flags to set all builds flags + +* Fri May 21 2021 Dmitry Belyavskiy - 8.6p1-3 +- Hostbased ssh authentication fails if session ID contains a '/' (#1963059) + +* Mon May 10 2021 Dmitry Belyavskiy - 8.6p1-2 +- restore the blocking mode on standard output (#1942901) + +* Mon Apr 19 2021 Dmitry Belyavskiy - 8.6p1-1 + 0.10.4-3 +- New upstream release (#1950819) - ssh-keygen printing fingerprint issue with Windows keys (#1901518) -- PIN is lost when iterating over tokens when adding pkcs11 keys to ssh-agent (#1843372) -- ssh-agent segfaults during ssh-add -s pkcs11 (#1868996) -- ssh-copy-id could not resolve ipv6 address ends with colon (#1933517) - sshd provides PAM an incorrect error code (#1879503) -* Tue Mar 16 2021 Dmitry Belyavskiy - 8.0p1-6 + 0.10.3-7 -- Openssh client window fix (#1913041) +* Tue Mar 09 2021 Rex Dieter - 8.5p1-2 +- ssh-agent.serivce is user unit (#1761817#27) -* Tue Mar 24 2020 Jakub Jelen - 8.0p1-5 + 0.10.3-7 -- Do not print "no slots" warning by default (#1744220) -- Unbreak connecting using gssapi through proxy commands (#1749862) -- Document in manual pages that CASignatureAlgorithms are handled by crypto policies (#1790604) -- Use SHA2-based signature algorithms by default for signing certificates (#1790610) -- Prevent simple ProxyJump loops in configuration files (#1804099) -- Teach ssh-keyscan to use SHA2 RSA variants (#1744108) -- Do not fail hard if getrandom() is not available and no SSH_USE_STRONG_RNG is specified (#1812120) -- Improve wording of crypto policies references in manual pages (#1812854) -- Do not break X11 forwarding if IPv6 is disabled (#1662189) -- Enable SHA2-based GSSAPI key exchange algorithms by default (#1816226) -- Mark RDomain server configuration option unsupported in RHEL (#1807686) -- Clarify crypto policies defaults in manual pages (#1724195) -- Mention RSA SHA2 variants in ssh-keygen manual page (#1665900) +* Wed Mar 03 2021 Jakub Jelen - 8.5p1-1 + 0.10.4-2 +- New upstream release (#1934336) -* Wed Jan 08 2020 Jakub Jelen - 8.0p1-4 + 0.10.3-7 -- Restore entropy patch for CC certification (#1785655) +* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 8.4p1-5.2 +- Rebuilt for updated systemd-rpm-macros + See https://pagure.io/fesco/issue/2583. -* Tue Jul 23 2019 Jakub Jelen - 8.0p1-3 + 0.10.3-7 -- Fix typos in manual pages (#1668325) -- Use the upstream support for PKCS#8 PEM files alongside with the legacy PEM files (#1712436) -- Unbreak ssh-keygen -A in FIPS mode (#1732424) -- Add missing RSA certificate types to offered hostkey types in FIPS mode (#1732449) +* Tue Jan 26 2021 Fedora Release Engineering - 8.4p1-5.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild -* Wed Jun 12 2019 Jakub Jelen - 8.0p1-2 + 0.10.3-7 -- Allow specifying a pin-value in PKCS #11 URI in ssh-add (#1639698) -- Whitelist another syscall variant for s390x cryptographic module (ibmca engine) (#1714915) +* Fri Jan 22 2021 Jakub Jelen - 8.4p1-5 + 0.10.4-1 +- Use /usr/share/empty.sshd instead of /var/empty/sshd +- Allow emptu labels in PKCS#11 tokens (#1919007) +- Drop openssh-cavs subpackage -* Tue May 14 2019 Jakub Jelen - 8.0p1-1 + 0.10.3-7 -- New upstream release (#1691045) -- Remove support for unused VendorPatchLevel configuration option -- Fix kerberos cleanup procedures (#1683295) -- Do not negotiate arbitrary primes with DH GEX in FIPS (#1685096) -- Several GSSAPI key exchange improvements and sync with Debian -- Allow to use labels in PKCS#11 URIs even if they do not match on private key (#1671262) -- Do not fall back to sshd_net_t SELinux context (#1678695) -- Use FIPS compliant high-level signature OpenSSL API and KDF -- Mention crypto-policies in manual pages -- Do not fail if non-FIPS approved algorithm is enabled in FIPS -- Generate the PEM files in new PKCS#8 format without the need of MD5 (#1712436) +* Tue Dec 01 2020 Jakub Jelen - 8.4p1-4 + 0.10.4-1 +- Remove "PasswordAuthentication yes" from vendor configuration as it is + already default and it might be hard to override. +- Fix broken obsoletes for openssh-ldap (#1902084) -* Mon Nov 26 2018 Jakub Jelen - 7.8p1-4 + 0.10.3-5 -- Unbreak PKCS#11 URI tests (#1648262) -- Allow to disable RSA signatures with SHA1 (#1648898) -- Dump missing GSS options from client configuration (#1649505) -- Minor fixes from Fedora related to GSSAPI and keberos -- Follow the system-wide PATH settings +* Thu Nov 19 2020 Jakub Jelen - 8.4p1-3 + 0.10.4-1 +- Unbreak seccomp filter on arm (#1897712) +- Add a workaround for Debian's broken OpenSSH (#1881301) + +* Tue Oct 06 2020 Jakub Jelen - 8.4p1-2 + 0.10.4-1 +- Unbreak ssh-copy-id after a release (#1884231) +- Remove misleading comment from sysconfig + +* Tue Sep 29 2020 Jakub Jelen - 8.4p1-1 + 0.10.4-1 +- New upstream release of OpenSSH and pam_ssh_agent_auth (#1882995) + +* Fri Aug 21 2020 Jakub Jelen - 8.3p1-4 + 0.10.3-10 +- Remove openssh-ldap subpackage (#1871025) +- pkcs11: Do not crash with invalid paths in ssh-agent (#1868996) +- Clarify documentation about sftp-server -m (#1862504) + +* Tue Jul 28 2020 Fedora Release Engineering - 8.3p1-3.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Wed Jun 10 2020 Jakub Jelen - 8.3p1-3 + 0.10.3-10 +- Do not lose PIN when more slots match PKCS#11 URI (#1843372) +- Update to new crypto-policies version on server (using sshd_config include) +- Move redhat configuraion files to larger number to allow simpler override +- Move sshd_config include before any other definitions (#1824913) + +* Mon Jun 01 2020 Jakub Jelen - 8.3p1-2 + 0.10.3-10 +- Fix crash on cleanup (#1842281) + +* Wed May 27 2020 Jakub Jelen - 8.3p1-1 + 0.10.3-10 +- New upstream release (#1840503) +- Unbreak corner cases of sshd_config include +- Fix order of gssapi key exchange algorithms + +* Wed Apr 08 2020 Jakub Jelen - 8.2p1-3 + 0.10.3-9 +- Simplify reference to crypto policies in configuration files +- Unbreak gssapi authentication with GSSAPITrustDNS over jump hosts +- Correctly print FIPS mode initialized in debug mode +- Enable SHA2-based GSSAPI key exchange methods (#1666781) +- Do not break X11 forwarding when IPv6 is disabled +- Remove fipscheck dependency as OpenSSH is no longer FIPS module +- Improve documentation about crypto policies defaults in manual pages + +* Thu Feb 20 2020 Jakub Jelen - 8.2p1-2 + 0.10.3-9 +- Build against libfido2 to unbreak internal u2f support + +* Mon Feb 17 2020 Jakub Jelen - 8.2p1-1 + 0.10.3-9 +- New upstrem reelase (#1803290) +- New /etc/ssh/sshd_config.d drop in directory +- Support for U2F security keys +- Correctly report invalid key permissions (#1801459) +- Do not write bogus information on stderr in FIPS mode (#1778224) + +* Mon Feb 03 2020 Jakub Jelen - 8.1p1-4 + 0.10.3-8 +- Unbreak seccomp filter on ARM (#1796267) + +* Wed Jan 29 2020 Fedora Release Engineering - 8.1p1-3.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Wed Nov 27 2019 Jakub Jelen - 8.1p1-3 + 0.10.3-8 +- Unbreak seccomp filter also on ARM (#1777054) + +* Thu Nov 14 2019 Jakub Jelen - 8.1p1-2 + 0.10.3-8 +- Unbreak seccomp filter with latest glibc (#1771946) + +* Wed Oct 09 2019 Jakub Jelen - 8.1p1-1 + 0.10.3-8 +- New upstream release (#1759750) + +* Thu Jul 25 2019 Fedora Release Engineering - 8.0p1-8.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Tue Jul 23 2019 Jakub Jelen - 8.0p1-8 + 0.10.3-7 +- Use the upstream-accepted version of the PKCS#8 PEM support (#1722285) + +* Fri Jul 12 2019 Jakub Jelen - 8.0p1-7 + 0.10.3-7 +- Use the environment file under /etc/sysconfig for anaconda configuration (#1722928) + +* Wed Jul 03 2019 Jakub Jelen - 8.0p1-6 + 0.10.3-7 +- Provide the entry point for anaconda configuration in service file (#1722928) + +* Wed Jun 26 2019 Jakub Jelen - 8.0p1-5 + 0.10.3-7 +- Disable root password logins (#1722928) +- Fix typo in manual pages related to crypto-policies +- Fix the gating test to make sure it removes the test user +- Cleanu up spec file and get rid of some rpmlint warnings + +* Mon Jun 17 2019 Jakub Jelen - 8.0p1-4 + 0.10.3-7 +- Compatibility with ibmca engine for ECC +- Generate more modern PEM files using new OpenSSL API +- Provide correct signature types for RSA keys using SHA2 from agent + +* Mon May 27 2019 Jakub Jelen - 8.0p1-3 + 0.10.3-7 +- Remove problematic patch updating cached pw structure +- Do not require the labels on the public objects (#1710832) + +* Tue May 14 2019 Jakub Jelen - 8.0p1-2 + 0.10.3-7 +- Use OpenSSL KDF +- Use high-level OpenSSL API for signatures handling +- Mention crypto-policies in manual pages instead of hardcoded defaults +- Verify in package testsuite that SCP vulnerabilities are fixed +- Do not fail in FIPS mode, when unsupported algorithm is listed in configuration + +* Fri Apr 26 2019 Jakub Jelen - 8.0p1-1 + 0.10.3-7 +- New upstream release (#1701072) +- Removed support for VendroPatchLevel configuration option +- Significant rework of GSSAPI Key Exchange +- Significant rework of PKCS#11 URI support + +* Mon Mar 11 2019 Jakub Jelen - 7.9p1-5 + 0.10.3.6 +- Fix kerberos cleanup procedures with GSSAPI +- Update cached passwd structure after PAM authentication +- Do not fall back to sshd_net_t SELinux context +- Fix corner cases of PKCS#11 URI implementation +- Do not negotiate arbitrary primes with DH GEX in FIPS + +* Wed Feb 06 2019 Jakub Jelen - 7.9p1-4 + 0.10.3.6 +- Log when a client requests an interactive session and only sftp is allowed +- Fix minor issues in ssh-copy-id +- Enclose redhat specific configuration with Match final block + +* Fri Feb 01 2019 Fedora Release Engineering - 7.9p1-3.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Jan 14 2019 Björn Esser - 7.9p1-3.1 +- Rebuilt for libcrypt.so.2 (#1666033) + +* Mon Jan 14 2019 Jakub Jelen - 7.9p1-3 + 0.10.3.6 +- Backport Match final to unbreak canonicalization with crypto-policies (#1630166) +- gsskex: Dump correct option +- Backport several fixes from 7_9 branch, mostly related to certificate authentication (#1665611) +- Backport patch for CVE-2018-20685 (#1665786) +- Correctly initialize ECDSA key structures from PKCS#11 + +* Wed Nov 14 2018 Jakub Jelen - 7.9p1-2 + 0.10.3-6 +- Fix LDAP configure test (#1642414) +- Avoid segfault on kerberos authentication failure +- Reference correct file in configuration example (#1643274) +- Dump missing GSSAPI configuration options +- Allow to disable RSA signatures with SHA-1 + +* Fri Oct 19 2018 Jakub Jelen - 7.9p1-1 + 0.10.3-6 +- New upstream release OpenSSH 7.9p1 (#1632902, #1630166) +- Honor GSSAPIServerIdentity option for GSSAPI key exchange +- Do not break gsssapi-keyex authentication method when specified in + AuthenticationMethods +- Follow the system-wide PATH settings (#1633756) +- Address some coverity issues * Mon Sep 24 2018 Jakub Jelen - 7.8p1-3 + 0.10.3-5 -- Disable OpenSSH hardening flags and use the ones provided by system (#1630615) -- Ignore unknown parts of PKCS#11 URI (#1631478) +- Disable OpenSSH hardening flags and use the ones provided by system +- Ignore unknown parts of PKCS#11 URI - Do not fail with GSSAPI enabled in match blocks (#1580017) -- Fix the segfaulting cavs test (#1629692) +- Fix the segfaulting cavs test (#1628962) * Fri Aug 31 2018 Jakub Jelen - 7.8p1-2 + 0.10.3-5 - New upstream release fixing CVE 2018-15473 - Remove unused patches - Remove reference to unused enviornment variable SSH_USE_STRONG_RNG - Address coverity issues -- Unbreak scp between two IPv6 hosts (#1620333) -- Unbreak GSSAPI key exchange (#1624323) +- Unbreak scp between two IPv6 hosts +- Unbreak GSSAPI key exchange (#1624344) - Unbreak rekeying with GSSAPI key exchange (#1624344) * Thu Aug 09 2018 Jakub Jelen - 7.7p1-6 + 0.10.3-4 @@ -989,6 +1074,9 @@ getent passwd sshd >/dev/null || \ - Allow aes-gcm cipher modes in FIPS mode - Coverity fixes +* Fri Jul 13 2018 Fedora Release Engineering - 7.7p1-5.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + * Tue Jul 03 2018 Jakub Jelen - 7.7p1-5 + 0.10.3-4 - Disable manual printing of motd by default (#1591381) diff --git a/parallel_test.Makefile b/parallel_test.Makefile new file mode 100644 index 0000000..f49df30 --- /dev/null +++ b/parallel_test.Makefile @@ -0,0 +1,14 @@ +# just a Makefile parallel_test.sh uses to run stuff in parallel with make +%: + $(MAKE) -j1 -C .t/$* $* + +t-exec-%: + $(MAKE) -j1 -C ".t/t-exec-$*" \ + TEST_SSH_PORT=10$*0 \ + SKIP_LTESTS="$(shell cat .ltests/not-in/$*)" \ + BUILDDIR="$(shell pwd)/.t/t-exec-$*" \ + TEST_SHELL=sh \ + MAKE=make \ + TEST_SSH_TRACE=yes \ + TEST_SSH_FAIL_FATAL=yes \ + t-exec \ diff --git a/parallel_test.sh b/parallel_test.sh new file mode 100755 index 0000000..c9c269d --- /dev/null +++ b/parallel_test.sh @@ -0,0 +1,91 @@ +#!/usr/bin/bash +set -uexo pipefail + +# The custom %check script to run the OpenSSH upstream testsuite in parallel. +# +# The upstream testsuite is serial, +# so the idea here is to split the testsuite into several $PARTS: +# * file-tests +# * interop-tests +# * unit +# * ltests-00 +# * ltests-01 +# * ... +# * ltests-23 +# and run them in parallel, using make, each in its own build subtree. + +PARALLEL_MAKEFILE=$1 + +SPLIT=24 +PARTS='file-tests interop-tests unit ' +for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i); + PARTS+="t-exec-$ii " +done + +# work around a selinux restriction: +#chcon -t unconfined_exec_t ssh-sk-helper || : + +# work around something else that only crops up in brew +export TEST_SSH_UNSAFE_PERMISSIONS=1 + +# create a .test directory to store all our files in: +mkdir -p .t .ltests/{in,not-in} + +# patch testsuite: use different ports to avoid port collisions +grep -REi 'port=[2-9][0-9]*' regress +sed -i 's|PORT=4242|PORT=$(expr $TEST_SSH_PORT + 1)|' \ + regress/test-exec.sh* +sed -i 's|^P=3301 # test port|P=$(expr $TEST_SSH_PORT + 1)|' \ + regress/multiplex.sh* +sed -i 's|^fwdport=3301|fwdport=$(expr $TEST_SSH_PORT + 1)|' \ + regress/cfgmatch.sh* regress/cfgmatchlisten.sh* +sed -i 's|^LFWD_PORT=.*|LFWD_PORT=$(expr $TEST_SSH_PORT + 1)|' \ + regress/forward-control.sh* +sed -i 's|^RFWD_PORT=.*|RFWD_PORT=$(expr $TEST_SSH_PORT + 2)|' \ + regress/forward-control.sh* +( ! grep -REi 'port=[2-9][0-9]*' regress) # try to find more of those + +# patch testsuite: speed up +sed -i 's|sleep 1$|sleep .25|' regress/forward-control.sh + +# extract LTESTS list to .tests/ltests/all: +grep -Ex 'tests:[[:space:]]*file-tests t-exec interop-tests extra-tests unit' Makefile +echo -ne '\necho-ltests:\n\techo ${LTESTS}' >> regress/Makefile +make -s -C regress echo-ltests | tr ' ' '\n' > .ltests/all + +# separate ltests into $SPLIT roughly equal .tests/ltests/in/$ii parts: +grep -qFx connect .ltests/all +( ! grep -qFx nonex .ltests/all ) +split -d -a2 --number=l/$SPLIT .ltests/all .ltests/in/ +wc -l .ltests/in/* +grep -qFx connect .ltests/in/* + +# generate the inverses of them --- .ltests/not-in/$ii: +( ! grep -qFx nonex .ltests/in/* ) +for ((i = 0; i < SPLIT; i++)); do ii=$(printf %02d $i); + while read -r tname; do + if ! grep -qFx "$tname" ".ltests/in/$ii"; then + echo -n "$tname " >> ".ltests/not-in/$ii" + fi + done < .ltests/all +done +grep . .ltests/not-in/* +( ! grep -q ^connect .ltests/not-in/0 ) +for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i); + grep -q ^connect .ltests/not-in/$ii +done + +# prepare several test directories: +for PART in $PARTS; do + mkdir .t/${PART} + cp -ra * .t/${PART}/ + sed -i "s|abs_top_srcdir=.*|abs_top_srcdir=$(pwd)/.t/${PART}|" \ + .t/${PART}/Makefile + sed -i "s|abs_top_builddir=.*|abs_top_builddir=$(pwd)/.t/${PART}|" \ + .t/${PART}/Makefile + sed -i "s|^BUILDDIR=.*|BUILDDIR=$(pwd)/.t/${PART}|" \ + .t/${PART}/Makefile +done + +# finally, run tests $PARTS in parallel in their own subtrees: +time make -f "$PARALLEL_MAKEFILE" -j$(nproc) $PARTS diff --git a/sources b/sources new file mode 100644 index 0000000..621f26d --- /dev/null +++ b/sources @@ -0,0 +1,2 @@ +SHA512 (gpgkey-736060BA.gpg) = df44f3fdbcd1d596705348c7f5aed3f738c5f626a55955e0642f7c6c082995cf36a1b1891bb41b8715cb2aff34fef1c877e0eff0d3507dd00a055ba695757a21 +SHA512 (openssh-9.8p1.tar.gz) = 95dec2f18e58eb47994f3de4430253e0665e185564b65088ca5f4108870e05feddef8cda8d3c0a4b75f18b98cc2c024df0e27de53b48c1a16da8da483cb8292a diff --git a/ssh-agent.service b/ssh-agent.service new file mode 100644 index 0000000..812303c --- /dev/null +++ b/ssh-agent.service @@ -0,0 +1,19 @@ +# Requires SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket" +# set in environment, handled for example in plasma via +# /etc/xdg/plasma-workspace/env/ssh-agent.sh +[Unit] +ConditionEnvironment=!SSH_AGENT_PID +Description=OpenSSH key agent +Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1) +Requires=ssh-agent.socket + +[Service] +Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket +ExecStartPre=/usr/bin/rm -f $SSH_AUTH_SOCK +ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK +PassEnvironment=SSH_AGENT_PID +SuccessExitStatus=2 +Type=simple + +[Install] +Also=ssh-agent.socket diff --git a/ssh-agent.socket b/ssh-agent.socket new file mode 100644 index 0000000..d589cbc --- /dev/null +++ b/ssh-agent.socket @@ -0,0 +1,14 @@ +[Unit] +Description=OpenSSH key agent +Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1) + +[Socket] +ListenStream=%t/ssh-agent.socket +Service=ssh-agent.service +Priority=6 +Backlog=5 +SocketMode=0600 +DirectoryMode=0700 + +[Install] +WantedBy=sockets.target diff --git a/ssh-host-keys-migration.service b/ssh-host-keys-migration.service new file mode 100644 index 0000000..41e2c6b --- /dev/null +++ b/ssh-host-keys-migration.service @@ -0,0 +1,15 @@ +[Unit] +Description=Update OpenSSH host key permissions +Documentation=https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +Before=sshd.service +After=ssh-keygen.target +ConditionPathExists=!/var/lib/.ssh-host-keys-migration + +[Service] +Type=oneshot +ExecStart=-/usr/libexec/openssh/ssh-host-keys-migration.sh +ExecStart=touch /var/lib/.ssh-host-keys-migration +RemainAfterExit=yes + +[Install] +WantedBy=sshd.service diff --git a/ssh-host-keys-migration.sh b/ssh-host-keys-migration.sh new file mode 100644 index 0000000..083326e --- /dev/null +++ b/ssh-host-keys-migration.sh @@ -0,0 +1,36 @@ +#!/usr/bin/bash +set -eu -o pipefail +# Detect existing non-conforming host keys and perform the permissions migration +# https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +# +# Example output looks like: +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# Permissions 0640 for '/etc/ssh/ssh_host_rsa_key' are too open. +# It is required that your private key files are NOT accessible by others. +# This private key will be ignored. +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# Permissions 0640 for '/etc/ssh/ssh_host_ecdsa_key' are too open. +# It is required that your private key files are NOT accessible by others. +# This private key will be ignored. +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# Permissions 0640 for '/etc/ssh/ssh_host_ed25519_key' are too open. +# It is required that your private key files are NOT accessible by others. +# This private key will be ignored. +# sshd: no hostkeys available -- exiting. +# +output="$(sshd -T 2>&1 || true)" # expected to fail +while read line; do + if [[ $line =~ ^Permissions\ [0-9]+\ for\ \'(.*)\'\ are\ too\ open. ]]; then + keyfile=${BASH_REMATCH[1]} + echo $line + echo -e "\t-> changing permissions on $keyfile" + chmod --verbose g-r $keyfile + chown --verbose root:root $keyfile + fi +done <<< "$output" diff --git a/SOURCES/ssh-keycat.pam b/ssh-keycat.pam similarity index 100% rename from SOURCES/ssh-keycat.pam rename to ssh-keycat.pam diff --git a/SOURCES/sshd-keygen b/sshd-keygen similarity index 64% rename from SOURCES/sshd-keygen rename to sshd-keygen index 141814c..b15fc8c 100644 --- a/SOURCES/sshd-keygen +++ b/sshd-keygen @@ -9,8 +9,14 @@ case $KEYTYPE in if [[ -r "$FIPS" && $(cat $FIPS) == "1" ]]; then exit 0 fi ;; - "rsa") ;; # always ok - "ecdsa") ;; + "rsa") + if [[ ! -z $SSH_RSA_BITS ]]; then + SSH_KEYGEN_OPTIONS="-b $SSH_RSA_BITS" + fi ;; # always ok + "ecdsa") + if [[ ! -z $SSH_ECDSA_BITS ]]; then + SSH_KEYGEN_OPTIONS="-b $SSH_ECDSA_BITS" + fi ;; *) # wrong argument exit 12 ;; esac @@ -25,13 +31,12 @@ fi rm -f $KEY{,.pub} # create new keys -if ! $KEYGEN -q -t $KEYTYPE -f $KEY -C '' -N '' >&/dev/null; then +if ! $KEYGEN -q -t $KEYTYPE $SSH_KEYGEN_OPTIONS -f $KEY -C '' -N '' >&/dev/null; then exit 1 fi # sanitize permissions -/usr/bin/chgrp ssh_keys $KEY -/usr/bin/chmod 640 $KEY +/usr/bin/chmod 600 $KEY /usr/bin/chmod 644 $KEY.pub if [[ -x /usr/sbin/restorecon ]]; then /usr/sbin/restorecon $KEY{,.pub} diff --git a/SOURCES/sshd-keygen.target b/sshd-keygen.target similarity index 100% rename from SOURCES/sshd-keygen.target rename to sshd-keygen.target diff --git a/SOURCES/sshd-keygen@.service b/sshd-keygen@.service similarity index 100% rename from SOURCES/sshd-keygen@.service rename to sshd-keygen@.service diff --git a/SOURCES/sshd.pam b/sshd.pam similarity index 100% rename from SOURCES/sshd.pam rename to sshd.pam diff --git a/SOURCES/sshd.service b/sshd.service similarity index 60% rename from SOURCES/sshd.service rename to sshd.service index f9a12a8..0cb2a26 100644 --- a/SOURCES/sshd.service +++ b/sshd.service @@ -3,12 +3,14 @@ Description=OpenSSH server daemon Documentation=man:sshd(8) man:sshd_config(5) After=network.target sshd-keygen.target Wants=sshd-keygen.target +# Migration for Fedora 38 change to remove group ownership for standard host keys +# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +Wants=ssh-host-keys-migration.service [Service] Type=notify -EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config EnvironmentFile=-/etc/sysconfig/sshd -ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY +ExecStart=/usr/sbin/sshd -D $OPTIONS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure diff --git a/SOURCES/sshd.socket b/sshd.socket similarity index 100% rename from SOURCES/sshd.socket rename to sshd.socket diff --git a/SOURCES/sshd.sysconfig b/sshd.sysconfig similarity index 58% rename from SOURCES/sshd.sysconfig rename to sshd.sysconfig index de7f0c6..ee44ae6 100644 --- a/SOURCES/sshd.sysconfig +++ b/sshd.sysconfig @@ -6,12 +6,5 @@ # of DSA key or systemctl mask sshd-keygen@rsa.service to disable RSA key # creation. -# Do not change this option unless you have hardware random -# generator and you REALLY know what you are doing - -SSH_USE_STRONG_RNG=0 -# SSH_USE_STRONG_RNG=1 - -# System-wide crypto policy: -# To opt-out, uncomment the following line -# CRYPTO_POLICY= +#SSH_RSA_BITS=3072 +#SSH_ECDSA_BITS=256 diff --git a/sshd@.service b/sshd@.service new file mode 100644 index 0000000..be6d3b9 --- /dev/null +++ b/sshd@.service @@ -0,0 +1,13 @@ +[Unit] +Description=OpenSSH per-connection server daemon +Documentation=man:sshd(8) man:sshd_config(5) +Wants=sshd-keygen.target +After=sshd-keygen.target +# Migration for Fedora 38 change to remove group ownership for standard host keys +# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +Wants=ssh-host-keys-migration.service + +[Service] +EnvironmentFile=-/etc/sysconfig/sshd +ExecStart=-/usr/sbin/sshd -i $OPTIONS +StandardInput=socket