diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2002-05-23 19:24:32 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2002-05-23 19:24:32 +0000 |
commit | f9af44845483e4aa0ad9f50a4b683b306722d93e (patch) | |
tree | 1fa2dfb1a9ba835c50cc1a79bec5e90bc6829c65 | |
parent | 0c6ba561e82f6676f56adebb7f07e20a76a24207 (diff) |
add /usr/libexec/ssh-keysign: a setuid helper program for hostbased authentication
in protocol v2 (needs to access the hostkeys).
-rw-r--r-- | usr.bin/ssh/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/ssh/authfile.c | 4 | ||||
-rw-r--r-- | usr.bin/ssh/authfile.h | 3 | ||||
-rw-r--r-- | usr.bin/ssh/lib/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/ssh/msg.c | 73 | ||||
-rw-r--r-- | usr.bin/ssh/msg.h | 31 | ||||
-rw-r--r-- | usr.bin/ssh/pathnames.h | 5 | ||||
-rw-r--r-- | usr.bin/ssh/ssh-keysign.c | 185 | ||||
-rw-r--r-- | usr.bin/ssh/ssh-keysign/Makefile | 18 | ||||
-rw-r--r-- | usr.bin/ssh/ssh.c | 21 | ||||
-rw-r--r-- | usr.bin/ssh/sshconnect.c | 8 | ||||
-rw-r--r-- | usr.bin/ssh/sshconnect.h | 15 | ||||
-rw-r--r-- | usr.bin/ssh/sshconnect1.c | 12 | ||||
-rw-r--r-- | usr.bin/ssh/sshconnect2.c | 95 |
14 files changed, 440 insertions, 38 deletions
diff --git a/usr.bin/ssh/Makefile b/usr.bin/ssh/Makefile index f1f871e8292..0b9c668b651 100644 --- a/usr.bin/ssh/Makefile +++ b/usr.bin/ssh/Makefile @@ -1,9 +1,9 @@ -# $OpenBSD: Makefile,v 1.10 2002/02/09 17:37:34 deraadt Exp $ +# $OpenBSD: Makefile,v 1.11 2002/05/23 19:24:30 markus Exp $ .include <bsd.own.mk> SUBDIR= lib ssh sshd ssh-add ssh-keygen ssh-agent scp sftp-server \ - ssh-keyscan sftp scard + ssh-keysign ssh-keyscan sftp scard distribution: install -C -o root -g wheel -m 0644 ${.CURDIR}/ssh_config \ diff --git a/usr.bin/ssh/authfile.c b/usr.bin/ssh/authfile.c index 337da595dda..f22a3d19bf4 100644 --- a/usr.bin/ssh/authfile.c +++ b/usr.bin/ssh/authfile.c @@ -36,7 +36,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: authfile.c,v 1.48 2002/02/28 15:46:33 markus Exp $"); +RCSID("$OpenBSD: authfile.c,v 1.49 2002/05/23 19:24:30 markus Exp $"); #include <openssl/err.h> #include <openssl/evp.h> @@ -421,7 +421,7 @@ fail: return NULL; } -static Key * +Key * key_load_private_pem(int fd, int type, const char *passphrase, char **commentp) { diff --git a/usr.bin/ssh/authfile.h b/usr.bin/ssh/authfile.h index c614ca12ce8..7f92701ec05 100644 --- a/usr.bin/ssh/authfile.h +++ b/usr.bin/ssh/authfile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.h,v 1.9 2002/03/04 17:27:39 stevesk Exp $ */ +/* $OpenBSD: authfile.h,v 1.10 2002/05/23 19:24:30 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -20,5 +20,6 @@ Key *key_load_public(const char *, char **); Key *key_load_public_type(int, const char *, char **); Key *key_load_private(const char *, const char *, char **); Key *key_load_private_type(int, const char *, const char *, char **); +Key *key_load_private_pem(int, int, const char *, char **); #endif diff --git a/usr.bin/ssh/lib/Makefile b/usr.bin/ssh/lib/Makefile index eabc9037da7..95036b4451b 100644 --- a/usr.bin/ssh/lib/Makefile +++ b/usr.bin/ssh/lib/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.33 2002/03/18 17:50:31 provos Exp $ +# $OpenBSD: Makefile,v 1.34 2002/05/23 19:24:31 markus Exp $ .PATH: ${.CURDIR}/.. @@ -9,7 +9,7 @@ SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \ rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c \ key.c dispatch.c kex.c mac.c uuencode.c misc.c \ rijndael.c ssh-dss.c ssh-rsa.c dh.c kexdh.c kexgex.c \ - scard.c monitor_wrap.c monitor_fdpass.c + scard.c monitor_wrap.c monitor_fdpass.c msg.c DEBUGLIBS= no NOPROFILE= yes diff --git a/usr.bin/ssh/msg.c b/usr.bin/ssh/msg.c new file mode 100644 index 00000000000..a159aae84a7 --- /dev/null +++ b/usr.bin/ssh/msg.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002 Markus Friedl. 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 "includes.h" +RCSID("$OpenBSD: msg.c,v 1.1 2002/05/23 19:24:30 markus Exp $"); + +#include "buffer.h" +#include "getput.h" +#include "log.h" +#include "atomicio.h" +#include "msg.h" + +void +msg_send(int fd, u_char type, Buffer *m) +{ + u_char buf[5]; + u_int mlen = buffer_len(m); + + debug3("msg_send: type %d", type); + + PUT_32BIT(buf, mlen + 1); + buf[4] = type; /* 1st byte of payload is mesg-type */ + if (atomicio(write, fd, buf, sizeof(buf)) != sizeof(buf)) + fatal("msg_send: write"); + if (atomicio(write, fd, buffer_ptr(m), mlen) != mlen) + fatal("msg_send: write"); +} + +int +msg_recv(int fd, Buffer *m) +{ + u_char buf[4]; + ssize_t res; + u_int msg_len; + + debug3("msg_recv entering"); + + res = atomicio(read, fd, buf, sizeof(buf)); + if (res != sizeof(buf)) { + if (res == 0) + return -1; + fatal("msg_recv: read: header %d", res); + } + msg_len = GET_32BIT(buf); + if (msg_len > 256 * 1024) + fatal("msg_recv: read: bad msg_len %d", msg_len); + buffer_clear(m); + buffer_append_space(m, msg_len); + res = atomicio(read, fd, buffer_ptr(m), msg_len); + if (res != msg_len) + fatal("msg_recv: read: %ld != msg_len", (long)res); + return 0; +} diff --git a/usr.bin/ssh/msg.h b/usr.bin/ssh/msg.h new file mode 100644 index 00000000000..13fa95b27eb --- /dev/null +++ b/usr.bin/ssh/msg.h @@ -0,0 +1,31 @@ +/* $OpenBSD: msg.h,v 1.1 2002/05/23 19:24:30 markus Exp $ */ +/* + * Copyright (c) 2002 Markus Friedl. 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 SSH_MSG_H +#define SSH_MSG_H + +void msg_send(int, u_char, Buffer *); +int msg_recv(int, Buffer *); + +#endif diff --git a/usr.bin/ssh/pathnames.h b/usr.bin/ssh/pathnames.h index 52845f64c36..3bc6b50e12b 100644 --- a/usr.bin/ssh/pathnames.h +++ b/usr.bin/ssh/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.12 2002/03/19 03:03:43 stevesk Exp $ */ +/* $OpenBSD: pathnames.h,v 1.13 2002/05/23 19:24:30 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -110,6 +110,9 @@ */ #define _PATH_SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass" +/* Location of ssh-keysign for hostbased authentication */ +#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign" + /* xauth for X11 forwarding */ #define _PATH_XAUTH "/usr/X11R6/bin/xauth" diff --git a/usr.bin/ssh/ssh-keysign.c b/usr.bin/ssh/ssh-keysign.c new file mode 100644 index 00000000000..a309852d3d7 --- /dev/null +++ b/usr.bin/ssh/ssh-keysign.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2002 Markus Friedl. 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 "includes.h" +RCSID("$OpenBSD: ssh-keysign.c,v 1.1 2002/05/23 19:24:30 markus Exp $"); + +#include <openssl/evp.h> + +#include "log.h" +#include "key.h" +#include "ssh2.h" +#include "misc.h" +#include "xmalloc.h" +#include "buffer.h" +#include "bufaux.h" +#include "authfile.h" +#include "msg.h" +#include "pathnames.h" + +static int +valid_request(struct passwd *pw, Key **ret, u_char *data, u_int datalen) +{ + Buffer b; + Key *key; + u_char *p, *pkblob; + u_int blen; + char *pkalg; + int pktype, fail; + + fail = 0; + + buffer_init(&b); + buffer_append(&b, data, datalen); + + /* session id */ + buffer_skip_string(&b); + if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + fail++; + + /* server user */ + buffer_skip_string(&b); + + /* service */ + p = buffer_get_string(&b, NULL); + if (strcmp("ssh-connection", p) != 0) + fail++; + xfree(p); + + /* method */ + p = buffer_get_string(&b, NULL); + if (strcmp("hostbased", p) != 0) + fail++; + xfree(p); + + /* pubkey */ + pkalg = buffer_get_string(&b, NULL); + pkblob = buffer_get_string(&b, &blen); + + pktype = key_type_from_name(pkalg); + if (pktype == KEY_UNSPEC) + fail++; + else if ((key = key_from_blob(pkblob, blen)) == NULL) + fail++; + else if (key->type != pktype) + fail++; + xfree(pkalg); + xfree(pkblob); + + /* chost */ + buffer_skip_string(&b); + + /* local user */ + p = buffer_get_string(&b, NULL); + if (strcmp(pw->pw_name, p) != 0) + fail++; + xfree(p); + + /* end of message */ + if (buffer_len(&b) != 0) + fail++; + + debug3("valid_request: fail %d", fail); + + if (fail && key != NULL) + key_free(key); + else + *ret = key; + + return (fail ? -1 : 0); +} + +int +main(int argc, char **argv) +{ + Buffer b; + Key *keys[2], *key; + struct passwd *pw; + int key_fd[2], i, found, version = 1; + u_char *signature, *data; + u_int slen, dlen; + + key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY); + key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); + + seteuid(getuid()); + setuid(getuid()); + +#ifdef DEBUG_SSH_KEYSIGN + log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); +#endif + + if (key_fd[0] == -1 && key_fd[1] == -1) + fatal("could not open any host key"); + + if ((pw = getpwuid(getuid())) == NULL) + fatal("getpwuid failed"); + pw = pwcopy(pw); + + SSLeay_add_all_algorithms(); + + found = 0; + for (i = 0; i < 2; i++) { + keys[i] = NULL; + if (key_fd[i] == -1) + continue; + keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC, + NULL, NULL); + close(key_fd[i]); + if (keys[i] != NULL) + found = 1; + } + if (!found) + fatal("no hostkey found"); + + buffer_init(&b); + if (msg_recv(STDIN_FILENO, &b) < 0) + fatal("msg_recv failed"); + if (buffer_get_char(&b) != version) + fatal("bad version"); + data = buffer_get_string(&b, &dlen); + if (valid_request(pw, &key, data, dlen) < 0) + fatal("not a valid request"); + xfree(data); + + found = 0; + for (i = 0; i < 2; i++) { + if (keys[i] != NULL && + key_equal(key, keys[i])) { + found = 1; + break; + } + } + if (!found) + fatal("no matching hostkey found"); + + if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) + fatal("key_sign failed"); + + /* send reply */ + buffer_clear(&b); + buffer_put_string(&b, signature, slen); + msg_send(STDOUT_FILENO, version, &b); + + return (0); +} diff --git a/usr.bin/ssh/ssh-keysign/Makefile b/usr.bin/ssh/ssh-keysign/Makefile new file mode 100644 index 00000000000..70edbeddaff --- /dev/null +++ b/usr.bin/ssh/ssh-keysign/Makefile @@ -0,0 +1,18 @@ +# $OpenBSD: Makefile,v 1.1 2002/05/23 19:24:31 markus Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= ssh-keysign +BINOWN= root + +BINMODE?=4555 + +BINDIR= /usr/libexec +NOMAN=yes + +SRCS= ssh-keysign.c + +.include <bsd.prog.mk> + +LDADD+= -lcrypto +DPADD+= ${LIBCRYPTO} diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c index 7022d04b616..a9dbea47030 100644 --- a/usr.bin/ssh/ssh.c +++ b/usr.bin/ssh/ssh.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.172 2002/05/22 23:18:25 deraadt Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.173 2002/05/23 19:24:30 markus Exp $"); #include <openssl/evp.h> #include <openssl/err.h> @@ -124,10 +124,7 @@ char *host; struct sockaddr_storage hostaddr; /* Private host keys. */ -struct { - Key **keys; - int nkeys; -} sensitive_data; +Sensitive sensitive_data; /* Original real UID. */ uid_t original_real_uid; @@ -669,6 +666,7 @@ again: */ sensitive_data.nkeys = 0; sensitive_data.keys = NULL; + sensitive_data.external_keysign = 0; if (!cerr && (options.rhosts_rsa_authentication || options.hostbased_authentication)) { sensitive_data.nkeys = 3; @@ -679,6 +677,16 @@ again: _PATH_HOST_DSA_KEY_FILE, "", NULL); sensitive_data.keys[2] = key_load_private_type(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL); + + if (sensitive_data.keys[0] == NULL && + sensitive_data.keys[1] == NULL && + sensitive_data.keys[2] == NULL) { + sensitive_data.keys[1] = key_load_public( + _PATH_HOST_DSA_KEY_FILE, NULL); + sensitive_data.keys[2] = key_load_public( + _PATH_HOST_RSA_KEY_FILE, NULL); + sensitive_data.external_keysign = 1; + } } /* * Get rid of any extra privileges that we may have. We will no @@ -738,8 +746,7 @@ again: signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ /* Log into the remote system. This never returns if the login fails. */ - ssh_login(sensitive_data.keys, sensitive_data.nkeys, - host, (struct sockaddr *)&hostaddr, pw); + ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw); /* We no longer need the private host keys. Clear them now. */ if (sensitive_data.nkeys != 0) { diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c index afa40bee573..a41a84abd62 100644 --- a/usr.bin/ssh/sshconnect.c +++ b/usr.bin/ssh/sshconnect.c @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.119 2002/01/21 15:13:51 markus Exp $"); +RCSID("$OpenBSD: sshconnect.c,v 1.120 2002/05/23 19:24:30 markus Exp $"); #include <openssl/bn.h> @@ -832,7 +832,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) * This function does not require super-user privileges. */ void -ssh_login(Key **keys, int nkeys, const char *orighost, +ssh_login(Sensitive *sensitive, const char *orighost, struct sockaddr *hostaddr, struct passwd *pw) { char *host, *cp; @@ -857,10 +857,10 @@ ssh_login(Key **keys, int nkeys, const char *orighost, /* authenticate user */ if (compat20) { ssh_kex2(host, hostaddr); - ssh_userauth2(local_user, server_user, host, keys, nkeys); + ssh_userauth2(local_user, server_user, host, sensitive); } else { ssh_kex(host, hostaddr); - ssh_userauth1(local_user, server_user, host, keys, nkeys); + ssh_userauth1(local_user, server_user, host, sensitive); } } diff --git a/usr.bin/ssh/sshconnect.h b/usr.bin/ssh/sshconnect.h index b475adde0df..ad34ee64abf 100644 --- a/usr.bin/ssh/sshconnect.h +++ b/usr.bin/ssh/sshconnect.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.13 2001/10/08 19:05:05 markus Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.14 2002/05/23 19:24:30 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -26,20 +26,27 @@ #ifndef SSHCONNECT_H #define SSHCONNECT_H +typedef struct Sensitive Sensitive; +struct Sensitive { + Key **keys; + int nkeys; + int external_keysign; +}; + int ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int, int, struct passwd *, const char *); void -ssh_login(Key **, int, const char *, struct sockaddr *, struct passwd *); +ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *); int verify_host_key(char *, struct sockaddr *, Key *); void ssh_kex(char *, struct sockaddr *); void ssh_kex2(char *, struct sockaddr *); -void ssh_userauth1(const char *, const char *, char *, Key **, int); -void ssh_userauth2(const char *, const char *, char *, Key **, int); +void ssh_userauth1(const char *, const char *, char *, Sensitive *); +void ssh_userauth2(const char *, const char *, char *, Sensitive *); void ssh_put_password(char *); diff --git a/usr.bin/ssh/sshconnect1.c b/usr.bin/ssh/sshconnect1.c index b762c1fa4cb..dab27715867 100644 --- a/usr.bin/ssh/sshconnect1.c +++ b/usr.bin/ssh/sshconnect1.c @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect1.c,v 1.50 2002/04/21 16:25:06 stevesk Exp $"); +RCSID("$OpenBSD: sshconnect1.c,v 1.51 2002/05/23 19:24:30 markus Exp $"); #include <openssl/bn.h> #include <openssl/md5.h> @@ -1092,7 +1092,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) */ void ssh_userauth1(const char *local_user, const char *server_user, char *host, - Key **keys, int nkeys) + Sensitive *sensitive) { #ifdef KRB5 krb5_context context = NULL; @@ -1178,9 +1178,11 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, */ if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) && options.rhosts_rsa_authentication) { - for (i = 0; i < nkeys; i++) { - if (keys[i] != NULL && keys[i]->type == KEY_RSA1 && - try_rhosts_rsa_authentication(local_user, keys[i])) + for (i = 0; i < sensitive->nkeys; i++) { + if (sensitive->keys[i] != NULL && + sensitive->keys[i]->type == KEY_RSA1 && + try_rhosts_rsa_authentication(local_user, + sensitive->keys[i])) goto success; } } diff --git a/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c index d8e1df5ca9d..0d81367d590 100644 --- a/usr.bin/ssh/sshconnect2.c +++ b/usr.bin/ssh/sshconnect2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.99 2002/03/26 15:58:46 markus Exp $"); +RCSID("$OpenBSD: sshconnect2.c,v 1.100 2002/05/23 19:24:30 markus Exp $"); #include "ssh.h" #include "ssh2.h" @@ -45,6 +45,8 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.99 2002/03/26 15:58:46 markus Exp $"); #include "match.h" #include "dispatch.h" #include "canohost.h" +#include "msg.h" +#include "pathnames.h" /* import */ extern char *client_version_string; @@ -154,8 +156,7 @@ struct Authctxt { int last_key_hint; AuthenticationConnection *agent; /* hostbased */ - Key **keys; - int nkeys; + Sensitive *sensitive; /* kbd-interactive */ int info_req_seen; }; @@ -215,7 +216,7 @@ Authmethod authmethods[] = { void ssh_userauth2(const char *local_user, const char *server_user, char *host, - Key **keys, int nkeys) + Sensitive *sensitive) { Authctxt authctxt; int type; @@ -255,8 +256,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, authctxt.success = 0; authctxt.method = authmethod_lookup("none"); authctxt.authlist = NULL; - authctxt.keys = keys; - authctxt.nkeys = nkeys; + authctxt.sensitive = sensitive; authctxt.info_req_seen = 0; if (authctxt.method == NULL) fatal("ssh_userauth2: internal error: cannot send userauth none request"); @@ -893,6 +893,75 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt) packet_send(); } +static int +ssh_keysign( + Key *key, + u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) +{ + Buffer b; + pid_t pid; + int to[2], from[2], status, version = 1; + + debug("ssh_keysign called"); + + if (fflush(stdout) != 0) + error("ssh_keysign: fflush: %s", strerror(errno)); + if (pipe(to) < 0) { + error("ssh_keysign: pipe: %s", strerror(errno)); + return -1; + } + if (pipe(from) < 0) { + error("ssh_keysign: pipe: %s", strerror(errno)); + return -1; + } + if ((pid = fork()) < 0) { + error("ssh_keysign: fork: %s", strerror(errno)); + return -1; + } + if (pid == 0) { + seteuid(getuid()); + setuid(getuid()); + close(from[0]); + if (dup2(from[1], STDOUT_FILENO) < 0) + fatal("ssh_keysign: dup2: %s", strerror(errno)); + close(to[1]); + if (dup2(to[0], STDIN_FILENO) < 0) + fatal("ssh_keysign: dup2: %s", strerror(errno)); + execlp(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); + fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN, + strerror(errno)); + } + close(from[1]); + close(to[0]); + + buffer_init(&b); + buffer_put_string(&b, data, datalen); + msg_send(to[1], version, &b); + + if (msg_recv(from[0], &b) < 0) { + debug("ssh_keysign: no reply"); + buffer_clear(&b); + return -1; + } + if (buffer_get_char(&b) != version) { + debug("ssh_keysign: bad version"); + buffer_clear(&b); + return -1; + } + *sigp = buffer_get_string(&b, lenp); + buffer_clear(&b); + + close(from[0]); + close(to[1]); + + while (waitpid(pid, &status, 0) < 0) + if (errno != EINTR) + break; + + return 0; +} + /* * this will be move to an external program (ssh-keysign) ASAP. ssh-keysign * will be setuid-root and the sbit can be removed from /usr/bin/ssh. @@ -901,6 +970,7 @@ int userauth_hostbased(Authctxt *authctxt) { Key *private = NULL; + Sensitive *sensitive = authctxt->sensitive; Buffer b; u_char *signature, *blob; char *chost, *pkalg, *p; @@ -909,12 +979,12 @@ userauth_hostbased(Authctxt *authctxt) int ok, i, len, found = 0; /* check for a useful key */ - for (i = 0; i < authctxt->nkeys; i++) { - private = authctxt->keys[i]; + for (i = 0; i < sensitive->nkeys; i++) { + private = sensitive->keys[i]; if (private && private->type != KEY_RSA1) { found = 1; /* we take and free the key */ - authctxt->keys[i] = NULL; + sensitive->keys[i] = NULL; break; } } @@ -956,7 +1026,12 @@ userauth_hostbased(Authctxt *authctxt) #ifdef DEBUG_PK buffer_dump(&b); #endif - ok = key_sign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); + if (sensitive->external_keysign) + ok = ssh_keysign(private, &signature, &slen, + buffer_ptr(&b), buffer_len(&b)); + else + ok = key_sign(private, &signature, &slen, + buffer_ptr(&b), buffer_len(&b)); key_free(private); buffer_free(&b); if (ok != 0) { |