diff options
Diffstat (limited to 'usr/src')
52 files changed, 515 insertions, 4560 deletions
diff --git a/usr/src/cmd/ssh/README.altprivsep b/usr/src/cmd/ssh/README.altprivsep index 610a610fa4..73cdeaf80f 100644 --- a/usr/src/cmd/ssh/README.altprivsep +++ b/usr/src/cmd/ssh/README.altprivsep @@ -1,4 +1,4 @@ - Copyright 2006 Sun Microsystems, Inc. All rights reserved. + Copyright 2007 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. #ident "%Z%%M% %I% %E% SMI" @@ -612,7 +612,7 @@ A. References Note that for SSHv1 no on-the-wire messages are processed by the monitor after authentication. In fact, the monitor thinks it's - running SSHv2, even if the on-the-wire protocol is v2. + running SSHv2, even if the on-the-wire protocol is v1. A. References diff --git a/usr/src/cmd/ssh/include/g11n.h b/usr/src/cmd/ssh/include/g11n.h index 0db14a6b27..9fff281c7b 100644 --- a/usr/src/cmd/ssh/include/g11n.h +++ b/usr/src/cmd/ssh/include/g11n.h @@ -18,7 +18,7 @@ * * CDDL HEADER END * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -72,6 +72,8 @@ char **g11n_langtag_set_locale_set_intersect(char *langtag_set, char *g11n_srvr_locale_negotiate(char *clnt_langtags, char **srvr_locales); +/* auxiliary functions */ +void g11n_freelist(char **list); /* * Functions for validating ASCII and UTF-8 strings diff --git a/usr/src/cmd/ssh/include/monitor.h b/usr/src/cmd/ssh/include/monitor.h deleted file mode 100644 index ea223d8a66..0000000000 --- a/usr/src/cmd/ssh/include/monitor.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* $OpenBSD: monitor.h,v 1.8 2002/09/26 11:38:43 markus Exp $ */ - -#ifndef _MONITOR_H -#define _MONITOR_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * 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. - */ - -enum monitor_reqtype { - MONITOR_REQ_MODULI, MONITOR_ANS_MODULI, - MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, - MONITOR_REQ_SIGN, MONITOR_ANS_SIGN, - MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM, - MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER, - MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD, - MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY, - MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND, - MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY, - MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND, -#ifdef GSSAPI - MONITOR_REQ_GSSSETUP,MONITOR_ANS_GSSSETUP, - MONITOR_REQ_GSSSTEP,MONITOR_ANS_GSSSTEP, - MONITOR_REQ_GSSSIGN,MONITOR_ANS_GSSSIGN, - MONITOR_REQ_GSSUSEROK,MONITOR_ANS_GSSUSEROK, - MONITOR_REQ_GSSMECHS,MONITOR_ANS_GSSMECHS, - MONITOR_REQ_GSSLOCALNAME,MONITOR_ANS_GSSLOCALNAME, - MONITOR_REQ_GSSERR,MONITOR_ANS_GSSERR, -#endif - MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED, - MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY, - MONITOR_REQ_KEYEXPORT, - MONITOR_REQ_PTY, MONITOR_ANS_PTY, - MONITOR_REQ_PTYCLEANUP, - MONITOR_REQ_SESSKEY, MONITOR_ANS_SESSKEY, - MONITOR_REQ_SESSID, - MONITOR_REQ_RSAKEYALLOWED, MONITOR_ANS_RSAKEYALLOWED, - MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE, - MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE, - MONITOR_REQ_KRB4, MONITOR_ANS_KRB4, - MONITOR_REQ_KRB5, MONITOR_ANS_KRB5, - MONITOR_REQ_PAM_START, - MONITOR_REQ_TERM -}; - -struct mm_master; -struct monitor { - int m_recvfd; - int m_sendfd; - struct mm_master *m_zback; - struct mm_master *m_zlib; - struct Kex **m_pkex; - pid_t m_pid; -}; - -struct monitor *monitor_init(void); -void monitor_reinit(struct monitor *); -void monitor_sync(struct monitor *); - -struct Authctxt; -struct Authctxt *monitor_child_preauth(struct monitor *); -void monitor_child_postauth(struct monitor *); - -struct mon_table; -int monitor_read(struct monitor*, struct mon_table *, struct mon_table **); - -/* Prototypes for request sending and receiving */ -void mm_request_send(int, enum monitor_reqtype, Buffer *); -void mm_request_receive(int, Buffer *); -void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *); - -#ifdef __cplusplus -} -#endif - -#endif /* _MONITOR_H */ diff --git a/usr/src/cmd/ssh/include/monitor_fdpass.h b/usr/src/cmd/ssh/include/monitor_fdpass.h deleted file mode 100644 index d43c0e4fbb..0000000000 --- a/usr/src/cmd/ssh/include/monitor_fdpass.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $OpenBSD: monitor_fdpass.h,v 1.2 2002/03/26 03:24:01 stevesk Exp $ */ - -#ifndef _MONITOR_FDPASS_H -#define _MONITOR_FDPASS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * 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. - */ - -void mm_send_fd(int, int); -int mm_receive_fd(int); - -#ifdef __cplusplus -} -#endif - -#endif /* _MONITOR_FDPASS_H */ diff --git a/usr/src/cmd/ssh/include/monitor_mm.h b/usr/src/cmd/ssh/include/monitor_mm.h deleted file mode 100644 index 37b53c7355..0000000000 --- a/usr/src/cmd/ssh/include/monitor_mm.h +++ /dev/null @@ -1,79 +0,0 @@ -/* $OpenBSD: monitor_mm.h,v 1.2 2002/03/26 03:24:01 stevesk Exp $ */ - -#ifndef _MONITOR_MM_H -#define _MONITOR_MM_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * 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 "sys-tree.h" - -struct mm_share { - RB_ENTRY(mm_share) next; - void *address; - size_t size; -}; - -struct mm_master { - RB_HEAD(mmtree, mm_share) rb_free; - struct mmtree rb_allocated; - void *address; - size_t size; - - struct mm_master *mmalloc; /* Used to completely share */ - - int write; /* used to writing to other party */ - int read; /* used for reading from other party */ -}; - -RB_PROTOTYPE(mmtree, mm_share, next, mm_compare) - -#define MM_MINSIZE 128 - -#define MM_ADDRESS_END(x) (void *)((u_char *)(x)->address + (x)->size) - -struct mm_master *mm_create(struct mm_master *, size_t); -void mm_destroy(struct mm_master *); - -void mm_share_sync(struct mm_master **, struct mm_master **); - -void *mm_malloc(struct mm_master *, size_t); -void *mm_xmalloc(struct mm_master *, size_t); -void mm_free(struct mm_master *, void *); - -void mm_memvalid(struct mm_master *, void *, size_t); - -#ifdef __cplusplus -} -#endif - -#endif /* _MONITOR_MM_H */ diff --git a/usr/src/cmd/ssh/include/monitor_wrap.h b/usr/src/cmd/ssh/include/monitor_wrap.h deleted file mode 100644 index 49a215af53..0000000000 --- a/usr/src/cmd/ssh/include/monitor_wrap.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* $OpenBSD: monitor_wrap.h,v 1.8 2002/09/26 11:38:43 markus Exp $ */ - -#ifndef _MONITOR_WRAP_H -#define _MONITOR_WRAP_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * 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 "key.h" -#include "buffer.h" - -extern int use_privsep; -#define PRIVSEP(x) (use_privsep ? mm_##x : x) - -enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY}; - -struct monitor; -struct mm_master; -struct passwd; -struct Authctxt; - -DH *mm_choose_dh(int, int, int); -int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); -void mm_inform_authserv(char *, char *); -struct passwd *mm_getpwnamallow(const char *); -char *mm_auth2_read_banner(void); -int mm_auth_password(struct Authctxt *, char *); -int mm_key_allowed(enum mm_keytype, char *, char *, Key *); -int mm_user_key_allowed(struct passwd *, Key *); -int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *); -int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); -int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); -int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); -int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *); -BIGNUM *mm_auth_rsa_generate_challenge(Key *); - -#ifdef USE_PAM -void mm_start_pam(char *); -#endif - -#ifdef GSSAPI -#include "ssh-gss.h" -OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *ctxt, gss_buffer_t recv, - gss_buffer_t send); -int mm_ssh_gssapi_userok(Gssctxt *ctx, char *user); -#endif - -void mm_terminate(void); -int mm_pty_allocate(int *, int *, char *, int); -void mm_session_pty_cleanup2(void *); - -/* SSHv1 interfaces */ -void mm_ssh1_session_id(u_char *); -int mm_ssh1_session_key(BIGNUM *); - -/* Key export functions */ -struct Newkeys *mm_newkeys_from_blob(u_char *, int); -int mm_newkeys_to_blob(int, u_char **, u_int *); - -void monitor_apply_keystate(struct monitor *); -void mm_get_keystate(struct monitor *); -void mm_send_keystate(struct monitor*); - -/* bsdauth */ -int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); -int mm_bsdauth_respond(void *, u_int, char **); - -/* skey */ -int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); -int mm_skey_respond(void *, u_int, char **); - -/* auth_krb */ -#ifdef KRB4 -int mm_auth_krb4(struct Authctxt *, void *, char **, void *); -#endif -#ifdef KRB5 -/* auth and reply are really krb5_data objects, but we don't want to - * include all of the krb5 headers here */ -int mm_auth_krb5(void *authctxt, void *auth, char **client, void *reply); -#endif - -/* zlib allocation hooks */ - -void *mm_zalloc(struct mm_master *, u_int, u_int); -void mm_zfree(struct mm_master *, void *); -void mm_init_compression(struct mm_master *); - -#ifdef __cplusplus -} -#endif - -#endif /* _MONITOR_WRAP_H */ diff --git a/usr/src/cmd/ssh/include/packet.h b/usr/src/cmd/ssh/include/packet.h index 2ad7a7f94d..8a71eb2864 100644 --- a/usr/src/cmd/ssh/include/packet.h +++ b/usr/src/cmd/ssh/include/packet.h @@ -1,15 +1,3 @@ -/* $OpenBSD: packet.h,v 1.35 2002/06/19 18:01:00 markus Exp $ */ - -#ifndef _PACKET_H -#define _PACKET_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -23,11 +11,24 @@ extern "C" { * called by a name other than "ssh" or "Secure Shell". */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +#ifndef _PACKET_H +#define _PACKET_H + +/* $OpenBSD: packet.h,v 1.35 2002/06/19 18:01:00 markus Exp $ */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + + #include <openssl/bn.h> +#include "kex.h" #ifdef ALTPRIVSEP /* Monitor-side functions */ @@ -89,14 +90,7 @@ void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); void set_newkeys(int mode); -int packet_get_keyiv_len(int); -void packet_get_keyiv(int, u_char *, u_int); -int packet_get_keycontext(int, u_char *); -void packet_set_keycontext(int, u_char *); -u_int32_t packet_get_seqnr(int); -void packet_set_seqnr(int, u_int32_t); -int packet_get_ssh1_cipher(void); -void packet_set_iv(int, u_char *); +void free_keys(Newkeys *keys); void packet_write_poll(void); void packet_write_wait(void); @@ -127,6 +121,9 @@ do { \ } \ } while (0) +int packet_need_rekeying(void); +void packet_set_rekey_limit(u_int32_t); + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/ssh/include/readconf.h b/usr/src/cmd/ssh/include/readconf.h index 3d1fe7b211..d4829960d8 100644 --- a/usr/src/cmd/ssh/include/readconf.h +++ b/usr/src/cmd/ssh/include/readconf.h @@ -150,6 +150,8 @@ typedef struct { int num_remote_forwards; Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; int clear_forwardings; + + int64_t rekey_limit; int no_host_authentication_for_localhost; int server_alive_interval; int server_alive_count_max; diff --git a/usr/src/cmd/ssh/libssh/Makefile.com b/usr/src/cmd/ssh/libssh/Makefile.com index ed02ab1de2..c691c21225 100644 --- a/usr/src/cmd/ssh/libssh/Makefile.com +++ b/usr/src/cmd/ssh/libssh/Makefile.com @@ -80,8 +80,6 @@ OBJECTS = \ uuencode.o \ xlist.o \ xmalloc.o \ - monitor_wrap.o \ - monitor_fdpass.o \ readconf.o \ sftp-common.o \ proxy-io.o diff --git a/usr/src/cmd/ssh/libssh/common/g11n.c b/usr/src/cmd/ssh/libssh/common/g11n.c index 95b61bef62..6a985db7f3 100644 --- a/usr/src/cmd/ssh/libssh/common/g11n.c +++ b/usr/src/cmd/ssh/libssh/common/g11n.c @@ -18,7 +18,7 @@ * * CDDL HEADER END * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -57,6 +57,10 @@ static char *g11n_locale2langtag(char *locale); uint_t g11n_validate_ascii(const char *str, uint_t len, uchar_t **error_str); uint_t g11n_validate_utf8(const uchar_t *str, uint_t len, uchar_t **error_str); +/* + * Convert locale string name into a language tag. The caller is responsible for + * freeing the memory allocated for the result. + */ static char * g11n_locale2langtag(char *locale) { @@ -67,7 +71,7 @@ g11n_locale2langtag(char *locale) return (NULL); if (strcmp(locale, "POSIX") == 0 || strcmp(locale, "C") == 0) - return ("i-default"); + return (xstrdup("i-default")); /* punt for language codes which are not exactly 2 letters */ if (strlen(locale) < 2 || @@ -270,8 +274,10 @@ g11n_getlocales() list[n_elems++] = xstrdup(locale); } - if (n_elems == 0) + if (n_elems == 0) { + xfree(list); return (NULL); + } list[n_elems] = NULL; (void) pclose(locale_out); @@ -300,7 +306,7 @@ char * g11n_locales2langs(char **locale_set) { char **p, **r, **q; - char *langtag; + char *langtag, *langs; int locales, skip; for (locales = 0, p = locale_set; p && *p; p++) @@ -321,10 +327,15 @@ g11n_locales2langs(char **locale_set) } if (!skip) *(q++) = langtag; + else + xfree(langtag); *q = NULL; } - return (xjoin(r, ',')); + langs = xjoin(r, ','); + g11n_freelist(r); + + return (langs); } static int @@ -343,12 +354,12 @@ g11n_langtag_match(char *langtag1, char *langtag2) char c1, c2; len1 = (strchr(langtag1, '-')) ? - (strchr(langtag1, '-') - langtag1) - : strlen(langtag1); + (strchr(langtag1, '-') - langtag1) + : strlen(langtag1); len2 = (strchr(langtag2, '-')) ? - (strchr(langtag2, '-') - langtag2) - : strlen(langtag2); + (strchr(langtag2, '-') - langtag2) + : strlen(langtag2); /* no match */ if (len1 != len2 || strncmp(langtag1, langtag2, len1) != 0) @@ -628,17 +639,25 @@ g11n_langtag_set_locale_set_intersect(char *langtag_set, char **locale_set) char * g11n_srvr_locale_negotiate(char *clnt_langtags, char **srvr_locales) { - char **results, *result = NULL; + char **results, **locales, *result = NULL; + + if (srvr_locales == NULL) + locales = g11n_getlocales(); + else + locales = srvr_locales; if ((results = g11n_langtag_set_locale_set_intersect(clnt_langtags, - srvr_locales ? srvr_locales : g11n_getlocales())) == NULL) - return (NULL); + locales)) == NULL) + goto err; if (*results != NULL) result = xstrdup(*results); xfree_split_list(results); +err: + if (locales != srvr_locales) + g11n_freelist(locales); return (result); } @@ -801,8 +820,8 @@ g11n_convert_from_ascii(const char *str, int *err_ptr, uchar_t **error_str) * same, and there are aliases of codesets to boot... */ if (strcmp("646", nl_langinfo(CODESET)) == 0 || - strcmp("ASCII", nl_langinfo(CODESET)) == 0 || - strcmp("US-ASCII", nl_langinfo(CODESET)) == 0) { + strcmp("ASCII", nl_langinfo(CODESET)) == 0 || + strcmp("US-ASCII", nl_langinfo(CODESET)) == 0) { initialized = 1; do_convert = 0; } else { @@ -1035,3 +1054,20 @@ do_iconv(iconv_t cd, uint_t *mul_ptr, const void *buf, uint_t len, return (converted); } + +/* + * Free all strings in the list and then free the list itself. We know that the + * list ends with a NULL pointer. + */ +void +g11n_freelist(char **list) +{ + int i = 0; + + while (list[i] != NULL) { + xfree(list[i]); + i++; + } + + xfree(list); +} diff --git a/usr/src/cmd/ssh/libssh/common/kex.c b/usr/src/cmd/ssh/libssh/common/kex.c index 0e3b8d9365..d535254210 100644 --- a/usr/src/cmd/ssh/libssh/common/kex.c +++ b/usr/src/cmd/ssh/libssh/common/kex.c @@ -21,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,7 +47,6 @@ RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $"); #include "mac.h" #include "match.h" #include "dispatch.h" -#include "monitor.h" #include "g11n.h" #ifdef GSSAPI @@ -56,10 +55,6 @@ RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $"); #define KEX_COOKIE_LEN 16 -/* Use privilege separation for sshd */ -int use_privsep; -struct monitor *pmonitor; - char *session_lang = NULL; @@ -182,11 +177,8 @@ skip_newkeys: buffer_clear(&kex->peer); /* buffer_clear(&kex->my); */ kex->flags &= ~KEX_INIT_SENT; -#if 0 - /* Must have this name for use in sshd (audit_save_kex())... */ xfree(kex->name); kex->name = NULL; -#endif } void @@ -543,6 +535,7 @@ kex_choose_conf(Kex *kex) g11n_setlocale(LC_ALL, locale); debug("Negotiated main locale: %s", locale); packet_send_debug("Negotiated main locale: %s", locale); + xfree(locale); } if (plangs != p_langs_s2c && p_langs_s2c && *p_langs_s2c) { @@ -550,14 +543,11 @@ kex_choose_conf(Kex *kex) if (locale) { g11n_setlocale(LC_MESSAGES, locale); debug("Negotiated messages locale: %s", locale); - packet_send_debug("Negotiated messages locale: %s", locale); + packet_send_debug("Negotiated " + "messages locale: %s", locale); + xfree(locale); } } - /* - * Should we free locale? Or does setlocale - * retain a reference? - */ - /*xfree(locale);*/ } } else { diff --git a/usr/src/cmd/ssh/libssh/common/kexdh.c b/usr/src/cmd/ssh/libssh/common/kexdh.c index 7af19994fb..b15ecd2c5b 100644 --- a/usr/src/cmd/ssh/libssh/common/kexdh.c +++ b/usr/src/cmd/ssh/libssh/common/kexdh.c @@ -39,7 +39,6 @@ RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $"); #include "packet.h" #include "dh.h" #include "ssh2.h" -#include "monitor_wrap.h" u_char * kex_dh_hash( diff --git a/usr/src/cmd/ssh/libssh/common/kexdhc.c b/usr/src/cmd/ssh/libssh/common/kexdhc.c index 6e7e7d7dc5..1c75f8449f 100644 --- a/usr/src/cmd/ssh/libssh/common/kexdhc.c +++ b/usr/src/cmd/ssh/libssh/common/kexdhc.c @@ -39,7 +39,6 @@ RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $"); #include "packet.h" #include "dh.h" #include "ssh2.h" -#include "monitor_wrap.h" void kexdh_client(Kex *kex) diff --git a/usr/src/cmd/ssh/libssh/common/kexdhs.c b/usr/src/cmd/ssh/libssh/common/kexdhs.c index 1fc9f4c2ee..5e14b1333f 100644 --- a/usr/src/cmd/ssh/libssh/common/kexdhs.c +++ b/usr/src/cmd/ssh/libssh/common/kexdhs.c @@ -39,7 +39,6 @@ RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $"); #include "packet.h" #include "dh.h" #include "ssh2.h" -#include "monitor_wrap.h" void kexdh_server(Kex *kex) @@ -123,7 +122,7 @@ kexdh_server(Kex *kex) /* sign H */ /* XXX hashlen depends on KEX */ - PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20)); + key_sign(server_host_key, &signature, &slen, hash, 20); /* destroy_sensitive_data(); */ diff --git a/usr/src/cmd/ssh/libssh/common/kexgex.c b/usr/src/cmd/ssh/libssh/common/kexgex.c index 3553bb130f..3652e1c020 100644 --- a/usr/src/cmd/ssh/libssh/common/kexgex.c +++ b/usr/src/cmd/ssh/libssh/common/kexgex.c @@ -40,7 +40,6 @@ RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $"); #include "dh.h" #include "ssh2.h" #include "compat.h" -#include "monitor_wrap.h" u_char * kexgex_hash( diff --git a/usr/src/cmd/ssh/libssh/common/kexgexc.c b/usr/src/cmd/ssh/libssh/common/kexgexc.c index 5f6ac3d283..5fddebaed9 100644 --- a/usr/src/cmd/ssh/libssh/common/kexgexc.c +++ b/usr/src/cmd/ssh/libssh/common/kexgexc.c @@ -40,7 +40,6 @@ RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $"); #include "dh.h" #include "ssh2.h" #include "compat.h" -#include "monitor_wrap.h" void kexgex_client(Kex *kex) diff --git a/usr/src/cmd/ssh/libssh/common/kexgexs.c b/usr/src/cmd/ssh/libssh/common/kexgexs.c index 60608d2a65..b0bd4e3272 100644 --- a/usr/src/cmd/ssh/libssh/common/kexgexs.c +++ b/usr/src/cmd/ssh/libssh/common/kexgexs.c @@ -40,7 +40,6 @@ RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $"); #include "dh.h" #include "ssh2.h" #include "compat.h" -#include "monitor_wrap.h" void kexgex_server(Kex *kex) @@ -85,7 +84,7 @@ kexgex_server(Kex *kex) min, nbits, max); /* Contact privileged parent */ - dh = PRIVSEP(choose_dh(min, nbits, max)); + dh = choose_dh(min, nbits, max); if (dh == NULL) packet_disconnect("Protocol error: no matching DH grp found"); @@ -168,7 +167,7 @@ kexgex_server(Kex *kex) /* sign H */ /* XXX hashlen depends on KEX */ - PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20)); + key_sign(server_host_key, &signature, &slen, hash, 20); /* destroy_sensitive_data(); */ diff --git a/usr/src/cmd/ssh/libssh/common/kexgsss.c b/usr/src/cmd/ssh/libssh/common/kexgsss.c index e6a6d67e61..61f3fb70f1 100644 --- a/usr/src/cmd/ssh/libssh/common/kexgsss.c +++ b/usr/src/cmd/ssh/libssh/common/kexgsss.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,7 +45,6 @@ #include "dh.h" #include "ssh2.h" #include "ssh-gss.h" -#include "monitor_wrap.h" #include "auth.h" Gssctxt *xxx_gssctxt; @@ -127,8 +126,7 @@ kexgss_server(Kex *kex) type); } - maj_status=PRIVSEP(ssh_gssapi_accept_ctx(ctxt,&recv_tok, - &send_tok)); + maj_status = ssh_gssapi_accept_ctx(ctxt,&recv_tok, &send_tok); xfree(recv_tok.value); /* We allocated this, not gss */ diff --git a/usr/src/cmd/ssh/libssh/common/llib-lssh b/usr/src/cmd/ssh/libssh/common/llib-lssh index f827580891..ed817d9385 100644 --- a/usr/src/cmd/ssh/libssh/common/llib-lssh +++ b/usr/src/cmd/ssh/libssh/common/llib-lssh @@ -84,10 +84,6 @@ #include <match.h> #include <misc.h> #include <mktemp.h> -#include <monitor_fdpass.h> -#include <monitor.h> -#include <monitor_mm.h> -#include <monitor_wrap.h> #include <mpaux.h> #include <msg.h> #include <myproposal.h> diff --git a/usr/src/cmd/ssh/libssh/common/monitor_fdpass.c b/usr/src/cmd/ssh/libssh/common/monitor_fdpass.c deleted file mode 100644 index 305e45e4cc..0000000000 --- a/usr/src/cmd/ssh/libssh/common/monitor_fdpass.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2001 Niels Provos <provos@citi.umich.edu> - * 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: monitor_fdpass.c,v 1.4 2002/06/26 14:50:04 deraadt Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/uio.h> - -#include "log.h" -#include "monitor_fdpass.h" - -void -mm_send_fd(int socket, int fd) -{ -#if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) - struct msghdr msg; - struct iovec vec; - char ch = '\0'; - ssize_t n; -#ifndef HAVE_ACCRIGHTS_IN_MSGHDR - char tmp[CMSG_SPACE(sizeof(int))]; - struct cmsghdr *cmsg; -#endif - - memset(&msg, 0, sizeof(msg)); -#ifdef HAVE_ACCRIGHTS_IN_MSGHDR - msg.msg_accrights = (caddr_t)&fd; - msg.msg_accrightslen = sizeof(fd); -#else - msg.msg_control = (caddr_t)tmp; - msg.msg_controllen = CMSG_LEN(sizeof(int)); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsg) = fd; -#endif - - vec.iov_base = &ch; - vec.iov_len = 1; - msg.msg_iov = &vec; - msg.msg_iovlen = 1; - - if ((n = sendmsg(socket, &msg, 0)) == -1) - fatal("%s: sendmsg(%d): %s", __func__, fd, - strerror(errno)); - if (n != 1) - fatal("%s: sendmsg: expected sent 1 got %ld", - __func__, (long)n); -#else - fatal("%s: UsePrivilegeSeparation=yes not supported", - __func__); -#endif -} - -int -mm_receive_fd(int socket) -{ -#if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) - struct msghdr msg; - struct iovec vec; - ssize_t n; - char ch; - int fd; -#ifndef HAVE_ACCRIGHTS_IN_MSGHDR - char tmp[CMSG_SPACE(sizeof(int))]; - struct cmsghdr *cmsg; -#endif - - memset(&msg, 0, sizeof(msg)); - vec.iov_base = &ch; - vec.iov_len = 1; - msg.msg_iov = &vec; - msg.msg_iovlen = 1; -#ifdef HAVE_ACCRIGHTS_IN_MSGHDR - msg.msg_accrights = (caddr_t)&fd; - msg.msg_accrightslen = sizeof(fd); -#else - msg.msg_control = tmp; - msg.msg_controllen = sizeof(tmp); -#endif - - if ((n = recvmsg(socket, &msg, 0)) == -1) - fatal("%s: recvmsg: %s", __func__, strerror(errno)); - if (n != 1) - fatal("%s: recvmsg: expected received 1 got %ld", - __func__, (long)n); - -#ifdef HAVE_ACCRIGHTS_IN_MSGHDR - if (msg.msg_accrightslen != sizeof(fd)) - fatal("%s: no fd", __func__); -#else - cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg->cmsg_type != SCM_RIGHTS) - fatal("%s: expected type %d got %d", __func__, - SCM_RIGHTS, cmsg->cmsg_type); - fd = (*(int *)CMSG_DATA(cmsg)); -#endif - return fd; -#else - fatal("%s: UsePrivilegeSeparation=yes not supported", - __func__); -#endif -} diff --git a/usr/src/cmd/ssh/libssh/common/monitor_wrap.c b/usr/src/cmd/ssh/libssh/common/monitor_wrap.c deleted file mode 100644 index 4882c3d967..0000000000 --- a/usr/src/cmd/ssh/libssh/common/monitor_wrap.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * Copyright 2002 Markus Friedl <markus@openbsd.org> - * 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: monitor_wrap.c,v 1.19 2002/09/26 11:38:43 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/bn.h> -#include <openssl/dh.h> - -#include "ssh.h" -#include "dh.h" -#include "kex.h" -#include "auth.h" -#include "buffer.h" -#include "bufaux.h" -#include "packet.h" -#include "mac.h" -#include "log.h" -#include "zlib.h" -#include "monitor.h" -#include "monitor_wrap.h" -#include "xmalloc.h" -#include "atomicio.h" -#include "monitor_fdpass.h" -#include "getput.h" - -#include "auth.h" -#include "channels.h" -#include "session.h" - -#ifdef GSSAPI -#include "ssh-gss.h" -#endif - -/* Imports */ -extern int compat20; -extern Newkeys *newkeys[]; -extern z_stream incoming_stream; -extern z_stream outgoing_stream; -extern struct monitor *pmonitor; -extern Buffer input, output; - -void -mm_request_send(int socket, enum monitor_reqtype type, Buffer *m) -{ - u_int mlen = buffer_len(m); - u_char buf[5]; - - debug3("%s entering: type %d", __func__, type); - - PUT_32BIT(buf, mlen + 1); - buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ - if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf)) - fatal("%s: write", __func__); - if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen) - fatal("%s: write", __func__); -} - -void -mm_request_receive(int socket, Buffer *m) -{ - u_char buf[4]; - u_int msg_len; - ssize_t res; - - debug3("%s entering", __func__); - - res = atomicio(read, socket, buf, sizeof(buf)); - if (res != sizeof(buf)) { - if (res == 0) - fatal_cleanup(); - fatal("%s: read: %ld", __func__, (long)res); - } - msg_len = GET_32BIT(buf); - if (msg_len > 256 * 1024) - fatal("%s: read: bad msg_len %d", __func__, msg_len); - buffer_clear(m); - buffer_append_space(m, msg_len); - res = atomicio(read, socket, buffer_ptr(m), msg_len); - if (res != msg_len) - fatal("%s: read: %ld != msg_len", __func__, (long)res); -} - -void -mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m) -{ - u_char rtype; - - debug3("%s entering: type %d", __func__, type); - - mm_request_receive(socket, m); - rtype = buffer_get_char(m); - if (rtype != type) - fatal("%s: read: rtype %d != type %d", __func__, - rtype, type); -} - -DH * -mm_choose_dh(int min, int nbits, int max) -{ - BIGNUM *p, *g; - int success = 0; - Buffer m; - - buffer_init(&m); - buffer_put_int(&m, min); - buffer_put_int(&m, nbits); - buffer_put_int(&m, max); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m); - - debug3("%s: waiting for MONITOR_ANS_MODULI", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m); - - success = buffer_get_char(&m); - if (success == 0) - fatal("%s: MONITOR_ANS_MODULI failed", __func__); - - if ((p = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - if ((g = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - buffer_get_bignum2(&m, p); - buffer_get_bignum2(&m, g); - - debug3("%s: remaining %d", __func__, buffer_len(&m)); - buffer_free(&m); - - return (dh_new_group(g, p)); -} - -int -mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) -{ - Kex *kex = *pmonitor->m_pkex; - Buffer m; - - debug3("%s entering", __func__); - - buffer_init(&m); - buffer_put_int(&m, kex->host_key_index(key)); - buffer_put_string(&m, data, datalen); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); - - debug3("%s: waiting for MONITOR_ANS_SIGN", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m); - *sigp = buffer_get_string(&m, lenp); - buffer_free(&m); - - return (0); -} - -struct passwd * -mm_getpwnamallow(const char *login) -{ - Buffer m; - struct passwd *pw; - u_int pwlen; - - debug3("%s entering", __func__); - - buffer_init(&m); - buffer_put_cstring(&m, login); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m); - - debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m); - - if (buffer_get_char(&m) == 0) { - buffer_free(&m); - return (NULL); - } - pw = buffer_get_string(&m, &pwlen); - if (pwlen != sizeof(struct passwd)) - fatal("%s: struct passwd size mismatch", __func__); - pw->pw_name = buffer_get_string(&m, NULL); - pw->pw_passwd = buffer_get_string(&m, NULL); - pw->pw_gecos = buffer_get_string(&m, NULL); -#ifdef HAVE_PW_CLASS_IN_PASSWD - pw->pw_class = buffer_get_string(&m, NULL); -#endif - pw->pw_dir = buffer_get_string(&m, NULL); - pw->pw_shell = buffer_get_string(&m, NULL); - buffer_free(&m); - - return (pw); -} - -char *mm_auth2_read_banner(void) -{ - Buffer m; - char *banner; - - debug3("%s entering", __func__); - - buffer_init(&m); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m); - buffer_clear(&m); - - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m); - banner = buffer_get_string(&m, NULL); - buffer_free(&m); - - return (banner); -} - -/* Inform the privileged process about service and style */ - -void -mm_inform_authserv(char *service, char *style) -{ - Buffer m; - - debug3("%s entering", __func__); - - buffer_init(&m); - buffer_put_cstring(&m, service); - buffer_put_cstring(&m, style ? style : ""); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m); - - buffer_free(&m); -} - -/* Do the password authentication */ -int -mm_auth_password(Authctxt *authctxt, char *password) -{ - Buffer m; - int authenticated = 0; - - debug3("%s entering", __func__); - - buffer_init(&m); - buffer_put_cstring(&m, password); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m); - - debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m); - - authenticated = buffer_get_int(&m); - - buffer_free(&m); - - debug3("%s: user %sauthenticated", - __func__, authenticated ? "" : "not "); - return (authenticated); -} - -int -mm_user_key_allowed(struct passwd *pw, Key *key) -{ - return (mm_key_allowed(MM_USERKEY, NULL, NULL, key)); -} - -int -mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host, - Key *key) -{ - return (mm_key_allowed(MM_HOSTKEY, user, host, key)); -} - -int -mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user, - char *host, Key *key) -{ - int ret; - - key->type = KEY_RSA; /* XXX hack for key_to_blob */ - ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key); - key->type = KEY_RSA1; - return (ret); -} - -static void -mm_send_debug(Buffer *m) -{ - char *msg; - - while (buffer_len(m)) { - msg = buffer_get_string(m, NULL); - debug3("%s: Sending debug: %s", __func__, msg); - packet_send_debug("%s", msg); - xfree(msg); - } -} - -int -mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key) -{ - Buffer m; - u_char *blob; - u_int len; - int allowed = 0; - - debug3("%s entering", __func__); - - /* Convert the key to a blob and the pass it over */ - if (!key_to_blob(key, &blob, &len)) - return (0); - - buffer_init(&m); - buffer_put_int(&m, type); - buffer_put_cstring(&m, user ? user : ""); - buffer_put_cstring(&m, host ? host : ""); - buffer_put_string(&m, blob, len); - xfree(blob); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m); - - debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m); - - allowed = buffer_get_int(&m); - - /* Send potential debug messages */ - mm_send_debug(&m); - - buffer_free(&m); - - return (allowed); -} - -/* - * This key verify needs to send the key type along, because the - * privileged parent makes the decision if the key is allowed - * for authentication. - */ - -int -mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) -{ - Buffer m; - u_char *blob; - u_int len; - int verified = 0; - - debug3("%s entering", __func__); - - /* Convert the key to a blob and the pass it over */ - if (!key_to_blob(key, &blob, &len)) - return (0); - - buffer_init(&m); - buffer_put_string(&m, blob, len); - buffer_put_string(&m, sig, siglen); - buffer_put_string(&m, data, datalen); - xfree(blob); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m); - - debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m); - - verified = buffer_get_int(&m); - - buffer_free(&m); - - return (verified); -} - -/* Export key state after authentication */ -Newkeys * -mm_newkeys_from_blob(u_char *blob, int blen) -{ - Buffer b; - u_int len; - Newkeys *newkey = NULL; - Enc *enc; - Mac *mac; - Comp *comp; - - debug3("%s: %p(%d)", __func__, blob, blen); -#ifdef DEBUG_PK - dump_base64(stderr, blob, blen); -#endif - buffer_init(&b); - buffer_append(&b, blob, blen); - - newkey = xmalloc(sizeof(*newkey)); - enc = &newkey->enc; - mac = &newkey->mac; - comp = &newkey->comp; - - /* Enc structure */ - enc->name = buffer_get_string(&b, NULL); - buffer_get(&b, &enc->cipher, sizeof(enc->cipher)); - enc->enabled = buffer_get_int(&b); - enc->block_size = buffer_get_int(&b); - enc->key = buffer_get_string(&b, &enc->key_len); - enc->iv = buffer_get_string(&b, &len); - if (len != enc->block_size) - fatal("%s: bad ivlen: expected %u != %u", __func__, - enc->block_size, len); - - if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher) - fatal("%s: bad cipher name %s or pointer %p", __func__, - enc->name, enc->cipher); - - /* Mac structure */ - mac->name = buffer_get_string(&b, NULL); - if (mac->name == NULL || mac_init(mac, mac->name) == -1) - fatal("%s: can not init mac %s", __func__, mac->name); - mac->enabled = buffer_get_int(&b); - mac->key = buffer_get_string(&b, &len); - if (len > mac->key_len) - fatal("%s: bad mac key length: %u > %d", __func__, len, - mac->key_len); - mac->key_len = len; - - /* Comp structure */ - comp->type = buffer_get_int(&b); - comp->enabled = buffer_get_int(&b); - comp->name = buffer_get_string(&b, NULL); - - len = buffer_len(&b); - if (len != 0) - error("newkeys_from_blob: remaining bytes in blob %u", len); - buffer_free(&b); - return (newkey); -} - -int -mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp) -{ - Buffer b; - int len; - Enc *enc; - Mac *mac; - Comp *comp; - Newkeys *newkey = newkeys[mode]; - - debug3("%s: converting %p", __func__, newkey); - - if (newkey == NULL) { - error("%s: newkey == NULL", __func__); - return 0; - } - enc = &newkey->enc; - mac = &newkey->mac; - comp = &newkey->comp; - - buffer_init(&b); - /* Enc structure */ - buffer_put_cstring(&b, enc->name); - /* The cipher struct is constant and shared, you export pointer */ - buffer_append(&b, &enc->cipher, sizeof(enc->cipher)); - buffer_put_int(&b, enc->enabled); - buffer_put_int(&b, enc->block_size); - buffer_put_string(&b, enc->key, enc->key_len); - packet_get_keyiv(mode, enc->iv, enc->block_size); - buffer_put_string(&b, enc->iv, enc->block_size); - - /* Mac structure */ - buffer_put_cstring(&b, mac->name); - buffer_put_int(&b, mac->enabled); - buffer_put_string(&b, mac->key, mac->key_len); - - /* Comp structure */ - buffer_put_int(&b, comp->type); - buffer_put_int(&b, comp->enabled); - buffer_put_cstring(&b, comp->name); - - len = buffer_len(&b); - if (lenp != NULL) - *lenp = len; - if (blobp != NULL) { - *blobp = xmalloc(len); - memcpy(*blobp, buffer_ptr(&b), len); - } - memset(buffer_ptr(&b), 0, len); - buffer_free(&b); - return len; -} - -static void -mm_send_kex(Buffer *m, Kex *kex) -{ - buffer_put_string(m, kex->session_id, kex->session_id_len); - buffer_put_int(m, kex->we_need); - buffer_put_int(m, kex->hostkey_type); - buffer_put_int(m, kex->kex_type); - buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my)); - buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer)); - buffer_put_int(m, kex->flags); - buffer_put_cstring(m, kex->client_version_string); - buffer_put_cstring(m, kex->server_version_string); -} - -void -mm_send_keystate(struct monitor *pmonitor) -{ - Buffer m; - u_char *blob, *p; - u_int bloblen, plen; - - buffer_init(&m); - - if (!compat20) { - u_char iv[24]; - u_char *key; - u_int ivlen, keylen; - - buffer_put_int(&m, packet_get_protocol_flags()); - - buffer_put_int(&m, packet_get_ssh1_cipher()); - - debug3("%s: Sending ssh1 KEY+IV", __func__); - keylen = packet_get_encryption_key(NULL); - key = xmalloc(keylen+1); /* add 1 if keylen == 0 */ - keylen = packet_get_encryption_key(key); - buffer_put_string(&m, key, keylen); - memset(key, 0, keylen); - xfree(key); - - ivlen = packet_get_keyiv_len(MODE_OUT); - packet_get_keyiv(MODE_OUT, iv, ivlen); - buffer_put_string(&m, iv, ivlen); - ivlen = packet_get_keyiv_len(MODE_OUT); - packet_get_keyiv(MODE_IN, iv, ivlen); - buffer_put_string(&m, iv, ivlen); - goto skip; - } else { - /* Kex for rekeying */ - mm_send_kex(&m, *pmonitor->m_pkex); - } - - debug3("%s: Sending new keys: %p %p", - __func__, newkeys[MODE_OUT], newkeys[MODE_IN]); - - /* Keys from Kex */ - if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen)) - fatal("%s: conversion of newkeys failed", __func__); - - buffer_put_string(&m, blob, bloblen); - xfree(blob); - - if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) - fatal("%s: conversion of newkeys failed", __func__); - - buffer_put_string(&m, blob, bloblen); - xfree(blob); - - buffer_put_int(&m, packet_get_seqnr(MODE_OUT)); - buffer_put_int(&m, packet_get_seqnr(MODE_IN)); - - debug3("%s: New keys have been sent", __func__); - skip: - /* More key context */ - plen = packet_get_keycontext(MODE_OUT, NULL); - p = xmalloc(plen+1); - packet_get_keycontext(MODE_OUT, p); - buffer_put_string(&m, p, plen); - xfree(p); - - plen = packet_get_keycontext(MODE_IN, NULL); - p = xmalloc(plen+1); - packet_get_keycontext(MODE_IN, p); - buffer_put_string(&m, p, plen); - xfree(p); - - /* Compression state */ - debug3("%s: Sending compression state", __func__); - buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream)); - buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream)); - - /* Network I/O buffers */ - buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input)); - buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output)); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); - debug3("%s: Finished sending state", __func__); - - buffer_free(&m); -} - -int -mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) -{ - Buffer m; - char *p; - int success = 0; - - buffer_init(&m); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m); - - debug3("%s: waiting for MONITOR_ANS_PTY", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m); - - success = buffer_get_int(&m); - if (success == 0) { - debug3("%s: pty alloc failed", __func__); - buffer_free(&m); - return (0); - } - p = buffer_get_string(&m, NULL); - buffer_free(&m); - - strlcpy(namebuf, p, namebuflen); /* Possible truncation */ - xfree(p); - - *ptyfd = mm_receive_fd(pmonitor->m_recvfd); - *ttyfd = mm_receive_fd(pmonitor->m_recvfd); - - /* Success */ - return (1); -} - -void -mm_session_pty_cleanup2(void *session) -{ - Session *s = session; - Buffer m; - - if (s->ttyfd == -1) - return; - buffer_init(&m); - buffer_put_cstring(&m, s->tty); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m); - buffer_free(&m); - - /* closed dup'ed master */ - if (close(s->ptymaster) < 0) - error("close(s->ptymaster): %s", strerror(errno)); - - /* unlink pty from session */ - s->ttyfd = -1; -} - -#ifdef USE_PAM -void -mm_start_pam(char *user) -{ - Buffer m; - - debug3("%s entering", __func__); - - buffer_init(&m); - buffer_put_cstring(&m, user); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m); - - buffer_free(&m); -} -#endif /* USE_PAM */ - -/* Request process termination */ - -void -mm_terminate(void) -{ - Buffer m; - - buffer_init(&m); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m); - buffer_free(&m); -} - -int -mm_ssh1_session_key(BIGNUM *num) -{ - int rsafail; - Buffer m; - - buffer_init(&m); - buffer_put_bignum2(&m, num); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m); - - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m); - - rsafail = buffer_get_int(&m); - buffer_get_bignum2(&m, num); - - buffer_free(&m); - - return (rsafail); -} - -static void -mm_chall_setup(char **name, char **infotxt, u_int *numprompts, - char ***prompts, u_int **echo_on) -{ - *name = xstrdup(""); - *infotxt = xstrdup(""); - *numprompts = 1; - *prompts = xmalloc(*numprompts * sizeof(char *)); - *echo_on = xmalloc(*numprompts * sizeof(u_int)); - (*echo_on)[0] = 0; -} - -int -mm_bsdauth_query(void *ctx, char **name, char **infotxt, - u_int *numprompts, char ***prompts, u_int **echo_on) -{ - Buffer m; - int res; - char *challenge; - - debug3("%s: entering", __func__); - - buffer_init(&m); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m); - - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY, - &m); - res = buffer_get_int(&m); - if (res == -1) { - debug3("%s: no challenge", __func__); - buffer_free(&m); - return (-1); - } - - /* Get the challenge, and format the response */ - challenge = buffer_get_string(&m, NULL); - buffer_free(&m); - - mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); - (*prompts)[0] = challenge; - - debug3("%s: received challenge: %s", __func__, challenge); - - return (0); -} - -int -mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) -{ - Buffer m; - int authok; - - debug3("%s: entering", __func__); - if (numresponses != 1) - return (-1); - - buffer_init(&m); - buffer_put_cstring(&m, responses[0]); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m); - - mm_request_receive_expect(pmonitor->m_recvfd, - MONITOR_ANS_BSDAUTHRESPOND, &m); - - authok = buffer_get_int(&m); - buffer_free(&m); - - return ((authok == 0) ? -1 : 0); -} - -int -mm_skey_query(void *ctx, char **name, char **infotxt, - u_int *numprompts, char ***prompts, u_int **echo_on) -{ - Buffer m; - int len, res; - char *p, *challenge; - - debug3("%s: entering", __func__); - - buffer_init(&m); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m); - - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY, - &m); - res = buffer_get_int(&m); - if (res == -1) { - debug3("%s: no challenge", __func__); - buffer_free(&m); - return (-1); - } - - /* Get the challenge, and format the response */ - challenge = buffer_get_string(&m, NULL); - buffer_free(&m); - - debug3("%s: received challenge: %s", __func__, challenge); - - mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); - - len = strlen(challenge) + strlen(SKEY_PROMPT) + 1; - p = xmalloc(len); - strlcpy(p, challenge, len); - strlcat(p, SKEY_PROMPT, len); - (*prompts)[0] = p; - xfree(challenge); - - return (0); -} - -int -mm_skey_respond(void *ctx, u_int numresponses, char **responses) -{ - Buffer m; - int authok; - - debug3("%s: entering", __func__); - if (numresponses != 1) - return (-1); - - buffer_init(&m); - buffer_put_cstring(&m, responses[0]); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m); - - mm_request_receive_expect(pmonitor->m_recvfd, - MONITOR_ANS_SKEYRESPOND, &m); - - authok = buffer_get_int(&m); - buffer_free(&m); - - return ((authok == 0) ? -1 : 0); -} - -void -mm_ssh1_session_id(u_char session_id[16]) -{ - Buffer m; - int i; - - debug3("%s entering", __func__); - - buffer_init(&m); - for (i = 0; i < 16; i++) - buffer_put_char(&m, session_id[i]); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m); - buffer_free(&m); -} - -int -mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) -{ - Buffer m; - Key *key; - u_char *blob; - u_int blen; - int allowed = 0; - - debug3("%s entering", __func__); - - buffer_init(&m); - buffer_put_bignum2(&m, client_n); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m); - - allowed = buffer_get_int(&m); - - if (allowed && rkey != NULL) { - blob = buffer_get_string(&m, &blen); - if ((key = key_from_blob(blob, blen)) == NULL) - fatal("%s: key_from_blob failed", __func__); - *rkey = key; - xfree(blob); - } - mm_send_debug(&m); - buffer_free(&m); - - return (allowed); -} - -BIGNUM * -mm_auth_rsa_generate_challenge(Key *key) -{ - Buffer m; - BIGNUM *challenge; - u_char *blob; - u_int blen; - - debug3("%s entering", __func__); - - if ((challenge = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - - key->type = KEY_RSA; /* XXX cheat for key_to_blob */ - if (key_to_blob(key, &blob, &blen) == 0) - fatal("%s: key_to_blob failed", __func__); - key->type = KEY_RSA1; - - buffer_init(&m); - buffer_put_string(&m, blob, blen); - xfree(blob); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m); - - buffer_get_bignum2(&m, challenge); - buffer_free(&m); - - return (challenge); -} - -int -mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) -{ - Buffer m; - u_char *blob; - u_int blen; - int success = 0; - - debug3("%s entering", __func__); - - key->type = KEY_RSA; /* XXX cheat for key_to_blob */ - if (key_to_blob(key, &blob, &blen) == 0) - fatal("%s: key_to_blob failed", __func__); - key->type = KEY_RSA1; - - buffer_init(&m); - buffer_put_string(&m, blob, blen); - buffer_put_string(&m, response, 16); - xfree(blob); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m); - - success = buffer_get_int(&m); - buffer_free(&m); - - return (success); -} - -#ifdef KRB4 -int -mm_auth_krb4(Authctxt *authctxt, void *_auth, char **client, void *_reply) -{ - KTEXT auth, reply; - Buffer m; - u_int rlen; - int success = 0; - char *p; - - debug3("%s entering", __func__); - auth = _auth; - reply = _reply; - - buffer_init(&m); - buffer_put_string(&m, auth->dat, auth->length); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB4, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB4, &m); - - success = buffer_get_int(&m); - if (success) { - *client = buffer_get_string(&m, NULL); - p = buffer_get_string(&m, &rlen); - if (rlen >= MAX_KTXT_LEN) - fatal("%s: reply from monitor too large", __func__); - reply->length = rlen; - memcpy(reply->dat, p, rlen); - memset(p, 0, rlen); - xfree(p); - } - buffer_free(&m); - return (success); -} -#endif - -#ifdef KRB5 -int -mm_auth_krb5(void *ctx, void *argp, char **userp, void *resp) -{ - krb5_data *tkt, *reply; - Buffer m; - int success; - - debug3("%s entering", __func__); - tkt = (krb5_data *) argp; - reply = (krb5_data *) resp; - - buffer_init(&m); - buffer_put_string(&m, tkt->data, tkt->length); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5, &m); - - success = buffer_get_int(&m); - if (success) { - u_int len; - - *userp = buffer_get_string(&m, NULL); - reply->data = buffer_get_string(&m, &len); - reply->length = len; - } else { - memset(reply, 0, sizeof(*reply)); - *userp = NULL; - } - - buffer_free(&m); - return (success); -} -#endif -#ifdef GSSAPI -OM_uint32 -mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) { - Buffer m; - OM_uint32 major; - - /* Client doesn't get to see the context */ - *ctx=NULL; - - buffer_init(&m); - buffer_put_string(&m,oid->elements,oid->length); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m); - - major=buffer_get_int(&m); - - buffer_free(&m); - return(major); -} - -OM_uint32 -mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_t in, - gss_buffer_t out) { - - Buffer m; - OM_uint32 major; - - buffer_init(&m); - buffer_put_string(&m, in->value, in->length); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m); - - major=buffer_get_int(&m); - out->value=buffer_get_string(&m,&out->length); - buffer_free(&m); - - return(major); -} - -int -mm_ssh_gssapi_userok(Gssctxt *ctx, char *user) { - Buffer m; - int authenticated = 0; - - buffer_init(&m); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK, - &m); - - authenticated = buffer_get_int(&m); - - buffer_free(&m); - debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); - return(authenticated); -} - -OM_uint32 -mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) { - Buffer m; - OM_uint32 major; - - buffer_init(&m); - buffer_put_string(&m, data->value, data->length); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); - - major=buffer_get_int(&m); - hash->value = buffer_get_string(&m, &hash->length); - - buffer_free(&m); - - return(major); -} - -char * -mm_ssh_gssapi_last_error(Gssctxt *ctx, OM_uint32 *major, OM_uint32 *minor) { - Buffer m; - OM_uint32 maj,min; - char *errstr; - - buffer_init(&m); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSERR, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSERR, &m); - - maj = buffer_get_int(&m); - min = buffer_get_int(&m); - - if (major) *major=maj; - if (minor) *minor=min; - - errstr=buffer_get_string(&m,NULL); - - buffer_free(&m); - - return(errstr); -} - -OM_uint32 -mm_gss_indicate_mechs(OM_uint32 *minor_status, gss_OID_set *mech_set) -{ - Buffer m; - OM_uint32 major,minor; - int count; - gss_OID_desc oid; - u_int length; - - buffer_init(&m); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSMECHS, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSMECHS, - &m); - major=buffer_get_int(&m); - count=buffer_get_int(&m); - - gss_create_empty_oid_set(&minor,mech_set); - while(count-->0) { - oid.elements=buffer_get_string(&m,&length); - oid.length=length; - gss_add_oid_set_member(&minor,&oid,mech_set); - } - - buffer_free(&m); - - return(major); -} - -int -mm_ssh_gssapi_localname(char **lname) -{ - Buffer m; - - buffer_init(&m); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSLOCALNAME, &m); - - debug3("%s: waiting for MONITOR_ANS_GSSLOCALNAME", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSLOCALNAME, - &m); - - *lname = buffer_get_string(&m, NULL); - - buffer_free(&m); - if (lname[0] == '\0') { - debug3("%s: gssapi identity mapping failed", __func__); - } else { - debug3("%s: gssapi identity mapped to %s", __func__, *lname); - } - - return(0); -} -#endif /* GSSAPI */ diff --git a/usr/src/cmd/ssh/libssh/common/packet.c b/usr/src/cmd/ssh/libssh/common/packet.c index 10fbdd0895..985666a576 100644 --- a/usr/src/cmd/ssh/libssh/common/packet.c +++ b/usr/src/cmd/ssh/libssh/common/packet.c @@ -36,30 +36,29 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#include "includes.h" -RCSID("$OpenBSD: packet.c,v 1.97 2002/07/04 08:12:15 deraadt Exp $"); +/* $OpenBSD: packet.c,v 1.148 2007/06/07 19:37:34 pvalchev Exp $ */ #pragma ident "%Z%%M% %I% %E% SMI" +#include "includes.h" + +#include "sys-queue.h" #include "xmalloc.h" #include "buffer.h" #include "packet.h" #include "bufaux.h" #include "crc32.h" #include "getput.h" - #include "compress.h" #include "deattack.h" #include "channels.h" - #include "compat.h" #include "ssh1.h" #include "ssh2.h" - #include "cipher.h" #include "kex.h" #include "mac.h" @@ -127,8 +126,14 @@ static int interactive_mode = 0; /* Session key information for Encryption and MAC */ Newkeys *newkeys[MODE_MAX]; -static u_int32_t read_seqnr = 0; -static u_int32_t send_seqnr = 0; +static struct packet_state { + u_int32_t seqnr; + u_int32_t packets; + u_int64_t blocks; +} p_read, p_send; + +static u_int64_t max_blocks_in, max_blocks_out; +static u_int32_t rekey_limit; /* Session key for protocol v1 */ static u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; @@ -137,6 +142,13 @@ static u_int ssh1_keylen; /* roundup current message to extra_pad bytes */ static u_char extra_pad = 0; +struct packet { + TAILQ_ENTRY(packet) next; + u_char type; + Buffer payload; +}; +TAILQ_HEAD(, packet) outgoing; + /* * Sets the descriptors used for communication. Disables encryption until * packet_set_encryption_key is called. @@ -159,6 +171,7 @@ packet_set_connection(int fd_in, int fd_out) buffer_init(&output); buffer_init(&outgoing_packet); buffer_init(&incoming_packet); + TAILQ_INIT(&outgoing); } else { buffer_clear(&input); buffer_clear(&output); @@ -202,99 +215,6 @@ packet_connection_is_on_socket(void) return 1; } -/* - * Exports an IV from the CipherContext required to export the key - * state back from the unprivileged child to the privileged parent - * process. - */ - -void -packet_get_keyiv(int mode, u_char *iv, u_int len) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &send_context; - else - cc = &receive_context; - - cipher_get_keyiv(cc, iv, len); -} - -int -packet_get_keycontext(int mode, u_char *dat) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &send_context; - else - cc = &receive_context; - - return (cipher_get_keycontext(cc, dat)); -} - -void -packet_set_keycontext(int mode, u_char *dat) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &send_context; - else - cc = &receive_context; - - cipher_set_keycontext(cc, dat); -} - -int -packet_get_keyiv_len(int mode) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &send_context; - else - cc = &receive_context; - - return (cipher_get_keyiv_len(cc)); -} -void -packet_set_iv(int mode, u_char *dat) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &send_context; - else - cc = &receive_context; - - cipher_set_keyiv(cc, dat); -} -int -packet_get_ssh1_cipher() -{ - return (cipher_get_number(receive_context.cipher)); -} - - -u_int32_t -packet_get_seqnr(int mode) -{ - return (mode == MODE_IN ? read_seqnr : send_seqnr); -} - -void -packet_set_seqnr(int mode, u_int32_t seqnr) -{ - if (mode == MODE_IN) - read_seqnr = seqnr; - else if (mode == MODE_OUT) - send_seqnr = seqnr; - else - fatal("packet_set_seqnr: bad mode %d", mode); -} - /* returns 1 if connection is via ipv4 */ int @@ -478,21 +398,25 @@ packet_put_char(int value) buffer_append(&outgoing_packet, &ch, 1); } + void packet_put_int(u_int value) { buffer_put_int(&outgoing_packet, value); } + void packet_put_string(const void *buf, u_int len) { buffer_put_string(&outgoing_packet, buf, len); } + void packet_put_cstring(const char *str) { buffer_put_cstring(&outgoing_packet, str); } + void packet_put_ascii_cstring(const char *str) { @@ -520,11 +444,13 @@ packet_put_raw(const void *buf, u_int len) { buffer_append(&outgoing_packet, buf, len); } + void packet_put_bignum(BIGNUM * value) { buffer_put_bignum(&outgoing_packet, value); } + void packet_put_bignum2(BIGNUM * value) { @@ -542,7 +468,7 @@ packet_send1(void) u_char buf[8], *cp; int i, padding, len; u_int checksum; - u_int32_t rand = 0; + u_int32_t rnd = 0; /* * If using packet compression, compress the payload of the outgoing @@ -568,9 +494,9 @@ packet_send1(void) cp = buffer_ptr(&outgoing_packet); for (i = 0; i < padding; i++) { if (i % 4 == 0) - rand = arc4random(); - cp[7 - i] = rand & 0xff; - rand >>= 8; + rnd = arc4random(); + cp[7 - i] = rnd & 0xff; + rnd >>= 8; } } buffer_consume(&outgoing_packet, 8 - padding); @@ -614,31 +540,26 @@ set_newkeys(int mode) Mac *mac; Comp *comp; CipherContext *cc; - int encrypt; + u_int64_t *max_blocks; + int crypt_type; - debug("newkeys: mode %d", mode); + debug2("set_newkeys: mode %d", mode); if (mode == MODE_OUT) { cc = &send_context; - encrypt = CIPHER_ENCRYPT; + crypt_type = CIPHER_ENCRYPT; + p_send.packets = p_send.blocks = 0; + max_blocks = &max_blocks_out; } else { cc = &receive_context; - encrypt = CIPHER_DECRYPT; + crypt_type = CIPHER_DECRYPT; + p_read.packets = p_read.blocks = 0; + max_blocks = &max_blocks_in; } if (newkeys[mode] != NULL) { - debug("newkeys: rekeying"); + debug("set_newkeys: rekeying"); cipher_cleanup(cc); - enc = &newkeys[mode]->enc; - mac = &newkeys[mode]->mac; - comp = &newkeys[mode]->comp; - memset(mac->key, 0, mac->key_len); - xfree(enc->name); - xfree(enc->iv); - xfree(enc->key); - xfree(mac->name); - xfree(mac->key); - xfree(comp->name); - xfree(newkeys[mode]); + free_keys(newkeys[mode]); } newkeys[mode] = kex_get_newkeys(mode); if (newkeys[mode] == NULL) @@ -650,7 +571,7 @@ set_newkeys(int mode) mac->enabled = 1; DBG(debug("cipher_init_context: %d", mode)); cipher_init(cc, enc->cipher, enc->key, enc->key_len, - enc->iv, enc->block_size, encrypt); + enc->iv, enc->block_size, crypt_type); /* Deleting the keys does not gain extra security */ /* memset(enc->iv, 0, enc->block_size); memset(enc->key, 0, enc->key_len); */ @@ -662,19 +583,74 @@ set_newkeys(int mode) buffer_compress_init_recv(); comp->enabled = 1; } + + /* + * In accordance to the RFCs listed below we enforce the key + * re-exchange for: + * + * - every 1GB of transmitted data if the selected cipher block size + * is less than 16 bytes (3DES, Blowfish) + * - every 2^(2*B) cipher blocks transmitted (B is block size in bytes) + * if the cipher block size is greater than or equal to 16 bytes (AES) + * - and we never send more than 2^32 SSH packets using the same keys. + * The recommendation of 2^31 packets is not enforced here but in + * packet_need_rekeying(). There is also a hard check in + * packet_send2_wrapped() that we don't send more than 2^32 packets. + * + * Note that if the SSH_BUG_NOREKEY compatibility flag is set then no + * automatic rekeying is performed nor do we enforce the 3rd rule. + * This means that we can be always forced by the opposite side to never + * initiate automatic key re-exchange. This might change in the future. + * + * The RekeyLimit option keyword may only enforce more frequent key + * renegotiation, never less. For more information on key renegotiation, + * see: + * + * - RFC 4253 (SSH Transport Layer Protocol), section "9. Key + * Re-Exchange" + * - RFC 4344 (SSH Transport Layer Encryption Modes), sections "3. + * Rekeying" and "6.1 Rekeying Considerations" + */ + if (enc->block_size >= 16) + *max_blocks = (u_int64_t)1 << (enc->block_size * 2); + else + *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; + + if (rekey_limit) + *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size); +} + +void +free_keys(Newkeys *keys) +{ + Enc *enc; + Mac *mac; + Comp *comp; + + enc = &keys->enc; + mac = &keys->mac; + comp = &keys->comp; + memset(mac->key, 0, mac->key_len); + xfree(enc->name); + xfree(enc->iv); + xfree(enc->key); + xfree(mac->name); + xfree(mac->key); + xfree(comp->name); + xfree(keys); } /* * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) */ static void -packet_send2(void) +packet_send2_wrapped(void) { u_char type, *cp, *macbuf = NULL; u_char padlen, pad; u_int packet_length = 0; u_int i, len; - u_int32_t rand = 0; + u_int32_t rnd = 0; Enc *enc = NULL; Mac *mac = NULL; Comp *comp = NULL; @@ -733,9 +709,9 @@ packet_send2(void) /* random padding */ for (i = 0; i < padlen; i++) { if (i % 4 == 0) - rand = arc4random(); - cp[i] = rand & 0xff; - rand >>= 8; + rnd = arc4random(); + cp[i] = rnd & 0xff; + rnd >>= 8; } } else { /* clear padding */ @@ -750,10 +726,10 @@ packet_send2(void) /* compute MAC over seqnr and packet(length fields, payload, padding) */ if (mac && mac->enabled) { - macbuf = mac_compute(mac, send_seqnr, + macbuf = mac_compute(mac, p_send.seqnr, buffer_ptr(&outgoing_packet), buffer_len(&outgoing_packet)); - DBG(debug("done calc MAC out #%d", send_seqnr)); + DBG(debug("done calc MAC out #%d", p_send.seqnr)); } /* encrypt packet and append to output buffer. */ cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); @@ -767,8 +743,25 @@ packet_send2(void) buffer_dump(&output); #endif /* increment sequence number for outgoing packets */ - if (++send_seqnr == 0) + if (++p_send.seqnr == 0) log("outgoing seqnr wraps around"); + + /* + * RFC 4344: 3.1. First Rekeying Recommendation + * + * "Because of possible information leakage through the MAC tag after a + * key exchange, .... an SSH implementation SHOULD NOT send more than + * 2**32 packets before rekeying again." + * + * The code below is a hard check so that we are sure we don't go across + * the suggestion. However, since the largest cipher block size we have + * (AES) is 16 bytes we can't reach 2^32 SSH packets encrypted with the + * same key while performing periodic rekeying. + */ + if (++p_send.packets == 0) + if (!(datafellows & SSH_BUG_NOREKEY)) + fatal("too many packets encrypted with same key"); + p_send.blocks += (packet_length + 4) / block_size; buffer_clear(&outgoing_packet); if (type == SSH2_MSG_NEWKEYS) @@ -779,6 +772,51 @@ packet_send2(void) set_newkeys(MODE_OUT); } +static void +packet_send2(void) +{ + static int rekeying = 0; + struct packet *p; + u_char type, *cp; + + cp = buffer_ptr(&outgoing_packet); + type = cp[5]; + + /* during rekeying we can only send key exchange messages */ + if (rekeying) { + if (!((type >= SSH2_MSG_TRANSPORT_MIN) && + (type <= SSH2_MSG_TRANSPORT_MAX))) { + debug("enqueue packet: %u", type); + p = xmalloc(sizeof(*p)); + p->type = type; + memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); + buffer_init(&outgoing_packet); + TAILQ_INSERT_TAIL(&outgoing, p, next); + return; + } + } + + /* rekeying starts with sending KEXINIT */ + if (type == SSH2_MSG_KEXINIT) + rekeying = 1; + + packet_send2_wrapped(); + + /* after a NEWKEYS message we can send the complete queue */ + if (type == SSH2_MSG_NEWKEYS) { + rekeying = 0; + while ((p = TAILQ_FIRST(&outgoing)) != NULL) { + type = p->type; + debug("dequeue packet: %u", type); + buffer_free(&outgoing_packet); + memcpy(&outgoing_packet, &p->payload, sizeof(Buffer)); + TAILQ_REMOVE(&outgoing, p, next); + xfree(p); + packet_send2_wrapped(); + } + } +} + void packet_send(void) { @@ -1003,7 +1041,7 @@ packet_read_poll2(u_int32_t *seqnr_p) buffer_dump(&incoming_packet); packet_disconnect("Bad packet length %d.", packet_length); } - DBG(debug("input: packet len %d", packet_length+4)); + DBG(debug("input: packet len %u", packet_length + 4)); buffer_consume(&input, block_size); } /* we have a partial packet of block_size bytes */ @@ -1031,19 +1069,25 @@ packet_read_poll2(u_int32_t *seqnr_p) * increment sequence number for incoming packet */ if (mac && mac->enabled) { - macbuf = mac_compute(mac, read_seqnr, + macbuf = mac_compute(mac, p_read.seqnr, buffer_ptr(&incoming_packet), buffer_len(&incoming_packet)); if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) packet_disconnect("Corrupted MAC on input."); - DBG(debug("MAC #%d ok", read_seqnr)); + DBG(debug("MAC #%d ok", p_read.seqnr)); buffer_consume(&input, mac->mac_len); } if (seqnr_p != NULL) - *seqnr_p = read_seqnr; - if (++read_seqnr == 0) + *seqnr_p = p_read.seqnr; + if (++p_read.seqnr == 0) log("incoming seqnr wraps around"); + /* see above for the comment on "First Rekeying Recommendation" */ + if (++p_read.packets == 0) + if (!(datafellows & SSH_BUG_NOREKEY)) + fatal("too many packets with same key"); + p_read.blocks += (packet_length + 4) / block_size; + /* get padlen */ cp = buffer_ptr(&incoming_packet); padlen = cp[4]; @@ -1518,7 +1562,7 @@ packet_add_padding(u_char pad) void packet_send_ignore(int nbytes) { - u_int32_t rand = 0; + u_int32_t rnd = 0; int i; #ifdef ALTPRIVSEP @@ -1531,12 +1575,31 @@ packet_send_ignore(int nbytes) packet_put_int(nbytes); for (i = 0; i < nbytes; i++) { if (i % 4 == 0) - rand = arc4random(); - packet_put_char(rand & 0xff); - rand >>= 8; + rnd = arc4random(); + packet_put_char((u_char)rnd & 0xff); + rnd >>= 8; } } +#define MAX_PACKETS (1U<<31) +int +packet_need_rekeying(void) +{ + if (datafellows & SSH_BUG_NOREKEY) + return 0; + return + (p_send.packets > MAX_PACKETS) || + (p_read.packets > MAX_PACKETS) || + (max_blocks_out && (p_send.blocks > max_blocks_out)) || + (max_blocks_in && (p_read.blocks > max_blocks_in)); +} + +void +packet_set_rekey_limit(u_int32_t bytes) +{ + rekey_limit = bytes; +} + #ifdef ALTPRIVSEP void packet_set_server(void) diff --git a/usr/src/cmd/ssh/libssh/common/readconf.c b/usr/src/cmd/ssh/libssh/common/readconf.c index 86caa54913..e08ff1e0b0 100644 --- a/usr/src/cmd/ssh/libssh/common/readconf.c +++ b/usr/src/cmd/ssh/libssh/common/readconf.c @@ -129,7 +129,8 @@ typedef enum { oClearAllForwardings, oNoHostAuthenticationForLocalhost, oFallBackToRsh, oUseRsh, oConnectTimeout, oHashKnownHosts, oServerAliveInterval, oServerAliveCountMax, oDisableBanner, - oIgnoreIfUnknown, oDeprecated + oIgnoreIfUnknown, oRekeyLimit, + oDeprecated } OpCodes; /* Textual representations of the tokens. */ @@ -215,6 +216,7 @@ static struct { { "smartcarddevice", oSmartcardDevice }, { "clearallforwardings", oClearAllForwardings }, { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, + { "rekeylimit", oRekeyLimit }, { "connecttimeout", oConnectTimeout }, { "serveraliveinterval", oServerAliveInterval }, { "serveralivecountmax", oServerAliveCountMax }, @@ -318,7 +320,8 @@ process_config_line(Options *options, const char *host, int *activep) { char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; - int opcode, *intptr, value, i; + int opcode, *intptr, value, scale, i; + long long orig, val64; StoredOption *so; Forward fwd; @@ -530,6 +533,44 @@ parse_flag: intptr = &options->compression_level; goto parse_int; + case oRekeyLimit: + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + if (arg[0] < '0' || arg[0] > '9') + fatal("%.200s line %d: Bad number.", filename, linenum); + orig = val64 = strtoll(arg, &endofnumber, 10); + if (arg == endofnumber) + fatal("%.200s line %d: Bad number.", filename, linenum); + switch (toupper(*endofnumber)) { + case '\0': + scale = 1; + break; + case 'K': + scale = 1<<10; + break; + case 'M': + scale = 1<<20; + break; + case 'G': + scale = 1<<30; + break; + default: + fatal("%.200s line %d: Invalid RekeyLimit suffix", + filename, linenum); + } + val64 *= scale; + /* detect integer wrap and too-large limits */ + if ((val64 / scale) != orig || val64 > UINT_MAX) + fatal("%.200s line %d: RekeyLimit too large", + filename, linenum); + if (val64 < 16) + fatal("%.200s line %d: RekeyLimit too small", + filename, linenum); + if (*activep && options->rekey_limit == -1) + options->rekey_limit = (u_int32_t)val64; + break; + case oIdentityFile: arg = strdelim(&s); if (!arg || *arg == '\0') @@ -938,7 +979,8 @@ initialize_options(Options * options) options->preferred_authentications = NULL; options->bind_address = NULL; options->smartcard_device = NULL; - options->no_host_authentication_for_localhost = - 1; + options->no_host_authentication_for_localhost = -1; + options->rekey_limit = -1; options->fallback_to_rsh = -1; options->use_rsh = -1; options->server_alive_interval = -1; @@ -1077,11 +1119,13 @@ fill_default_options(Options * options) options->log_level = SYSLOG_LEVEL_INFO; if (options->clear_forwardings == 1) clear_forwardings(options); - if (options->no_host_authentication_for_localhost == - 1) + if (options->no_host_authentication_for_localhost == -1) options->no_host_authentication_for_localhost = 0; - if (options->fallback_to_rsh == - 1) + if (options->rekey_limit == -1) + options->rekey_limit = 0; + if (options->fallback_to_rsh == -1) options->fallback_to_rsh = 0; - if (options->use_rsh == - 1) + if (options->use_rsh == -1) options->use_rsh = 0; if (options->server_alive_interval == -1) options->server_alive_interval = 0; diff --git a/usr/src/cmd/ssh/libssh/common/ssh-gss.c b/usr/src/cmd/ssh/libssh/common/ssh-gss.c index 17af3f0c41..fcf8e11b51 100644 --- a/usr/src/cmd/ssh/libssh/common/ssh-gss.c +++ b/usr/src/cmd/ssh/libssh/common/ssh-gss.c @@ -21,7 +21,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -44,7 +44,6 @@ #include "log.h" #include "compat.h" #include "xlist.h" -#include "monitor_wrap.h" #include <netdb.h> @@ -523,13 +522,17 @@ void ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid) { /* All this effort to report an error ... */ void -ssh_gssapi_error(Gssctxt *ctxt, const char *where) { - if (where) - debug("GSS-API error while %s: %s", where, - ssh_gssapi_last_error(ctxt,NULL,NULL)); +ssh_gssapi_error(Gssctxt *ctxt, const char *where) +{ + char *errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL); + + if (where != NULL) + debug("GSS-API error while %s: %s", where, errmsg); else - debug("GSS-API error: %s", - ssh_gssapi_last_error(ctxt,NULL,NULL)); + debug("GSS-API error: %s", errmsg); + + /* ssh_gssapi_last_error() can't return NULL */ + xfree(errmsg); } char * diff --git a/usr/src/cmd/ssh/libssh/common/xlist.c b/usr/src/cmd/ssh/libssh/common/xlist.c index 45a5611510..c44e420eeb 100644 --- a/usr/src/cmd/ssh/libssh/common/xlist.c +++ b/usr/src/cmd/ssh/libssh/common/xlist.c @@ -1,7 +1,7 @@ - /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -13,66 +13,73 @@ char ** xsplit(char *list, char sep) { - char **a; - char *p, *q; - u_int n = 0; + char **a; + char *p, *q; + uint_t n = 0; - for (n = 0, p = list ; p && *p ; ) { - while (p && *p && *p == sep) p++; - if (!*p) break; - n++; - p = strchr(p, sep); - } - a = (char **) xmalloc(sizeof(char *) * (n + 2)); - for (n = 0, p = list ; p && *p ; ) { - while (*p == sep) p++; - if (!*p) break; - q = strchr(p, sep); - if (!q) - q = p + strlen(p); - a[n] = (char *) xmalloc((q - p + 2)); - (void) strncpy(a[n], p, q - p); - a[n][q - p] = '\0'; - n++; - if (!*q) break; - p = q+1; - } - a[n] = NULL; - return a; + for (n = 0, p = list; p && *p; ) { + while (p && *p && *p == sep) + p++; + if (!*p) + break; + n++; + p = strchr(p, sep); + } + a = (char **)xmalloc(sizeof (char *) * (n + 2)); + for (n = 0, p = list; p && *p; ) { + while (*p == sep) + p++; + if (!*p) + break; + q = strchr(p, sep); + if (!q) + q = p + strlen(p); + a[n] = (char *)xmalloc((q - p + 2)); + (void) strncpy(a[n], p, q - p); + a[n][q - p] = '\0'; + n++; + if (!*q) + break; + p = q + 1; + } + a[n] = NULL; + return (a); } void xfree_split_list(char **list) { - char **p; - for (p = list ; p && *p ; p++) { - xfree(*p); - } - xfree(list); + char **p; + for (p = list; p && *p; p++) { + xfree(*p); + } + xfree(list); } char * xjoin(char **alist, char sep) { - char **p; - char *list; - char sep_str[2]; - u_int n; + char **p; + char *list; + char sep_str[2]; + uint_t n; - for (n = 1, p = alist ; p && *p ; p++) { - if (!*p || !**p) continue; - n += strlen(*p) + 1; - } - list = (char *) xmalloc(n); - *list = '\0'; + for (n = 1, p = alist; p && *p; p++) { + if (!*p || !**p) + continue; + n += strlen(*p) + 1; + } + list = (char *)xmalloc(n); + *list = '\0'; - sep_str[0] = sep; - sep_str[1] = '\0'; - for (p = alist ; p && *p ; p++) { - if (!*p || !**p) continue; - if (*list != '\0') - (void) strlcat(list, sep_str, n); - (void) strlcat(list, *p, n); - } - return list; + sep_str[0] = sep; + sep_str[1] = '\0'; + for (p = alist; p && *p; p++) { + if (!*p || !**p) + continue; + if (*list != '\0') + (void) strlcat(list, sep_str, n); + (void) strlcat(list, *p, n); + } + return (list); } diff --git a/usr/src/cmd/ssh/ssh/clientloop.c b/usr/src/cmd/ssh/ssh/clientloop.c index 6485414a57..5929b7b6e0 100644 --- a/usr/src/cmd/ssh/ssh/clientloop.c +++ b/usr/src/cmd/ssh/ssh/clientloop.c @@ -1176,9 +1176,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* Do channel operations unless rekeying in progress. */ if (!rekeying) { channel_after_select(readset, writeset); - - if (need_rekeying) { - debug("user requests rekeying"); + if (need_rekeying || packet_need_rekeying()) { + debug("need rekeying"); xxx_kex->done = 0; kex_send_kexinit(xxx_kex); need_rekeying = 0; diff --git a/usr/src/cmd/ssh/ssh/gss-clnt.c b/usr/src/cmd/ssh/ssh/gss-clnt.c index da65fe4666..3d536da7a6 100644 --- a/usr/src/cmd/ssh/ssh/gss-clnt.c +++ b/usr/src/cmd/ssh/ssh/gss-clnt.c @@ -21,7 +21,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,7 +43,6 @@ #include "kex.h" #include "log.h" #include "compat.h" -#include "monitor_wrap.h" #include <netdb.h> @@ -72,6 +71,7 @@ ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs) gss_buffer_desc tok; OM_uint32 maj, min; int i; + char *errmsg; if (!mechs) return; @@ -85,8 +85,9 @@ ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs) maj = gss_create_empty_oid_set(&min, &supported); if (GSS_ERROR(maj)) { - debug("Failed to allocate resources (%s) for GSS-API", - ssh_gssapi_last_error(NULL, &maj, &min)); + errmsg = ssh_gssapi_last_error(NULL, &maj, &min); + debug("Failed to allocate resources (%s) for GSS-API", errmsg); + xfree(errmsg); (void) gss_release_oid_set(&min, &indicated); return; } @@ -94,9 +95,10 @@ ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs) GSS_C_INITIATE, &creds, &acquired, NULL); if (GSS_ERROR(maj)) { + errmsg = ssh_gssapi_last_error(NULL, &maj, &min); debug("Failed to acquire GSS-API credentials for any " - "mechanisms (%s)", - ssh_gssapi_last_error(NULL, &maj, &min)); + "mechanisms (%s)", errmsg); + xfree(errmsg); (void) gss_release_oid_set(&min, &indicated); (void) gss_release_oid_set(&min, &supported); return; @@ -125,18 +127,22 @@ ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs) maj = ssh_gssapi_init_ctx(ctxt, server_host, 0, NULL, &tok); if (GSS_ERROR(maj)) { + errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL); debug("Skipping GSS-API mechanism %s (%s)", - ssh_gssapi_oid_to_name(mech), - ssh_gssapi_last_error(ctxt, NULL, NULL)); + ssh_gssapi_oid_to_name(mech), errmsg); + xfree(errmsg); continue; } (void) gss_release_buffer(&min, &tok); maj = gss_add_oid_set_member(&min, mech, &supported); - if (GSS_ERROR(maj)) + if (GSS_ERROR(maj)) { + errmsg = ssh_gssapi_last_error(NULL, &maj, &min); debug("Failed to allocate resources (%s) for GSS-API", - ssh_gssapi_last_error(NULL, &maj, &min)); + errmsg); + xfree(errmsg); + } } *mechs = supported; diff --git a/usr/src/cmd/ssh/ssh/sshconnect2.c b/usr/src/cmd/ssh/ssh/sshconnect2.c index 5b2901ee32..9b95a15f2c 100644 --- a/usr/src/cmd/ssh/ssh/sshconnect2.c +++ b/usr/src/cmd/ssh/ssh/sshconnect2.c @@ -137,6 +137,9 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = options.hostkeyalgorithms; + if (options.rekey_limit) + packet_set_rekey_limit((u_int32_t)options.rekey_limit); + if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) { char *locale = setlocale(LC_ALL, ""); diff --git a/usr/src/cmd/ssh/sshd/Makefile b/usr/src/cmd/ssh/sshd/Makefile index 9999f6feff..51392676fb 100644 --- a/usr/src/cmd/ssh/sshd/Makefile +++ b/usr/src/cmd/ssh/sshd/Makefile @@ -60,8 +60,6 @@ OBJS = sshd.o \ gss-serv.o \ loginrec.o \ md5crypt.o \ - monitor.o \ - monitor_mm.o \ servconf.o \ serverloop.o \ session.o \ diff --git a/usr/src/cmd/ssh/sshd/altprivsep.c b/usr/src/cmd/ssh/sshd/altprivsep.c index e3636efeb7..c2c0a17e8b 100644 --- a/usr/src/cmd/ssh/sshd/altprivsep.c +++ b/usr/src/cmd/ssh/sshd/altprivsep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,7 +18,7 @@ * * CDDL HEADER END * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -235,7 +234,7 @@ altprivsep_start_monitor(Authctxt *authctxt) if (fcntl(pipe_fd, F_SETFL, O_NONBLOCK) < 0) error("fcntl O_NONBLOCK: %.100s", strerror(errno)); - /* signal readyness of monitor */ + /* signal readiness of monitor */ (void) write(pipe_fd, &pid, sizeof (pid)); aps_started = 1; @@ -583,6 +582,7 @@ aps_send_newkeys(void) packet_put_cstring(comp->name); packet_send(); + free_keys(newkeys); } struct _aps_login_rec { diff --git a/usr/src/cmd/ssh/sshd/auth-bsdauth.c b/usr/src/cmd/ssh/sshd/auth-bsdauth.c index e6ea549620..090fa0ef39 100644 --- a/usr/src/cmd/ssh/sshd/auth-bsdauth.c +++ b/usr/src/cmd/ssh/sshd/auth-bsdauth.c @@ -30,7 +30,6 @@ RCSID("$OpenBSD: auth-bsdauth.c,v 1.5 2002/06/30 21:59:45 deraadt Exp $"); #include "xmalloc.h" #include "auth.h" #include "log.h" -#include "monitor_wrap.h" static void * bsdauth_init_ctx(Authctxt *authctxt) diff --git a/usr/src/cmd/ssh/sshd/auth-options.c b/usr/src/cmd/ssh/sshd/auth-options.c index 37930663f6..b186cbe045 100644 --- a/usr/src/cmd/ssh/sshd/auth-options.c +++ b/usr/src/cmd/ssh/sshd/auth-options.c @@ -22,7 +22,6 @@ RCSID("$OpenBSD: auth-options.c,v 1.26 2002/07/30 17:03:55 markus Exp $"); #include "auth-options.h" #include "servconf.h" #include "misc.h" -#include "monitor_wrap.h" #include "auth.h" /* Flags set authorized_keys flags */ @@ -282,8 +281,7 @@ next_option: /* Process the next option. */ } - if (!use_privsep) - auth_debug_send(); + auth_debug_send(); /* grant access */ return 1; @@ -294,8 +292,7 @@ bad_option: auth_debug_add("Bad options in %.100s file, line %lu: %.50s", file, linenum, opts); - if (!use_privsep) - auth_debug_send(); + auth_debug_send(); /* deny access */ return 0; diff --git a/usr/src/cmd/ssh/sshd/auth-pam.c b/usr/src/cmd/ssh/sshd/auth-pam.c index a666edfa87..6763035a72 100644 --- a/usr/src/cmd/ssh/sshd/auth-pam.c +++ b/usr/src/cmd/ssh/sshd/auth-pam.c @@ -39,14 +39,12 @@ #include "compat.h" #include "misc.h" #include "sshlogin.h" -#include "monitor_wrap.h" +#include "ssh-gss.h" #include <security/pam_appl.h> extern char *__progname; -extern int use_privsep; - extern u_int utmp_len; extern ServerOptions options; @@ -58,8 +56,6 @@ RCSID("$Id: auth-pam.c,v 1.54 2002/07/28 20:24:08 stevesk Exp $"); #define NEW_AUTHTOK_MSG \ "Warning: Your password has expired, please change it now." -#define NEW_AUTHTOK_MSG_PRIVSEP \ - "Your password has expired, the session cannot proceed." /* PAM conversation for non-interactive userauth methods */ static int do_pam_conversation(int num_msg, const struct pam_message **msg, @@ -282,7 +278,7 @@ finish_userauth_do_pam(Authctxt *authctxt) if (strcmp(user, authctxt->user) != 0) { log("PAM changed the SSH username"); pwfree(&authctxt->pw); - authctxt->pw = PRIVSEP(getpwnamallow(user)); + authctxt->pw = getpwnamallow(user); authctxt->valid = (authctxt->pw != NULL); xfree(authctxt->user); authctxt->user = xstrdup(user); diff --git a/usr/src/cmd/ssh/sshd/auth-rh-rsa.c b/usr/src/cmd/ssh/sshd/auth-rh-rsa.c index c6c9060c06..ab10e1738a 100644 --- a/usr/src/cmd/ssh/sshd/auth-rh-rsa.c +++ b/usr/src/cmd/ssh/sshd/auth-rh-rsa.c @@ -27,8 +27,6 @@ RCSID("$OpenBSD: auth-rh-rsa.c,v 1.34 2002/03/25 09:25:06 markus Exp $"); #include "auth.h" #include "canohost.h" -#include "monitor_wrap.h" - /* import */ extern ServerOptions options; @@ -68,7 +66,7 @@ auth_rhosts_rsa(struct passwd *pw, char *cuser, Key *client_host_key) chost = (char *)get_canonical_hostname(options.verify_reverse_mapping); debug("Rhosts RSA authentication: canonical host %.900s", chost); - if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) { + if (!auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key)) { debug("Rhosts with RSA host authentication denied: unknown or invalid host key"); packet_send_debug("Your host key cannot be verified: unknown or invalid host key."); return 0; diff --git a/usr/src/cmd/ssh/sshd/auth-rhosts.c b/usr/src/cmd/ssh/sshd/auth-rhosts.c index 0b0d44a56f..2326eef8ae 100644 --- a/usr/src/cmd/ssh/sshd/auth-rhosts.c +++ b/usr/src/cmd/ssh/sshd/auth-rhosts.c @@ -28,7 +28,6 @@ RCSID("$OpenBSD: auth-rhosts.c,v 1.28 2002/05/13 21:26:49 markus Exp $"); /* import */ extern ServerOptions options; -extern int use_privsep; /* * This function processes an rhosts-style file (.rhosts, .shosts, or @@ -295,7 +294,6 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, auth_debug_reset(); ret = auth_rhosts2_raw(pw, client_user, hostname, ipaddr); - if (!use_privsep) - auth_debug_send(); + auth_debug_send(); return ret; } diff --git a/usr/src/cmd/ssh/sshd/auth-rsa.c b/usr/src/cmd/ssh/sshd/auth-rsa.c index a4896f20e1..3e0e6ea50d 100644 --- a/usr/src/cmd/ssh/sshd/auth-rsa.c +++ b/usr/src/cmd/ssh/sshd/auth-rsa.c @@ -34,7 +34,6 @@ RCSID("$OpenBSD: auth-rsa.c,v 1.56 2002/06/10 16:53:06 stevesk Exp $"); #include "servconf.h" #include "auth.h" #include "hostfile.h" -#include "monitor_wrap.h" #include "ssh.h" /* import */ @@ -124,7 +123,7 @@ auth_rsa_challenge_dialog(Key *key) if ((encrypted_challenge = BN_new()) == NULL) fatal("auth_rsa_challenge_dialog: BN_new() failed"); - challenge = PRIVSEP(auth_rsa_generate_challenge(key)); + challenge = auth_rsa_generate_challenge(key); /* Encrypt the challenge with the public key. */ rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); @@ -142,7 +141,7 @@ auth_rsa_challenge_dialog(Key *key) response[i] = packet_get_char(); packet_check_eom(); - success = PRIVSEP(auth_rsa_verify_response(key, challenge, response)); + success = auth_rsa_verify_response(key, challenge, response); BN_clear_free(challenge); return (success); } @@ -295,7 +294,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) if (pw == NULL) return 0; - if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) { + if (!auth_rsa_key_allowed(pw, client_n, &key)) { auth_clear_options(); return (0); } diff --git a/usr/src/cmd/ssh/sshd/auth-skey.c b/usr/src/cmd/ssh/sshd/auth-skey.c index 67ed5a6434..436f66aed8 100644 --- a/usr/src/cmd/ssh/sshd/auth-skey.c +++ b/usr/src/cmd/ssh/sshd/auth-skey.c @@ -32,7 +32,6 @@ RCSID("$OpenBSD: auth-skey.c,v 1.20 2002/06/30 21:59:45 deraadt Exp $"); #include "xmalloc.h" #include "auth.h" -#include "monitor_wrap.h" static void * skey_init_ctx(Authctxt *authctxt) diff --git a/usr/src/cmd/ssh/sshd/auth1.c b/usr/src/cmd/ssh/sshd/auth1.c index a797962fc8..0eed0c90c8 100644 --- a/usr/src/cmd/ssh/sshd/auth1.c +++ b/usr/src/cmd/ssh/sshd/auth1.c @@ -9,7 +9,7 @@ * called by a name other than "ssh" or "Secure Shell". */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,7 +31,6 @@ RCSID("$OpenBSD: auth1.c,v 1.44 2002/09/26 11:38:43 markus Exp $"); #include "channels.h" #include "session.h" #include "uidswap.h" -#include "monitor_wrap.h" #ifdef HAVE_BSM #include "bsmaudit.h" @@ -95,7 +94,7 @@ do_authloop(Authctxt *authctxt) #if defined(KRB4) || defined(KRB5) (!options.kerberos_authentication || options.kerberos_or_local_passwd) && #endif - PRIVSEP(auth_password(authctxt, ""))) { + auth_password(authctxt, "")) { auth_log(authctxt, 1, "without authentication", ""); return; } @@ -137,8 +136,8 @@ do_authloop(Authctxt *authctxt) if (tkt.length < MAX_KTXT_LEN) memcpy(tkt.dat, kdata, tkt.length); - if (PRIVSEP(auth_krb4(authctxt, &tkt, - &client_user, &reply))) { + if (auth_krb4(authctxt, &tkt, + &client_user, &reply)) { authenticated = 1; snprintf(info, sizeof(info), " tktuser %.100s", @@ -158,8 +157,8 @@ do_authloop(Authctxt *authctxt) tkt.length = dlen; tkt.data = kdata; - if (PRIVSEP(auth_krb5(authctxt, &tkt, - &client_user, &reply))) { + if (auth_krb5(authctxt, &tkt, + &client_user, &reply)) { authenticated = 1; snprintf(info, sizeof(info), " tktuser %.100s", @@ -279,8 +278,7 @@ do_authloop(Authctxt *authctxt) if (authctxt->init_failures < options.max_init_auth_tries) authenticated = - PRIVSEP(auth_password(authctxt, - password)); + auth_password(authctxt, password); memset(password, 0, strlen(password)); xfree(password); @@ -351,16 +349,11 @@ do_authloop(Authctxt *authctxt) } #else /* Special handling for root */ - if (!use_privsep && - authenticated && authctxt->pw->pw_uid == 0 && + if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(get_authname(type))) authenticated = 0; #endif #ifdef USE_PAM - /* XXX PAM and PRIVSEP don't mix */ - if (use_privsep && authenticated) - fatal("Privsep is not supported"); - if (authenticated && type != SSH_CMSG_AUTH_PASSWORD) authenticated = do_pam_non_initial_userauth(authctxt); else if (authenticated && !AUTHPAM_DONE(authctxt)) @@ -440,28 +433,21 @@ do_authentication(void) #endif /* HAVE_BSM */ /* Verify that the user is a valid user. */ - if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) { + if ((authctxt->pw = getpwnamallow(user)) != NULL) { authctxt->valid = 1; } else { authctxt->valid = 0; debug("do_authentication: illegal user %s", user); } - setproctitle("%s%s", authctxt->pw ? user : "unknown", - use_privsep ? " [net]" : ""); - -#if 0 -#ifdef USE_PAM - PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user)); -#endif -#endif + setproctitle("%s", authctxt->pw ? user : "unknown"); /* * If we are not running as root, the user must have the same uid as * the server. (Unless you are running Windows) */ #ifndef HAVE_CYGWIN - if (!use_privsep && getuid() != 0 && authctxt->pw && + if (getuid() != 0 && authctxt->pw && authctxt->pw->pw_uid != getuid()) packet_disconnect("Cannot change user when server not running as root."); #endif diff --git a/usr/src/cmd/ssh/sshd/auth2-gss.c b/usr/src/cmd/ssh/sshd/auth2-gss.c index 8892f6f718..70560dad3a 100644 --- a/usr/src/cmd/ssh/sshd/auth2-gss.c +++ b/usr/src/cmd/ssh/sshd/auth2-gss.c @@ -41,7 +41,6 @@ #include "buffer.h" #include "bufaux.h" #include "packet.h" -#include "monitor_wrap.h" #include <gssapi/gssapi.h> #include "ssh-gss.h" @@ -202,15 +201,14 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) u_int len; if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL && !use_privsep)) + (authctxt->method->method_data == NULL)) fatal("No authentication or GSSAPI context during gssapi-with-mic userauth"); gssctxt=authctxt->method->method_data; recv_tok.value=packet_get_string(&len); recv_tok.length=len; /* u_int vs. size_t */ - maj_status=PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, - &send_tok)); + maj_status = ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok); packet_check_eom(); if (GSS_ERROR(maj_status)) { @@ -251,7 +249,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) gss_buffer_desc send_tok,recv_tok; if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL && !use_privsep)) + (authctxt->method->method_data == NULL)) fatal("No authentication or GSSAPI context during gssapi-with-mic userauth"); gssctxt=authctxt->method->method_data; @@ -259,7 +257,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) packet_check_eom(); /* Push the error token into GSSAPI to see what it says */ - (void) PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok)); + (void) ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok); debug("Client sent GSS-API error token during GSS userauth-- %s", ssh_gssapi_last_error(gssctxt, NULL, NULL)); @@ -352,7 +350,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) packet_check_eom(); if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL && !use_privsep)) + (authctxt->method->method_data == NULL)) fatal("No authentication or GSSAPI context"); gssctxt=authctxt->method->method_data; @@ -380,7 +378,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) * this will do for now. */ #if 0 - authctxt->method->authenticated = PRIVSEP(ssh_gssapi_userok(gssctxt, authctxt->user)); + authctxt->method->authenticated = ssh_gssapi_userok(gssctxt, authctxt->user); #endif if (xxx_gssctxt != gssctxt) @@ -425,7 +423,7 @@ userauth_gssapi_finish(Authctxt *authctxt, Gssctxt *gssctxt) OM_uint32 major; if (*authctxt->user != '\0' && - PRIVSEP(ssh_gssapi_userok(gssctxt, authctxt->user))) { + ssh_gssapi_userok(gssctxt, authctxt->user)) { /* * If the client princ did not map to the requested diff --git a/usr/src/cmd/ssh/sshd/auth2-hostbased.c b/usr/src/cmd/ssh/sshd/auth2-hostbased.c index f7bef1197b..c88e308100 100644 --- a/usr/src/cmd/ssh/sshd/auth2-hostbased.c +++ b/usr/src/cmd/ssh/sshd/auth2-hostbased.c @@ -47,7 +47,6 @@ RCSID("$OpenBSD: auth2-hostbased.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); #include "key.h" #include "canohost.h" -#include "monitor_wrap.h" #include "pathnames.h" /* import */ @@ -119,9 +118,8 @@ userauth_hostbased(Authctxt *authctxt) #endif /* test for allowed key and correct signature */ authenticated = 0; - if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && - PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) + if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) && + key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) authenticated = 1; buffer_clear(&b); diff --git a/usr/src/cmd/ssh/sshd/auth2-none.c b/usr/src/cmd/ssh/sshd/auth2-none.c index 94dbf7d18a..8732cf168e 100644 --- a/usr/src/cmd/ssh/sshd/auth2-none.c +++ b/usr/src/cmd/ssh/sshd/auth2-none.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,7 +39,6 @@ RCSID("$OpenBSD: auth2-none.c,v 1.4 2002/06/27 10:35:47 deraadt Exp $"); #include "atomicio.h" #include "compat.h" #include "ssh2.h" -#include "monitor_wrap.h" /* import */ extern ServerOptions options; @@ -83,7 +82,7 @@ userauth_banner(void) if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) return; - if ((banner = PRIVSEP(auth2_read_banner())) == NULL) + if ((banner = auth2_read_banner()) == NULL) goto done; packet_start(SSH2_MSG_USERAUTH_BANNER); @@ -110,7 +109,7 @@ userauth_none(Authctxt *authctxt) if (check_nt_auth(1, authctxt->pw) == 0) return(0); #endif - authctxt->method->authenticated = PRIVSEP(auth_password(authctxt, "")); + authctxt->method->authenticated = auth_password(authctxt, ""); } Authmethod method_none = { diff --git a/usr/src/cmd/ssh/sshd/auth2-pam.c b/usr/src/cmd/ssh/sshd/auth2-pam.c index 0c866c9625..802378fded 100644 --- a/usr/src/cmd/ssh/sshd/auth2-pam.c +++ b/usr/src/cmd/ssh/sshd/auth2-pam.c @@ -23,7 +23,6 @@ RCSID("$Id: auth2-pam.c,v 1.14 2002/06/28 16:48:12 mouring Exp $"); #include "canohost.h" #include "log.h" #include "servconf.h" -#include "monitor_wrap.h" #include "misc.h" #ifdef HAVE_BSM @@ -251,6 +250,8 @@ do_pam_conv_kbd_int(int num_msg, struct pam_message **msg, } if (conv_ctxt->num_expected == 0 && text == NULL) { + xfree(conv_ctxt->prompts); + xfree(conv_ctxt->responses); xfree(conv_ctxt); return PAM_SUCCESS; } @@ -301,6 +302,8 @@ do_pam_conv_kbd_int(int num_msg, struct pam_message **msg, if (conv_ctxt->abandoned) { authctxt->unwind_dispatch_loop = 1; + xfree(conv_ctxt->prompts); + xfree(conv_ctxt->responses); xfree(conv_ctxt); debug("PAM conv function returns PAM_CONV_ERR"); return PAM_CONV_ERR; @@ -308,12 +311,15 @@ do_pam_conv_kbd_int(int num_msg, struct pam_message **msg, if (conv_ctxt->num_received == conv_ctxt->num_expected) { *resp = conv_ctxt->responses; + xfree(conv_ctxt->prompts); xfree(conv_ctxt); debug("PAM conv function returns PAM_SUCCESS"); return PAM_SUCCESS; } debug("PAM conv function returns PAM_CONV_ERR"); + xfree(conv_ctxt->prompts); + xfree(conv_ctxt->responses); xfree(conv_ctxt); return PAM_CONV_ERR; } diff --git a/usr/src/cmd/ssh/sshd/auth2-passwd.c b/usr/src/cmd/ssh/sshd/auth2-passwd.c index 4c8ca86ff0..9a1837fb05 100644 --- a/usr/src/cmd/ssh/sshd/auth2-passwd.c +++ b/usr/src/cmd/ssh/sshd/auth2-passwd.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,7 +35,6 @@ RCSID("$OpenBSD: auth2-passwd.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); #include "packet.h" #include "log.h" #include "auth.h" -#include "monitor_wrap.h" #include "servconf.h" /* import */ @@ -60,8 +59,9 @@ userauth_passwd(Authctxt *authctxt) #ifdef HAVE_CYGWIN check_nt_auth(1, authctxt->pw) && #endif - PRIVSEP(auth_password(authctxt, password)) == 1) + auth_password(authctxt, password) == 1) { authctxt->method->authenticated = 1; + } memset(password, 0, len); xfree(password); } diff --git a/usr/src/cmd/ssh/sshd/auth2-pubkey.c b/usr/src/cmd/ssh/sshd/auth2-pubkey.c index 9b02597d65..a6544f4f54 100644 --- a/usr/src/cmd/ssh/sshd/auth2-pubkey.c +++ b/usr/src/cmd/ssh/sshd/auth2-pubkey.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,7 +45,6 @@ RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); #include "uidswap.h" #include "auth-options.h" #include "canohost.h" -#include "monitor_wrap.h" #ifdef USE_PAM #include <security/pam_appl.h> @@ -155,10 +154,11 @@ userauth_pubkey(Authctxt *authctxt) buffer_dump(&b); #endif /* test for correct signature */ - if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && - PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) + if (user_key_allowed(authctxt->pw, key) && + key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b)) == 1) { authenticated = 1; + } authctxt->method->postponed = 0; buffer_clear(&b); xfree(sig); @@ -174,7 +174,7 @@ userauth_pubkey(Authctxt *authctxt) * if a user is not allowed to login. is this an * issue? -markus */ - if (PRIVSEP(user_key_allowed(authctxt->pw, key))) { + if (user_key_allowed(authctxt->pw, key)) { packet_start(SSH2_MSG_USERAUTH_PK_OK); packet_put_string(pkalg, alen); packet_put_string(pkblob, blen); diff --git a/usr/src/cmd/ssh/sshd/auth2.c b/usr/src/cmd/ssh/sshd/auth2.c index d220276339..eba64ed56d 100644 --- a/usr/src/cmd/ssh/sshd/auth2.c +++ b/usr/src/cmd/ssh/sshd/auth2.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,7 +42,6 @@ RCSID("$OpenBSD: auth2.c,v 1.95 2002/08/22 21:33:58 markus Exp $"); #include "dispatch.h" #include "sshlogin.h" #include "pathnames.h" -#include "monitor_wrap.h" #ifdef HAVE_BSM #include "bsmaudit.h" @@ -120,8 +119,6 @@ do_authentication2(void) options.kbd_interactive_authentication = 1; if (options.pam_authentication_via_kbd_int) options.kbd_interactive_authentication = 1; - if (use_privsep) - options.pam_authentication_via_kbd_int = 0; dispatch_init(&dispatch_protocol_error); dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); @@ -193,7 +190,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) if (authctxt->attempt == 1) { /* setup auth context */ - authctxt->pw = PRIVSEP(getpwnamallow(user)); + authctxt->pw = getpwnamallow(user); /* May want to abstract SSHv2 services someday */ if (authctxt->pw && strcmp(service, "ssh-connection")==0) { /* enforced in userauth_finish() below */ @@ -202,14 +199,11 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) } else { log("input_userauth_request: illegal user %s", user); } - setproctitle("%s%s", authctxt->pw ? user : "unknown", - use_privsep ? " [net]" : ""); + setproctitle("%s", authctxt->pw ? user : "unknown"); authctxt->user = xstrdup(user); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; userauth_reset_methods(); - if (use_privsep) - mm_inform_authserv(service, style); } else { char *abandoned; @@ -293,8 +287,7 @@ userauth_finish(Authctxt *authctxt, char *method) #ifndef USE_PAM /* Special handling for root (done elsewhere for PAM) */ - if (!use_privsep && - authctxt->method->authenticated && + if (authctxt->method->authenticated && authctxt->pw != NULL && authctxt->pw->pw_uid == 0 && !auth_root_allowed(method)) authctxt->method->authenticated = 0; @@ -457,7 +450,7 @@ userauth_user_svc_change(Authctxt *authctxt, char *user, char *service) xfree(authctxt->user); authctxt->user = xstrdup(user); pwfree(&authctxt->pw); - authctxt->pw = PRIVSEP(getpwnamallow(user)); + authctxt->pw = getpwnamallow(user); authctxt->valid = (authctxt->pw != NULL); /* Forget method state; abandon postponed userauths */ diff --git a/usr/src/cmd/ssh/sshd/gss-serv.c b/usr/src/cmd/ssh/sshd/gss-serv.c index ad0d7c65f5..98b962b3d0 100644 --- a/usr/src/cmd/ssh/sshd/gss-serv.c +++ b/usr/src/cmd/ssh/sshd/gss-serv.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -51,7 +51,6 @@ #include "servconf.h" #include "uidswap.h" #include "compat.h" -#include "monitor_wrap.h" #include <pwd.h> #include "ssh-gss.h" diff --git a/usr/src/cmd/ssh/sshd/monitor.c b/usr/src/cmd/ssh/sshd/monitor.c deleted file mode 100644 index c14973160b..0000000000 --- a/usr/src/cmd/ssh/sshd/monitor.c +++ /dev/null @@ -1,1852 +0,0 @@ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * Copyright 2002 Markus Friedl <markus@openbsd.org> - * 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. - * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: monitor.c,v 1.29 2002/09/26 11:38:43 markus Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <openssl/dh.h> - -#ifdef SKEY -#include <skey.h> -#endif - -#include "ssh.h" -#include "auth.h" -#include "kex.h" -#include "dh.h" -#include "zlib.h" -#include "packet.h" -#include "auth-options.h" -#include "sshpty.h" -#include "channels.h" -#include "session.h" -#include "sshlogin.h" -#include "canohost.h" -#include "log.h" -#include "servconf.h" -#include "monitor.h" -#include "monitor_mm.h" -#include "monitor_wrap.h" -#include "monitor_fdpass.h" -#include "xmalloc.h" -#include "misc.h" -#include "buffer.h" -#include "bufaux.h" -#include "compat.h" -#include "ssh2.h" -#include "mpaux.h" - -#ifndef lint - -#ifdef GSSAPI -#include "ssh-gss.h" -static Gssctxt *gsscontext = NULL; -#endif - -/* Imports */ -extern ServerOptions options; -extern u_int utmp_len; -extern Newkeys *current_keys[]; -extern z_stream incoming_stream; -extern z_stream outgoing_stream; -extern u_char session_id[]; -extern Buffer input, output; -extern Buffer auth_debug; -extern int auth_debug_init; - -/* State exported from the child */ - -struct { - z_stream incoming; - z_stream outgoing; - u_char *keyin; - u_int keyinlen; - u_char *keyout; - u_int keyoutlen; - u_char *ivin; - u_int ivinlen; - u_char *ivout; - u_int ivoutlen; - u_char *ssh1key; - u_int ssh1keylen; - int ssh1cipher; - int ssh1protoflags; - u_char *input; - u_int ilen; - u_char *output; - u_int olen; -} child_state; - -/* Functions on the montior that answer unprivileged requests */ - -int mm_answer_moduli(int, Buffer *); -int mm_answer_sign(int, Buffer *); -int mm_answer_pwnamallow(int, Buffer *); -int mm_answer_auth2_read_banner(int, Buffer *); -int mm_answer_authserv(int, Buffer *); -int mm_answer_authpassword(int, Buffer *); -int mm_answer_bsdauthquery(int, Buffer *); -int mm_answer_bsdauthrespond(int, Buffer *); -int mm_answer_skeyquery(int, Buffer *); -int mm_answer_skeyrespond(int, Buffer *); -int mm_answer_keyallowed(int, Buffer *); -int mm_answer_keyverify(int, Buffer *); -int mm_answer_pty(int, Buffer *); -int mm_answer_pty_cleanup(int, Buffer *); -int mm_answer_term(int, Buffer *); -int mm_answer_rsa_keyallowed(int, Buffer *); -int mm_answer_rsa_challenge(int, Buffer *); -int mm_answer_rsa_response(int, Buffer *); -int mm_answer_sesskey(int, Buffer *); -int mm_answer_sessid(int, Buffer *); - -#ifdef USE_PAM -int mm_answer_pam_start(int, Buffer *); -#endif - -#ifdef KRB4 -int mm_answer_krb4(int, Buffer *); -#endif -#ifdef KRB5 -int mm_answer_krb5(int, Buffer *); -#endif - -#ifdef GSSAPI -int mm_answer_gss_setup_ctx(int, Buffer *); -int mm_answer_gss_accept_ctx(int, Buffer *); -int mm_answer_gss_userok(int, Buffer *); -int mm_answer_gss_sign(int, Buffer *); -int mm_answer_gss_error(int, Buffer *); -int mm_answer_gss_indicate_mechs(int, Buffer *); -int mm_answer_gss_localname(int, Buffer *); -#endif - -static Authctxt *authctxt; -static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ - -/* local state for key verify */ -static u_char *key_blob = NULL; -static u_int key_bloblen = 0; -static int key_blobtype = MM_NOKEY; -static char *hostbased_cuser = NULL; -static char *hostbased_chost = NULL; -static char *auth_method = "unknown"; -static int session_id2_len = 0; -static u_char *session_id2 = NULL; - -struct mon_table { - enum monitor_reqtype type; - int flags; - int (*f)(int, Buffer *); -}; - -#define MON_ISAUTH 0x0004 /* Required for Authentication */ -#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ -#define MON_ONCE 0x0010 /* Disable after calling */ - -#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) - -#define MON_PERMIT 0x1000 /* Request is permitted */ - -struct mon_table mon_dispatch_proto20[] = { - {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, - {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, - {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, - {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, - {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, - {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, -#ifdef USE_PAM - {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, -#endif -#ifdef BSD_AUTH - {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, - {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond}, -#endif -#ifdef SKEY - {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, - {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, -#endif -#ifdef GSSAPI - {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, - {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, - {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, - {MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error}, - {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs}, - {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, -/* Turn this off until we use it */ -#if 0 - {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname}, -#endif -#endif - {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, - {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, - {0, 0, NULL} -}; - -struct mon_table mon_dispatch_postauth20[] = { -#ifdef GSSAPI - {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, - {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, - {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, - {MONITOR_REQ_GSSERR, 0, mm_answer_gss_error}, - {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs}, -#endif - {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, - {MONITOR_REQ_SIGN, 0, mm_answer_sign}, - {MONITOR_REQ_PTY, 0, mm_answer_pty}, - {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, - {MONITOR_REQ_TERM, 0, mm_answer_term}, - {0, 0, NULL} -}; - -struct mon_table mon_dispatch_proto15[] = { - {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, - {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, - {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, - {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, - {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed}, - {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, - {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, - {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, -#ifdef BSD_AUTH - {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, - {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond}, -#endif -#ifdef SKEY - {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, - {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, -#endif -#ifdef USE_PAM - {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, -#endif -#ifdef KRB4 - {MONITOR_REQ_KRB4, MON_ONCE|MON_AUTH, mm_answer_krb4}, -#endif -#ifdef KRB5 - {MONITOR_REQ_KRB5, MON_ONCE|MON_AUTH, mm_answer_krb5}, -#endif - {0, 0, NULL} -}; - -struct mon_table mon_dispatch_postauth15[] = { - {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, - {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, - {MONITOR_REQ_TERM, 0, mm_answer_term}, - {0, 0, NULL} -}; - -struct mon_table *mon_dispatch; - -/* Specifies if a certain message is allowed at the moment */ - -static void -monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) -{ - while (ent->f != NULL) { - if (ent->type == type) { - ent->flags &= ~MON_PERMIT; - ent->flags |= permit ? MON_PERMIT : 0; - return; - } - ent++; - } -} - -static void -monitor_permit_authentications(int permit) -{ - struct mon_table *ent = mon_dispatch; - - while (ent->f != NULL) { - if (ent->flags & MON_AUTH) { - ent->flags &= ~MON_PERMIT; - ent->flags |= permit ? MON_PERMIT : 0; - } - ent++; - } -} - -Authctxt * -monitor_child_preauth(struct monitor *pmonitor) -{ - struct mon_table *ent; - int authenticated = 0; - - debug3("preauth child monitor started"); - - if (compat20) { - mon_dispatch = mon_dispatch_proto20; - - /* Permit requests for moduli and signatures */ - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); -#ifdef GSSAPI - /* and for the GSSAPI key exchange */ - monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1); -#endif - } else { - mon_dispatch = mon_dispatch_proto15; - - monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); - } - - authctxt = authctxt_new(); - - /* The first few requests do not require asynchronous access */ - while (!authenticated) { - authenticated = monitor_read(pmonitor, mon_dispatch, &ent); - if (authenticated) { - if (!(ent->flags & MON_AUTHDECIDE)) - fatal("%s: unexpected authentication from %d", - __func__, ent->type); - if (authctxt->pw->pw_uid == 0 && - !auth_root_allowed(auth_method)) - authenticated = 0; -#ifdef USE_PAM - /*if (!do_pam_account(authctxt->pw->pw_name, * NULL))*/ - if (!do_pam_non_initial_userauth(authctxt)) - authenticated = 0; -#endif - } - - if (ent->flags & MON_AUTHDECIDE) { - auth_log(authctxt, authenticated, auth_method, - compat20 ? " ssh2" : ""); - if (!authenticated) - authctxt->failures++; - } - } - - if (!authctxt->valid) - fatal("%s: authenticated invalid user", __func__); - - debug("%s: %s has been authenticated by privileged process", - __func__, authctxt->user); - - mm_get_keystate(pmonitor); - - return (authctxt); -} - -void -monitor_child_postauth(struct monitor *pmonitor) -{ - if (compat20) { - mon_dispatch = mon_dispatch_postauth20; - - /* Permit requests for moduli and signatures */ - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); - -#ifdef GSSAPI - /* and for the GSSAPI key exchange */ - monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS,1); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP,1); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR,1); -#endif - - } else { - mon_dispatch = mon_dispatch_postauth15; - monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); - } - if (!no_pty_flag) { - monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); - } - - for (;;) - monitor_read(pmonitor, mon_dispatch, NULL); -} - -void -monitor_sync(struct monitor *pmonitor) -{ - if (options.compression) { - /* The member allocation is not visible, so sync it */ - mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback); - } -} - -int -monitor_read(struct monitor *pmonitor, struct mon_table *ent, - struct mon_table **pent) -{ - Buffer m; - int ret; - u_char type; - - buffer_init(&m); - - mm_request_receive(pmonitor->m_sendfd, &m); - type = buffer_get_char(&m); - - debug3("%s: checking request %d", __func__, type); - - while (ent->f != NULL) { - if (ent->type == type) - break; - ent++; - } - - if (ent->f != NULL) { - if (!(ent->flags & MON_PERMIT)) - fatal("%s: unpermitted request %d", __func__, - type); - ret = (*ent->f)(pmonitor->m_sendfd, &m); - buffer_free(&m); - - /* The child may use this request only once, disable it */ - if (ent->flags & MON_ONCE) { - debug2("%s: %d used once, disabling now", __func__, - type); - ent->flags &= ~MON_PERMIT; - } - - if (pent != NULL) - *pent = ent; - - return ret; - } - - fatal("%s: unsupported request: %d", __func__, type); - - /* NOTREACHED */ - return (-1); -} - -/* allowed key state */ -static int -monitor_allowed_key(u_char *blob, u_int bloblen) -{ - /* make sure key is allowed */ - if (key_blob == NULL || key_bloblen != bloblen || - memcmp(key_blob, blob, key_bloblen)) - return (0); - return (1); -} - -static void -monitor_reset_key_state(void) -{ - /* reset state */ - if (key_blob != NULL) - xfree(key_blob); - if (hostbased_cuser != NULL) - xfree(hostbased_cuser); - if (hostbased_chost != NULL) - xfree(hostbased_chost); - key_blob = NULL; - key_bloblen = 0; - key_blobtype = MM_NOKEY; - hostbased_cuser = NULL; - hostbased_chost = NULL; -} - -int -mm_answer_moduli(int socket, Buffer *m) -{ - DH *dh; - int min, want, max; - - min = buffer_get_int(m); - want = buffer_get_int(m); - max = buffer_get_int(m); - - debug3("%s: got parameters: %d %d %d", - __func__, min, want, max); - /* We need to check here, too, in case the child got corrupted */ - if (max < min || want < min || max < want) - fatal("%s: bad parameters: %d %d %d", - __func__, min, want, max); - - buffer_clear(m); - - dh = choose_dh(min, want, max); - if (dh == NULL) { - buffer_put_char(m, 0); - return (0); - } else { - /* Send first bignum */ - buffer_put_char(m, 1); - buffer_put_bignum2(m, dh->p); - buffer_put_bignum2(m, dh->g); - - DH_free(dh); - } - mm_request_send(socket, MONITOR_ANS_MODULI, m); - return (0); -} - -int -mm_answer_sign(int socket, Buffer *m) -{ - Key *key; - u_char *p; - u_char *signature; - u_int siglen, datlen; - int keyid; - - debug3("%s", __func__); - - keyid = buffer_get_int(m); - p = buffer_get_string(m, &datlen); - - if (datlen != 20) - fatal("%s: data length incorrect: %u", __func__, datlen); - - /* save session id, it will be passed on the first call */ - if (session_id2_len == 0) { - session_id2_len = datlen; - session_id2 = xmalloc(session_id2_len); - memcpy(session_id2, p, session_id2_len); - } - - if ((key = get_hostkey_by_index(keyid)) == NULL) - fatal("%s: no hostkey from index %d", __func__, keyid); - if (key_sign(key, &signature, &siglen, p, datlen) < 0) - fatal("%s: key_sign failed", __func__); - - debug3("%s: signature %p(%u)", __func__, signature, siglen); - - buffer_clear(m); - buffer_put_string(m, signature, siglen); - - xfree(p); - xfree(signature); - - mm_request_send(socket, MONITOR_ANS_SIGN, m); - - /* Turn on permissions for getpwnam */ - monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); - - return (0); -} - -/* Retrieves the password entry and also checks if the user is permitted */ - -int -mm_answer_pwnamallow(int socket, Buffer *m) -{ - char *login; - struct passwd *pwent; - int allowed = 0; - - debug3("%s", __func__); - - if (authctxt->attempt++ != 0) - fatal("%s: multiple attempts for getpwnam", __func__); - - login = buffer_get_string(m, NULL); - - pwent = getpwnamallow(login); - - authctxt->user = xstrdup(login); - setproctitle("%s [priv]", pwent ? login : "unknown"); - xfree(login); - - buffer_clear(m); - - if (pwent == NULL) { - buffer_put_char(m, 0); - goto out; - } - - allowed = 1; - authctxt->pw = pwent; - authctxt->valid = 1; - - buffer_put_char(m, 1); - buffer_put_string(m, pwent, sizeof(struct passwd)); - buffer_put_cstring(m, pwent->pw_name); - buffer_put_cstring(m, "*"); - buffer_put_cstring(m, pwent->pw_gecos); -#ifdef HAVE_PW_CLASS_IN_PASSWD - buffer_put_cstring(m, pwent->pw_class); -#endif - buffer_put_cstring(m, pwent->pw_dir); - buffer_put_cstring(m, pwent->pw_shell); - - out: - debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); - mm_request_send(socket, MONITOR_ANS_PWNAM, m); - - /* For SSHv1 allow authentication now */ - if (!compat20) - monitor_permit_authentications(1); - else { - /* Allow service/style information on the auth context */ - monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); - } - -#ifdef USE_PAM - monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); -#endif - - return (0); -} - -int mm_answer_auth2_read_banner(int socket, Buffer *m) -{ - char *banner; - - buffer_clear(m); - banner = auth2_read_banner(); - buffer_put_cstring(m, banner != NULL ? banner : ""); - mm_request_send(socket, MONITOR_ANS_AUTH2_READ_BANNER, m); - - if (banner != NULL) - xfree(banner); - - return (0); -} - -int -mm_answer_authserv(int socket, Buffer *m) -{ - monitor_permit_authentications(1); - - authctxt->service = buffer_get_string(m, NULL); - authctxt->style = buffer_get_string(m, NULL); - debug3("%s: service=%s, style=%s", - __func__, authctxt->service, authctxt->style); - - if (strlen(authctxt->style) == 0) { - xfree(authctxt->style); - authctxt->style = NULL; - } - - return (0); -} - -int -mm_answer_authpassword(int socket, Buffer *m) -{ - static int call_count; - char *passwd; - int authenticated; - u_int plen; - - passwd = buffer_get_string(m, &plen); - /* Only authenticate if the context is valid */ - authenticated = options.password_authentication && - authctxt->valid && auth_password(authctxt, passwd); - memset(passwd, 0, strlen(passwd)); - xfree(passwd); - - buffer_clear(m); - buffer_put_int(m, authenticated); - - debug3("%s: sending result %d", __func__, authenticated); - mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m); - - call_count++; - if (plen == 0 && call_count == 1) - auth_method = "none"; - else - auth_method = "password"; - - /* Causes monitor loop to terminate if authenticated */ - return (authenticated); -} - -#ifdef BSD_AUTH -int -mm_answer_bsdauthquery(int socket, Buffer *m) -{ - char *name, *infotxt; - u_int numprompts; - u_int *echo_on; - char **prompts; - int res; - - res = bsdauth_query(authctxt, &name, &infotxt, &numprompts, - &prompts, &echo_on); - - buffer_clear(m); - buffer_put_int(m, res); - if (res != -1) - buffer_put_cstring(m, prompts[0]); - - debug3("%s: sending challenge res: %d", __func__, res); - mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m); - - if (res != -1) { - xfree(name); - xfree(infotxt); - xfree(prompts); - xfree(echo_on); - } - - return (0); -} - -int -mm_answer_bsdauthrespond(int socket, Buffer *m) -{ - char *response; - int authok; - - if (authctxt->as == 0) - fatal("%s: no bsd auth session", __func__); - - response = buffer_get_string(m, NULL); - authok = options.challenge_response_authentication && - auth_userresponse(authctxt->as, response, 0); - authctxt->as = NULL; - debug3("%s: <%s> = <%d>", __func__, response, authok); - xfree(response); - - buffer_clear(m); - buffer_put_int(m, authok); - - debug3("%s: sending authenticated: %d", __func__, authok); - mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m); - - auth_method = "bsdauth"; - - return (authok != 0); -} -#endif - -#ifdef SKEY -int -mm_answer_skeyquery(int socket, Buffer *m) -{ - struct skey skey; - char challenge[1024]; - int res; - - res = skeychallenge(&skey, authctxt->user, challenge); - - buffer_clear(m); - buffer_put_int(m, res); - if (res != -1) - buffer_put_cstring(m, challenge); - - debug3("%s: sending challenge res: %d", __func__, res); - mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m); - - return (0); -} - -int -mm_answer_skeyrespond(int socket, Buffer *m) -{ - char *response; - int authok; - - response = buffer_get_string(m, NULL); - - authok = (options.challenge_response_authentication && - authctxt->valid && - skey_haskey(authctxt->pw->pw_name) == 0 && - skey_passcheck(authctxt->pw->pw_name, response) != -1); - - xfree(response); - - buffer_clear(m); - buffer_put_int(m, authok); - - debug3("%s: sending authenticated: %d", __func__, authok); - mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m); - - auth_method = "skey"; - - return (authok != 0); -} -#endif - -#ifdef USE_PAM -int -mm_answer_pam_start(int socket, Buffer *m) -{ - char *user; - - user = buffer_get_string(m, NULL); - - new_start_pam(authctxt, /*XXX*/ NULL); - - xfree(user); - - return (0); -} -#endif - -static void -mm_append_debug(Buffer *m) -{ - if (auth_debug_init && buffer_len(&auth_debug)) { - debug3("%s: Appending debug messages for child", __func__); - buffer_append(m, buffer_ptr(&auth_debug), - buffer_len(&auth_debug)); - buffer_clear(&auth_debug); - } -} - -int -mm_answer_keyallowed(int socket, Buffer *m) -{ - Key *key; - char *cuser, *chost; - u_char *blob; - u_int bloblen; - enum mm_keytype type = 0; - int allowed = 0; - - debug3("%s entering", __func__); - - type = buffer_get_int(m); - cuser = buffer_get_string(m, NULL); - chost = buffer_get_string(m, NULL); - blob = buffer_get_string(m, &bloblen); - - key = key_from_blob(blob, bloblen); - - if ((compat20 && type == MM_RSAHOSTKEY) || - (!compat20 && type != MM_RSAHOSTKEY)) - fatal("%s: key type and protocol mismatch", __func__); - - debug3("%s: key_from_blob: %p", __func__, key); - - if (key != NULL && authctxt->pw != NULL) { - switch(type) { - case MM_USERKEY: - allowed = options.pubkey_authentication && - user_key_allowed(authctxt->pw, key); - break; - case MM_HOSTKEY: - allowed = options.hostbased_authentication && - hostbased_key_allowed(authctxt->pw, - cuser, chost, key); - break; - case MM_RSAHOSTKEY: - key->type = KEY_RSA1; /* XXX */ - allowed = options.rhosts_rsa_authentication && - auth_rhosts_rsa_key_allowed(authctxt->pw, - cuser, chost, key); - break; - default: - fatal("%s: unknown key type %d", __func__, type); - break; - } - key_free(key); - } - - /* clear temporarily storage (used by verify) */ - monitor_reset_key_state(); - - if (allowed) { - /* Save temporarily for comparison in verify */ - key_blob = blob; - key_bloblen = bloblen; - key_blobtype = type; - hostbased_cuser = cuser; - hostbased_chost = chost; - } - - debug3("%s: key %p is %s", - __func__, key, allowed ? "allowed" : "disallowed"); - - buffer_clear(m); - buffer_put_int(m, allowed); - - mm_append_debug(m); - - mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m); - - if (type == MM_RSAHOSTKEY) - monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); - - return (0); -} - -static int -monitor_valid_userblob(u_char *data, u_int datalen) -{ - Buffer b; - char *p; - u_int len; - int fail = 0; - - buffer_init(&b); - buffer_append(&b, data, datalen); - - if (datafellows & SSH_OLD_SESSIONID) { - p = buffer_ptr(&b); - len = buffer_len(&b); - if ((session_id2 == NULL) || - (len < session_id2_len) || - (memcmp(p, session_id2, session_id2_len) != 0)) - fail++; - buffer_consume(&b, session_id2_len); - } else { - p = buffer_get_string(&b, &len); - if ((session_id2 == NULL) || - (len != session_id2_len) || - (memcmp(p, session_id2, session_id2_len) != 0)) - fail++; - xfree(p); - } - if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) - fail++; - p = buffer_get_string(&b, NULL); - if (strcmp(authctxt->user, p) != 0) { - log("wrong user name passed to monitor: expected %s != %.100s", - authctxt->user, p); - fail++; - } - xfree(p); - buffer_skip_string(&b); - if (datafellows & SSH_BUG_PKAUTH) { - if (!buffer_get_char(&b)) - fail++; - } else { - p = buffer_get_string(&b, NULL); - if (strcmp("publickey", p) != 0) - fail++; - xfree(p); - if (!buffer_get_char(&b)) - fail++; - buffer_skip_string(&b); - } - buffer_skip_string(&b); - if (buffer_len(&b) != 0) - fail++; - buffer_free(&b); - return (fail == 0); -} - -static int -monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, - char *chost) -{ - Buffer b; - char *p; - u_int len; - int fail = 0; - - buffer_init(&b); - buffer_append(&b, data, datalen); - - p = buffer_get_string(&b, &len); - if ((session_id2 == NULL) || - (len != session_id2_len) || - (memcmp(p, session_id2, session_id2_len) != 0)) - fail++; - xfree(p); - - if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) - fail++; - p = buffer_get_string(&b, NULL); - if (strcmp(authctxt->user, p) != 0) { - log("wrong user name passed to monitor: expected %s != %.100s", - authctxt->user, p); - fail++; - } - xfree(p); - buffer_skip_string(&b); /* service */ - p = buffer_get_string(&b, NULL); - if (strcmp(p, "hostbased") != 0) - fail++; - xfree(p); - buffer_skip_string(&b); /* pkalg */ - buffer_skip_string(&b); /* pkblob */ - - /* verify client host, strip trailing dot if necessary */ - p = buffer_get_string(&b, NULL); - if (((len = strlen(p)) > 0) && p[len - 1] == '.') - p[len - 1] = '\0'; - if (strcmp(p, chost) != 0) - fail++; - xfree(p); - - /* verify client user */ - p = buffer_get_string(&b, NULL); - if (strcmp(p, cuser) != 0) - fail++; - xfree(p); - - if (buffer_len(&b) != 0) - fail++; - buffer_free(&b); - return (fail == 0); -} - -int -mm_answer_keyverify(int socket, Buffer *m) -{ - Key *key; - u_char *signature, *data, *blob; - u_int signaturelen, datalen, bloblen; - int verified = 0; - int valid_data = 0; - - blob = buffer_get_string(m, &bloblen); - signature = buffer_get_string(m, &signaturelen); - data = buffer_get_string(m, &datalen); - - if (hostbased_cuser == NULL || hostbased_chost == NULL || - !monitor_allowed_key(blob, bloblen)) - fatal("%s: bad key, not previously allowed", __func__); - - key = key_from_blob(blob, bloblen); - if (key == NULL) - fatal("%s: bad public key blob", __func__); - - switch (key_blobtype) { - case MM_USERKEY: - valid_data = monitor_valid_userblob(data, datalen); - break; - case MM_HOSTKEY: - valid_data = monitor_valid_hostbasedblob(data, datalen, - hostbased_cuser, hostbased_chost); - break; - default: - valid_data = 0; - break; - } - if (!valid_data) - fatal("%s: bad signature data blob", __func__); - - verified = key_verify(key, signature, signaturelen, data, datalen); - debug3("%s: key %p signature %s", - __func__, key, verified ? "verified" : "unverified"); - - key_free(key); - xfree(blob); - xfree(signature); - xfree(data); - - auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; - - monitor_reset_key_state(); - - buffer_clear(m); - buffer_put_int(m, verified); - mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m); - - return (verified); -} - -static void -mm_record_login(Session *s, struct passwd *pw) -{ - /* Record that there was a login on that tty from the remote host. */ - record_login(s->pid, s->tty, NULL, pw->pw_name); -} - -static void -mm_session_close(Session *s) -{ - debug3("%s: session %d pid %ld", __func__, s->self, s->pid); - if (s->ttyfd != -1) { - debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); - fatal_remove_cleanup(session_pty_cleanup2, (void *)s); - session_pty_cleanup2(s); - } - s->used = 0; -} - -int -mm_answer_pty(int socket, Buffer *m) -{ - extern struct monitor *pmonitor; - Session *s; - int res, fd0; - - debug3("%s entering", __func__); - - buffer_clear(m); - s = session_new(); - if (s == NULL) - goto error; - s->authctxt = authctxt; - s->pw = authctxt->pw; - s->pid = pmonitor->m_pid; - res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); - if (res == 0) - goto error; - fatal_add_cleanup(session_pty_cleanup2, (void *)s); - pty_setowner(authctxt->pw, s->tty); - - buffer_put_int(m, 1); - buffer_put_cstring(m, s->tty); - mm_request_send(socket, MONITOR_ANS_PTY, m); - - mm_send_fd(socket, s->ptyfd); - mm_send_fd(socket, s->ttyfd); - - /* We need to trick ttyslot */ - if (dup2(s->ttyfd, 0) == -1) - fatal("%s: dup2", __func__); - - mm_record_login(s, authctxt->pw); - - /* Now we can close the file descriptor again */ - close(0); - - /* make sure nothing uses fd 0 */ - if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) - fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); - if (fd0 != 0) - error("%s: fd0 %d != 0", __func__, fd0); - - /* slave is not needed */ - close(s->ttyfd); - s->ttyfd = s->ptyfd; - /* no need to dup() because nobody closes ptyfd */ - s->ptymaster = s->ptyfd; - - debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); - - return (0); - - error: - if (s != NULL) - mm_session_close(s); - buffer_put_int(m, 0); - mm_request_send(socket, MONITOR_ANS_PTY, m); - return (0); -} - -int -mm_answer_pty_cleanup(int socket, Buffer *m) -{ - Session *s; - char *tty; - - debug3("%s entering", __func__); - - tty = buffer_get_string(m, NULL); - if ((s = session_by_tty(tty)) != NULL) - mm_session_close(s); - buffer_clear(m); - xfree(tty); - return (0); -} - -int -mm_answer_sesskey(int socket, Buffer *m) -{ - BIGNUM *p; - int rsafail; - - /* Turn off permissions */ - monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); - - if ((p = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - buffer_get_bignum2(m, p); - - rsafail = ssh1_session_key(p); - - buffer_clear(m); - buffer_put_int(m, rsafail); - buffer_put_bignum2(m, p); - - BN_clear_free(p); - - mm_request_send(socket, MONITOR_ANS_SESSKEY, m); - - /* Turn on permissions for sessid passing */ - monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); - - return (0); -} - -int -mm_answer_sessid(int socket, Buffer *m) -{ - int i; - - debug3("%s entering", __func__); - - if (buffer_len(m) != 16) - fatal("%s: bad ssh1 session id", __func__); - for (i = 0; i < 16; i++) - session_id[i] = buffer_get_char(m); - - /* Turn on permissions for getpwnam */ - monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); - - return (0); -} - -int -mm_answer_rsa_keyallowed(int socket, Buffer *m) -{ - BIGNUM *client_n; - Key *key = NULL; - u_char *blob = NULL; - u_int blen = 0; - int allowed = 0; - - debug3("%s entering", __func__); - - if (options.rsa_authentication && authctxt->valid) { - if ((client_n = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - buffer_get_bignum2(m, client_n); - allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); - BN_clear_free(client_n); - } - buffer_clear(m); - buffer_put_int(m, allowed); - - /* clear temporarily storage (used by generate challenge) */ - monitor_reset_key_state(); - - if (allowed && key != NULL) { - key->type = KEY_RSA; /* cheat for key_to_blob */ - if (key_to_blob(key, &blob, &blen) == 0) - fatal("%s: key_to_blob failed", __func__); - buffer_put_string(m, blob, blen); - - /* Save temporarily for comparison in verify */ - key_blob = blob; - key_bloblen = blen; - key_blobtype = MM_RSAUSERKEY; - key_free(key); - } - - mm_append_debug(m); - - mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m); - - monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); - monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); - return (0); -} - -int -mm_answer_rsa_challenge(int socket, Buffer *m) -{ - Key *key = NULL; - u_char *blob; - u_int blen; - - debug3("%s entering", __func__); - - if (!authctxt->valid) - fatal("%s: authctxt not valid", __func__); - blob = buffer_get_string(m, &blen); - if (!monitor_allowed_key(blob, blen)) - fatal("%s: bad key, not previously allowed", __func__); - if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) - fatal("%s: key type mismatch", __func__); - if ((key = key_from_blob(blob, blen)) == NULL) - fatal("%s: received bad key", __func__); - - if (ssh1_challenge) - BN_clear_free(ssh1_challenge); - ssh1_challenge = auth_rsa_generate_challenge(key); - - buffer_clear(m); - buffer_put_bignum2(m, ssh1_challenge); - - debug3("%s sending reply", __func__); - mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m); - - monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); - return (0); -} - -int -mm_answer_rsa_response(int socket, Buffer *m) -{ - Key *key = NULL; - u_char *blob, *response; - u_int blen, len; - int success; - - debug3("%s entering", __func__); - - if (!authctxt->valid) - fatal("%s: authctxt not valid", __func__); - if (ssh1_challenge == NULL) - fatal("%s: no ssh1_challenge", __func__); - - blob = buffer_get_string(m, &blen); - if (!monitor_allowed_key(blob, blen)) - fatal("%s: bad key, not previously allowed", __func__); - if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) - fatal("%s: key type mismatch: %d", __func__, key_blobtype); - if ((key = key_from_blob(blob, blen)) == NULL) - fatal("%s: received bad key", __func__); - response = buffer_get_string(m, &len); - if (len != 16) - fatal("%s: received bad response to challenge", __func__); - success = auth_rsa_verify_response(key, ssh1_challenge, response); - - key_free(key); - xfree(response); - - auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; - - /* reset state */ - BN_clear_free(ssh1_challenge); - ssh1_challenge = NULL; - monitor_reset_key_state(); - - buffer_clear(m); - buffer_put_int(m, success); - mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m); - - return (success); -} - -#ifdef KRB4 -int -mm_answer_krb4(int socket, Buffer *m) -{ - KTEXT_ST auth, reply; - char *client, *p; - int success; - u_int alen; - - reply.length = auth.length = 0; - - p = buffer_get_string(m, &alen); - if (alen >= MAX_KTXT_LEN) - fatal("%s: auth too large", __func__); - memcpy(auth.dat, p, alen); - auth.length = alen; - memset(p, 0, alen); - xfree(p); - - success = options.kerberos_authentication && - authctxt->valid && - auth_krb4(authctxt, &auth, &client, &reply); - - memset(auth.dat, 0, alen); - buffer_clear(m); - buffer_put_int(m, success); - - if (success) { - buffer_put_cstring(m, client); - buffer_put_string(m, reply.dat, reply.length); - if (client) - xfree(client); - if (reply.length) - memset(reply.dat, 0, reply.length); - } - - debug3("%s: sending result %d", __func__, success); - mm_request_send(socket, MONITOR_ANS_KRB4, m); - - auth_method = "kerberos"; - - /* Causes monitor loop to terminate if authenticated */ - return (success); -} -#endif - -#ifdef KRB5 -int -mm_answer_krb5(int socket, Buffer *m) -{ - krb5_data tkt, reply; - char *client_user; - u_int len; - int success; - - /* use temporary var to avoid size issues on 64bit arch */ - tkt.data = buffer_get_string(m, &len); - tkt.length = len; - - success = options.kerberos_authentication && - authctxt->valid && - auth_krb5(authctxt, &tkt, &client_user, &reply); - - if (tkt.length) - xfree(tkt.data); - - buffer_clear(m); - buffer_put_int(m, success); - - if (success) { - buffer_put_cstring(m, client_user); - buffer_put_string(m, reply.data, reply.length); - if (client_user) - xfree(client_user); - if (reply.length) - xfree(reply.data); - } - mm_request_send(socket, MONITOR_ANS_KRB5, m); - - return success; -} -#endif - -int -mm_answer_term(int socket, Buffer *req) -{ - extern struct monitor *pmonitor; - int res, status; - - debug3("%s: tearing down sessions", __func__); - - /* The child is terminating */ - session_destroy_all(&mm_session_close); - - while (waitpid(pmonitor->m_pid, &status, 0) == -1) - if (errno != EINTR) - exit(1); - - res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; - - /* Terminate process */ - return (res); - /* NOTREACHED */ -} - -void -monitor_apply_keystate(struct monitor *pmonitor) -{ - if (compat20) { - set_newkeys(MODE_IN); - set_newkeys(MODE_OUT); - } else { - packet_set_protocol_flags(child_state.ssh1protoflags); - packet_set_encryption_key(child_state.ssh1key, - child_state.ssh1keylen, child_state.ssh1cipher); - xfree(child_state.ssh1key); - } - - /* for rc4 and other stateful ciphers */ - packet_set_keycontext(MODE_OUT, child_state.keyout); - xfree(child_state.keyout); - packet_set_keycontext(MODE_IN, child_state.keyin); - xfree(child_state.keyin); - - if (!compat20) { - packet_set_iv(MODE_OUT, child_state.ivout); - xfree(child_state.ivout); - packet_set_iv(MODE_IN, child_state.ivin); - xfree(child_state.ivin); - } - - memcpy(&incoming_stream, &child_state.incoming, - sizeof(incoming_stream)); - memcpy(&outgoing_stream, &child_state.outgoing, - sizeof(outgoing_stream)); - - /* Update with new address */ - if (options.compression) - mm_init_compression(pmonitor->m_zlib); - - /* Network I/O buffers */ - /* XXX inefficient for large buffers, need: buffer_init_from_string */ - buffer_clear(&input); - buffer_append(&input, child_state.input, child_state.ilen); - memset(child_state.input, 0, child_state.ilen); - xfree(child_state.input); - - buffer_clear(&output); - buffer_append(&output, child_state.output, child_state.olen); - memset(child_state.output, 0, child_state.olen); - xfree(child_state.output); -} - -static Kex * -mm_get_kex(Buffer *m) -{ - Kex *kex; - void *blob; - u_int bloblen; - - kex = xmalloc(sizeof(*kex)); - memset(kex, 0, sizeof(*kex)); - kex->session_id = buffer_get_string(m, &kex->session_id_len); - if ((session_id2 == NULL) || - (kex->session_id_len != session_id2_len) || - (memcmp(kex->session_id, session_id2, session_id2_len) != 0)) - fatal("mm_get_get: internal error: bad session id"); - kex->we_need = buffer_get_int(m); - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; -#ifdef GSSAPI - kex->kex[KEX_GSS_GRP1_SHA1] =kexgss_server; -#endif - kex->server = 1; - kex->hostkey_type = buffer_get_int(m); - kex->kex_type = buffer_get_int(m); - blob = buffer_get_string(m, &bloblen); - buffer_init(&kex->my); - buffer_append(&kex->my, blob, bloblen); - xfree(blob); - blob = buffer_get_string(m, &bloblen); - buffer_init(&kex->peer); - buffer_append(&kex->peer, blob, bloblen); - xfree(blob); - kex->done = 1; - kex->flags = buffer_get_int(m); - kex->client_version_string = buffer_get_string(m, NULL); - kex->server_version_string = buffer_get_string(m, NULL); - kex->load_host_key=&get_hostkey_by_type; - kex->host_key_index=&get_hostkey_index; - - return (kex); -} - -/* This function requries careful sanity checking */ - -void -mm_get_keystate(struct monitor *pmonitor) -{ - Buffer m; - u_char *blob, *p; - u_int bloblen, plen; - - debug3("%s: Waiting for new keys", __func__); - - buffer_init(&m); - mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); - if (!compat20) { - child_state.ssh1protoflags = buffer_get_int(&m); - child_state.ssh1cipher = buffer_get_int(&m); - child_state.ssh1key = buffer_get_string(&m, - &child_state.ssh1keylen); - child_state.ivout = buffer_get_string(&m, - &child_state.ivoutlen); - child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); - goto skip; - } else { - /* Get the Kex for rekeying */ - *pmonitor->m_pkex = mm_get_kex(&m); - } - - blob = buffer_get_string(&m, &bloblen); - current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); - xfree(blob); - - debug3("%s: Waiting for second key", __func__); - blob = buffer_get_string(&m, &bloblen); - current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); - xfree(blob); - - /* Now get sequence numbers for the packets */ - packet_set_seqnr(MODE_OUT, buffer_get_int(&m)); - packet_set_seqnr(MODE_IN, buffer_get_int(&m)); - - skip: - /* Get the key context */ - child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); - child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); - - debug3("%s: Getting compression state", __func__); - /* Get compression state */ - p = buffer_get_string(&m, &plen); - if (plen != sizeof(child_state.outgoing)) - fatal("%s: bad request size", __func__); - memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); - xfree(p); - - p = buffer_get_string(&m, &plen); - if (plen != sizeof(child_state.incoming)) - fatal("%s: bad request size", __func__); - memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); - xfree(p); - - /* Network I/O buffers */ - debug3("%s: Getting Network I/O buffers", __func__); - child_state.input = buffer_get_string(&m, &child_state.ilen); - child_state.output = buffer_get_string(&m, &child_state.olen); - - buffer_free(&m); -} - - -/* Allocation functions for zlib */ -void * -mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) -{ - size_t len = size * ncount; - void *address; - - if (len == 0 || ncount > SIZE_T_MAX / size) - fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); - - address = mm_malloc(mm, len); - - return (address); -} - -void -mm_zfree(struct mm_master *mm, void *address) -{ - mm_free(mm, address); -} - -void -mm_init_compression(struct mm_master *mm) -{ - outgoing_stream.zalloc = (alloc_func)mm_zalloc; - outgoing_stream.zfree = (free_func)mm_zfree; - outgoing_stream.opaque = mm; - - incoming_stream.zalloc = (alloc_func)mm_zalloc; - incoming_stream.zfree = (free_func)mm_zfree; - incoming_stream.opaque = mm; -} - -/* XXX */ - -#define FD_CLOSEONEXEC(x) do { \ - if (fcntl(x, F_SETFD, 1) == -1) \ - fatal("fcntl(%d, F_SETFD)", x); \ -} while (0) - -static void -monitor_socketpair(int *pair) -{ -#ifdef HAVE_SOCKETPAIR - if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) - fatal("%s: socketpair", __func__); -#else - fatal("%s: UsePrivilegeSeparation=yes not supported", - __func__); -#endif - FD_CLOSEONEXEC(pair[0]); - FD_CLOSEONEXEC(pair[1]); -} - -#define MM_MEMSIZE 65536 - -struct monitor * -monitor_init(void) -{ - struct monitor *mon; - int pair[2]; - - mon = xmalloc(sizeof(*mon)); - - monitor_socketpair(pair); - - mon->m_recvfd = pair[0]; - mon->m_sendfd = pair[1]; - - /* Used to share zlib space across processes */ - if (options.compression) { - mon->m_zback = mm_create(NULL, MM_MEMSIZE); - mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); - - /* Compression needs to share state across borders */ - mm_init_compression(mon->m_zlib); - } - - return mon; -} - -void -monitor_reinit(struct monitor *mon) -{ - int pair[2]; - - monitor_socketpair(pair); - - mon->m_recvfd = pair[0]; - mon->m_sendfd = pair[1]; -} - -#ifdef GSSAPI -int -mm_answer_gss_setup_ctx(int socket, Buffer *m) { - gss_OID_desc oid; - OM_uint32 major; - u_int len; - - oid.elements=buffer_get_string(m,&len); - oid.length=len; - - /* XXX */ - ssh_gssapi_build_ctx(&gsscontext, 0, GSS_C_NULL_OID); - - xfree(oid.elements); - - buffer_clear(m); - buffer_put_int(m,major); - - mm_request_send(socket,MONITOR_ANS_GSSSETUP,m); - - /* Now we have a context, enable the step and sign */ - monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP,1); - - return(0); -} - -int -mm_answer_gss_accept_ctx(int socket, Buffer *m) { - gss_buffer_desc in,out; - OM_uint32 major,minor; - OM_uint32 flags = 0; /* GSI needs this */ - - in.value = buffer_get_string(m,&in.length); - major=ssh_gssapi_accept_ctx(gsscontext, &in, &out); - xfree(in.value); - - buffer_clear(m); - buffer_put_int(m, major); - buffer_put_string(m, out.value, out.length); - buffer_put_int(m, flags); - mm_request_send(socket,MONITOR_ANS_GSSSTEP,m); - - gss_release_buffer(&minor, &out); - - /* Complete - now we can do signing */ - if (major==GSS_S_COMPLETE) { - monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP,0); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN,1); - } - return(0); -} - -int -mm_answer_gss_userok(int socket, Buffer *m) { - int authenticated; - - authenticated = authctxt->valid && - ssh_gssapi_userok(gsscontext, authctxt->user); - - buffer_clear(m); - buffer_put_int(m, authenticated); - - debug3("%s: sending result %d", __func__, authenticated); - mm_request_send(socket, MONITOR_ANS_GSSUSEROK, m); - - /* XXX - auth method could also be 'external' */ - auth_method="gssapi"; - - /* Monitor loop will terminate if authenticated */ - return(authenticated); -} - -int -mm_answer_gss_sign(int socket, Buffer *m) { - gss_buffer_desc data,hash; - OM_uint32 major,minor; - - data.value = buffer_get_string(m,&data.length); - if (data.length != 20) - fatal("%s: data length incorrect: %d", __func__, data.length); - - /* Save the session ID - only first time round */ - if (session_id2_len == 0) { - session_id2_len=data.length; - session_id2 = xmalloc(session_id2_len); - memcpy(session_id2, data.value, session_id2_len); - } - major=ssh_gssapi_get_mic(gsscontext, &data, &hash); - - xfree(data.value); - - buffer_clear(m); - buffer_put_int(m, major); - buffer_put_string(m, hash.value, hash.length); - - mm_request_send(socket,MONITOR_ANS_GSSSIGN,m); - - gss_release_buffer(&minor,&hash); - - /* Turn on permissions for getpwnam */ - monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); - - return(0); -} - -int -mm_answer_gss_error(int socket, Buffer *m) { - OM_uint32 major,minor; - char *msg; - - msg=ssh_gssapi_last_error(gsscontext,&major,&minor); - buffer_clear(m); - buffer_put_int(m,major); - buffer_put_int(m,minor); - buffer_put_cstring(m,msg); - - mm_request_send(socket,MONITOR_ANS_GSSERR,m); - - xfree(msg); - - return(0); -} - -int -mm_answer_gss_indicate_mechs(int socket, Buffer *m) { - OM_uint32 major,minor; - gss_OID_set mech_set; - int i; - - major=gss_indicate_mechs(&minor, &mech_set); - - buffer_clear(m); - buffer_put_int(m, major); - buffer_put_int(m, mech_set->count); - for (i=0; i < mech_set->count; i++) { - buffer_put_string(m, mech_set->elements[i].elements, - mech_set->elements[i].length); - } - - gss_release_oid_set(&minor,&mech_set); - - mm_request_send(socket,MONITOR_ANS_GSSMECHS,m); - - return(0); -} - -int -mm_answer_gss_localname(int socket, Buffer *m) { - char *name; - - name = ssh_gssapi_localname(gsscontext); - - buffer_clear(m); - if (name) { - buffer_put_cstring(m, name); - debug3("%s: sending result %s", __func__, name); - xfree(name); - } else { - buffer_put_cstring(m, ""); - debug3("%s: sending result \"\"", __func__); - } - - mm_request_send(socket, MONITOR_ANS_GSSLOCALNAME, m); - - return(0); -} -#endif /* GSSAPI */ -#endif /* lint */ diff --git a/usr/src/cmd/ssh/sshd/monitor_mm.c b/usr/src/cmd/ssh/sshd/monitor_mm.c deleted file mode 100644 index 04a82d28f8..0000000000 --- a/usr/src/cmd/ssh/sshd/monitor_mm.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * 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. - * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" -RCSID("$OpenBSD: monitor_mm.c,v 1.8 2002/08/02 14:43:15 millert Exp $"); - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - -#include "xmmap.h" -#include "ssh.h" -#include "xmalloc.h" -#include "log.h" -#include "monitor_mm.h" - -#ifndef lint - -static int -mm_compare(struct mm_share *a, struct mm_share *b) -{ - long diff = (char *)a->address - (char *)b->address; - - if (diff == 0) - return (0); - else if (diff < 0) - return (-1); - else - return (1); -} - -RB_GENERATE(mmtree, mm_share, next, mm_compare) - -static struct mm_share * -mm_make_entry(struct mm_master *mm, struct mmtree *head, - void *address, size_t size) -{ - struct mm_share *tmp, *tmp2; - - if (mm->mmalloc == NULL) - tmp = xmalloc(sizeof(struct mm_share)); - else - tmp = mm_xmalloc(mm->mmalloc, sizeof(struct mm_share)); - tmp->address = address; - tmp->size = size; - - tmp2 = RB_INSERT(mmtree, head, tmp); - if (tmp2 != NULL) - fatal("mm_make_entry(%p): double address %p->%p(%lu)", - mm, tmp2, address, (u_long)size); - - return (tmp); -} - -/* Creates a shared memory area of a certain size */ - -struct mm_master * -mm_create(struct mm_master *mmalloc, size_t size) -{ - void *address; - struct mm_master *mm; - - if (mmalloc == NULL) - mm = xmalloc(sizeof(struct mm_master)); - else - mm = mm_xmalloc(mmalloc, sizeof(struct mm_master)); - - /* - * If the memory map has a mm_master it can be completely - * shared including authentication between the child - * and the client. - */ - mm->mmalloc = mmalloc; - - address = xmmap(size); - if (address == MAP_FAILED) - fatal("mmap(%lu): %s", (u_long)size, strerror(errno)); - - mm->address = address; - mm->size = size; - - RB_INIT(&mm->rb_free); - RB_INIT(&mm->rb_allocated); - - mm_make_entry(mm, &mm->rb_free, address, size); - - return (mm); -} - -/* Frees either the allocated or the free list */ - -static void -mm_freelist(struct mm_master *mmalloc, struct mmtree *head) -{ - struct mm_share *mms, *next; - - for (mms = RB_ROOT(head); mms; mms = next) { - next = RB_NEXT(mmtree, head, mms); - RB_REMOVE(mmtree, head, mms); - if (mmalloc == NULL) - xfree(mms); - else - mm_free(mmalloc, mms); - } -} - -/* Destroys a memory mapped area */ - -void -mm_destroy(struct mm_master *mm) -{ - mm_freelist(mm->mmalloc, &mm->rb_free); - mm_freelist(mm->mmalloc, &mm->rb_allocated); - -#ifdef HAVE_MMAP - if (munmap(mm->address, mm->size) == -1) - fatal("munmap(%p, %lu): %s", mm->address, (u_long)mm->size, - strerror(errno)); -#else - fatal("%s: UsePrivilegeSeparation=yes and Compression=yes not supported", - __func__); -#endif - if (mm->mmalloc == NULL) - xfree(mm); - else - mm_free(mm->mmalloc, mm); -} - -void * -mm_xmalloc(struct mm_master *mm, size_t size) -{ - void *address; - - address = mm_malloc(mm, size); - if (address == NULL) - fatal("%s: mm_malloc(%lu)", __func__, (u_long)size); - return (address); -} - - -/* Allocates data from a memory mapped area */ - -void * -mm_malloc(struct mm_master *mm, size_t size) -{ - struct mm_share *mms, *tmp; - - if (size == 0) - fatal("mm_malloc: try to allocate 0 space"); - if (size > SIZE_T_MAX - MM_MINSIZE + 1) - fatal("mm_malloc: size too big"); - - size = ((size + (MM_MINSIZE - 1)) / MM_MINSIZE) * MM_MINSIZE; - - RB_FOREACH(mms, mmtree, &mm->rb_free) { - if (mms->size >= size) - break; - } - - if (mms == NULL) - return (NULL); - - /* Debug */ - memset(mms->address, 0xd0, size); - - tmp = mm_make_entry(mm, &mm->rb_allocated, mms->address, size); - - /* Does not change order in RB tree */ - mms->size -= size; - mms->address = (u_char *)mms->address + size; - - if (mms->size == 0) { - RB_REMOVE(mmtree, &mm->rb_free, mms); - if (mm->mmalloc == NULL) - xfree(mms); - else - mm_free(mm->mmalloc, mms); - } - - return (tmp->address); -} - -/* Frees memory in a memory mapped area */ - -void -mm_free(struct mm_master *mm, void *address) -{ - struct mm_share *mms, *prev, tmp; - - tmp.address = address; - mms = RB_FIND(mmtree, &mm->rb_allocated, &tmp); - if (mms == NULL) - fatal("mm_free(%p): can not find %p", mm, address); - - /* Debug */ - memset(mms->address, 0xd0, mms->size); - - /* Remove from allocated list and insert in free list */ - RB_REMOVE(mmtree, &mm->rb_allocated, mms); - if (RB_INSERT(mmtree, &mm->rb_free, mms) != NULL) - fatal("mm_free(%p): double address %p", mm, address); - - /* Find previous entry */ - prev = mms; - if (RB_LEFT(prev, next)) { - prev = RB_LEFT(prev, next); - while (RB_RIGHT(prev, next)) - prev = RB_RIGHT(prev, next); - } else { - if (RB_PARENT(prev, next) && - (prev == RB_RIGHT(RB_PARENT(prev, next), next))) - prev = RB_PARENT(prev, next); - else { - while (RB_PARENT(prev, next) && - (prev == RB_LEFT(RB_PARENT(prev, next), next))) - prev = RB_PARENT(prev, next); - prev = RB_PARENT(prev, next); - } - } - - /* Check if range does not overlap */ - if (prev != NULL && MM_ADDRESS_END(prev) > address) - fatal("mm_free: memory corruption: %p(%lu) > %p", - prev->address, (u_long)prev->size, address); - - /* See if we can merge backwards */ - if (prev != NULL && MM_ADDRESS_END(prev) == address) { - prev->size += mms->size; - RB_REMOVE(mmtree, &mm->rb_free, mms); - if (mm->mmalloc == NULL) - xfree(mms); - else - mm_free(mm->mmalloc, mms); - } else - prev = mms; - - if (prev == NULL) - return; - - /* Check if we can merge forwards */ - mms = RB_NEXT(mmtree, &mm->rb_free, prev); - if (mms == NULL) - return; - - if (MM_ADDRESS_END(prev) > mms->address) - fatal("mm_free: memory corruption: %p < %p(%lu)", - mms->address, prev->address, (u_long)prev->size); - if (MM_ADDRESS_END(prev) != mms->address) - return; - - prev->size += mms->size; - RB_REMOVE(mmtree, &mm->rb_free, mms); - - if (mm->mmalloc == NULL) - xfree(mms); - else - mm_free(mm->mmalloc, mms); -} - -static void -mm_sync_list(struct mmtree *oldtree, struct mmtree *newtree, - struct mm_master *mm, struct mm_master *mmold) -{ - struct mm_master *mmalloc = mm->mmalloc; - struct mm_share *mms, *new; - - /* Sync free list */ - RB_FOREACH(mms, mmtree, oldtree) { - /* Check the values */ - mm_memvalid(mmold, mms, sizeof(struct mm_share)); - mm_memvalid(mm, mms->address, mms->size); - - new = mm_xmalloc(mmalloc, sizeof(struct mm_share)); - memcpy(new, mms, sizeof(struct mm_share)); - RB_INSERT(mmtree, newtree, new); - } -} - -void -mm_share_sync(struct mm_master **pmm, struct mm_master **pmmalloc) -{ - struct mm_master *mm; - struct mm_master *mmalloc; - struct mm_master *mmold; - struct mmtree rb_free, rb_allocated; - - debug3("%s: Share sync", __func__); - - mm = *pmm; - mmold = mm->mmalloc; - mm_memvalid(mmold, mm, sizeof(*mm)); - - mmalloc = mm_create(NULL, mm->size); - mm = mm_xmalloc(mmalloc, sizeof(struct mm_master)); - memcpy(mm, *pmm, sizeof(struct mm_master)); - mm->mmalloc = mmalloc; - - rb_free = mm->rb_free; - rb_allocated = mm->rb_allocated; - - RB_INIT(&mm->rb_free); - RB_INIT(&mm->rb_allocated); - - mm_sync_list(&rb_free, &mm->rb_free, mm, mmold); - mm_sync_list(&rb_allocated, &mm->rb_allocated, mm, mmold); - - mm_destroy(mmold); - - *pmm = mm; - *pmmalloc = mmalloc; - - debug3("%s: Share sync end", __func__); -} - -void -mm_memvalid(struct mm_master *mm, void *address, size_t size) -{ - void *end = (u_char *)address + size; - - if (address < mm->address) - fatal("mm_memvalid: address too small: %p", address); - if (end < address) - fatal("mm_memvalid: end < address: %p < %p", end, address); - if (end > (void *)((u_char *)mm->address + mm->size)) - fatal("mm_memvalid: address too large: %p", address); -} -#endif /* lint */ diff --git a/usr/src/cmd/ssh/sshd/servconf.c b/usr/src/cmd/ssh/sshd/servconf.c index 863a75af74..6f2cdbdc84 100644 --- a/usr/src/cmd/ssh/sshd/servconf.c +++ b/usr/src/cmd/ssh/sshd/servconf.c @@ -56,8 +56,6 @@ static void add_one_listen_addr(ServerOptions *, char *, u_short); /* AF_UNSPEC or AF_INET or AF_INET6 */ extern int IPv4or6; -/* Use of privilege separation or not */ -extern int use_privsep; /* Initializes the server options to their default values. */ @@ -149,9 +147,6 @@ initialize_server_options(ServerOptions *options) options->max_init_auth_tries_log = -1; options->lookup_client_hostnames = -1; - - /* Needs to be accessable in many places */ - use_privsep = -1; } #ifdef HAVE_DEFOPEN @@ -380,21 +375,6 @@ fill_default_server_options(ServerOptions *options) if (options->lookup_client_hostnames == -1) options->lookup_client_hostnames = 1; - - /* XXX SUNWssh resync */ - /* Turn privilege separation OFF by default */ - if (use_privsep == -1) - use_privsep = 0; - -#ifndef HAVE_MMAP - if (use_privsep && options->compression == 1) { - error("This platform does not support both privilege " - "separation and compression"); - error("Compression disabled"); - options->compression = 0; - } -#endif - } /* Keyword tokens. */ @@ -939,8 +919,11 @@ parse_flag: goto parse_flag; case sUsePrivilegeSeparation: - intptr = &use_privsep; - goto parse_flag; + log("%s line %d: ignoring UsePrivilegeSeparation option value." + " This option is always on.", filename, linenum); + while (arg) + arg = strdelim(&cp); + break; case sAllowUsers: while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { diff --git a/usr/src/cmd/ssh/sshd/serverloop.c b/usr/src/cmd/ssh/sshd/serverloop.c index a720fae405..e7e7711f81 100644 --- a/usr/src/cmd/ssh/sshd/serverloop.c +++ b/usr/src/cmd/ssh/sshd/serverloop.c @@ -953,8 +953,14 @@ server_loop2(Authctxt *authctxt) collect_children(); - if (!rekeying) + if (!rekeying) { channel_after_select(readset, writeset); + if (packet_need_rekeying()) { + debug("need rekeying"); + xxx_kex->done = 0; + kex_send_kexinit(xxx_kex); + } + } #ifdef ALTPRIVSEP else altprivsep_process_input(xxx_kex, readset); @@ -991,7 +997,6 @@ server_input_channel_failure(int type, u_int32_t seq, void *ctxt) client_alive_timeouts = 0; } - static void server_input_stdin_data(int type, u_int32_t seq, void *ctxt) { diff --git a/usr/src/cmd/ssh/sshd/session.c b/usr/src/cmd/ssh/sshd/session.c index d85558a44e..04b1c1f7e0 100644 --- a/usr/src/cmd/ssh/sshd/session.c +++ b/usr/src/cmd/ssh/sshd/session.c @@ -71,7 +71,6 @@ RCSID("$OpenBSD: session.c,v 1.150 2002/09/16 19:55:33 stevesk Exp $"); #include "serverloop.h" #include "canohost.h" #include "session.h" -#include "monitor_wrap.h" #ifdef USE_PAM #include <security/pam_appl.h> @@ -786,11 +785,6 @@ do_login(Session *s, const char *command) #ifdef ALTPRIVSEP debug3("Recording SSHv2 channel login in utmpx/wtmpx"); altprivsep_record_login(pid, s->tty); -#else /* ALTPRIVSEP*/ - if (!use_privsep) { - debug3("Recording SSHv2 channel login in utmpx/wtmpx"); - record_login(pid, s->tty, NULL, pw->pw_name); - } #endif /* ALTPRIVSEP*/ if (check_quietlogin(s, command)) @@ -1776,7 +1770,7 @@ session_pty_req(Session *s) /* Allocate a pty and open it. */ debug("Allocating pty."); - if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) { + if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) { if (s->term) xfree(s->term); s->term = NULL; @@ -1797,8 +1791,7 @@ session_pty_req(Session *s) * time in case we call fatal() (e.g., the connection gets closed). */ fatal_add_cleanup(session_pty_cleanup, (void *)s); - if (!use_privsep) - pty_setowner(s->pw, s->tty); + pty_setowner(s->pw, s->tty); /* Set window size from the packet. */ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); @@ -2164,8 +2157,6 @@ session_pty_cleanup2(void *session) debug3("Recording SSHv2 channel login in utmpx/wtmpx"); #ifdef ALTPRIVSEP altprivsep_record_logout(s->pid); -#else /* ALTPRIVSEP */ - record_logout(s->pid, s->tty, NULL, s->pw->pw_name); #endif /* ALTPRIVSEP */ } @@ -2188,7 +2179,7 @@ session_pty_cleanup2(void *session) void session_pty_cleanup(void *session) { - PRIVSEP(session_pty_cleanup2(session)); + session_pty_cleanup2(session); } /* diff --git a/usr/src/cmd/ssh/sshd/sshd.c b/usr/src/cmd/ssh/sshd/sshd.c index 03e81f71e9..199f12ec31 100644 --- a/usr/src/cmd/ssh/sshd/sshd.c +++ b/usr/src/cmd/ssh/sshd/sshd.c @@ -87,10 +87,6 @@ RCSID("$OpenBSD: sshd.c,v 1.260 2002/09/27 10:42:09 mickey Exp $"); #include "dispatch.h" #include "channels.h" #include "session.h" -#include "monitor_mm.h" -#include "monitor.h" -#include "monitor_wrap.h" -#include "monitor_fdpass.h" #include "g11n.h" #include "sshlogin.h" #include "xlist.h" @@ -234,10 +230,6 @@ u_int utmp_len = MAXHOSTNAMELEN; static int *startup_pipes = NULL; static int startup_pipe = -1; /* in child */ -/* variables used for privilege separation */ -extern struct monitor *pmonitor; -extern int use_privsep; - #ifdef GSSAPI static gss_OID_set mechs = GSS_C_NULL_OID_SET; #endif /* GSSAPI */ @@ -697,155 +689,6 @@ demote_sensitive_data(void) /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ } -static void -privsep_preauth_child(void) -{ - u_int32_t rnd[256]; - gid_t gidset[1]; - struct passwd *pw; - int i; - - /* Enable challenge-response authentication for privilege separation */ - privsep_challenge_enable(); - - for (i = 0; i < 256; i++) - rnd[i] = arc4random(); - RAND_seed(rnd, sizeof(rnd)); - - /* Demote the private keys to public keys. */ - demote_sensitive_data(); - - if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) - fatal("Privilege separation user %s does not exist", - SSH_PRIVSEP_USER); - (void) memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); - endpwent(); - - /* Change our root directory */ - if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) - fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, - strerror(errno)); - if (chdir("/") == -1) - fatal("chdir(\"/\"): %s", strerror(errno)); - - /* Drop our privileges */ - debug3("privsep user:group %u:%u", (u_int)pw->pw_uid, - (u_int)pw->pw_gid); -#if 0 - /* XXX not ready, to heavy after chroot */ - do_setusercontext(pw); -#else - gidset[0] = pw->pw_gid; - if (setgid(pw->pw_gid) < 0) - fatal("setgid failed for %u", pw->pw_gid); - if (setgroups(1, gidset) < 0) - fatal("setgroups: %.100s", strerror(errno)); - permanently_set_uid(pw); -#endif -} - -static Authctxt * -privsep_preauth(void) -{ - Authctxt *authctxt = NULL; - int status; - pid_t pid; - - /* Set up unprivileged child process to deal with network data */ - pmonitor = monitor_init(); - /* Store a pointer to the kex for later rekeying */ - pmonitor->m_pkex = &xxx_kex; - - pid = fork(); - if (pid == -1) { - fatal("fork of unprivileged child failed"); - } else if (pid != 0) { - fatal_remove_cleanup((void (*) (void *)) packet_close, NULL); - - debug2("Network child is on pid %ld", (long)pid); - - (void) close(pmonitor->m_recvfd); - authctxt = monitor_child_preauth(pmonitor); - (void) close(pmonitor->m_sendfd); - - /* Sync memory */ - monitor_sync(pmonitor); - - /* Wait for the child's exit status */ - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - break; - - /* Reinstall, since the child has finished */ - fatal_add_cleanup((void (*) (void *)) packet_close, NULL); - - return (authctxt); - } else { - /* child */ - - (void) close(pmonitor->m_sendfd); - - /* Demote the child */ - if (getuid() == 0 || geteuid() == 0) - privsep_preauth_child(); - setproctitle("%s", "[net]"); - } - return (NULL); -} - -static void -privsep_postauth(Authctxt *authctxt) -{ - extern Authctxt *x_authctxt; - - /* XXX - Remote port forwarding */ - x_authctxt = authctxt; - -#ifdef DISABLE_FD_PASSING - if (1) { -#else - if (authctxt->pw->pw_uid == 0 || options.use_login) { -#endif - /* File descriptor passing is broken or root login */ - monitor_apply_keystate(pmonitor); - use_privsep = 0; - return; - } - - if (startup_pipe != -1) { - (void) close(startup_pipe); - startup_pipe = -1; - } - - /* New socket pair */ - monitor_reinit(pmonitor); - - pmonitor->m_pid = fork(); - if (pmonitor->m_pid == -1) - fatal("fork of unprivileged child failed"); - else if (pmonitor->m_pid != 0) { - fatal_remove_cleanup((void (*) (void *)) packet_close, NULL); - - debug2("User child is on pid %ld", (long)pmonitor->m_pid); - (void) close(pmonitor->m_recvfd); - monitor_child_postauth(pmonitor); - - /* NEVERREACHED */ - exit(0); - } - - (void) close(pmonitor->m_sendfd); - - /* Demote the private keys to public keys. */ - demote_sensitive_data(); - - /* Drop privileges */ - do_setusercontext(authctxt->pw); - - /* It is safe now to apply the key state */ - monitor_apply_keystate(pmonitor); -} - static char * list_hostkey_types(void) { @@ -1240,28 +1083,6 @@ main(int ac, char **av) } } - if (use_privsep) { - struct stat st; - - if (getpwnam(SSH_PRIVSEP_USER) == NULL) - fatal("Privilege separation user %s does not exist", - SSH_PRIVSEP_USER); - if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || - (S_ISDIR(st.st_mode) == 0)) - fatal("Missing privilege separation directory: %s", - _PATH_PRIVSEP_CHROOT_DIR); - -#ifdef HAVE_CYGWIN - if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) && - (st.st_uid != getuid () || - (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)) -#else - if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0) -#endif - fatal("Bad owner or mode for %s", - _PATH_PRIVSEP_CHROOT_DIR); - } - /* Configuration looks good, so exit if in test mode. */ if (test_flag) exit(0); @@ -1565,6 +1386,7 @@ main(int ac, char **av) #ifdef HAVE_SOLARIS_CONTRACTS contracts_post_fork_child(); #endif /* HAVE_SOLARIS_CONTRACTS */ + xfree(fdset); startup_pipe = startup_p[1]; close_startup_pipes(); close_listen_socks(); @@ -1714,10 +1536,6 @@ main(int ac, char **av) packet_set_nonblocking(); - if (use_privsep) - if ((authctxt = privsep_preauth()) != NULL) - goto authenticated; - /* perform the key exchange */ /* authenticate user and start session */ if (compat20) { @@ -1728,15 +1546,6 @@ main(int ac, char **av) authctxt = do_authentication(); } - /* - * If we use privilege separation, the unprivileged child transfers - * the current keystate and exits - */ - if (use_privsep) { - mm_send_keystate(pmonitor); - exit(0); - } - authenticated: /* Authentication complete */ (void) alarm(0); @@ -1746,17 +1555,6 @@ authenticated: startup_pipe = -1; } - /* - * In privilege separation, we fork another child and prepare - * file descriptor passing. - */ - if (use_privsep) { - privsep_postauth(authctxt); - /* the monitor process [priv] will not return */ - if (!compat20) - destroy_sensitive_data(); - } - #ifdef ALTPRIVSEP if ((aps_child = altprivsep_start_monitor(authctxt)) == -1) fatal("Monitor could not be started."); @@ -1781,7 +1579,7 @@ authenticated: * * NOTE: Order matters -- these fatal cleanups must come before * the audit logout fatal cleanup as these functions are called - * in in LIFO. + * in LIFO. * * NOTE: The monitor will packet_close(), which will close * "newsock," so we dup() it. @@ -1893,70 +1691,6 @@ authenticated: /* NOTREACHED */ } - -#else /* ALTPRIVSEP */ - - if (compat20) { - debug3("Recording SSHv2 session login in wtmpx"); - record_login(getpid(), NULL, "sshd", authctxt->user); - } - -#ifdef HAVE_BSM - fatal_remove_cleanup( - (void (*)(void *))audit_failed_login_cleanup, - (void *)authctxt); - - /* Initialize the group list, audit sometimes needs it. */ - if (initgroups(authctxt->pw->pw_name, authctxt->pw->pw_gid) < 0) { - perror("initgroups"); - exit (1); - } - audit_sshd_login(&ah, authctxt->pw->pw_uid, - authctxt->pw->pw_gid); - - fatal_add_cleanup((void (*)(void *))audit_sshd_logout, - (void *)&ah); -#endif /* HAVE_BSM */ - -#ifdef GSSAPI - fatal_add_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds, - (void *)&xxx_gssctxt); -#endif /* GSSAPI */ - - /* Perform session preparation. */ - do_authenticated(authctxt); - - /* XXX - Add PRIVSEP() macro */ - if (compat20) { - debug3("Recording SSHv2 session logout in wtmpx"); - record_logout(getpid(), NULL, "sshd", authctxt->user); - } - -#ifdef GSSAPI - fatal_remove_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds, - &xxx_gssctxt); - ssh_gssapi_cleanup_creds(xxx_gssctxt); - ssh_gssapi_server_mechs(NULL); /* release cached server mechs */ -#endif /* GSSAPI */ - -#ifdef HAVE_BSM - fatal_remove_cleanup((void (*)(void *))audit_sshd_logout, (void *)&ah); - audit_sshd_logout(&ah); -#endif /* HAVE_BSM */ - -#ifdef USE_PAM - finish_pam(authctxt); -#endif /* USE_PAM */ - - /* The connection has been terminated. */ - verbose("Closing connection to %.100s", remote_ip); - - packet_close(); - - if (use_privsep) - mm_terminate(); - - return (0); #endif /* ALTPRIVSEP */ } @@ -2123,7 +1857,7 @@ do_ssh1_kex(void) packet_check_eom(); /* Decrypt session_key_int using host/server keys */ - rsafail = PRIVSEP(ssh1_session_key(session_key_int)); + rsafail = ssh1_session_key(session_key_int); /* * Extract session key from the decrypted integer. The key is in the @@ -2178,9 +1912,6 @@ do_ssh1_kex(void) /* Destroy the private and public keys. No longer. */ destroy_sensitive_data(); - if (use_privsep) - mm_ssh1_session_id(session_id); - /* Destroy the decrypted integer. It is no longer needed. */ BN_clear_free(session_key_int); @@ -2249,6 +1980,9 @@ do_ssh2_kex(void) g11n_locales2langs(locales); } + if (locales != NULL) + g11n_freelist(locales); + if ((myproposal[PROPOSAL_LANG_STOC] != NULL) || (strcmp(myproposal[PROPOSAL_LANG_STOC], "")) != 0) myproposal[PROPOSAL_LANG_CTOS] = @@ -2261,6 +1995,12 @@ do_ssh2_kex(void) /* start key exchange */ kex = kex_setup(NULL, myproposal, kex_hook); + + if (myproposal[PROPOSAL_LANG_STOC] != NULL) + xfree(myproposal[PROPOSAL_LANG_STOC]); + if (myproposal[PROPOSAL_LANG_CTOS] != NULL) + xfree(myproposal[PROPOSAL_LANG_CTOS]); + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; #ifdef GSSAPI |