Exit status on `ssh-add` failure

Damien Miller djm at mindrot.org
Tue Jun 2 09:22:55 AEST 2026


On Mon, 1 Jun 2026, Wiktor Kwapisiewicz via openssh-unix-dev wrote:

> On 1.06.2026 10:35, Damien Miller wrote:
> > maybe it's time to change the behaviour?
> 
> That would be most welcome, thank you!
> 
> > diff --git a/ssh-add.c b/ssh-add.c
> > index 2788f7e..ca5d206 100644
> > --- a/ssh-add.c
> > +++ b/ssh-add.c
> > @@ -398,6 +398,7 @@ add_file(int agent_fd, const char *filename, int
> > key_only, int cert_only,
> >   		goto out;
> >   	}
> >   +	ret = -1; /* cert errors after here yield a nonzero exit status */
> >   	if (!sshkey_equal_public(cert, private)) {
> >   		error("Certificate %s does not match private key %s",
> >   		    certpath, filename);
> 
> I've tested this change on top of de97e5a44c88179b834939b84cd555249382de0e
> (current master) and it works fine. ssh-add fails successfully :)
> 
> But now it seems to fail even on successful append of the cert...
> 
> Based on the message I'm getting ("Certificate id_rsa-cert.pub (darren) add
> failed: communication with agent failed") I've moved that ret here:
> 
> diff --git a/ssh-add.c b/ssh-add.c
> index 1e9eddf90..9248ef3b4 100644
> --- a/ssh-add.c
> +++ b/ssh-add.c
> @@ -433,6 +433,7 @@ add_file(int agent_fd, const char *filename, int key_only,
> int cert_only,
>             dest_constraints, ndest_constraints)) != 0) {
>                 error_r(r, "Certificate %s (%s) add failed", certpath,
>                     private->cert->key_id);
> +               ret = -1;
>                 goto out;
>         }
>         /* success */
> 
> And now it seems to fail when adding the cert fails and succeed when it
> succeeds. I'm happy to test more patches in case there's a better way to solve
> this.

try this

diff --git a/ssh-add.c b/ssh-add.c
index 2788f7e..410277b 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -392,12 +392,15 @@ add_file(int agent_fd, const char *filename, int key_only, int cert_only,
 	/* Now try to add the certificate flavour too */
 	xasprintf(&certpath, "%s-cert.pub", filename);
 	if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) {
-		if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
+		if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT) {
+			ret = -1;
 			error_r(r, "Failed to load certificate \"%s\"",
 			    certpath);
+		}
 		goto out;
 	}
 
+	ret = -1; /* cert errors after here yield a nonzero exit status */
 	if (!sshkey_equal_public(cert, private)) {
 		error("Certificate %s does not match private key %s",
 		    certpath, filename);
@@ -429,6 +432,7 @@ add_file(int agent_fd, const char *filename, int key_only, int cert_only,
 		goto out;
 	}
 	/* success */
+	ret = 0;
 	if (!qflag) {
 		fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
 		    private->cert->key_id);


More information about the openssh-unix-dev mailing list