From 653cc18c922fc387b3d3aa1b081c5e5283cce28a Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Tue, 26 Jan 2021 00:47:47 +0000
Subject: [PATCH 07/12] upstream: use recallocarray to allocate the agent
 sockets table;

also clear socket entries that are being marked as unused.

spinkle in some debug2() spam to make it easier to watch an agent
do its thing.

ok markus

OpenBSD-Commit-ID: 74582c8e82e96afea46f6c7b6813a429cbc75922

Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/1fe16fd61bb53944ec510882acc0491abd66ff76]
CVE: CVE-2023-38408
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
---
 ssh-agent.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/ssh-agent.c b/ssh-agent.c
index 78f7268..2635bc5 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.264 2020/09/18 08:16:38 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.269 2021/01/26 00:47:47 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -175,11 +175,12 @@ static void
 close_socket(SocketEntry *e)
 {
	close(e->fd);
-	e->fd = -1;
-	e->type = AUTH_UNUSED;
	sshbuf_free(e->input);
	sshbuf_free(e->output);
	sshbuf_free(e->request);
+	memset(e, '\0', sizeof(*e));
+	e->fd = -1;
+	e->type = AUTH_UNUSED;
 }

 static void
@@ -249,6 +250,8 @@ process_request_identities(SocketEntry *e)
	struct sshbuf *msg;
	int r;

+	debug2("%s: entering", __func__);
+
	if ((msg = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);
	if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
@@ -441,6 +444,7 @@ process_remove_identity(SocketEntry *e)
	struct sshkey *key = NULL;
	Identity *id;

+	debug2("%s: entering", __func__);
	if ((r = sshkey_froms(e->request, &key)) != 0) {
		error("%s: get key: %s", __func__, ssh_err(r));
		goto done;
@@ -467,6 +471,7 @@ process_remove_all_identities(SocketEntry *e)
 {
	Identity *id;

+	debug2("%s: entering", __func__);
	/* Loop over all identities and clear the keys. */
	for (id = TAILQ_FIRST(&idtab->idlist); id;
	    id = TAILQ_FIRST(&idtab->idlist)) {
@@ -520,6 +525,7 @@ process_add_identity(SocketEntry *e)
	u_char ctype;
	int r = SSH_ERR_INTERNAL_ERROR;

+	debug2("%s: entering", __func__);
	if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
	    k == NULL ||
	    (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
@@ -667,6 +673,7 @@ process_lock_agent(SocketEntry *e, int lock)
	static u_int fail_count = 0;
	size_t pwlen;

+	debug2("%s: entering", __func__);
	/*
	 * This is deliberately fatal: the user has requested that we lock,
	 * but we can't parse their request properly. The only safe thing to
@@ -738,6 +745,7 @@ process_add_smartcard_key(SocketEntry *e)
	struct sshkey **keys = NULL, *k;
	Identity *id;

+	debug2("%s: entering", __func__);
	if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
	    (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
		error("%s: buffer error: %s", __func__, ssh_err(r));
@@ -818,6 +826,7 @@ process_remove_smartcard_key(SocketEntry *e)
	int r, success = 0;
	Identity *id, *nxt;

+	debug2("%s: entering", __func__);
	if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
	    (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
		error("%s: buffer error: %s", __func__, ssh_err(r));
@@ -962,6 +971,8 @@ new_socket(sock_type type, int fd)
 {
	u_int i, old_alloc, new_alloc;

+	debug("%s: type = %s", __func__, type == AUTH_CONNECTION ? "CONNECTION" :
+	    (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN"));
	set_nonblock(fd);

	if (fd > max_fd)
@@ -981,7 +992,8 @@ new_socket(sock_type type, int fd)
		}
	old_alloc = sockets_alloc;
	new_alloc = sockets_alloc + 10;
-	sockets = xreallocarray(sockets, new_alloc, sizeof(sockets[0]));
+	sockets = xrecallocarray(sockets, old_alloc, new_alloc,
+	    sizeof(sockets[0]));
	for (i = old_alloc; i < new_alloc; i++)
		sockets[i].type = AUTH_UNUSED;
	sockets_alloc = new_alloc;
--
2.41.0
