mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-01-03 00:02:05 +00:00
upstream commit
move authfd.c and its tentacles to the new buffer/key API; ok markus@
This commit is contained in:
parent
0088c57af3
commit
141efe4954
60
authfd.h
60
authfd.h
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: authfd.h,v 1.37 2009/08/27 17:44:52 djm Exp $ */
|
/* $OpenBSD: authfd.h,v 1.38 2015/01/14 20:05:27 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -16,6 +16,33 @@
|
|||||||
#ifndef AUTHFD_H
|
#ifndef AUTHFD_H
|
||||||
#define AUTHFD_H
|
#define AUTHFD_H
|
||||||
|
|
||||||
|
/* List of identities returned by ssh_fetch_identitylist() */
|
||||||
|
struct ssh_identitylist {
|
||||||
|
size_t nkeys;
|
||||||
|
struct sshkey **keys;
|
||||||
|
char **comments;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ssh_get_authentication_socket(int *fdp);
|
||||||
|
void ssh_close_authentication_socket(int sock);
|
||||||
|
|
||||||
|
int ssh_lock_agent(int sock, int lock, const char *password);
|
||||||
|
int ssh_fetch_identitylist(int sock, int version,
|
||||||
|
struct ssh_identitylist **idlp);
|
||||||
|
void ssh_free_identitylist(struct ssh_identitylist *idl);
|
||||||
|
int ssh_add_identity_constrained(int sock, struct sshkey *key,
|
||||||
|
const char *comment, u_int life, u_int confirm);
|
||||||
|
int ssh_remove_identity(int sock, struct sshkey *key);
|
||||||
|
int ssh_update_card(int sock, int add, const char *reader_id,
|
||||||
|
const char *pin, u_int life, u_int confirm);
|
||||||
|
int ssh_remove_all_identities(int sock, int version);
|
||||||
|
|
||||||
|
int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
|
||||||
|
u_char session_id[16], u_char response[16]);
|
||||||
|
int ssh_agent_sign(int sock, struct sshkey *key,
|
||||||
|
u_char **sigp, size_t *lenp,
|
||||||
|
const u_char *data, size_t datalen, u_int compat);
|
||||||
|
|
||||||
/* Messages for the authentication agent connection. */
|
/* Messages for the authentication agent connection. */
|
||||||
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||||
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
||||||
@ -60,35 +87,4 @@
|
|||||||
|
|
||||||
#define SSH_AGENT_OLD_SIGNATURE 0x01
|
#define SSH_AGENT_OLD_SIGNATURE 0x01
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int fd;
|
|
||||||
Buffer identities;
|
|
||||||
int howmany;
|
|
||||||
} AuthenticationConnection;
|
|
||||||
|
|
||||||
int ssh_agent_present(void);
|
|
||||||
int ssh_get_authentication_socket(void);
|
|
||||||
void ssh_close_authentication_socket(int);
|
|
||||||
|
|
||||||
AuthenticationConnection *ssh_get_authentication_connection(void);
|
|
||||||
void ssh_close_authentication_connection(AuthenticationConnection *);
|
|
||||||
int ssh_get_num_identities(AuthenticationConnection *, int);
|
|
||||||
Key *ssh_get_first_identity(AuthenticationConnection *, char **, int);
|
|
||||||
Key *ssh_get_next_identity(AuthenticationConnection *, char **, int);
|
|
||||||
int ssh_add_identity_constrained(AuthenticationConnection *, Key *,
|
|
||||||
const char *, u_int, u_int);
|
|
||||||
int ssh_remove_identity(AuthenticationConnection *, Key *);
|
|
||||||
int ssh_remove_all_identities(AuthenticationConnection *, int);
|
|
||||||
int ssh_lock_agent(AuthenticationConnection *, int, const char *);
|
|
||||||
int ssh_update_card(AuthenticationConnection *, int, const char *,
|
|
||||||
const char *, u_int, u_int);
|
|
||||||
|
|
||||||
int
|
|
||||||
ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
|
|
||||||
u_int, u_char[16]);
|
|
||||||
|
|
||||||
int
|
|
||||||
ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *,
|
|
||||||
u_int);
|
|
||||||
|
|
||||||
#endif /* AUTHFD_H */
|
#endif /* AUTHFD_H */
|
||||||
|
20
clientloop.c
20
clientloop.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: clientloop.c,v 1.261 2014/07/15 15:54:14 millert Exp $ */
|
/* $OpenBSD: clientloop.c,v 1.262 2015/01/14 20:05:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -110,6 +110,7 @@
|
|||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
|
||||||
/* import options */
|
/* import options */
|
||||||
extern Options options;
|
extern Options options;
|
||||||
@ -1782,7 +1783,7 @@ static void
|
|||||||
client_input_agent_open(int type, u_int32_t seq, void *ctxt)
|
client_input_agent_open(int type, u_int32_t seq, void *ctxt)
|
||||||
{
|
{
|
||||||
Channel *c = NULL;
|
Channel *c = NULL;
|
||||||
int remote_id, sock;
|
int r, remote_id, sock;
|
||||||
|
|
||||||
/* Read the remote channel number from the message. */
|
/* Read the remote channel number from the message. */
|
||||||
remote_id = packet_get_int();
|
remote_id = packet_get_int();
|
||||||
@ -1792,7 +1793,11 @@ client_input_agent_open(int type, u_int32_t seq, void *ctxt)
|
|||||||
* Get a connection to the local authentication agent (this may again
|
* Get a connection to the local authentication agent (this may again
|
||||||
* get forwarded).
|
* get forwarded).
|
||||||
*/
|
*/
|
||||||
sock = ssh_get_authentication_socket();
|
if ((r = ssh_get_authentication_socket(&sock)) != 0 &&
|
||||||
|
r != SSH_ERR_AGENT_NOT_PRESENT)
|
||||||
|
debug("%s: ssh_get_authentication_socket: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we could not connect the agent, send an error message back to
|
* If we could not connect the agent, send an error message back to
|
||||||
@ -1910,7 +1915,7 @@ static Channel *
|
|||||||
client_request_agent(const char *request_type, int rchan)
|
client_request_agent(const char *request_type, int rchan)
|
||||||
{
|
{
|
||||||
Channel *c = NULL;
|
Channel *c = NULL;
|
||||||
int sock;
|
int r, sock;
|
||||||
|
|
||||||
if (!options.forward_agent) {
|
if (!options.forward_agent) {
|
||||||
error("Warning: ssh server tried agent forwarding.");
|
error("Warning: ssh server tried agent forwarding.");
|
||||||
@ -1918,9 +1923,12 @@ client_request_agent(const char *request_type, int rchan)
|
|||||||
"malicious server.");
|
"malicious server.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
sock = ssh_get_authentication_socket();
|
if ((r = ssh_get_authentication_socket(&sock)) != 0) {
|
||||||
if (sock < 0)
|
if (r != SSH_ERR_AGENT_NOT_PRESENT)
|
||||||
|
debug("%s: ssh_get_authentication_socket: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
c = channel_new("authentication agent connection",
|
c = channel_new("authentication agent connection",
|
||||||
SSH_CHANNEL_OPEN, sock, sock, -1,
|
SSH_CHANNEL_OPEN, sock, sock, -1,
|
||||||
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
|
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
|
||||||
|
42
monitor.c
42
monitor.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: monitor.c,v 1.137 2015/01/13 07:39:19 djm Exp $ */
|
/* $OpenBSD: monitor.c,v 1.138 2015/01/14 20:05:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||||
@ -101,6 +101,7 @@
|
|||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
|
||||||
#ifdef GSSAPI
|
#ifdef GSSAPI
|
||||||
static Gssctxt *gsscontext = NULL;
|
static Gssctxt *gsscontext = NULL;
|
||||||
@ -685,28 +686,28 @@ mm_answer_moduli(int sock, Buffer *m)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern AuthenticationConnection *auth_conn;
|
|
||||||
|
|
||||||
int
|
int
|
||||||
mm_answer_sign(int sock, Buffer *m)
|
mm_answer_sign(int sock, Buffer *m)
|
||||||
{
|
{
|
||||||
Key *key;
|
extern int auth_sock; /* XXX move to state struct? */
|
||||||
|
struct sshkey *key;
|
||||||
u_char *p;
|
u_char *p;
|
||||||
u_char *signature;
|
u_char *signature;
|
||||||
u_int siglen, datlen;
|
size_t datlen, siglen;
|
||||||
int keyid;
|
int r, keyid;
|
||||||
|
|
||||||
debug3("%s", __func__);
|
debug3("%s", __func__);
|
||||||
|
|
||||||
keyid = buffer_get_int(m);
|
if ((r = sshbuf_get_u32(m, &keyid)) != 0 ||
|
||||||
p = buffer_get_string(m, &datlen);
|
(r = sshbuf_get_string(m, &p, &datlen)) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
|
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
|
||||||
* SHA384 (48 bytes) and SHA512 (64 bytes).
|
* SHA384 (48 bytes) and SHA512 (64 bytes).
|
||||||
*/
|
*/
|
||||||
if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64)
|
if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64)
|
||||||
fatal("%s: data length incorrect: %u", __func__, datlen);
|
fatal("%s: data length incorrect: %zu", __func__, datlen);
|
||||||
|
|
||||||
/* save session id, it will be passed on the first call */
|
/* save session id, it will be passed on the first call */
|
||||||
if (session_id2_len == 0) {
|
if (session_id2_len == 0) {
|
||||||
@ -716,20 +717,25 @@ mm_answer_sign(int sock, Buffer *m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((key = get_hostkey_by_index(keyid)) != NULL) {
|
if ((key = get_hostkey_by_index(keyid)) != NULL) {
|
||||||
if (key_sign(key, &signature, &siglen, p, datlen) < 0)
|
if ((r = sshkey_sign(key, &signature, &siglen, p, datlen,
|
||||||
fatal("%s: key_sign failed", __func__);
|
datafellows)) != 0)
|
||||||
|
fatal("%s: sshkey_sign failed: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
} else if ((key = get_hostkey_public_by_index(keyid)) != NULL &&
|
} else if ((key = get_hostkey_public_by_index(keyid)) != NULL &&
|
||||||
auth_conn != NULL) {
|
auth_sock > 0) {
|
||||||
if (ssh_agent_sign(auth_conn, key, &signature, &siglen, p,
|
if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
|
||||||
datlen) < 0)
|
p, datlen, datafellows)) != 0) {
|
||||||
fatal("%s: ssh_agent_sign failed", __func__);
|
fatal("%s: ssh_agent_sign failed: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
fatal("%s: no hostkey from index %d", __func__, keyid);
|
fatal("%s: no hostkey from index %d", __func__, keyid);
|
||||||
|
|
||||||
debug3("%s: signature %p(%u)", __func__, signature, siglen);
|
debug3("%s: signature %p(%zu)", __func__, signature, siglen);
|
||||||
|
|
||||||
buffer_clear(m);
|
sshbuf_reset(m);
|
||||||
buffer_put_string(m, signature, siglen);
|
if ((r = sshbuf_put_string(m, signature, siglen)) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
free(p);
|
free(p);
|
||||||
free(signature);
|
free(signature);
|
||||||
|
10
session.c
10
session.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: session.c,v 1.275 2014/12/22 07:55:51 djm Exp $ */
|
/* $OpenBSD: session.c,v 1.276 2015/01/14 20:05:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
@ -1620,11 +1620,11 @@ launch_login(struct passwd *pw, const char *hostname)
|
|||||||
static void
|
static void
|
||||||
child_close_fds(void)
|
child_close_fds(void)
|
||||||
{
|
{
|
||||||
extern AuthenticationConnection *auth_conn;
|
extern int auth_sock;
|
||||||
|
|
||||||
if (auth_conn) {
|
if (auth_sock != -1) {
|
||||||
ssh_close_authentication_connection(auth_conn);
|
close(auth_sock);
|
||||||
auth_conn = NULL;
|
auth_sock = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet_get_connection_in() == packet_get_connection_out())
|
if (packet_get_connection_in() == packet_get_connection_out())
|
||||||
|
259
ssh-add.c
259
ssh-add.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-add.c,v 1.115 2014/12/21 22:27:56 djm Exp $ */
|
/* $OpenBSD: ssh-add.c,v 1.116 2015/01/14 20:05:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -44,6 +44,7 @@
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include "openbsd-compat/openssl-compat.h"
|
#include "openbsd-compat/openssl-compat.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -56,8 +57,8 @@
|
|||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "key.h"
|
#include "sshkey.h"
|
||||||
#include "buffer.h"
|
#include "sshbuf.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
@ -103,22 +104,22 @@ clear_pass(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
delete_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
delete_file(int agent_fd, const char *filename, int key_only)
|
||||||
{
|
{
|
||||||
Key *public = NULL, *cert = NULL;
|
struct sshkey *public, *cert = NULL;
|
||||||
char *certpath = NULL, *comment = NULL;
|
char *certpath = NULL, *comment = NULL;
|
||||||
int ret = -1;
|
int r, ret = -1;
|
||||||
|
|
||||||
public = key_load_public(filename, &comment);
|
if ((r = sshkey_load_public(filename, &public, &comment)) != 0) {
|
||||||
if (public == NULL) {
|
printf("Bad key file %s: %s\n", filename, ssh_err(r));
|
||||||
printf("Bad key file %s\n", filename);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ssh_remove_identity(ac, public)) {
|
if ((r = ssh_remove_identity(agent_fd, public)) == 0) {
|
||||||
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
|
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else
|
} else
|
||||||
fprintf(stderr, "Could not remove identity: %s\n", filename);
|
fprintf(stderr, "Could not remove identity \"%s\": %s\n",
|
||||||
|
filename, ssh_err(r));
|
||||||
|
|
||||||
if (key_only)
|
if (key_only)
|
||||||
goto out;
|
goto out;
|
||||||
@ -127,13 +128,13 @@ delete_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||||||
free(comment);
|
free(comment);
|
||||||
comment = NULL;
|
comment = NULL;
|
||||||
xasprintf(&certpath, "%s-cert.pub", filename);
|
xasprintf(&certpath, "%s-cert.pub", filename);
|
||||||
if ((cert = key_load_public(certpath, &comment)) == NULL)
|
if ((r = sshkey_load_public(certpath, &cert, &comment)) == 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (!key_equal_public(cert, public))
|
if (!sshkey_equal_public(cert, public))
|
||||||
fatal("Certificate %s does not match private key %s",
|
fatal("Certificate %s does not match private key %s",
|
||||||
certpath, filename);
|
certpath, filename);
|
||||||
|
|
||||||
if (ssh_remove_identity(ac, cert)) {
|
if (ssh_remove_identity(agent_fd, cert)) {
|
||||||
fprintf(stderr, "Identity removed: %s (%s)\n", certpath,
|
fprintf(stderr, "Identity removed: %s (%s)\n", certpath,
|
||||||
comment);
|
comment);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -142,9 +143,9 @@ delete_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
if (cert != NULL)
|
if (cert != NULL)
|
||||||
key_free(cert);
|
sshkey_free(cert);
|
||||||
if (public != NULL)
|
if (public != NULL)
|
||||||
key_free(public);
|
sshkey_free(public);
|
||||||
free(certpath);
|
free(certpath);
|
||||||
free(comment);
|
free(comment);
|
||||||
|
|
||||||
@ -153,14 +154,15 @@ delete_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||||||
|
|
||||||
/* Send a request to remove all identities. */
|
/* Send a request to remove all identities. */
|
||||||
static int
|
static int
|
||||||
delete_all(AuthenticationConnection *ac)
|
delete_all(int agent_fd)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (ssh_remove_all_identities(ac, 1))
|
if (ssh_remove_all_identities(agent_fd, 1) == 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
/* ignore error-code for ssh2 */
|
/* ignore error-code for ssh2 */
|
||||||
ssh_remove_all_identities(ac, 2);
|
/* XXX revisit */
|
||||||
|
ssh_remove_all_identities(agent_fd, 2);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
fprintf(stderr, "All identities removed.\n");
|
fprintf(stderr, "All identities removed.\n");
|
||||||
@ -171,13 +173,13 @@ delete_all(AuthenticationConnection *ac)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
add_file(int agent_fd, const char *filename, int key_only)
|
||||||
{
|
{
|
||||||
Key *private, *cert;
|
struct sshkey *private, *cert;
|
||||||
char *comment = NULL;
|
char *comment = NULL;
|
||||||
char msg[1024], *certpath = NULL;
|
char msg[1024], *certpath = NULL;
|
||||||
int r, fd, perms_ok, ret = -1;
|
int r, fd, ret = -1;
|
||||||
Buffer keyblob;
|
struct sshbuf *keyblob;
|
||||||
|
|
||||||
if (strcmp(filename, "-") == 0) {
|
if (strcmp(filename, "-") == 0) {
|
||||||
fd = STDIN_FILENO;
|
fd = STDIN_FILENO;
|
||||||
@ -192,30 +194,38 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||||||
* will occur multiple times, so check perms first and bail if wrong.
|
* will occur multiple times, so check perms first and bail if wrong.
|
||||||
*/
|
*/
|
||||||
if (fd != STDIN_FILENO) {
|
if (fd != STDIN_FILENO) {
|
||||||
perms_ok = key_perm_ok(fd, filename);
|
if (sshkey_perm_ok(fd, filename) != 0) {
|
||||||
if (!perms_ok) {
|
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer_init(&keyblob);
|
if ((keyblob = sshbuf_new()) == NULL)
|
||||||
if (!key_load_file(fd, filename, &keyblob)) {
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
buffer_free(&keyblob);
|
if ((r = sshkey_load_file(fd, keyblob)) != 0) {
|
||||||
|
fprintf(stderr, "Error loading key \"%s\": %s\n",
|
||||||
|
filename, ssh_err(r));
|
||||||
|
sshbuf_free(keyblob);
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
/* At first, try empty passphrase */
|
/* At first, try empty passphrase */
|
||||||
if ((r = sshkey_parse_private_fileblob(&keyblob, "", filename,
|
if ((r = sshkey_parse_private_fileblob(keyblob, "", filename,
|
||||||
&private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE)
|
&private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
|
||||||
fatal("Cannot parse %s: %s", filename, ssh_err(r));
|
fprintf(stderr, "Error loading key \"%s\": %s\n",
|
||||||
|
filename, ssh_err(r));
|
||||||
|
goto fail_load;
|
||||||
|
}
|
||||||
/* try last */
|
/* try last */
|
||||||
if (private == NULL && pass != NULL) {
|
if (private == NULL && pass != NULL) {
|
||||||
if ((r = sshkey_parse_private_fileblob(&keyblob, pass, filename,
|
if ((r = sshkey_parse_private_fileblob(keyblob, pass, filename,
|
||||||
&private, &comment)) != 0 &&
|
&private, &comment)) != 0 &&
|
||||||
r != SSH_ERR_KEY_WRONG_PASSPHRASE)
|
r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
|
||||||
fatal("Cannot parse %s: %s", filename, ssh_err(r));
|
fprintf(stderr, "Error loading key \"%s\": %s\n",
|
||||||
|
filename, ssh_err(r));
|
||||||
|
goto fail_load;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (comment == NULL)
|
if (comment == NULL)
|
||||||
comment = xstrdup(filename);
|
comment = xstrdup(filename);
|
||||||
@ -226,28 +236,30 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||||||
comment);
|
comment);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
pass = read_passphrase(msg, RP_ALLOW_STDIN);
|
pass = read_passphrase(msg, RP_ALLOW_STDIN);
|
||||||
if (strcmp(pass, "") == 0) {
|
if (strcmp(pass, "") == 0)
|
||||||
|
goto fail_load;
|
||||||
|
if ((r = sshkey_parse_private_fileblob(keyblob, pass,
|
||||||
|
filename, &private, NULL)) == 0)
|
||||||
|
break;
|
||||||
|
else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error loading key \"%s\": %s\n",
|
||||||
|
filename, ssh_err(r));
|
||||||
|
fail_load:
|
||||||
clear_pass();
|
clear_pass();
|
||||||
free(comment);
|
free(comment);
|
||||||
buffer_free(&keyblob);
|
sshbuf_free(keyblob);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((r = sshkey_parse_private_fileblob(&keyblob,
|
|
||||||
pass, filename, &private, NULL)) != 0 &&
|
|
||||||
r != SSH_ERR_KEY_WRONG_PASSPHRASE)
|
|
||||||
fatal("Cannot parse %s: %s",
|
|
||||||
filename, ssh_err(r));
|
|
||||||
if (private != NULL)
|
|
||||||
break;
|
|
||||||
clear_pass();
|
clear_pass();
|
||||||
snprintf(msg, sizeof msg,
|
snprintf(msg, sizeof msg,
|
||||||
"Bad passphrase, try again for %.200s: ", comment);
|
"Bad passphrase, try again for %.200s: ", comment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer_free(&keyblob);
|
sshbuf_free(keyblob);
|
||||||
|
|
||||||
if (ssh_add_identity_constrained(ac, private, comment, lifetime,
|
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
|
||||||
confirm)) {
|
lifetime, confirm)) == 0) {
|
||||||
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
|
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (lifetime != 0)
|
if (lifetime != 0)
|
||||||
@ -257,7 +269,8 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"The user must confirm each use of the key\n");
|
"The user must confirm each use of the key\n");
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Could not add identity: %s\n", filename);
|
fprintf(stderr, "Could not add identity \"%s\": %s\n",
|
||||||
|
filename, ssh_err(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip trying to load the cert if requested */
|
/* Skip trying to load the cert if requested */
|
||||||
@ -266,29 +279,39 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||||||
|
|
||||||
/* Now try to add the certificate flavour too */
|
/* Now try to add the certificate flavour too */
|
||||||
xasprintf(&certpath, "%s-cert.pub", filename);
|
xasprintf(&certpath, "%s-cert.pub", filename);
|
||||||
if ((cert = key_load_public(certpath, NULL)) == NULL)
|
if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) {
|
||||||
|
if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
|
||||||
|
error("Failed to load certificate \"%s\": %s",
|
||||||
|
certpath, ssh_err(r));
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (!key_equal_public(cert, private)) {
|
if (!sshkey_equal_public(cert, private)) {
|
||||||
error("Certificate %s does not match private key %s",
|
error("Certificate %s does not match private key %s",
|
||||||
certpath, filename);
|
certpath, filename);
|
||||||
key_free(cert);
|
sshkey_free(cert);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Graft with private bits */
|
/* Graft with private bits */
|
||||||
if (key_to_certified(private, key_cert_is_legacy(cert)) != 0) {
|
if ((r = sshkey_to_certified(private,
|
||||||
error("%s: key_to_certified failed", __func__);
|
sshkey_cert_is_legacy(cert))) != 0) {
|
||||||
key_free(cert);
|
error("%s: sshkey_to_certified: %s", __func__, ssh_err(r));
|
||||||
|
sshkey_free(cert);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
key_cert_copy(cert, private);
|
if ((r = sshkey_cert_copy(cert, private)) != 0) {
|
||||||
key_free(cert);
|
error("%s: key_cert_copy: %s", __func__, ssh_err(r));
|
||||||
|
sshkey_free(cert);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
sshkey_free(cert);
|
||||||
|
|
||||||
if (!ssh_add_identity_constrained(ac, private, comment,
|
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
|
||||||
lifetime, confirm)) {
|
lifetime, confirm)) != 0) {
|
||||||
error("Certificate %s (%s) add failed", certpath,
|
error("Certificate %s (%s) add failed: %s", certpath,
|
||||||
private->cert->key_id);
|
private->cert->key_id, ssh_err(r));
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
|
fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
|
||||||
private->cert->key_id);
|
private->cert->key_id);
|
||||||
@ -297,19 +320,18 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||||||
if (confirm != 0)
|
if (confirm != 0)
|
||||||
fprintf(stderr, "The user must confirm each use of the key\n");
|
fprintf(stderr, "The user must confirm each use of the key\n");
|
||||||
out:
|
out:
|
||||||
if (certpath != NULL)
|
free(certpath);
|
||||||
free(certpath);
|
|
||||||
free(comment);
|
free(comment);
|
||||||
key_free(private);
|
sshkey_free(private);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
update_card(AuthenticationConnection *ac, int add, const char *id)
|
update_card(int agent_fd, int add, const char *id)
|
||||||
{
|
{
|
||||||
char *pin = NULL;
|
char *pin = NULL;
|
||||||
int ret = -1;
|
int r, ret = -1;
|
||||||
|
|
||||||
if (add) {
|
if (add) {
|
||||||
if ((pin = read_passphrase("Enter passphrase for PKCS#11: ",
|
if ((pin = read_passphrase("Enter passphrase for PKCS#11: ",
|
||||||
@ -317,14 +339,14 @@ update_card(AuthenticationConnection *ac, int add, const char *id)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssh_update_card(ac, add, id, pin == NULL ? "" : pin,
|
if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin,
|
||||||
lifetime, confirm)) {
|
lifetime, confirm)) == 0) {
|
||||||
fprintf(stderr, "Card %s: %s\n",
|
fprintf(stderr, "Card %s: %s\n",
|
||||||
add ? "added" : "removed", id);
|
add ? "added" : "removed", id);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Could not %s card: %s\n",
|
fprintf(stderr, "Could not %s card \"%s\": %s\n",
|
||||||
add ? "add" : "remove", id);
|
add ? "add" : "remove", id, ssh_err(r));
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
free(pin);
|
free(pin);
|
||||||
@ -332,32 +354,42 @@ update_card(AuthenticationConnection *ac, int add, const char *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
list_identities(AuthenticationConnection *ac, int do_fp)
|
list_identities(int agent_fd, int do_fp)
|
||||||
{
|
{
|
||||||
Key *key;
|
char *fp;
|
||||||
char *comment, *fp;
|
int version, r, had_identities = 0;
|
||||||
int had_identities = 0;
|
struct ssh_identitylist *idlist;
|
||||||
int version;
|
size_t i;
|
||||||
|
|
||||||
for (version = 1; version <= 2; version++) {
|
for (version = 1; version <= 2; version++) {
|
||||||
for (key = ssh_get_first_identity(ac, &comment, version);
|
if ((r = ssh_fetch_identitylist(agent_fd, version,
|
||||||
key != NULL;
|
&idlist)) != 0) {
|
||||||
key = ssh_get_next_identity(ac, &comment, version)) {
|
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
|
||||||
|
fprintf(stderr, "error fetching identities for "
|
||||||
|
"protocol %d: %s\n", version, ssh_err(r));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (i = 0; i < idlist->nkeys; i++) {
|
||||||
had_identities = 1;
|
had_identities = 1;
|
||||||
if (do_fp) {
|
if (do_fp) {
|
||||||
fp = key_fingerprint(key, fingerprint_hash,
|
fp = sshkey_fingerprint(idlist->keys[i],
|
||||||
SSH_FP_DEFAULT);
|
fingerprint_hash, SSH_FP_DEFAULT);
|
||||||
printf("%d %s %s (%s)\n",
|
printf("%d %s %s (%s)\n",
|
||||||
key_size(key), fp, comment, key_type(key));
|
sshkey_size(idlist->keys[i]), fp,
|
||||||
|
idlist->comments[i],
|
||||||
|
sshkey_type(idlist->keys[i]));
|
||||||
free(fp);
|
free(fp);
|
||||||
} else {
|
} else {
|
||||||
if (!key_write(key, stdout))
|
if ((r = sshkey_write(idlist->keys[i],
|
||||||
fprintf(stderr, "key_write failed");
|
stdout)) != 0) {
|
||||||
fprintf(stdout, " %s\n", comment);
|
fprintf(stderr, "sshkey_write: %s\n",
|
||||||
|
ssh_err(r));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fprintf(stdout, " %s\n", idlist->comments[i]);
|
||||||
}
|
}
|
||||||
key_free(key);
|
|
||||||
free(comment);
|
|
||||||
}
|
}
|
||||||
|
ssh_free_identitylist(idlist);
|
||||||
}
|
}
|
||||||
if (!had_identities) {
|
if (!had_identities) {
|
||||||
printf("The agent has no identities.\n");
|
printf("The agent has no identities.\n");
|
||||||
@ -367,10 +399,10 @@ list_identities(AuthenticationConnection *ac, int do_fp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lock_agent(AuthenticationConnection *ac, int lock)
|
lock_agent(int agent_fd, int lock)
|
||||||
{
|
{
|
||||||
char prompt[100], *p1, *p2;
|
char prompt[100], *p1, *p2;
|
||||||
int passok = 1, ret = -1;
|
int r, passok = 1, ret = -1;
|
||||||
|
|
||||||
strlcpy(prompt, "Enter lock password: ", sizeof(prompt));
|
strlcpy(prompt, "Enter lock password: ", sizeof(prompt));
|
||||||
p1 = read_passphrase(prompt, RP_ALLOW_STDIN);
|
p1 = read_passphrase(prompt, RP_ALLOW_STDIN);
|
||||||
@ -384,24 +416,28 @@ lock_agent(AuthenticationConnection *ac, int lock)
|
|||||||
explicit_bzero(p2, strlen(p2));
|
explicit_bzero(p2, strlen(p2));
|
||||||
free(p2);
|
free(p2);
|
||||||
}
|
}
|
||||||
if (passok && ssh_lock_agent(ac, lock, p1)) {
|
if (passok) {
|
||||||
fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
|
if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) {
|
||||||
ret = 0;
|
fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
|
||||||
} else
|
ret = 0;
|
||||||
fprintf(stderr, "Failed to %slock agent.\n", lock ? "" : "un");
|
} else {
|
||||||
|
fprintf(stderr, "Failed to %slock agent: %s\n",
|
||||||
|
lock ? "" : "un", ssh_err(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
explicit_bzero(p1, strlen(p1));
|
explicit_bzero(p1, strlen(p1));
|
||||||
free(p1);
|
free(p1);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_file(AuthenticationConnection *ac, int deleting, int key_only, char *file)
|
do_file(int agent_fd, int deleting, int key_only, char *file)
|
||||||
{
|
{
|
||||||
if (deleting) {
|
if (deleting) {
|
||||||
if (delete_file(ac, file, key_only) == -1)
|
if (delete_file(agent_fd, file, key_only) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
if (add_file(ac, file, key_only) == -1)
|
if (add_file(agent_fd, file, key_only) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -431,9 +467,9 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
AuthenticationConnection *ac = NULL;
|
int agent_fd;
|
||||||
char *pkcs11provider = NULL;
|
char *pkcs11provider = NULL;
|
||||||
int i, ch, deleting = 0, ret = 0, key_only = 0;
|
int r, i, ch, deleting = 0, ret = 0, key_only = 0;
|
||||||
int xflag = 0, lflag = 0, Dflag = 0;
|
int xflag = 0, lflag = 0, Dflag = 0;
|
||||||
|
|
||||||
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
|
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
|
||||||
@ -448,13 +484,19 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
||||||
/* At first, get a connection to the authentication agent. */
|
/* First, get a connection to the authentication agent. */
|
||||||
ac = ssh_get_authentication_connection();
|
switch (r = ssh_get_authentication_socket(&agent_fd)) {
|
||||||
if (ac == NULL) {
|
case 0:
|
||||||
fprintf(stderr,
|
break;
|
||||||
"Could not open a connection to your authentication agent.\n");
|
case SSH_ERR_AGENT_NOT_PRESENT:
|
||||||
|
fprintf(stderr, "Could not open a connection to your "
|
||||||
|
"authentication agent.\n");
|
||||||
|
exit(2);
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Error connecting to agent: %s\n", ssh_err(r));
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) {
|
while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'E':
|
case 'E':
|
||||||
@ -510,15 +552,15 @@ main(int argc, char **argv)
|
|||||||
if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
|
if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
|
||||||
fatal("Invalid combination of actions");
|
fatal("Invalid combination of actions");
|
||||||
else if (xflag) {
|
else if (xflag) {
|
||||||
if (lock_agent(ac, xflag == 'x' ? 1 : 0) == -1)
|
if (lock_agent(agent_fd, xflag == 'x' ? 1 : 0) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto done;
|
goto done;
|
||||||
} else if (lflag) {
|
} else if (lflag) {
|
||||||
if (list_identities(ac, lflag == 'l' ? 1 : 0) == -1)
|
if (list_identities(agent_fd, lflag == 'l' ? 1 : 0) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto done;
|
goto done;
|
||||||
} else if (Dflag) {
|
} else if (Dflag) {
|
||||||
if (delete_all(ac) == -1)
|
if (delete_all(agent_fd) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -526,7 +568,7 @@ main(int argc, char **argv)
|
|||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
if (pkcs11provider != NULL) {
|
if (pkcs11provider != NULL) {
|
||||||
if (update_card(ac, !deleting, pkcs11provider) == -1)
|
if (update_card(agent_fd, !deleting, pkcs11provider) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -548,7 +590,7 @@ main(int argc, char **argv)
|
|||||||
default_files[i]);
|
default_files[i]);
|
||||||
if (stat(buf, &st) < 0)
|
if (stat(buf, &st) < 0)
|
||||||
continue;
|
continue;
|
||||||
if (do_file(ac, deleting, key_only, buf) == -1)
|
if (do_file(agent_fd, deleting, key_only, buf) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
else
|
else
|
||||||
count++;
|
count++;
|
||||||
@ -557,13 +599,14 @@ main(int argc, char **argv)
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
if (do_file(ac, deleting, key_only, argv[i]) == -1)
|
if (do_file(agent_fd, deleting, key_only,
|
||||||
|
argv[i]) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clear_pass();
|
clear_pass();
|
||||||
|
|
||||||
done:
|
done:
|
||||||
ssh_close_authentication_connection(ac);
|
ssh_close_authentication_socket(agent_fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
11
ssh.c
11
ssh.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh.c,v 1.411 2015/01/08 10:15:45 djm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.412 2015/01/14 20:05:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -107,6 +107,7 @@
|
|||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
|
||||||
#ifdef ENABLE_PKCS11
|
#ifdef ENABLE_PKCS11
|
||||||
#include "ssh-pkcs11.h"
|
#include "ssh-pkcs11.h"
|
||||||
@ -1502,10 +1503,16 @@ ssh_init_forwarding(void)
|
|||||||
static void
|
static void
|
||||||
check_agent_present(void)
|
check_agent_present(void)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
if (options.forward_agent) {
|
if (options.forward_agent) {
|
||||||
/* Clear agent forwarding if we don't have an agent. */
|
/* Clear agent forwarding if we don't have an agent. */
|
||||||
if (!ssh_agent_present())
|
if ((r = ssh_get_authentication_socket(NULL)) != 0) {
|
||||||
options.forward_agent = 0;
|
options.forward_agent = 0;
|
||||||
|
if (r != SSH_ERR_AGENT_NOT_PRESENT)
|
||||||
|
debug("ssh_get_authentication_socket: %s",
|
||||||
|
ssh_err(r));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshconnect1.c,v 1.76 2014/07/15 15:54:14 millert Exp $ */
|
/* $OpenBSD: sshconnect1.c,v 1.77 2015/01/14 20:05:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -49,6 +50,7 @@
|
|||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "digest.h"
|
#include "digest.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
|
||||||
/* Session id for the current session. */
|
/* Session id for the current session. */
|
||||||
u_char session_id[16];
|
u_char session_id[16];
|
||||||
@ -64,33 +66,38 @@ extern char *__progname;
|
|||||||
static int
|
static int
|
||||||
try_agent_authentication(void)
|
try_agent_authentication(void)
|
||||||
{
|
{
|
||||||
int type;
|
int r, type, agent_fd, ret = 0;
|
||||||
char *comment;
|
|
||||||
AuthenticationConnection *auth;
|
|
||||||
u_char response[16];
|
u_char response[16];
|
||||||
u_int i;
|
size_t i;
|
||||||
Key *key;
|
|
||||||
BIGNUM *challenge;
|
BIGNUM *challenge;
|
||||||
|
struct ssh_identitylist *idlist = NULL;
|
||||||
|
|
||||||
/* Get connection to the agent. */
|
/* Get connection to the agent. */
|
||||||
auth = ssh_get_authentication_connection();
|
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
|
||||||
if (!auth)
|
if (r != SSH_ERR_AGENT_NOT_PRESENT)
|
||||||
|
debug("%s: ssh_get_authentication_socket: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((challenge = BN_new()) == NULL)
|
if ((challenge = BN_new()) == NULL)
|
||||||
fatal("try_agent_authentication: BN_new failed");
|
fatal("try_agent_authentication: BN_new failed");
|
||||||
/* Loop through identities served by the agent. */
|
|
||||||
for (key = ssh_get_first_identity(auth, &comment, 1);
|
|
||||||
key != NULL;
|
|
||||||
key = ssh_get_next_identity(auth, &comment, 1)) {
|
|
||||||
|
|
||||||
|
/* Loop through identities served by the agent. */
|
||||||
|
if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) {
|
||||||
|
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
|
||||||
|
debug("%s: ssh_fetch_identitylist: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
for (i = 0; i < idlist->nkeys; i++) {
|
||||||
/* Try this identity. */
|
/* Try this identity. */
|
||||||
debug("Trying RSA authentication via agent with '%.100s'", comment);
|
debug("Trying RSA authentication via agent with '%.100s'",
|
||||||
free(comment);
|
idlist->comments[i]);
|
||||||
|
|
||||||
/* Tell the server that we are willing to authenticate using this key. */
|
/* Tell the server that we are willing to authenticate using this key. */
|
||||||
packet_start(SSH_CMSG_AUTH_RSA);
|
packet_start(SSH_CMSG_AUTH_RSA);
|
||||||
packet_put_bignum(key->rsa->n);
|
packet_put_bignum(idlist->keys[i]->rsa->n);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
|
|
||||||
@ -101,7 +108,6 @@ try_agent_authentication(void)
|
|||||||
does not support RSA authentication. */
|
does not support RSA authentication. */
|
||||||
if (type == SSH_SMSG_FAILURE) {
|
if (type == SSH_SMSG_FAILURE) {
|
||||||
debug("Server refused our key.");
|
debug("Server refused our key.");
|
||||||
key_free(key);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Otherwise it should have sent a challenge. */
|
/* Otherwise it should have sent a challenge. */
|
||||||
@ -115,16 +121,17 @@ try_agent_authentication(void)
|
|||||||
debug("Received RSA challenge from server.");
|
debug("Received RSA challenge from server.");
|
||||||
|
|
||||||
/* Ask the agent to decrypt the challenge. */
|
/* Ask the agent to decrypt the challenge. */
|
||||||
if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
|
if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i],
|
||||||
|
challenge, session_id, response)) != 0) {
|
||||||
/*
|
/*
|
||||||
* The agent failed to authenticate this identifier
|
* The agent failed to authenticate this identifier
|
||||||
* although it advertised it supports this. Just
|
* although it advertised it supports this. Just
|
||||||
* return a wrong value.
|
* return a wrong value.
|
||||||
*/
|
*/
|
||||||
logit("Authentication agent failed to decrypt challenge.");
|
logit("Authentication agent failed to decrypt "
|
||||||
|
"challenge: %s", ssh_err(r));
|
||||||
explicit_bzero(response, sizeof(response));
|
explicit_bzero(response, sizeof(response));
|
||||||
}
|
}
|
||||||
key_free(key);
|
|
||||||
debug("Sending response to RSA challenge.");
|
debug("Sending response to RSA challenge.");
|
||||||
|
|
||||||
/* Send the decrypted challenge back to the server. */
|
/* Send the decrypted challenge back to the server. */
|
||||||
@ -137,22 +144,25 @@ try_agent_authentication(void)
|
|||||||
/* Wait for response from the server. */
|
/* Wait for response from the server. */
|
||||||
type = packet_read();
|
type = packet_read();
|
||||||
|
|
||||||
/* The server returns success if it accepted the authentication. */
|
/*
|
||||||
|
* The server returns success if it accepted the
|
||||||
|
* authentication.
|
||||||
|
*/
|
||||||
if (type == SSH_SMSG_SUCCESS) {
|
if (type == SSH_SMSG_SUCCESS) {
|
||||||
ssh_close_authentication_connection(auth);
|
|
||||||
BN_clear_free(challenge);
|
|
||||||
debug("RSA authentication accepted by server.");
|
debug("RSA authentication accepted by server.");
|
||||||
return 1;
|
ret = 1;
|
||||||
}
|
break;
|
||||||
/* Otherwise it should return failure. */
|
} else if (type != SSH_SMSG_FAILURE)
|
||||||
if (type != SSH_SMSG_FAILURE)
|
packet_disconnect("Protocol error waiting RSA auth "
|
||||||
packet_disconnect("Protocol error waiting RSA auth response: %d",
|
"response: %d", type);
|
||||||
type);
|
|
||||||
}
|
}
|
||||||
ssh_close_authentication_connection(auth);
|
if (ret != 1)
|
||||||
|
debug("RSA authentication using agent refused.");
|
||||||
|
out:
|
||||||
|
ssh_free_identitylist(idlist);
|
||||||
|
ssh_close_authentication_socket(agent_fd);
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
debug("RSA authentication using agent refused.");
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
173
sshconnect2.c
173
sshconnect2.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshconnect2.c,v 1.213 2015/01/08 10:14:08 djm Exp $ */
|
/* $OpenBSD: sshconnect2.c,v 1.214 2015/01/14 20:05:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
||||||
@ -70,6 +70,7 @@
|
|||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
|
||||||
#ifdef GSSAPI
|
#ifdef GSSAPI
|
||||||
#include "ssh-gss.h"
|
#include "ssh-gss.h"
|
||||||
@ -131,10 +132,10 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
while ((alg = strsep(&avail, ",")) && *alg != '\0') {
|
while ((alg = strsep(&avail, ",")) && *alg != '\0') {
|
||||||
if ((ktype = key_type_from_name(alg)) == KEY_UNSPEC)
|
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC)
|
||||||
fatal("%s: unknown alg %s", __func__, alg);
|
fatal("%s: unknown alg %s", __func__, alg);
|
||||||
if (lookup_key_in_hostkeys_by_type(hostkeys,
|
if (lookup_key_in_hostkeys_by_type(hostkeys,
|
||||||
key_type_plain(ktype), NULL))
|
sshkey_type_plain(ktype), NULL))
|
||||||
ALG_APPEND(first, alg);
|
ALG_APPEND(first, alg);
|
||||||
else
|
else
|
||||||
ALG_APPEND(last, alg);
|
ALG_APPEND(last, alg);
|
||||||
@ -242,15 +243,15 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
|
|||||||
* Authenticate user
|
* Authenticate user
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct Authctxt Authctxt;
|
typedef struct cauthctxt Authctxt;
|
||||||
typedef struct Authmethod Authmethod;
|
typedef struct cauthmethod Authmethod;
|
||||||
typedef struct identity Identity;
|
typedef struct identity Identity;
|
||||||
typedef struct idlist Idlist;
|
typedef struct idlist Idlist;
|
||||||
|
|
||||||
struct identity {
|
struct identity {
|
||||||
TAILQ_ENTRY(identity) next;
|
TAILQ_ENTRY(identity) next;
|
||||||
AuthenticationConnection *ac; /* set if agent supports key */
|
int agent_fd; /* >=0 if agent supports key */
|
||||||
Key *key; /* public/private key */
|
struct sshkey *key; /* public/private key */
|
||||||
char *filename; /* comment for agent-only keys */
|
char *filename; /* comment for agent-only keys */
|
||||||
int tried;
|
int tried;
|
||||||
int isprivate; /* key points to the private key */
|
int isprivate; /* key points to the private key */
|
||||||
@ -258,17 +259,18 @@ struct identity {
|
|||||||
};
|
};
|
||||||
TAILQ_HEAD(idlist, identity);
|
TAILQ_HEAD(idlist, identity);
|
||||||
|
|
||||||
struct Authctxt {
|
struct cauthctxt {
|
||||||
const char *server_user;
|
const char *server_user;
|
||||||
const char *local_user;
|
const char *local_user;
|
||||||
const char *host;
|
const char *host;
|
||||||
const char *service;
|
const char *service;
|
||||||
Authmethod *method;
|
struct cauthmethod *method;
|
||||||
sig_atomic_t success;
|
sig_atomic_t success;
|
||||||
char *authlist;
|
char *authlist;
|
||||||
|
int attempt;
|
||||||
/* pubkey */
|
/* pubkey */
|
||||||
Idlist keys;
|
struct idlist keys;
|
||||||
AuthenticationConnection *agent;
|
int agent_fd;
|
||||||
/* hostbased */
|
/* hostbased */
|
||||||
Sensitive *sensitive;
|
Sensitive *sensitive;
|
||||||
/* kbd-interactive */
|
/* kbd-interactive */
|
||||||
@ -276,7 +278,8 @@ struct Authctxt {
|
|||||||
/* generic */
|
/* generic */
|
||||||
void *methoddata;
|
void *methoddata;
|
||||||
};
|
};
|
||||||
struct Authmethod {
|
|
||||||
|
struct cauthmethod {
|
||||||
char *name; /* string to compare against server's list */
|
char *name; /* string to compare against server's list */
|
||||||
int (*userauth)(Authctxt *authctxt);
|
int (*userauth)(Authctxt *authctxt);
|
||||||
void (*cleanup)(Authctxt *authctxt);
|
void (*cleanup)(Authctxt *authctxt);
|
||||||
@ -582,7 +585,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
|
|||||||
key->type, pktype);
|
key->type, pktype);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
fp = key_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
|
fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||||
debug2("input_userauth_pk_ok: fp %s", fp);
|
debug2("input_userauth_pk_ok: fp %s", fp);
|
||||||
free(fp);
|
free(fp);
|
||||||
|
|
||||||
@ -956,27 +959,29 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
identity_sign(Identity *id, u_char **sigp, u_int *lenp,
|
identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
|
||||||
u_char *data, u_int datalen)
|
const u_char *data, size_t datalen, u_int compat)
|
||||||
{
|
{
|
||||||
Key *prv;
|
Key *prv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* the agent supports this key */
|
/* the agent supports this key */
|
||||||
if (id->ac)
|
if (id->agent_fd)
|
||||||
return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
|
return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
|
||||||
data, datalen));
|
data, datalen, compat);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we have already loaded the private key or
|
* we have already loaded the private key or
|
||||||
* the private key is stored in external hardware
|
* the private key is stored in external hardware
|
||||||
*/
|
*/
|
||||||
if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
|
if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
|
||||||
return (key_sign(id->key, sigp, lenp, data, datalen));
|
return (sshkey_sign(id->key, sigp, lenp, data, datalen,
|
||||||
|
compat));
|
||||||
/* load the private key from the file */
|
/* load the private key from the file */
|
||||||
if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL)
|
if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL)
|
||||||
return (-1);
|
return (-1); /* XXX return decent error code */
|
||||||
ret = key_sign(prv, sigp, lenp, data, datalen);
|
ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat);
|
||||||
key_free(prv);
|
sshkey_free(prv);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -985,7 +990,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
|
|||||||
{
|
{
|
||||||
Buffer b;
|
Buffer b;
|
||||||
u_char *blob, *signature;
|
u_char *blob, *signature;
|
||||||
u_int bloblen, slen;
|
u_int bloblen;
|
||||||
|
size_t slen;
|
||||||
u_int skip = 0;
|
u_int skip = 0;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int have_sig = 1;
|
int have_sig = 1;
|
||||||
@ -1026,8 +1032,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
|
|||||||
|
|
||||||
/* generate signature */
|
/* generate signature */
|
||||||
ret = identity_sign(id, &signature, &slen,
|
ret = identity_sign(id, &signature, &slen,
|
||||||
buffer_ptr(&b), buffer_len(&b));
|
buffer_ptr(&b), buffer_len(&b), datafellows);
|
||||||
if (ret == -1) {
|
if (ret != 0) {
|
||||||
free(blob);
|
free(blob);
|
||||||
buffer_free(&b);
|
buffer_free(&b);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1102,7 +1108,7 @@ load_identity_file(char *filename, int userprovided)
|
|||||||
{
|
{
|
||||||
Key *private;
|
Key *private;
|
||||||
char prompt[300], *passphrase;
|
char prompt[300], *passphrase;
|
||||||
int perm_ok = 0, quit, i;
|
int r, perm_ok = 0, quit, i;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (stat(filename, &st) < 0) {
|
if (stat(filename, &st) < 0) {
|
||||||
@ -1110,33 +1116,49 @@ load_identity_file(char *filename, int userprovided)
|
|||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok);
|
snprintf(prompt, sizeof prompt,
|
||||||
if (!perm_ok) {
|
"Enter passphrase for key '%.100s': ", filename);
|
||||||
if (private != NULL)
|
for (i = 0; i <= options.number_of_password_prompts; i++) {
|
||||||
key_free(private);
|
if (i == 0)
|
||||||
return NULL;
|
passphrase = "";
|
||||||
}
|
else {
|
||||||
if (private == NULL) {
|
|
||||||
if (options.batch_mode)
|
|
||||||
return NULL;
|
|
||||||
snprintf(prompt, sizeof prompt,
|
|
||||||
"Enter passphrase for key '%.100s': ", filename);
|
|
||||||
for (i = 0; i < options.number_of_password_prompts; i++) {
|
|
||||||
passphrase = read_passphrase(prompt, 0);
|
passphrase = read_passphrase(prompt, 0);
|
||||||
if (strcmp(passphrase, "") != 0) {
|
if (*passphrase == '\0') {
|
||||||
private = key_load_private_type(KEY_UNSPEC,
|
|
||||||
filename, passphrase, NULL, NULL);
|
|
||||||
quit = 0;
|
|
||||||
} else {
|
|
||||||
debug2("no passphrase given, try next key");
|
debug2("no passphrase given, try next key");
|
||||||
quit = 1;
|
free(passphrase);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
switch ((r = sshkey_load_private_type(KEY_UNSPEC, filename,
|
||||||
|
passphrase, &private, NULL, &perm_ok))) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case SSH_ERR_KEY_WRONG_PASSPHRASE:
|
||||||
|
if (options.batch_mode) {
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug2("bad passphrase given, try again...");
|
||||||
|
break;
|
||||||
|
case SSH_ERR_SYSTEM_ERROR:
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
debug2("Load key \"%s\": %s",
|
||||||
|
filename, ssh_err(r));
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
default:
|
||||||
|
error("Load key \"%s\": %s", filename, ssh_err(r));
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
explicit_bzero(passphrase, strlen(passphrase));
|
explicit_bzero(passphrase, strlen(passphrase));
|
||||||
free(passphrase);
|
free(passphrase);
|
||||||
if (private != NULL || quit)
|
|
||||||
break;
|
|
||||||
debug2("bad passphrase given, try again...");
|
|
||||||
}
|
}
|
||||||
|
if (private != NULL || quit)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return private;
|
return private;
|
||||||
}
|
}
|
||||||
@ -1150,12 +1172,12 @@ load_identity_file(char *filename, int userprovided)
|
|||||||
static void
|
static void
|
||||||
pubkey_prepare(Authctxt *authctxt)
|
pubkey_prepare(Authctxt *authctxt)
|
||||||
{
|
{
|
||||||
Identity *id, *id2, *tmp;
|
struct identity *id, *id2, *tmp;
|
||||||
Idlist agent, files, *preferred;
|
struct idlist agent, files, *preferred;
|
||||||
Key *key;
|
struct sshkey *key;
|
||||||
AuthenticationConnection *ac;
|
int agent_fd, i, r, found;
|
||||||
char *comment;
|
size_t j;
|
||||||
int i, found;
|
struct ssh_identitylist *idlist;
|
||||||
|
|
||||||
TAILQ_INIT(&agent); /* keys from the agent */
|
TAILQ_INIT(&agent); /* keys from the agent */
|
||||||
TAILQ_INIT(&files); /* keys from the config file */
|
TAILQ_INIT(&files); /* keys from the config file */
|
||||||
@ -1185,7 +1207,7 @@ pubkey_prepare(Authctxt *authctxt)
|
|||||||
if (id2->key == NULL ||
|
if (id2->key == NULL ||
|
||||||
(id2->key->flags & SSHKEY_FLAG_EXT) == 0)
|
(id2->key->flags & SSHKEY_FLAG_EXT) == 0)
|
||||||
continue;
|
continue;
|
||||||
if (key_equal(id->key, id2->key)) {
|
if (sshkey_equal(id->key, id2->key)) {
|
||||||
TAILQ_REMOVE(&files, id, next);
|
TAILQ_REMOVE(&files, id, next);
|
||||||
TAILQ_INSERT_TAIL(preferred, id, next);
|
TAILQ_INSERT_TAIL(preferred, id, next);
|
||||||
found = 1;
|
found = 1;
|
||||||
@ -1200,37 +1222,48 @@ pubkey_prepare(Authctxt *authctxt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* list of keys supported by the agent */
|
/* list of keys supported by the agent */
|
||||||
if ((ac = ssh_get_authentication_connection())) {
|
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
|
||||||
for (key = ssh_get_first_identity(ac, &comment, 2);
|
if (r != SSH_ERR_AGENT_NOT_PRESENT)
|
||||||
key != NULL;
|
debug("%s: ssh_get_authentication_socket: %s",
|
||||||
key = ssh_get_next_identity(ac, &comment, 2)) {
|
__func__, ssh_err(r));
|
||||||
|
} else if ((r = ssh_fetch_identitylist(agent_fd, 2, &idlist)) != 0) {
|
||||||
|
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
|
||||||
|
debug("%s: ssh_fetch_identitylist: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
|
} else {
|
||||||
|
for (j = 0; j < idlist->nkeys; j++) {
|
||||||
found = 0;
|
found = 0;
|
||||||
TAILQ_FOREACH(id, &files, next) {
|
TAILQ_FOREACH(id, &files, next) {
|
||||||
/* agent keys from the config file are preferred */
|
/*
|
||||||
if (key_equal(key, id->key)) {
|
* agent keys from the config file are
|
||||||
key_free(key);
|
* preferred
|
||||||
free(comment);
|
*/
|
||||||
|
if (sshkey_equal(idlist->keys[j], id->key)) {
|
||||||
TAILQ_REMOVE(&files, id, next);
|
TAILQ_REMOVE(&files, id, next);
|
||||||
TAILQ_INSERT_TAIL(preferred, id, next);
|
TAILQ_INSERT_TAIL(preferred, id, next);
|
||||||
id->ac = ac;
|
id->agent_fd = agent_fd;
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found && !options.identities_only) {
|
if (!found && !options.identities_only) {
|
||||||
id = xcalloc(1, sizeof(*id));
|
id = xcalloc(1, sizeof(*id));
|
||||||
id->key = key;
|
/* XXX "steals" key/comment from idlist */
|
||||||
id->filename = comment;
|
id->key = idlist->keys[j];
|
||||||
id->ac = ac;
|
id->filename = idlist->comments[j];
|
||||||
|
idlist->keys[j] = NULL;
|
||||||
|
idlist->comments[j] = NULL;
|
||||||
|
id->agent_fd = agent_fd;
|
||||||
TAILQ_INSERT_TAIL(&agent, id, next);
|
TAILQ_INSERT_TAIL(&agent, id, next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ssh_free_identitylist(idlist);
|
||||||
/* append remaining agent keys */
|
/* append remaining agent keys */
|
||||||
for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
|
for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
|
||||||
TAILQ_REMOVE(&agent, id, next);
|
TAILQ_REMOVE(&agent, id, next);
|
||||||
TAILQ_INSERT_TAIL(preferred, id, next);
|
TAILQ_INSERT_TAIL(preferred, id, next);
|
||||||
}
|
}
|
||||||
authctxt->agent = ac;
|
authctxt->agent_fd = agent_fd;
|
||||||
}
|
}
|
||||||
/* append remaining keys from the config file */
|
/* append remaining keys from the config file */
|
||||||
for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
|
for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
|
||||||
@ -1248,13 +1281,13 @@ pubkey_cleanup(Authctxt *authctxt)
|
|||||||
{
|
{
|
||||||
Identity *id;
|
Identity *id;
|
||||||
|
|
||||||
if (authctxt->agent != NULL)
|
if (authctxt->agent_fd != -1)
|
||||||
ssh_close_authentication_connection(authctxt->agent);
|
ssh_close_authentication_socket(authctxt->agent_fd);
|
||||||
for (id = TAILQ_FIRST(&authctxt->keys); id;
|
for (id = TAILQ_FIRST(&authctxt->keys); id;
|
||||||
id = TAILQ_FIRST(&authctxt->keys)) {
|
id = TAILQ_FIRST(&authctxt->keys)) {
|
||||||
TAILQ_REMOVE(&authctxt->keys, id, next);
|
TAILQ_REMOVE(&authctxt->keys, id, next);
|
||||||
if (id->key)
|
if (id->key)
|
||||||
key_free(id->key);
|
sshkey_free(id->key);
|
||||||
free(id->filename);
|
free(id->filename);
|
||||||
free(id);
|
free(id);
|
||||||
}
|
}
|
||||||
|
43
sshd.c
43
sshd.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshd.c,v 1.431 2015/01/07 18:15:07 tedu Exp $ */
|
/* $OpenBSD: sshd.c,v 1.432 2015/01/14 20:05:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -123,6 +123,7 @@
|
|||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
#include "ssh-sandbox.h"
|
#include "ssh-sandbox.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
|
||||||
#ifndef O_NOCTTY
|
#ifndef O_NOCTTY
|
||||||
#define O_NOCTTY 0
|
#define O_NOCTTY 0
|
||||||
@ -191,7 +192,7 @@ char *server_version_string = NULL;
|
|||||||
Kex *xxx_kex;
|
Kex *xxx_kex;
|
||||||
|
|
||||||
/* Daemon's agent connection */
|
/* Daemon's agent connection */
|
||||||
AuthenticationConnection *auth_conn = NULL;
|
int auth_sock = -1;
|
||||||
int have_agent = 0;
|
int have_agent = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -655,7 +656,7 @@ privsep_preauth_child(void)
|
|||||||
static int
|
static int
|
||||||
privsep_preauth(Authctxt *authctxt)
|
privsep_preauth(Authctxt *authctxt)
|
||||||
{
|
{
|
||||||
int status;
|
int status, r;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
struct ssh_sandbox *box = NULL;
|
struct ssh_sandbox *box = NULL;
|
||||||
|
|
||||||
@ -673,8 +674,14 @@ privsep_preauth(Authctxt *authctxt)
|
|||||||
debug2("Network child is on pid %ld", (long)pid);
|
debug2("Network child is on pid %ld", (long)pid);
|
||||||
|
|
||||||
pmonitor->m_pid = pid;
|
pmonitor->m_pid = pid;
|
||||||
if (have_agent)
|
if (have_agent) {
|
||||||
auth_conn = ssh_get_authentication_connection();
|
r = ssh_get_authentication_socket(&auth_sock);
|
||||||
|
if (r != 0) {
|
||||||
|
error("Could not get agent socket: %s",
|
||||||
|
ssh_err(r));
|
||||||
|
have_agent = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (box != NULL)
|
if (box != NULL)
|
||||||
ssh_sandbox_parent_preauth(box, pid);
|
ssh_sandbox_parent_preauth(box, pid);
|
||||||
monitor_child_preauth(authctxt, pmonitor);
|
monitor_child_preauth(authctxt, pmonitor);
|
||||||
@ -1397,7 +1404,7 @@ main(int ac, char **av)
|
|||||||
{
|
{
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
int opt, i, j, on = 1;
|
int r, opt, i, j, on = 1;
|
||||||
int sock_in = -1, sock_out = -1, newsock = -1;
|
int sock_in = -1, sock_out = -1, newsock = -1;
|
||||||
const char *remote_ip;
|
const char *remote_ip;
|
||||||
int remote_port;
|
int remote_port;
|
||||||
@ -1706,7 +1713,7 @@ main(int ac, char **av)
|
|||||||
if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME))
|
if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME))
|
||||||
setenv(SSH_AUTHSOCKET_ENV_NAME,
|
setenv(SSH_AUTHSOCKET_ENV_NAME,
|
||||||
options.host_key_agent, 1);
|
options.host_key_agent, 1);
|
||||||
have_agent = ssh_agent_present();
|
have_agent = ssh_get_authentication_socket(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < options.num_host_key_files; i++) {
|
for (i = 0; i < options.num_host_key_files; i++) {
|
||||||
@ -2103,8 +2110,12 @@ main(int ac, char **av)
|
|||||||
if (use_privsep) {
|
if (use_privsep) {
|
||||||
if (privsep_preauth(authctxt) == 1)
|
if (privsep_preauth(authctxt) == 1)
|
||||||
goto authenticated;
|
goto authenticated;
|
||||||
} else if (compat20 && have_agent)
|
} else if (compat20 && have_agent) {
|
||||||
auth_conn = ssh_get_authentication_connection();
|
if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) {
|
||||||
|
error("Unable to get agent socket: %s", ssh_err(r));
|
||||||
|
have_agent = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* perform the key exchange */
|
/* perform the key exchange */
|
||||||
/* authenticate user and start session */
|
/* authenticate user and start session */
|
||||||
@ -2425,6 +2436,8 @@ void
|
|||||||
sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen,
|
sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen,
|
||||||
u_char *data, u_int dlen)
|
u_char *data, u_int dlen)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
if (privkey) {
|
if (privkey) {
|
||||||
if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0))
|
if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0))
|
||||||
fatal("%s: key_sign failed", __func__);
|
fatal("%s: key_sign failed", __func__);
|
||||||
@ -2432,9 +2445,15 @@ sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen,
|
|||||||
if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0)
|
if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0)
|
||||||
fatal("%s: pubkey_sign failed", __func__);
|
fatal("%s: pubkey_sign failed", __func__);
|
||||||
} else {
|
} else {
|
||||||
if (ssh_agent_sign(auth_conn, pubkey, signature, slen, data,
|
size_t xxx_slen;
|
||||||
dlen))
|
|
||||||
fatal("%s: ssh_agent_sign failed", __func__);
|
if ((r = ssh_agent_sign(auth_sock, pubkey, signature, &xxx_slen,
|
||||||
|
data, dlen, datafellows)) != 0)
|
||||||
|
fatal("%s: ssh_agent_sign failed: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
|
/* XXX: Old API is u_int; new size_t */
|
||||||
|
if (slen != NULL)
|
||||||
|
*slen = xxx_slen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user