aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssh/authfd.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/authfd.c')
-rw-r--r--crypto/openssh/authfd.c178
1 files changed, 125 insertions, 53 deletions
diff --git a/crypto/openssh/authfd.c b/crypto/openssh/authfd.c
index ecdd869abf01..9f092f7cf955 100644
--- a/crypto/openssh/authfd.c
+++ b/crypto/openssh/authfd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.c,v 1.111 2018/07/09 21:59:10 markus Exp $ */
+/* $OpenBSD: authfd.c,v 1.127 2021/01/26 00:46:17 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -44,8 +44,8 @@
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
-#include <stdarg.h>
#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
@@ -62,7 +62,7 @@
#include "ssherr.h"
#define MAX_AGENT_IDENTITIES 2048 /* Max keys in agent reply */
-#define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */
+#define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */
/* macro to check for "agent failure" message */
#define agent_failed(x) \
@@ -82,31 +82,26 @@ decode_reply(u_char type)
return SSH_ERR_INVALID_FORMAT;
}
-/* Returns the number of the authentication fd, or -1 if there is none. */
+/*
+ * Opens an authentication socket at the provided path and stores the file
+ * descriptor in fdp. Returns 0 on success and an error on failure.
+ */
int
-ssh_get_authentication_socket(int *fdp)
+ssh_get_authentication_socket_path(const char *authsocket, int *fdp)
{
- const char *authsocket;
int sock, oerrno;
struct sockaddr_un sunaddr;
- if (fdp != NULL)
- *fdp = -1;
-
- authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
- if (!authsocket)
- return SSH_ERR_AGENT_NOT_PRESENT;
-
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
- if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
return SSH_ERR_SYSTEM_ERROR;
/* close on exec */
if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 ||
- connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
+ connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
oerrno = errno;
close(sock);
errno = oerrno;
@@ -119,6 +114,25 @@ ssh_get_authentication_socket(int *fdp)
return 0;
}
+/*
+ * Opens the default authentication socket and stores the file descriptor in
+ * fdp. Returns 0 on success and an error on failure.
+ */
+int
+ssh_get_authentication_socket(int *fdp)
+{
+ const char *authsocket;
+
+ if (fdp != NULL)
+ *fdp = -1;
+
+ authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
+ if (authsocket == NULL || *authsocket == '\0')
+ return SSH_ERR_AGENT_NOT_PRESENT;
+
+ return ssh_get_authentication_socket_path(authsocket, fdp);
+}
+
/* Communicate with agent: send request and read reply */
static int
ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
@@ -163,6 +177,27 @@ ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
return 0;
}
+/* Communicate with agent: sent request, read and decode status reply */
+static int
+ssh_request_reply_decode(int sock, struct sshbuf *request)
+{
+ struct sshbuf *reply;
+ int r;
+ u_char type;
+
+ if ((reply = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = ssh_request_reply(sock, request, reply)) != 0 ||
+ (r = sshbuf_get_u8(reply, &type)) != 0 ||
+ (r = decode_reply(type)) != 0)
+ goto out;
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(reply);
+ return r;
+}
+
/*
* Closes the agent socket if it should be closed (depends on how it was
* obtained). The argument must have been returned by
@@ -186,13 +221,11 @@ ssh_lock_agent(int sock, int lock, const char *password)
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
- (r = sshbuf_put_cstring(msg, password)) != 0)
- goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
- goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
+ (r = sshbuf_put_cstring(msg, password)) != 0 ||
+ (r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
sshbuf_free(msg);
return r;
@@ -312,10 +345,38 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
if (idl->comments != NULL)
free(idl->comments[i]);
}
+ free(idl->keys);
+ free(idl->comments);
free(idl);
}
/*
+ * Check if the ssh agent has a given key.
+ * Returns 0 if found, or a negative SSH_ERR_* error code on failure.
+ */
+int
+ssh_agent_has_key(int sock, const struct sshkey *key)
+{
+ int r, ret = SSH_ERR_KEY_NOT_FOUND;
+ size_t i;
+ struct ssh_identitylist *idlist = NULL;
+
+ if ((r = ssh_fetch_identitylist(sock, &idlist)) != 0) {
+ return r;
+ }
+
+ for (i = 0; i < idlist->nkeys; i++) {
+ if (sshkey_equal_public(idlist->keys[i], key)) {
+ ret = 0;
+ break;
+ }
+ }
+
+ ssh_free_identitylist(idlist);
+ return ret;
+}
+
+/*
* Sends a challenge (typically from a server via ssh(1)) to the agent,
* and waits for a response from the agent.
* Returns true (non-zero) if the agent gave the correct answer, zero
@@ -327,10 +388,12 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
static u_int
agent_encode_alg(const struct sshkey *key, const char *alg)
{
- if (alg != NULL && key->type == KEY_RSA) {
- if (strcmp(alg, "rsa-sha2-256") == 0)
+ if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) {
+ if (strcmp(alg, "rsa-sha2-256") == 0 ||
+ strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
return SSH_AGENT_RSA_SHA2_256;
- else if (strcmp(alg, "rsa-sha2-512") == 0)
+ if (strcmp(alg, "rsa-sha2-512") == 0 ||
+ strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
return SSH_AGENT_RSA_SHA2_512;
}
return 0;
@@ -393,7 +456,8 @@ ssh_agent_sign(int sock, const struct sshkey *key,
static int
-encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign)
+encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign,
+ const char *provider)
{
int r;
@@ -411,6 +475,14 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign)
(r = sshbuf_put_u32(m, maxsign)) != 0)
goto out;
}
+ if (provider != NULL) {
+ if ((r = sshbuf_put_u8(m,
+ SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 ||
+ (r = sshbuf_put_cstring(m,
+ "sk-provider@openssh.com")) != 0 ||
+ (r = sshbuf_put_cstring(m, provider)) != 0)
+ goto out;
+ }
r = 0;
out:
return r;
@@ -421,11 +493,12 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign)
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
-ssh_add_identity_constrained(int sock, const struct sshkey *key,
- const char *comment, u_int life, u_int confirm, u_int maxsign)
+ssh_add_identity_constrained(int sock, struct sshkey *key,
+ const char *comment, u_int life, u_int confirm, u_int maxsign,
+ const char *provider)
{
struct sshbuf *msg;
- int r, constrained = (life || confirm || maxsign);
+ int r, constrained = (life || confirm || maxsign || provider);
u_char type;
if ((msg = sshbuf_new()) == NULL)
@@ -439,9 +512,13 @@ ssh_add_identity_constrained(int sock, const struct sshkey *key,
case KEY_DSA_CERT:
case KEY_ECDSA:
case KEY_ECDSA_CERT:
+ case KEY_ECDSA_SK:
+ case KEY_ECDSA_SK_CERT:
#endif
case KEY_ED25519:
case KEY_ED25519_CERT:
+ case KEY_ED25519_SK:
+ case KEY_ED25519_SK_CERT:
case KEY_XMSS:
case KEY_XMSS_CERT:
type = constrained ?
@@ -449,7 +526,7 @@ ssh_add_identity_constrained(int sock, const struct sshkey *key,
SSH2_AGENTC_ADD_IDENTITY;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshkey_private_serialize_maxsign(key, msg, maxsign,
- NULL)) != 0 ||
+ 0)) != 0 ||
(r = sshbuf_put_cstring(msg, comment)) != 0)
goto out;
break;
@@ -458,13 +535,13 @@ ssh_add_identity_constrained(int sock, const struct sshkey *key,
goto out;
}
if (constrained &&
- (r = encode_constraints(msg, life, confirm, maxsign)) != 0)
+ (r = encode_constraints(msg, life, confirm, maxsign,
+ provider)) != 0)
goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
+ if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
- goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
sshbuf_free(msg);
return r;
@@ -475,11 +552,11 @@ ssh_add_identity_constrained(int sock, const struct sshkey *key,
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
-ssh_remove_identity(int sock, struct sshkey *key)
+ssh_remove_identity(int sock, const struct sshkey *key)
{
struct sshbuf *msg;
int r;
- u_char type, *blob = NULL;
+ u_char *blob = NULL;
size_t blen;
if ((msg = sshbuf_new()) == NULL)
@@ -496,16 +573,13 @@ ssh_remove_identity(int sock, struct sshkey *key)
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
+ if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
- goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
- if (blob != NULL) {
- explicit_bzero(blob, blen);
- free(blob);
- }
+ if (blob != NULL)
+ freezero(blob, blen);
sshbuf_free(msg);
return r;
}
@@ -536,13 +610,12 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
(r = sshbuf_put_cstring(msg, pin)) != 0)
goto out;
if (constrained &&
- (r = encode_constraints(msg, life, confirm, 0)) != 0)
+ (r = encode_constraints(msg, life, confirm, 0, NULL)) != 0)
goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
- goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
+ if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
sshbuf_free(msg);
return r;
@@ -569,11 +642,10 @@ ssh_remove_all_identities(int sock, int version)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0)
goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
- goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
+ if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
sshbuf_free(msg);
return r;