diff -ruN openssh-5.6p1/auth2-hostbased.c openssh-5.6p1+x509-6.2.3/auth2-hostbased.c --- openssh-5.6p1/auth2-hostbased.c 2010-08-05 06:04:50.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/auth2-hostbased.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.14 2010/08/04 05:42:47 djm Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -53,6 +53,8 @@ extern u_char *session_id2; extern u_int session_id2_len; +static int hostbased_algorithm_allowed(int pktype); + static int userauth_hostbased(Authctxt *authctxt) { @@ -90,6 +92,11 @@ "public key algorithm: %s", pkalg); goto done; } + if (!hostbased_algorithm_allowed(pktype)) { + debug("userauth_hostbased: disallowed " + "public key algorithm: %s", pkalg); + goto done; + } key = key_from_blob(pkblob, blen); if (key == NULL) { error("userauth_hostbased: cannot decode key: %s", pkalg); @@ -136,6 +143,28 @@ return authenticated; } +/* return 1 if given hostbased algorithm is allowed */ +static int +hostbased_algorithm_allowed(int pktype) +{ + char *s, *cp, *p; + + if (options.hostbased_algorithms == NULL) return(1); + + s = cp = xstrdup(options.hostbased_algorithms); + for (p = strsep(&cp, ","); + p && *p != '\0'; + p = strsep(&cp, ",") + ) { + if (pktype == key_type_from_name(p)) { + xfree(s); + return(1); + } + } + xfree(s); + return(0); +} + /* return 1 if given hostkey is allowed */ int hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, diff -ruN openssh-5.6p1/auth2-pubkey.c openssh-5.6p1+x509-6.2.3/auth2-pubkey.c --- openssh-5.6p1/auth2-pubkey.c 2010-07-02 06:35:19.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/auth2-pubkey.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.26 2010/06/29 23:16:46 djm Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -55,6 +55,7 @@ #include "ssh-gss.h" #endif #include "monitor_wrap.h" +#include "ssh-x509.h" #include "misc.h" #include "authfile.h" #include "match.h" @@ -64,6 +65,8 @@ extern u_char *session_id2; extern u_int session_id2_len; +static int pubkey_algorithm_allowed(int pktype); + static int userauth_pubkey(Authctxt *authctxt) { @@ -100,6 +103,11 @@ pkalg); goto done; } + if (!pubkey_algorithm_allowed(pktype)) { + debug("userauth_pubkey: disallowed public key algorithm: %s", + pkalg); + goto done; + } key = key_from_blob(pkblob, blen); if (key == NULL) { error("userauth_pubkey: cannot decode key: %s", pkalg); @@ -254,6 +262,121 @@ return 0; } +/* return 1 if given publickey algorithm is allowed */ +static int +pubkey_algorithm_allowed(int pktype) +{ + char *s, *cp, *p; + + if (options.pubkey_algorithms == NULL) return(1); + + s = cp = xstrdup(options.pubkey_algorithms); + for (p = strsep(&cp, ","); + p && *p != '\0'; + p = strsep(&cp, ",") + ) { + if (pktype == key_type_from_name(p)) { + xfree(s); + return(1); + } + } + xfree(s); + return(0); +} + +static int +key_readx(Key *ret, char **cpp) { + int flag; + + flag = key_read(ret, cpp); + if (flag == 1) return(1); + + switch (ret->type) { + case KEY_X509_RSA: + debug3("pubkey key_readx(RSA)"); + ret->type = KEY_RSA; + flag = key_read(ret, cpp); + break; + case KEY_X509_DSA: + debug3("pubkey key_readx(DSA)"); + ret->type = KEY_DSA; + flag = key_read(ret, cpp); + break; + } + return(flag); +} + +static int +key_match(const Key *key, const Key *found) { + if (key == NULL || found == NULL) + return(0); + + if (key->type == found->type) { +#ifdef SSH_X509STORE_DISABLED + return(key_equal(key, found)); +#else /*ndef SSH_X509STORE_DISABLED*/ + if (!key_equal(key, found)) + return(0); + + /* + * Key are equal but in case of certificates + * when x509store is enabled found key may + * contain only distinguished name. + */ + if ((found->type != KEY_X509_RSA) && + (found->type != KEY_X509_DSA)) + return(1); + + debug3("key_match:found matching certificate"); + if (!ssh_x509flags.key_allow_selfissued) { + /* + * Only the verification process can + * allow the received certificate. + */ + return(1); + } + + /* + * The public key or certificate found in + * autorized keys file can allow self-issued. + */ + if (!ssh_is_selfsigned(key->x509)) + return(1); + + debug3("key_match:self-signed certificate"); + ssh_x509flags.key_allow_selfissued = 0; + if (ssh_x509cert_check(key->x509) == 1) { + /* the certificated is trusted by x509store */ + ssh_x509flags.key_allow_selfissued = 1; + return(1); + } + ssh_x509flags.key_allow_selfissued = 1; + + /* the certificate can be allowed by public key */ +#endif /*ndef SSH_X509STORE_DISABLED*/ + } + + if ((key->type == KEY_X509_RSA) && + ((found->type == KEY_RSA) || (found->type == KEY_X509_RSA)) + ) { + debug3("key_match:RSA"); + return(key->rsa != NULL && found->rsa != NULL && + BN_cmp(key->rsa->e, found->rsa->e) == 0 && + BN_cmp(key->rsa->n, found->rsa->n) == 0); + } + if ((key->type == KEY_X509_DSA) && + ((found->type == KEY_DSA) || (found->type == KEY_X509_DSA)) + ) { + debug3("key_match:DSA"); + return(key->dsa != NULL && found->dsa != NULL && + BN_cmp(key->dsa->p, found->dsa->p) == 0 && + BN_cmp(key->dsa->q, found->dsa->q) == 0 && + BN_cmp(key->dsa->g, found->dsa->g) == 0 && + BN_cmp(key->dsa->pub_key, found->dsa->pub_key) == 0); + } + return(0); +} + /* return 1 if user allows given key */ static int user_key_allowed2(struct passwd *pw, Key *key, char *file) @@ -291,7 +414,8 @@ if (!*cp || *cp == '\n' || *cp == '#') continue; - if (key_read(found, &cp) != 1) { + found->type = key->type; + if (key_readx(found, &cp) != 1) { /* no key? check if there are options for this key */ int quoted = 0; debug2("user_key_allowed: check options: '%s'", cp); @@ -305,7 +429,8 @@ /* Skip remaining whitespace. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; - if (key_read(found, &cp) != 1) { + found->type = key_is_cert(key) ? KEY_UNSPEC : key->type; + if (key_readx(found, &cp) != 1) { debug2("user_key_allowed: advance: '%s'", cp); /* still no key? advance to next line*/ continue; @@ -353,7 +478,7 @@ xfree(fp); found_key = 1; break; - } else if (key_equal(found, key)) { + } else if (key_match(key, found)) { if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; @@ -362,9 +487,21 @@ found_key = 1; debug("matching key found: file %s, line %lu", file, linenum); - fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + /* Variable key always contain public key or + * certificate. In case of X.509 certificate + * x509 attribute of Key structure "found" + * can contain only "Distinguished Name" ! + */ + fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); verbose("Found matching %s key: %s", key_type(found), fp); + if ((key->type == KEY_X509_RSA) || + (key->type == KEY_X509_DSA)) { + if (ssh_x509cert_check(key->x509) != 1) { + found_key = 0; + verbose("x509 certificate check reject matching key"); + } + } xfree(fp); break; } diff -ruN openssh-5.6p1/authfd.c openssh-5.6p1+x509-6.2.3/authfd.c --- openssh-5.6p1/authfd.c 2010-04-16 08:56:22.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/authfd.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.83 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -13,6 +13,8 @@ * * SSH2 implementation, * Copyright (c) 2000 Markus Friedl. All rights reserved. + * X509 certificate support, + * Copyright (c) 2002 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -476,6 +478,7 @@ buffer_put_cstring(b, key_ssh_name(key)); switch (key->type) { case KEY_RSA: + case KEY_X509_RSA: buffer_put_bignum2(b, key->rsa->n); buffer_put_bignum2(b, key->rsa->e); buffer_put_bignum2(b, key->rsa->d); @@ -495,6 +498,7 @@ buffer_put_bignum2(b, key->rsa->q); break; case KEY_DSA: + case KEY_X509_DSA: buffer_put_bignum2(b, key->dsa->p); buffer_put_bignum2(b, key->dsa->q); buffer_put_bignum2(b, key->dsa->g); @@ -510,6 +514,21 @@ buffer_put_bignum2(b, key->dsa->priv_key); break; } + if ((key->type == KEY_X509_RSA) || (key->type == KEY_X509_DSA)) { + int len; + void* str; + unsigned char *p; + + len = i2d_X509(key->x509, NULL); + str = xmalloc(len); + if (str == NULL) + { error("ssh_encode_identity_ssh2: out of memory"); return; } + + p = str; + i2d_X509(key->x509, &p); + buffer_put_string(b, str, len); + xfree(str); + } buffer_put_cstring(b, comment); } @@ -541,6 +560,8 @@ case KEY_DSA: case KEY_DSA_CERT: case KEY_DSA_CERT_V00: + case KEY_X509_RSA: + case KEY_X509_DSA: type = constrained ? SSH2_AGENTC_ADD_ID_CONSTRAINED : SSH2_AGENTC_ADD_IDENTITY; @@ -589,7 +610,9 @@ buffer_put_bignum(&msg, key->rsa->e); buffer_put_bignum(&msg, key->rsa->n); } else if (key_type_plain(key->type) == KEY_DSA || - key_type_plain(key->type) == KEY_RSA) { + key->type == KEY_X509_RSA || + key->type == KEY_X509_DSA || + key_type_plain(key->type) == KEY_RSA ) { key_to_blob(key, &blob, &blen); buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); buffer_put_string(&msg, blob, blen); diff -ruN openssh-5.6p1/authfile.c openssh-5.6p1+x509-6.2.3/authfile.c --- openssh-5.6p1/authfile.c 2010-08-05 06:05:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/authfile.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.c,v 1.82 2010/08/04 05:49:22 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -14,6 +14,8 @@ * * * Copyright (c) 2000 Markus Friedl. All rights reserved. + * X509 certificate support, + * Copyright (c) 2002-2006 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -66,6 +68,7 @@ #include "log.h" #include "authfile.h" #include "rsa.h" +#include "ssh-x509.h" #include "misc.h" #include "atomicio.h" @@ -217,6 +220,10 @@ success = PEM_write_RSAPrivateKey(fp, key->rsa, cipher, passphrase, len, NULL, NULL); break; + case KEY_X509_RSA: + case KEY_X509_DSA: + success = x509key_save_pem(fp, key, cipher, passphrase, len); + break; } fclose(fp); return success; @@ -232,6 +239,8 @@ comment); case KEY_DSA: case KEY_RSA: + case KEY_X509_RSA: + case KEY_X509_DSA: return key_save_private_pem(key, filename, passphrase, comment); default: @@ -477,6 +486,7 @@ Key *prv = NULL; char *name = ""; + debug("read PEM private key begin"); fp = fdopen(fd, "r"); if (fp == NULL) { error("fdopen failed: %s", strerror(errno)); @@ -514,6 +524,17 @@ error("PEM_read_PrivateKey: mismatch or " "unknown EVP_PKEY save_type %d", pk->save_type); } + if (prv) { + debug("read X.509 certificate begin"); + /* if we use lseek on some gnu libc versions stream will be not synchronized */ + fseek(fp, (off_t) 0, SEEK_SET); /* rewind */ + x509key_load_cert(prv, fp); + if (prv->x509 != NULL) { + if (!X509_check_private_key(prv->x509, pk)) { + fatal("X509 certificate don't match private key"); + } + } + } fclose(fp); if (pk != NULL) EVP_PKEY_free(pk); @@ -671,6 +692,7 @@ char file[MAXPATHLEN]; /* try rsa1 private key */ + debug3("key_load_public(%.200s,...)", filename); pub = key_load_public_type(KEY_RSA1, filename, commentp); if (pub != NULL) return pub; diff -ruN openssh-5.6p1/config.h.in openssh-5.6p1+x509-6.2.3/config.h.in --- openssh-5.6p1/config.h.in 2010-08-23 06:21:20.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/config.h.in 2010-08-24 09:06:01.000000000 +0300 @@ -323,6 +323,18 @@ /* Define if your system has /etc/default/login */ #undef HAVE_ETC_DEFAULT_LOGIN +/* Define to 1 if `cleanup' is member of `EVP_MD'. */ +#undef HAVE_EVP_MD_CLEANUP + +/* Define to 1 if `copy' is member of `EVP_MD'. */ +#undef HAVE_EVP_MD_COPY + +/* Define to 1 if `md_data' is member of `EVP_MD_CTX'. */ +#undef HAVE_EVP_MD_CTX_MD_DATA + +/* Define to 1 if `flags' is member of `EVP_MD'. */ +#undef HAVE_EVP_MD_FLAGS + /* Define to 1 if you have the `EVP_sha256' function. */ #undef HAVE_EVP_SHA256 @@ -536,6 +548,24 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LASTLOG_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LBER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LDAP_H + +/* Define to 1 if you have the `ldap_initialize' function. */ +#undef HAVE_LDAP_INITIALIZE + +/* Define to 1 if you have the `ldap_parse_result' function. */ +#undef HAVE_LDAP_PARSE_RESULT + +/* Define to 1 if you have the `ldap_sasl_bind_s' function. */ +#undef HAVE_LDAP_SASL_BIND_S + +/* Define to 1 if you have the `ldap_search_ext_s' function. */ +#undef HAVE_LDAP_SEARCH_EXT_S + /* Define to 1 if you have the `bsm' library (-lbsm). */ #undef HAVE_LIBBSM @@ -650,6 +680,9 @@ /* Define to 1 if you have the `nsleep' function. */ #undef HAVE_NSLEEP +/* Define to 1 if you have the `OCSP_sendreq_bio' function. */ +#undef HAVE_OCSP_SENDREQ_BIO + /* Define to 1 if you have the `ogetaddrinfo' function. */ #undef HAVE_OGETADDRINFO @@ -1143,6 +1176,9 @@ /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID +/* Define to 1 if `param' is member of `X509_STORE_CTX'. */ +#undef HAVE_X509_STORE_CTX_PARAM + /* Define to 1 if you have the `_getlong' function. */ #undef HAVE__GETLONG @@ -1194,6 +1230,9 @@ /* Define if pututxline updates lastlog too */ #undef LASTLOG_WRITE_PUTUTXLINE +/* Define if you want to enable LDAP queries */ +#undef LDAP_ENABLED + /* Define if you want TCP Wrappers support */ #undef LIBWRAP @@ -1330,6 +1369,9 @@ bsd-setproctitle.c */ #undef SPT_TYPE +/* Specify location of ssh CA root */ +#undef SSHCADIR + /* Define if sshd somehow reacquires a controlling TTY after setsid() */ #undef SSHD_ACQUIRES_CTTY @@ -1342,6 +1384,13 @@ /* Windows is sensitive to read buffer size */ #undef SSH_IOBUFSZ +/* Define if you don't want to validate X.509 certificates with OCSP */ +#undef SSH_OCSP_ENABLED + +/* Define if your openssl library don't support Email in X.509 'Distinguished + Name' */ +#undef SSH_OPENSSL_DN_WITHOUT_EMAIL + /* non-privileged user for privilege separation */ #undef SSH_PRIVSEP_USER @@ -1363,6 +1412,9 @@ /* Prepend the address family to IP tunnel traffic */ #undef SSH_TUN_PREPEND_AF +/* Define if you don't want to verify certificates */ +#undef SSH_X509STORE_DISABLED + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff -ruN openssh-5.6p1/configure openssh-5.6p1+x509-6.2.3/configure --- openssh-5.6p1/configure 2010-08-23 06:21:22.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/configure 2010-08-24 09:06:02.000000000 +0300 @@ -723,6 +723,17 @@ MANTYPE mansubdir user_path +sshcadir +OCSP_ON +OCSP_OFF +LDAP_BINDIR +LDAP_LIBEXECDIR +LDAP_SYSCONFDIR +LDAP_LDFLAGS +LDAP_CPPFLAGS +LDAP_LIBS +LDAP_ON +LDAP_OFF piddir TEST_SSH_IPV6 LIBOBJS @@ -1314,6 +1325,9 @@ --disable-largefile omit support for large files --disable-strip Disable calling strip(1) on install --disable-etc-default-login Disable using PATH from /etc/default/login no + --disable-x509store Disable X.509 store + --disable-ocsp Disable OCSP validation + --enable-ldap Enable LDAP queries --disable-lastlog disable use of lastlog even if detected no --disable-utmp disable use of utmp even if detected no --disable-utmpx disable use of utmpx even if detected no @@ -1362,6 +1376,15 @@ --with-superuser-path= Specify different path for super-user --with-4in6 Check for and convert IPv4 in IPv6 mapped addresses --with-bsd-auth Enable BSD auth support + --with-sshca-dir=PATH Specify location of ssh CA root + --with-ldap-prefix=PATH Prefix where LDAP is installed (optional) + --with-ldap-bindir=PATH Prefix where LDAP user executables are installed (optional) + --with-ldap-libexecdir=PATH Prefix where LDAP program executables are installed (optional) + --with-ldap-sysconfdir=PATH Prefix where LDAP single-machine data are installed (optional) + --with-ldap-libdir=PATH Prefix where LDAP libaries are installed (optional) + --with-ldap-includedir=PATH Prefix where LDAP header files are installed (optional) + --with-ldap-libs=LIBS Specify LDAP libraries to link with. + (default is -lldap -llber -lssl -lcrypto) --with-pid-dir=PATH Specify location of ssh.pid file --with-lastlog=FILE|DIR specify lastlog location common locations @@ -1808,6 +1831,19 @@ +# Options to build with LDAP +# +# Author: Roumen Petrov +# Revision: 22 Oct 2007 +# + + + + +# AC_LDAP_FUNCS(FUNCTION...) +# -------------------------------- + + ac_config_headers="$ac_config_headers config.h" @@ -29070,27 +29106,27 @@ fi -# Where to place sshd.pid -piddir=/var/run -# make sure the directory exists -if test ! -d $piddir ; then - piddir=`eval echo ${sysconfdir}` - case $piddir in - NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;; - esac -fi +# X.509 support +ssh_x509="yes" +# Reserved for future use +#AC_DEFINE_UNQUOTED( +# X509_DISABLED, 1, +# [Define if you want to disable X.509 certificates]) + +# Where to place ssh CA root +sshcadir='${sysconfdir}/ca' +sshcadir=`eval echo ${sshcadir}` +sshcadir=`eval echo ${sshcadir}` +case $sshcadir in + NONE/*) sshcadir=`echo $sshcadir | sed "s~NONE~$ac_default_prefix~"` ;; +esac -# Check whether --with-pid-dir was given. -if test "${with_pid_dir+set}" = set; then - withval=$with_pid_dir; - if test -n "$withval" && test "x$withval" != "xno" && \ - test "x${withval}" != "xyes"; then - piddir=$withval - if test ! -d $piddir ; then - { echo "$as_me:$LINENO: WARNING: ** no $piddir directory on this system **" >&5 -echo "$as_me: WARNING: ** no $piddir directory on this system **" >&2;} - fi +# Check whether --with-sshca-dir was given. +if test "${with_sshca_dir+set}" = set; then + withval=$with_sshca_dir; + if test "x$withval" != "xno" ; then + sshcadir=$withval fi @@ -29099,174 +29135,122 @@ cat >>confdefs.h <<_ACEOF -#define _PATH_SSH_PIDDIR "$piddir" -_ACEOF - - - -# Check whether --enable-lastlog was given. -if test "${enable_lastlog+set}" = set; then - enableval=$enable_lastlog; - if test "x$enableval" = "xno" ; then - cat >>confdefs.h <<\_ACEOF -#define DISABLE_LASTLOG 1 -_ACEOF - - fi - - -fi - -# Check whether --enable-utmp was given. -if test "${enable_utmp+set}" = set; then - enableval=$enable_utmp; - if test "x$enableval" = "xno" ; then - cat >>confdefs.h <<\_ACEOF -#define DISABLE_UTMP 1 -_ACEOF - - fi - - -fi - -# Check whether --enable-utmpx was given. -if test "${enable_utmpx+set}" = set; then - enableval=$enable_utmpx; - if test "x$enableval" = "xno" ; then - -cat >>confdefs.h <<\_ACEOF -#define DISABLE_UTMPX 1 -_ACEOF - - fi - - -fi - -# Check whether --enable-wtmp was given. -if test "${enable_wtmp+set}" = set; then - enableval=$enable_wtmp; - if test "x$enableval" = "xno" ; then - cat >>confdefs.h <<\_ACEOF -#define DISABLE_WTMP 1 +#define SSHCADIR "$sshcadir" _ACEOF - fi - - -fi - -# Check whether --enable-wtmpx was given. -if test "${enable_wtmpx+set}" = set; then - enableval=$enable_wtmpx; - if test "x$enableval" = "xno" ; then - -cat >>confdefs.h <<\_ACEOF -#define DISABLE_WTMPX 1 -_ACEOF - - fi - -fi -# Check whether --enable-libutil was given. -if test "${enable_libutil+set}" = set; then - enableval=$enable_libutil; - if test "x$enableval" = "xno" ; then - cat >>confdefs.h <<\_ACEOF -#define DISABLE_LOGIN 1 -_ACEOF - fi +ssh_x509store="yes" +# Check whether --enable-x509store was given. +if test "${enable_x509store+set}" = set; then + enableval=$enable_x509store; + if test "x$enableval" = "xno"; then + ssh_x509store="no" + fi fi -# Check whether --enable-pututline was given. -if test "${enable_pututline+set}" = set; then - enableval=$enable_pututline; - if test "x$enableval" = "xno" ; then +if test "x$ssh_x509store" = "xno"; then -cat >>confdefs.h <<\_ACEOF -#define DISABLE_PUTUTLINE 1 +cat >>confdefs.h <<_ACEOF +#define SSH_X509STORE_DISABLED 1 _ACEOF - fi - - fi -# Check whether --enable-pututxline was given. -if test "${enable_pututxline+set}" = set; then - enableval=$enable_pututxline; - if test "x$enableval" = "xno" ; then - -cat >>confdefs.h <<\_ACEOF -#define DISABLE_PUTUTXLINE 1 -_ACEOF +# enable/disable OCSP requests +# Check whether --enable-ocsp was given. +if test "${enable_ocsp+set}" = set; then + enableval=$enable_ocsp; + if test "x$enableval" = "xyes"; then + if test "x$ssh_x509store" != "xyes"; then + { { echo "$as_me:$LINENO: error: cannot enable OCSP when x509store is disabled" >&5 +echo "$as_me: error: cannot enable OCSP when x509store is disabled" >&2;} + { (exit 1); exit 1; }; } fi + ssh_ocsp="yes" + else + ssh_ocsp="no" + fi +else -fi - - -# Check whether --with-lastlog was given. -if test "${with_lastlog+set}" = set; then - withval=$with_lastlog; - if test "x$withval" = "xno" ; then - cat >>confdefs.h <<\_ACEOF -#define DISABLE_LASTLOG 1 -_ACEOF - - elif test -n "$withval" && test "x${withval}" != "xyes"; then - conf_lastlog_location=$withval - fi - + if test "x$ssh_x509store" = "xyes"; then + ssh_ocsp="yes" + else + ssh_ocsp="no" + { echo "$as_me:$LINENO: x509store is disabled - skiping OCSP" >&5 +echo "$as_me: x509store is disabled - skiping OCSP" >&6;} + fi fi +if test "x$ssh_ocsp" = "xyes"; then - -{ echo "$as_me:$LINENO: checking if your system defines LASTLOG_FILE" >&5 -echo $ECHO_N "checking if your system defines LASTLOG_FILE... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF +for ac_func in OCSP_sendreq_bio +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func -#include -#include -#ifdef HAVE_LASTLOG_H -# include +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include #endif -#ifdef HAVE_PATHS_H -# include + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" #endif -#ifdef HAVE_LOGIN_H -# include +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me #endif int main () { - char *lastlog = LASTLOG_FILE; +return $ac_func (); ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 + (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 @@ -29275,41 +29259,47 @@ (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err - } && test -s conftest.$ac_objext; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 + eval "$as_ac_var=no" +fi - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - { echo "$as_me:$LINENO: checking if your system defines _PATH_LASTLOG" >&5 -echo $ECHO_N "checking if your system defines _PATH_LASTLOG... $ECHO_C" >&6; } - cat >conftest.$ac_ext <<_ACEOF +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + + if test "${ac_cv_header_openssl_ocsp_h+set}" = set; then + { echo "$as_me:$LINENO: checking for openssl/ocsp.h" >&5 +echo $ECHO_N "checking for openssl/ocsp.h... $ECHO_C" >&6; } +if test "${ac_cv_header_openssl_ocsp_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_openssl_ocsp_h" >&5 +echo "${ECHO_T}$ac_cv_header_openssl_ocsp_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking openssl/ocsp.h usability" >&5 +echo $ECHO_N "checking openssl/ocsp.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - -#include -#include -#ifdef HAVE_LASTLOG_H -# include -#endif -#ifdef HAVE_PATHS_H -# include -#endif - -int -main () -{ - char *lastlog = _PATH_LASTLOG; - ; - return 0; -} +$ac_includes_default +#include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" @@ -29328,21 +29318,1568 @@ test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } + ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - system_lastlog_path=no - + ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking openssl/ocsp.h presence" >&5 +echo $ECHO_N "checking openssl/ocsp.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: openssl/ocsp.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: openssl/ocsp.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ocsp.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: openssl/ocsp.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: openssl/ocsp.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: openssl/ocsp.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ocsp.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: openssl/ocsp.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ocsp.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: openssl/ocsp.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ocsp.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: openssl/ocsp.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ocsp.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: openssl/ocsp.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ocsp.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: openssl/ocsp.h: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------------- ## +## Report this to openssh-unix-dev@mindrot.org ## +## ------------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for openssl/ocsp.h" >&5 +echo $ECHO_N "checking for openssl/ocsp.h... $ECHO_C" >&6; } +if test "${ac_cv_header_openssl_ocsp_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_openssl_ocsp_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_openssl_ocsp_h" >&5 +echo "${ECHO_T}$ac_cv_header_openssl_ocsp_h" >&6; } + +fi +if test $ac_cv_header_openssl_ocsp_h = yes; then + : +else + + ssh_ocsp="no" + { { echo "$as_me:$LINENO: error: OCSP header not found" >&5 +echo "$as_me: error: OCSP header not found" >&2;} + { (exit 1); exit 1; }; } + +fi + + + +else + + ssh_ocsp="no" + { echo "$as_me:$LINENO: WARNING: Cannot find OCSP functions - OCSP is disabled" >&5 +echo "$as_me: WARNING: Cannot find OCSP functions - OCSP is disabled" >&2;} + +fi +done + +fi +if test "x$ssh_ocsp" = "xyes"; then + +cat >>confdefs.h <<_ACEOF +#define SSH_OCSP_ENABLED 1 +_ACEOF + + OCSP_ON='' + OCSP_OFF='#' + LIBS="-lssl $LIBS" +else + OCSP_ON='#' + OCSP_OFF='' +fi + + + + +# enable LDAP queries +LDAP_MSG="no" +if test "x$ssh_x509store" = "xyes"; then + + +ac_ldap='none' +# Check whether --enable-ldap was given. +if test "${enable_ldap+set}" = set; then + enableval=$enable_ldap; ac_ldap="$enableval" + +fi + + +if test "x$ac_ldap" = xyes; then + ac_ldap_prefix="" + +# Check whether --with-ldap-prefix was given. +if test "${with_ldap_prefix+set}" = set; then + withval=$with_ldap_prefix; ac_ldap_prefix="$withval" + +fi + + + +# Check whether --with-ldap-bindir was given. +if test "${with_ldap_bindir+set}" = set; then + withval=$with_ldap_bindir; LDAP_BINDIR="$withval" +else + + if test "x$ac_ldap_prefix" != "x"; then + LDAP_BINDIR="$ac_ldap_prefix/bin" + fi + + +fi + + + + +# Check whether --with-ldap-libexecdir was given. +if test "${with_ldap_libexecdir+set}" = set; then + withval=$with_ldap_libexecdir; LDAP_LIBEXECDIR="$withval" +else + + if test "x$ac_ldap_prefix" = "x"; then + LDAP_LIBEXECDIR="/usr/libexec" + else + LDAP_LIBEXECDIR="$ac_ldap_prefix/libexec" + fi + + +fi + + + + +# Check whether --with-ldap-sysconfdir was given. +if test "${with_ldap_sysconfdir+set}" = set; then + withval=$with_ldap_sysconfdir; LDAP_SYSCONFDIR="$withval" +else + LDAP_SYSCONFDIR="$ac_ldap_prefix/etc/openldap" + +fi + + + + + +# Check whether --with-ldap-libdir was given. +if test "${with_ldap_libdir+set}" = set; then + withval=$with_ldap_libdir; LDAP_LDFLAGS="-L$withval" +else + + if test "x$ac_ldap_prefix" != "x"; then + LDAP_LDFLAGS="-L$ac_ldap_prefix/lib" + else + LDAP_LDFLAGS="" + fi + + +fi + + + + +# Check whether --with-ldap-includedir was given. +if test "${with_ldap_includedir+set}" = set; then + withval=$with_ldap_includedir; LDAP_CPPFLAGS="-I$withval" +else + + if test "x$ac_ldap_prefix" != "x"; then + LDAP_CPPFLAGS="-I$ac_ldap_prefix/include" + else + LDAP_CPPFLAGS="" + fi + + +fi + + + + + ac_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $LDAP_CPPFLAGS" + + +for ac_header in lber.h ldap.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------------- ## +## Report this to openssh-unix-dev@mindrot.org ## +## ------------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + + { { echo "$as_me:$LINENO: error: cannot found LDAP headers" >&5 +echo "$as_me: error: cannot found LDAP headers" >&2;} + { (exit 1); exit 1; }; } + + +fi + +done + + CPPFLAGS="$ac_save_CPPFLAGS" + + ac_ldap_libs="" + +# Check whether --with-ldap-libs was given. +if test "${with_ldap_libs+set}" = set; then + withval=$with_ldap_libs; ac_ldap_libs="$withval" + +fi + + +### Try to link with LDAP libs + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + + LDFLAGS="$LDAP_LDFLAGS $LDFLAGS" + ac_LDAP_LINK="" + if test "x$ac_ldap_libs" != "x"; then + { echo "$as_me:$LINENO: checking to link with specified LDAP libs" >&5 +echo $ECHO_N "checking to link with specified LDAP libs... $ECHO_C" >&6; } + + LDAP_LIBS="$ac_ldap_libs" + LIBS="$LDAP_LIBS $ac_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_init (); +int +main () +{ +return ldap_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_LDAP_LINK="yes" + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + if test "x$ac_LDAP_LINK" != "xyes"; then + { { echo "$as_me:$LINENO: error: cannot link with specified LDAP libs" >&5 +echo "$as_me: error: cannot link with specified LDAP libs" >&2;} + { (exit 1); exit 1; }; } + fi + else + { echo "$as_me:$LINENO: checking how to link LDAP libs" >&5 +echo $ECHO_N "checking how to link LDAP libs... $ECHO_C" >&6; } + + LDAP_LIBS="-lldap" + for L in lber ssl crypto; do + LDAP_LIBS="$LDAP_LIBS -l$L" + LIBS="$LDAP_LIBS $ac_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_init (); +int +main () +{ +return ldap_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_LDAP_LINK="yes" + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + if test "x$ac_LDAP_LINK" = "xyes"; then + break + fi + done + if test "x$ac_LDAP_LINK" != "xyes"; then + { { echo "$as_me:$LINENO: error: cannot link with default LDAP libs" >&5 +echo "$as_me: error: cannot link with default LDAP libs" >&2;} + { (exit 1); exit 1; }; } + fi + fi + { echo "$as_me:$LINENO: result: done" >&5 +echo "${ECHO_T}done" >&6; } + LIBS="$ac_save_LIBS" + LDFLAGS="$ac_save_LDFLAGS" + +else + { echo "$as_me:$LINENO: LDAP is disabled" >&5 +echo "$as_me: LDAP is disabled" >&6;} +fi + +if test "x$ac_ldap" = "xyes"; then + +cat >>confdefs.h <<_ACEOF +#define LDAP_ENABLED 1 +_ACEOF + + LDAP_ON='' + LDAP_OFF='#' +else + LDAP_ON='#' + LDAP_OFF='' +fi + + + + if test "x$LDAP_ON" = "x"; then + LDAP_MSG="yes" + fi + + +if test "x$ac_ldap" = "xyes"; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $LDAP_CPPFLAGS" + LDFLAGS="$LDFLAGS $LDAP_LDFLAGS" + LIBS="$LDAP_LIBS $LIBS" + + + + +for ac_func in \ + ldap_initialize \ + ldap_parse_result \ + ldap_sasl_bind_s \ + ldap_search_ext_s \ + +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS="$ac_save_LIBS" + LDFLAGS="$ac_save_LDFLAGS" + CPPFLAGS="$ac_save_CPPFLAGS" +fi + +else + { echo "$as_me:$LINENO: x509store is disabled - skiping LDAP" >&5 +echo "$as_me: x509store is disabled - skiping LDAP" >&6;} +fi + + +ssh_x509dn_email="yes" +if test "x$ssh_x509store" = "xyes"; then + # Check for Email in X.509 'Distinguished Name' + { echo "$as_me:$LINENO: checking for Email in X.509 'Distinguished Name'" >&5 +echo $ECHO_N "checking for Email in X.509 'Distinguished Name'... $ECHO_C" >&6; } + if test "$cross_compiling" = yes; then + + { echo "$as_me:$LINENO: WARNING: cross compiling: assuming no" >&5 +echo "$as_me: WARNING: cross compiling: assuming no" >&2;} + ssh_x509dn_email="no" + + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include + +int main(void) { + int nid; + nid = OBJ_txt2nid("Email"); + if (nid == NID_undef) + exit (1); + exit (0); + return (0); +} + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + ssh_x509dn_email="no" + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + # Check for the existence of "X509_VERIFY_PARAM *param" + { echo "$as_me:$LINENO: checking for X509_STORE_CTX.param" >&5 +echo $ECHO_N "checking for X509_STORE_CTX.param... $ECHO_C" >&6; } +if test "${ac_cv_member_X509_STORE_CTX_param+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static X509_STORE_CTX ac_aggr; +if (ac_aggr.param) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_X509_STORE_CTX_param=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static X509_STORE_CTX ac_aggr; +if (sizeof ac_aggr.param) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_X509_STORE_CTX_param=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_X509_STORE_CTX_param=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_X509_STORE_CTX_param" >&5 +echo "${ECHO_T}$ac_cv_member_X509_STORE_CTX_param" >&6; } +if test $ac_cv_member_X509_STORE_CTX_param = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_X509_STORE_CTX_PARAM 1 +_ACEOF + + +fi + +fi +if test "x$ssh_x509dn_email" = "xno"; then + +cat >>confdefs.h <<_ACEOF +#define SSH_OPENSSL_DN_WITHOUT_EMAIL 1 +_ACEOF + +fi + +# Check for the existence of "EVP_MD members" +{ echo "$as_me:$LINENO: checking for EVP_MD.flags" >&5 +echo $ECHO_N "checking for EVP_MD.flags... $ECHO_C" >&6; } +if test "${ac_cv_member_EVP_MD_flags+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static EVP_MD ac_aggr; +if (ac_aggr.flags) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_EVP_MD_flags=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static EVP_MD ac_aggr; +if (sizeof ac_aggr.flags) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_EVP_MD_flags=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_EVP_MD_flags=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_EVP_MD_flags" >&5 +echo "${ECHO_T}$ac_cv_member_EVP_MD_flags" >&6; } +if test $ac_cv_member_EVP_MD_flags = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_EVP_MD_FLAGS 1 +_ACEOF + + +fi + +{ echo "$as_me:$LINENO: checking for EVP_MD.copy" >&5 +echo $ECHO_N "checking for EVP_MD.copy... $ECHO_C" >&6; } +if test "${ac_cv_member_EVP_MD_copy+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static EVP_MD ac_aggr; +if (ac_aggr.copy) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_EVP_MD_copy=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static EVP_MD ac_aggr; +if (sizeof ac_aggr.copy) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_EVP_MD_copy=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_EVP_MD_copy=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_EVP_MD_copy" >&5 +echo "${ECHO_T}$ac_cv_member_EVP_MD_copy" >&6; } +if test $ac_cv_member_EVP_MD_copy = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_EVP_MD_COPY 1 +_ACEOF + + +fi + +{ echo "$as_me:$LINENO: checking for EVP_MD.cleanup" >&5 +echo $ECHO_N "checking for EVP_MD.cleanup... $ECHO_C" >&6; } +if test "${ac_cv_member_EVP_MD_cleanup+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static EVP_MD ac_aggr; +if (ac_aggr.cleanup) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_EVP_MD_cleanup=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static EVP_MD ac_aggr; +if (sizeof ac_aggr.cleanup) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_EVP_MD_cleanup=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_EVP_MD_cleanup=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_EVP_MD_cleanup" >&5 +echo "${ECHO_T}$ac_cv_member_EVP_MD_cleanup" >&6; } +if test $ac_cv_member_EVP_MD_cleanup = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_EVP_MD_CLEANUP 1 +_ACEOF + + +fi + +{ echo "$as_me:$LINENO: checking for EVP_MD_CTX.md_data" >&5 +echo $ECHO_N "checking for EVP_MD_CTX.md_data... $ECHO_C" >&6; } +if test "${ac_cv_member_EVP_MD_CTX_md_data+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static EVP_MD_CTX ac_aggr; +if (ac_aggr.md_data) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_EVP_MD_CTX_md_data=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +static EVP_MD_CTX ac_aggr; +if (sizeof ac_aggr.md_data) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_EVP_MD_CTX_md_data=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_EVP_MD_CTX_md_data=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_EVP_MD_CTX_md_data" >&5 +echo "${ECHO_T}$ac_cv_member_EVP_MD_CTX_md_data" >&6; } +if test $ac_cv_member_EVP_MD_CTX_md_data = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_EVP_MD_CTX_MD_DATA 1 +_ACEOF + + +fi + + +# Where to place sshd.pid +piddir=/var/run +# make sure the directory exists +if test ! -d $piddir ; then + piddir=`eval echo ${sysconfdir}` + case $piddir in + NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;; + esac +fi + + +# Check whether --with-pid-dir was given. +if test "${with_pid_dir+set}" = set; then + withval=$with_pid_dir; + if test -n "$withval" && test "x$withval" != "xno" && \ + test "x${withval}" != "xyes"; then + piddir=$withval + if test ! -d $piddir ; then + { echo "$as_me:$LINENO: WARNING: ** no $piddir directory on this system **" >&5 +echo "$as_me: WARNING: ** no $piddir directory on this system **" >&2;} + fi + fi + + +fi + + + +cat >>confdefs.h <<_ACEOF +#define _PATH_SSH_PIDDIR "$piddir" +_ACEOF + + + +# Check whether --enable-lastlog was given. +if test "${enable_lastlog+set}" = set; then + enableval=$enable_lastlog; + if test "x$enableval" = "xno" ; then + cat >>confdefs.h <<\_ACEOF +#define DISABLE_LASTLOG 1 +_ACEOF + + fi + + +fi + +# Check whether --enable-utmp was given. +if test "${enable_utmp+set}" = set; then + enableval=$enable_utmp; + if test "x$enableval" = "xno" ; then + cat >>confdefs.h <<\_ACEOF +#define DISABLE_UTMP 1 +_ACEOF + + fi + + +fi + +# Check whether --enable-utmpx was given. +if test "${enable_utmpx+set}" = set; then + enableval=$enable_utmpx; + if test "x$enableval" = "xno" ; then + +cat >>confdefs.h <<\_ACEOF +#define DISABLE_UTMPX 1 +_ACEOF + + fi + + +fi + +# Check whether --enable-wtmp was given. +if test "${enable_wtmp+set}" = set; then + enableval=$enable_wtmp; + if test "x$enableval" = "xno" ; then + cat >>confdefs.h <<\_ACEOF +#define DISABLE_WTMP 1 +_ACEOF + + fi + + +fi + +# Check whether --enable-wtmpx was given. +if test "${enable_wtmpx+set}" = set; then + enableval=$enable_wtmpx; + if test "x$enableval" = "xno" ; then + +cat >>confdefs.h <<\_ACEOF +#define DISABLE_WTMPX 1 +_ACEOF + + fi + + +fi + +# Check whether --enable-libutil was given. +if test "${enable_libutil+set}" = set; then + enableval=$enable_libutil; + if test "x$enableval" = "xno" ; then + cat >>confdefs.h <<\_ACEOF +#define DISABLE_LOGIN 1 +_ACEOF + + fi + + +fi + +# Check whether --enable-pututline was given. +if test "${enable_pututline+set}" = set; then + enableval=$enable_pututline; + if test "x$enableval" = "xno" ; then + +cat >>confdefs.h <<\_ACEOF +#define DISABLE_PUTUTLINE 1 +_ACEOF + + fi + + +fi + +# Check whether --enable-pututxline was given. +if test "${enable_pututxline+set}" = set; then + enableval=$enable_pututxline; + if test "x$enableval" = "xno" ; then + +cat >>confdefs.h <<\_ACEOF +#define DISABLE_PUTUTXLINE 1 +_ACEOF + + fi + + +fi + + +# Check whether --with-lastlog was given. +if test "${with_lastlog+set}" = set; then + withval=$with_lastlog; + if test "x$withval" = "xno" ; then + cat >>confdefs.h <<\_ACEOF +#define DISABLE_LASTLOG 1 +_ACEOF + + elif test -n "$withval" && test "x${withval}" != "xyes"; then + conf_lastlog_location=$withval + fi + + +fi + + + +{ echo "$as_me:$LINENO: checking if your system defines LASTLOG_FILE" >&5 +echo $ECHO_N "checking if your system defines LASTLOG_FILE... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +#ifdef HAVE_LASTLOG_H +# include +#endif +#ifdef HAVE_PATHS_H +# include +#endif +#ifdef HAVE_LOGIN_H +# include +#endif + +int +main () +{ + char *lastlog = LASTLOG_FILE; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { echo "$as_me:$LINENO: checking if your system defines _PATH_LASTLOG" >&5 +echo $ECHO_N "checking if your system defines _PATH_LASTLOG... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +#ifdef HAVE_LASTLOG_H +# include +#endif +#ifdef HAVE_PATHS_H +# include +#endif + +int +main () +{ + char *lastlog = _PATH_LASTLOG; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + system_lastlog_path=no + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi @@ -29668,7 +31205,7 @@ -ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile ssh_prng_cmds survey.sh" +ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile tests/CA/Makefile tests/CA/env ssh_prng_cmds survey.sh" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -30230,6 +31767,8 @@ "openssh.xml") CONFIG_FILES="$CONFIG_FILES openssh.xml" ;; "openbsd-compat/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/Makefile" ;; "openbsd-compat/regress/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/regress/Makefile" ;; + "tests/CA/Makefile") CONFIG_FILES="$CONFIG_FILES tests/CA/Makefile" ;; + "tests/CA/env") CONFIG_FILES="$CONFIG_FILES tests/CA/env" ;; "ssh_prng_cmds") CONFIG_FILES="$CONFIG_FILES ssh_prng_cmds" ;; "survey.sh") CONFIG_FILES="$CONFIG_FILES survey.sh" ;; @@ -30441,13 +31980,24 @@ MANTYPE!$MANTYPE$ac_delim mansubdir!$mansubdir$ac_delim user_path!$user_path$ac_delim +sshcadir!$sshcadir$ac_delim +OCSP_ON!$OCSP_ON$ac_delim +OCSP_OFF!$OCSP_OFF$ac_delim +LDAP_BINDIR!$LDAP_BINDIR$ac_delim +LDAP_LIBEXECDIR!$LDAP_LIBEXECDIR$ac_delim +LDAP_SYSCONFDIR!$LDAP_SYSCONFDIR$ac_delim +LDAP_LDFLAGS!$LDAP_LDFLAGS$ac_delim +LDAP_CPPFLAGS!$LDAP_CPPFLAGS$ac_delim +LDAP_LIBS!$LDAP_LIBS$ac_delim +LDAP_ON!$LDAP_ON$ac_delim +LDAP_OFF!$LDAP_OFF$ac_delim piddir!$piddir$ac_delim TEST_SSH_IPV6!$TEST_SSH_IPV6$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 14; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 25; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -30896,6 +32446,7 @@ echo " User binaries: $B" echo " System binaries: $C" echo " Configuration files: $D" +echo " CA root: $sshcadir" echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" @@ -30922,6 +32473,9 @@ echo " S/KEY support: $SKEY_MSG" echo " TCP Wrappers support: $TCPW_MSG" echo " MD5 password support: $MD5_MSG" +echo " X.509 store support: $ssh_x509store" +echo " OCSP support: $ssh_ocsp" +echo " LDAP queries: $LDAP_MSG" echo " libedit support: $LIBEDIT_MSG" echo " Solaris process contract support: $SPC_MSG" echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" @@ -30951,6 +32505,20 @@ echo "" fi +if test "x$LDAP_MSG" = "xyes" ; then +echo "Extra LDAP flags:" +echo " LDAP compiler flags: ${LDAP_CFLAGS}" +echo "LDAP preprocessor flags: ${LDAP_CPPFLAGS}" +echo " LDAP linker flags: ${LDAP_LDFLAGS}" +echo " LDAP libraries: ${LDAP_LIBS}" +echo "" +echo "LDAP paths(used only in tests):" +echo " LDAP sysconfig dir: ${LDAP_SYSCONFDIR}" +echo " LDAP libexec dir: ${LDAP_LIBEXECDIR}" +echo " LDAP bin dir: ${LDAP_BINDIR}" +echo "" +fi + if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " diff -ruN openssh-5.6p1/configure.ac openssh-5.6p1+x509-6.2.3/configure.ac --- openssh-5.6p1/configure.ac 2010-08-16 06:15:23.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/configure.ac 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.451 2010/08/16 03:15:23 dtucker Exp $ +# $Id$ # # Copyright (c) 1999-2004 Damien Miller # @@ -17,6 +17,7 @@ AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org) AC_REVISION($Revision: 1.451 $) AC_CONFIG_SRCDIR([ssh.c]) +m4_include([m4/ldap.m4]) AC_CONFIG_HEADER(config.h) AC_PROG_CC @@ -3859,6 +3860,161 @@ ] ) +# X.509 support +ssh_x509="yes" +# Reserved for future use +#AC_DEFINE_UNQUOTED( +# X509_DISABLED, 1, +# [Define if you want to disable X.509 certificates]) + +# Where to place ssh CA root +sshcadir='${sysconfdir}/ca' +sshcadir=`eval echo ${sshcadir}` +sshcadir=`eval echo ${sshcadir}` +case $sshcadir in + NONE/*) sshcadir=`echo $sshcadir | sed "s~NONE~$ac_default_prefix~"` ;; +esac + +AC_ARG_WITH(sshca-dir, + [ --with-sshca-dir=PATH Specify location of ssh CA root], + [ + if test "x$withval" != "xno" ; then + sshcadir=$withval + fi + ] +) + +AC_DEFINE_UNQUOTED(SSHCADIR, "$sshcadir", [Specify location of ssh CA root]) +AC_SUBST(sshcadir) + + +ssh_x509store="yes" +AC_ARG_ENABLE(x509store, + [ --disable-x509store Disable X.509 store], + [ + if test "x$enableval" = "xno"; then + ssh_x509store="no" + fi + ] +) +if test "x$ssh_x509store" = "xno"; then + AC_DEFINE_UNQUOTED( + SSH_X509STORE_DISABLED, 1, + [Define if you don't want to verify certificates]) +fi + + +# enable/disable OCSP requests +AC_ARG_ENABLE(ocsp, + [ --disable-ocsp Disable OCSP validation], + [ + if test "x$enableval" = "xyes"; then + if test "x$ssh_x509store" != "xyes"; then + AC_MSG_ERROR([cannot enable OCSP when x509store is disabled]) + fi + ssh_ocsp="yes" + else + ssh_ocsp="no" + fi + ], + [ + if test "x$ssh_x509store" = "xyes"; then + ssh_ocsp="yes" + else + ssh_ocsp="no" + AC_MSG_NOTICE([x509store is disabled - skiping OCSP]) + fi + ]) +if test "x$ssh_ocsp" = "xyes"; then + AC_CHECK_FUNCS(OCSP_sendreq_bio, + [ + AC_CHECK_HEADER(openssl/ocsp.h, + [], + [ + ssh_ocsp="no" + AC_MSG_ERROR([OCSP header not found]) + ]) + ], + [ + ssh_ocsp="no" + AC_MSG_WARN([Cannot find OCSP functions - OCSP is disabled]) + ]) +fi +if test "x$ssh_ocsp" = "xyes"; then + AC_DEFINE_UNQUOTED( + SSH_OCSP_ENABLED, 1, + [Define if you don't want to validate X.509 certificates with OCSP]) + OCSP_ON='' + OCSP_OFF='#' + LIBS="-lssl $LIBS" +else + OCSP_ON='#' + OCSP_OFF='' +fi +AC_SUBST(OCSP_ON) +AC_SUBST(OCSP_OFF) + + +# enable LDAP queries +LDAP_MSG="no" +if test "x$ssh_x509store" = "xyes"; then + AC_WITH_LDAP + if test "x$LDAP_ON" = "x"; then + LDAP_MSG="yes" + fi + AC_LDAP_FUNCS([\ + ldap_initialize \ + ldap_parse_result \ + ldap_sasl_bind_s \ + ldap_search_ext_s \ + ]) +else + AC_MSG_NOTICE([x509store is disabled - skiping LDAP]) +fi + + +ssh_x509dn_email="yes" +if test "x$ssh_x509store" = "xyes"; then + # Check for Email in X.509 'Distinguished Name' + AC_MSG_CHECKING([for Email in X.509 'Distinguished Name']) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([ +#include + +int main(void) { + int nid; + nid = OBJ_txt2nid("Email"); + if (nid == NID_undef) + exit (1); + exit (0); + return (0); +} + ])], + [ AC_MSG_RESULT(yes) ], + [ + AC_MSG_RESULT(no) + ssh_x509dn_email="no" + ], + [ + AC_MSG_WARN([cross compiling: assuming no]) + ssh_x509dn_email="no" + ] +) + # Check for the existence of "X509_VERIFY_PARAM *param" + AC_CHECK_MEMBERS([X509_STORE_CTX.param],,,[#include ]) +fi +if test "x$ssh_x509dn_email" = "xno"; then + AC_DEFINE_UNQUOTED( + SSH_OPENSSL_DN_WITHOUT_EMAIL, 1, + [Define if your openssl library don't support Email in X.509 'Distinguished Name']) +fi + +# Check for the existence of "EVP_MD members" +AC_CHECK_MEMBERS([EVP_MD.flags],,,[#include ]) +AC_CHECK_MEMBERS([EVP_MD.copy],,,[#include ]) +AC_CHECK_MEMBERS([EVP_MD.cleanup],,,[#include ]) +AC_CHECK_MEMBERS([EVP_MD_CTX.md_data],,,[#include ]) + # Where to place sshd.pid piddir=/var/run # make sure the directory exists @@ -4141,6 +4297,7 @@ AC_EXEEXT AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \ openbsd-compat/Makefile openbsd-compat/regress/Makefile \ + tests/CA/Makefile tests/CA/env \ ssh_prng_cmds survey.sh]) AC_OUTPUT @@ -4163,6 +4320,7 @@ echo " User binaries: $B" echo " System binaries: $C" echo " Configuration files: $D" +echo " CA root: $sshcadir" echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" @@ -4189,6 +4347,9 @@ echo " S/KEY support: $SKEY_MSG" echo " TCP Wrappers support: $TCPW_MSG" echo " MD5 password support: $MD5_MSG" +echo " X.509 store support: $ssh_x509store" +echo " OCSP support: $ssh_ocsp" +echo " LDAP queries: $LDAP_MSG" echo " libedit support: $LIBEDIT_MSG" echo " Solaris process contract support: $SPC_MSG" echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" @@ -4218,6 +4379,20 @@ echo "" fi +if test "x$LDAP_MSG" = "xyes" ; then +echo "Extra LDAP flags:" +echo " LDAP compiler flags: ${LDAP_CFLAGS}" +echo "LDAP preprocessor flags: ${LDAP_CPPFLAGS}" +echo " LDAP linker flags: ${LDAP_LDFLAGS}" +echo " LDAP libraries: ${LDAP_LIBS}" +echo "" +echo "LDAP paths(used only in tests):" +echo " LDAP sysconfig dir: ${LDAP_SYSCONFDIR}" +echo " LDAP libexec dir: ${LDAP_LIBEXECDIR}" +echo " LDAP bin dir: ${LDAP_BINDIR}" +echo "" +fi + if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " diff -ruN openssh-5.6p1/dns.c openssh-5.6p1+x509-6.2.3/dns.c --- openssh-5.6p1/dns.c 2010-02-26 22:55:05.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/dns.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,9 +1,12 @@ -/* $OpenBSD: dns.c,v 1.26 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 Jakob Schlyter. All rights reserved. * + * X.509 certificates support: + * Copyright (c) 2005 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,9 +40,25 @@ #include "xmalloc.h" #include "key.h" +#include "ssh-x509.h" +#include "uuencode.h" #include "dns.h" #include "log.h" + +struct ssh_dns_cert_param_s { + int cert_type; + int key_tag; + int algo; + u_char *cert_data; + size_t cert_len; + u_char *b64_data; + size_t b64_len; +}; + +typedef struct ssh_dns_cert_param_s ssh_dns_cert_param; + + static const char *errset_text[] = { "success", /* 0 ERRSET_SUCCESS */ "out of memory", /* 1 ERRSET_NOMEMORY */ @@ -106,6 +125,158 @@ return success; } +static void +cert_param_clean(ssh_dns_cert_param *param) { + if (param == NULL) return; + + if (param->cert_data) { + param->cert_len = 0; + xfree(param->cert_data); + param->cert_data = NULL; + } + if (param->b64_data) { + param->b64_len = 0; + xfree(param->b64_data); + param->b64_data = NULL; + } +} + +static const char* +bind_cert_type(const ssh_dns_cert_param *param) { + switch(param->cert_type) { + case DNS_CERT_TYPE_PKIX: return("PKIX"); +#if 0 + case DNS_CERT_TYPE_SPKI: return("SPKI"); + case DNS_CERT_TYPE_PGP : return("PGP"); + case DNS_CERT_TYPE_URI : return("URI"); + case DNS_CERT_TYPE_OID : return("OID"); +#endif + default: + break; + } + return(""); +} + +static const char* +bind_key_algo(const ssh_dns_cert_param *param) { + switch(param->algo) { +#if 0 + case DNS_KEY_ALGO_UNKNOWN: /*specific case for CERT RR*/ + return("????"); +#endif + case DNS_KEY_ALGO_RSAMD5 : return("RSAMD5"); + case DNS_KEY_ALGO_DSA : return("DSA"); + } + return(""); +} + +static u_int16_t +calc_dns_key_tag(X509 *x509) { + /* [RFC 2535] Appendix C: Key Tag Calculation */ + + /* TODO: to be implemented or not ? + * I'm happy without this. + */ + return(1); +} + +static u_int8_t +get_dns_sign_algo(X509 *x509) { + int rsa_algo = DNS_KEY_ALGO_UNKNOWN; + int algo_nid; + + X509_CINF *ci; + X509_ALGOR *sig; + ASN1_OBJECT *alg; + + if (x509 == NULL) goto done; + + ci = x509->cert_info; + if (ci == NULL) goto done; + + sig = ci->signature; + if (sig == NULL) goto done; + + alg = sig->algorithm; + if (alg == NULL) goto done; + + algo_nid = OBJ_obj2nid(alg); + debug3("get_dns_sign_algo: nid=%d(%s)\n", algo_nid, OBJ_nid2ln(algo_nid)); + + switch(algo_nid) { + case NID_md5WithRSAEncryption: + rsa_algo = DNS_KEY_ALGO_RSAMD5; + break; + case NID_sha1WithRSAEncryption: + case NID_md2WithRSAEncryption: + case NID_md4WithRSAEncryption: + case NID_ripemd160WithRSA: + /* not defined in [RFC 2535] ! */ + rsa_algo = DNS_KEY_ALGO_UNKNOWN; + break; + case NID_dsaWithSHA1: + rsa_algo = DNS_KEY_ALGO_DSA; + break; + default: + rsa_algo = DNS_KEY_ALGO_UNKNOWN; + } + +done: + return(rsa_algo); +} + +/* + * Read CERT parameters from key buffer. + */ +static int/*bool*/ +dns_read_cert(ssh_dns_cert_param *param, const Key *key) +{ + int ret = 0; + X509 *x509 = NULL; + BIO *bio = NULL; + int k = 0; + + if (param == NULL) goto done; + if (key == NULL) goto done; + + switch (key->type) { + case KEY_X509_RSA: + case KEY_X509_DSA: { + } break; + default: + goto done; + } + + x509 = key->x509; + if (x509 == NULL) goto done; + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) goto done; + + i2d_X509_bio(bio, x509); + BIO_flush(bio); + + cert_param_clean(param); + + k = BIO_pending(bio); + param->cert_data = xmalloc(k + 1); /*fatal on error*/ + param->cert_len = BIO_read(bio, param->cert_data, k); + + k = param->cert_len << 1; + param->b64_data = xmalloc(k); /*fatal on error*/ + param->b64_len = uuencode(param->cert_data, param->cert_len, (char*)param->b64_data, k); + + param->algo = get_dns_sign_algo(x509); + param->key_tag = calc_dns_key_tag(x509); + param->cert_type = DNS_CERT_TYPE_PKIX; + + ret = 1; + +done: + if (bio) BIO_free_all(bio); + return(ret); +} + /* * Read SSHFP parameters from rdata buffer. */ @@ -167,6 +338,127 @@ } /* + * Read CERT parameters from rdata buffer. + */ +static int/*bool*/ +dns_read_cert_rdata(ssh_dns_cert_param *param, u_char *rdata, int rdata_len) +{ + size_t len ; + + cert_param_clean(param); + + if (rdata_len < 5) return(0); + + param->cert_type = (rdata[0] << 8) + rdata[1]; + param->key_tag = (rdata[2] << 8) + rdata[3]; + param->algo = rdata[4]; + + len = rdata_len - 5; + param->cert_len = len; + if (len > 0) { + param->cert_data = (u_char *) xmalloc(len); + memcpy(param->cert_data, rdata + 5, len); + } + return(1); +} + +/* + * Verify the given hostname, address and host key using DNS. + * Returns 0 if lookup succeeds, -1 otherwise + */ +static int +verify_hostcert_dns(const char *hostname, const Key *hostkey, int *flags) +{ + u_int counter; + int result; + struct rrsetinfo *certs = NULL; + + ssh_dns_cert_param hostkey_param; + ssh_dns_cert_param dnskey_param; + + debug3("verify_hostcert_dns"); + + memset(&hostkey_param, 0, sizeof(hostkey_param)); + memset(&dnskey_param , 0, sizeof(dnskey_param )); + + result = getrrsetbyname(hostname, DNS_RDATACLASS_IN, + DNS_RDATATYPE_CERT, 0, &certs); + if (result) { + verbose("DNS lookup error: %s", dns_result_totext(result)); + return(-1); + } + + if (certs->rri_flags & RRSET_VALIDATED) { + *flags |= DNS_VERIFY_SECURE; + debug("found %d secure certificates in DNS", + certs->rri_nrdatas); + } else { + debug("found %d insecure certificates in DNS", + certs->rri_nrdatas); + } + + /* Initialize host key parameters */ + if (!dns_read_cert(&hostkey_param, hostkey)) { + error("Error calculating host key certificate."); + cert_param_clean(&hostkey_param); + freerrset(certs); + return(-1); + } + + if (certs->rri_nrdatas) + *flags |= DNS_VERIFY_FOUND; + + for (counter = 0 ; counter < certs->rri_nrdatas ; counter++) { + Key* dns_cert = NULL; + /* + * Extract the key from the answer. Ignore any badly + * formatted certificates. + */ + if (!dns_read_cert_rdata(&dnskey_param, + certs->rri_rdatas[counter].rdi_data, + certs->rri_rdatas[counter].rdi_length + )) { + verbose("Error parsing certificate from DNS."); + goto next; + } + + if (hostkey_param.cert_type != dnskey_param.cert_type) continue; + + /* We will skip useless "key tag" */ + + /* We will ignore "algorithm" since number of + * algorithms defined in [RFC 2535] is limited. + */ + dns_cert = x509key_from_blob(dnskey_param.cert_data, dnskey_param.cert_len); + if (dns_cert == NULL) { + verbose("Invalid certificate from DNS."); + goto next; + } + if (X509_cmp(hostkey->x509, dns_cert->x509) == 0) { + *flags |= DNS_VERIFY_MATCH; + } + key_free(dns_cert); + dns_cert = NULL; + +next: + cert_param_clean(&dnskey_param); + } + + cert_param_clean(&hostkey_param); + freerrset(certs); + + if (*flags & DNS_VERIFY_FOUND) + if (*flags & DNS_VERIFY_MATCH) + debug("matching host key certificate found in DNS"); + else + debug("mismatching host key certificate found in DNS"); + else + debug("no host key certificate found in DNS"); + + return(0); +} + +/* * Verify the given hostname, address and host key using DNS. * Returns 0 if lookup succeeds, -1 otherwise */ @@ -199,6 +491,14 @@ return -1; } + if ((hostkey->type == KEY_X509_RSA) || (hostkey->type == KEY_X509_DSA)) { + result = verify_hostcert_dns(hostname, hostkey, flags); + if (*flags & DNS_VERIFY_FOUND) { + return(result); + } + /*try to found SSHFP RR*/ + } + result = getrrsetbyname(hostname, DNS_RDATACLASS_IN, DNS_RDATATYPE_SSHFP, 0, &fingerprints); if (result) { @@ -277,10 +577,57 @@ u_int8_t rdata_digest_type = SSHFP_HASH_SHA1; u_char *rdata_digest; u_int rdata_digest_len; + ssh_dns_cert_param cert_param; u_int i; int success = 0; + memset(&cert_param, 0, sizeof(cert_param)); + + if (dns_read_cert(&cert_param, key)) { + u_char *p; + int k; + + if (generic || (cert_param.algo == DNS_KEY_ALGO_UNKNOWN)) { + fprintf(f, "%s\tIN\tTYPE%d \\# %d %04x %04x %02x (\n\t" + , hostname + , DNS_RDATATYPE_CERT + , 5 + cert_param.cert_len + , cert_param.cert_type + , cert_param.key_tag + , cert_param.algo + ); + p = cert_param.cert_data; + i = cert_param.cert_len; + k = 32; + for (; i > 0; i--, p++) { + fprintf(f, "%02x", (int) *p); + if (--k <= 0) { + fprintf(f, "\n\t"); + k = 32; + } + } + } else { + fprintf(f, "%s\tIN\tCERT\t%s %d %s (\n\t" + , hostname + , bind_cert_type(&cert_param) + , cert_param.key_tag + , bind_key_algo(&cert_param) + ); + p = cert_param.b64_data; + i = cert_param.b64_len; + k = 64; + for (; i > 0; i--, p++) { + fprintf(f, "%c", *p); + if (--k <= 0) { + fprintf(f, "\n\t"); + k = 64; + } + } + } + fprintf(f, "\n\t)\n"); + success = 1; + } else if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type, &rdata_digest, &rdata_digest_len, key)) { @@ -301,5 +648,6 @@ error("export_dns_rr: unsupported algorithm"); } + cert_param_clean(&cert_param); return success; } diff -ruN openssh-5.6p1/dns.h openssh-5.6p1+x509-6.2.3/dns.h --- openssh-5.6p1/dns.h 2010-02-26 22:55:05.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/dns.h 2010-08-24 09:06:00.000000000 +0300 @@ -1,9 +1,12 @@ -/* $OpenBSD: dns.h,v 1.11 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 Jakob Schlyter. All rights reserved. * + * X.509 certificates support: + * Copyright (c) 2005 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,12 +37,39 @@ SSHFP_KEY_DSA }; +enum dns_cert_types { + DNS_CERT_TYPE_RESERVER = 0, + DNS_CERT_TYPE_PKIX = 1, /* X.509 as per PKIX */ + DNS_CERT_TYPE_SPKI = 2, /* SPKI cert */ + DNS_CERT_TYPE_PGP = 3, /* PGP cert */ +/* 4-252 available for IANA assignment */ + DNS_CERT_TYPE_URI = 253, /* URI private */ + DNS_CERT_TYPE_OID = 254, /* OID private */ +/* 255-65534 available for IANA assignment */ + DNS_CERT_TYPE_RESERVER2 = 65535 +}; + enum sshfp_hashes { SSHFP_HASH_RESERVED, SSHFP_HASH_SHA1 }; +enum dns_key_algo { + DNS_KEY_ALGO_RESERVED = 0, /* reserved, see [RFC 2535] Section 11 */ + DNS_KEY_ALGO_UNKNOWN = 0, /* when algorithm is unknown to a secure DNS [RFC 2538] */ + DNS_KEY_ALGO_RSAMD5 = 1, /* RSA/MD5 [RFC 2537] */ + DNS_KEY_ALGO_DH = 2, /* Diffie-Hellman [RFC 2539] */ + DNS_KEY_ALGO_DSA = 3, /* DSA [RFC 2536] */ + DNS_KEY_ALGO_ECC = 4, /* reserved for elliptic curve crypto */ +/* 5-251 available, see [RFC 2535] Section 11 */ + DNS_KEY_ALGO_INDIRECT = 252, /* reserved for indirect keys */ + DNS_KEY_ALGO_PRIVATEDNS = 253, /* private - domain name (see [RFC 2535]) */ + DNS_KEY_ALGO_PRIVATEOID = 254, /* private - OID (see [RFC 2535]) */ + DNS_KEY_ALGO_RESERVED2 = 255 /* reserved, see [RFC 2535] Section 11 */ +}; + #define DNS_RDATACLASS_IN 1 +#define DNS_RDATATYPE_CERT 37 #define DNS_RDATATYPE_SSHFP 44 #define DNS_VERIFY_FOUND 0x00000001 diff -ruN openssh-5.6p1/hostfile.c openssh-5.6p1+x509-6.2.3/hostfile.c --- openssh-5.6p1/hostfile.c 2010-03-04 12:53:35.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/hostfile.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.c,v 1.48 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -14,6 +14,8 @@ * * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. * Copyright (c) 1999 Niels Provos. All rights reserved. + * X.509 certificates support, + * Copyright (c) 2002-2003 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -56,6 +58,7 @@ #include "key.h" #include "hostfile.h" #include "log.h" +#include "ssh-x509.h" static int extract_salt(const char *s, u_int l, char *salt, size_t salt_len) @@ -425,7 +428,17 @@ } fprintf(f, "%s ", store_hash ? hashed_host : host); - if (key_write(key, f)) { +#ifndef SSH_X509STORE_DISABLED + if ((key->type == KEY_X509_RSA) || (key->type == KEY_X509_DSA)) { + /* key_write will print x509 certificate in blob format :-( */ + success = x509key_write_subject(key, f); + } else { +#endif /*ndef SSH_X509STORE_DISABLED*/ + success = key_write(key, f); +#ifndef SSH_X509STORE_DISABLED + } +#endif /*ndef SSH_X509STORE_DISABLED*/ + if (success) { success = 1; } else { error("add_host_to_hostfile: saving key in %s failed", filename); diff -ruN openssh-5.6p1/INSTALL openssh-5.6p1+x509-6.2.3/INSTALL --- openssh-5.6p1/INSTALL 2010-02-12 00:34:22.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/INSTALL 2010-08-24 09:06:00.000000000 +0300 @@ -98,6 +98,9 @@ implementation (http://www.openbsm.org). +X.509 certificate support: +http://roumenpetrov.info/openssh + 2. Building / Installation -------------------------- @@ -208,6 +211,15 @@ --with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to real (AF_INET) IPv4 addresses. Works around some quirks on Linux. +--with-sshca-dir=PATH allows you to specify location of ssh CA root +used by ssh "x509 store" to verify certificates. + +--disable-x509store allows you to disable ssh "x509 store". In that +case ssh don't verify certificates. Format "Distinguished Name" for a +certificate in ssh files is disabled too. In that case ssh accept only +blob format of certificate in files (aka format of pub files). +See 'README.x509v3' for more details. + If you need to pass special options to the compiler or linker, you can specify these as environment variables before running ./configure. For example: @@ -262,4 +274,4 @@ http://www.openssh.com/ -$Id: INSTALL,v 1.85 2010/02/11 22:34:22 djm Exp $ +$Id$ diff -ruN openssh-5.6p1/key.c openssh-5.6p1+x509-6.2.3/key.c --- openssh-5.6p1/key.c 2010-07-16 06:58:37.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/key.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.90 2010/07/13 23:13:16 djm Exp $ */ +/* $OpenBSD$ */ /* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,6 +11,8 @@ * * * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * X.509 certificates support, + * Copyright (c) 2002-2005 Roumen Petrov. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,6 +51,7 @@ #include "xmalloc.h" #include "key.h" #include "rsa.h" +#include "ssh-x509.h" #include "uuencode.h" #include "buffer.h" #include "log.h" @@ -80,10 +83,12 @@ k->type = type; k->dsa = NULL; k->rsa = NULL; + k->x509 = NULL; k->cert = NULL; switch (k->type) { case KEY_RSA1: case KEY_RSA: + case KEY_X509_RSA: case KEY_RSA_CERT_V00: case KEY_RSA_CERT: if ((rsa = RSA_new()) == NULL) @@ -93,8 +98,13 @@ if ((rsa->e = BN_new()) == NULL) fatal("key_new: BN_new failed"); k->rsa = rsa; + if (k->type == KEY_X509_RSA) { + if ((k->x509 = X509_new()) == NULL) + fatal("key_new: X509_new failed"); + } break; case KEY_DSA: + case KEY_X509_DSA: case KEY_DSA_CERT_V00: case KEY_DSA_CERT: if ((dsa = DSA_new()) == NULL) @@ -108,6 +118,10 @@ if ((dsa->pub_key = BN_new()) == NULL) fatal("key_new: BN_new failed"); k->dsa = dsa; + if (k->type == KEY_X509_DSA) { + if ((k->x509 = X509_new()) == NULL) + fatal("key_new: X509_new failed"); + } break; case KEY_UNSPEC: break; @@ -128,6 +142,7 @@ switch (k->type) { case KEY_RSA1: case KEY_RSA: + case KEY_X509_RSA: case KEY_RSA_CERT_V00: case KEY_RSA_CERT: if ((k->rsa->d = BN_new()) == NULL) @@ -142,12 +157,27 @@ fatal("key_new_private: BN_new failed"); if ((k->rsa->dmp1 = BN_new()) == NULL) fatal("key_new_private: BN_new failed"); + if (k->type == KEY_X509_RSA) { + debug3("key_new_private: X509(rsa) MORE ...?"); + /* + if ((k->x509 = X509_new()) == NULL) + fatal("key_new: X509_new failed"); + */ + } break; case KEY_DSA: + case KEY_X509_DSA: case KEY_DSA_CERT_V00: case KEY_DSA_CERT: if ((k->dsa->priv_key = BN_new()) == NULL) fatal("key_new_private: BN_new failed"); + if (k->type == KEY_X509_DSA) { + debug3("key_new_private: X509(dsa) MORE ...?"); + /* + if ((k->x509 = X509_new()) == NULL) + fatal("key_new: X509_new failed"); + */ + } break; case KEY_UNSPEC: break; @@ -204,6 +234,21 @@ DSA_free(k->dsa); k->dsa = NULL; break; + case KEY_X509_RSA: + case KEY_X509_DSA: + if (k->dsa != NULL) { + DSA_free(k->dsa); + k->dsa = NULL; + } + if (k->rsa != NULL) { + RSA_free(k->rsa); + k->rsa = NULL; + } + if (k->x509 != NULL) { + X509_free(k->x509); + k->x509 = NULL; + } + break; case KEY_UNSPEC: break; default: @@ -250,17 +295,29 @@ case KEY_RSA_CERT_V00: case KEY_RSA_CERT: case KEY_RSA: +#ifdef SSH_X509STORE_DISABLED + case KEY_X509_RSA: +#endif return a->rsa != NULL && b->rsa != NULL && BN_cmp(a->rsa->e, b->rsa->e) == 0 && BN_cmp(a->rsa->n, b->rsa->n) == 0; case KEY_DSA_CERT_V00: case KEY_DSA_CERT: case KEY_DSA: +#ifdef SSH_X509STORE_DISABLED + case KEY_X509_DSA: +#endif return a->dsa != NULL && b->dsa != NULL && BN_cmp(a->dsa->p, b->dsa->p) == 0 && BN_cmp(a->dsa->q, b->dsa->q) == 0 && BN_cmp(a->dsa->g, b->dsa->g) == 0 && BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; +#ifndef SSH_X509STORE_DISABLED + case KEY_X509_RSA: + case KEY_X509_DSA: + return ssh_x509_equal(a, b) == 0; + break; +#endif /*ndef SSH_X509STORE_DISABLED*/ default: fatal("key_equal: bad key type %d", a->type); } @@ -313,6 +370,8 @@ break; case KEY_DSA: case KEY_RSA: + case KEY_X509_RSA: + case KEY_X509_DSA: key_to_blob(k, &blob, &len); break; case KEY_DSA_CERT_V00: @@ -491,7 +550,7 @@ field[x][y] = len; /* fill in retval */ - snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k)); + snprintf(retval, FLDSIZE_X, "+[%.8s %4u]", key_type(k), key_size(k)); p = strchr(retval, '\0'); /* output upper border */ @@ -644,6 +703,8 @@ case KEY_UNSPEC: case KEY_RSA: case KEY_DSA: + case KEY_X509_RSA: + case KEY_X509_DSA: case KEY_DSA_CERT_V00: case KEY_RSA_CERT_V00: case KEY_DSA_CERT: @@ -672,6 +733,11 @@ debug3("key_read: type mismatch"); return -1; } +#ifndef SSH_X509STORE_DISABLED + k = x509key_from_subject(type, cp); + if(k != NULL) + goto noblob; +#endif /*ndef SSH_X509STORE_DISABLED*/ len = 2*strlen(cp); blob = xmalloc(len); n = uudecode(cp, blob, len); @@ -691,7 +757,30 @@ key_free(k); return -1; } +noblob: /*XXXX*/ + if (ret->type == KEY_X509_RSA || + ret->type == KEY_X509_DSA ) { + if (ret->rsa != NULL) + RSA_free(ret->rsa); + ret->rsa = k->rsa; + k->rsa = NULL; + if (ret->dsa != NULL) + DSA_free(ret->dsa); + ret->dsa = k->dsa; + k->dsa = NULL; + if (ret->x509 != NULL) + X509_free(ret->x509); + ret->x509 = k->x509; + k->x509 = NULL; +#ifdef DEBUG_PK + if (ret->type == KEY_X509_RSA) + RSA_print_fp(stderr, ret->rsa, 8); + else + DSA_print_fp(stderr, ret->dsa, 8); +#endif + goto x509blob; + } if (key_is_cert(ret)) { if (!key_is_cert(k)) { error("key_read: loaded key is not a cert"); @@ -721,6 +810,7 @@ DSA_print_fp(stderr, ret->dsa, 8); #endif } +x509blob: success = 1; /*XXXX*/ key_free(k); @@ -783,6 +873,9 @@ if (key->rsa == NULL) return 0; break; + case KEY_X509_RSA: + case KEY_X509_DSA: + return x509key_write(key, f); default: return 0; } @@ -810,6 +903,12 @@ return "RSA"; case KEY_DSA: return "DSA"; + case KEY_X509_RSA: + if(k->rsa) return "RSA+cert"; + return "X509(rsa)"; + case KEY_X509_DSA: + if(k->dsa) return "DSA+cert"; + return "X509(dsa)"; case KEY_RSA_CERT_V00: return "RSA-CERT-V00"; case KEY_DSA_CERT_V00: @@ -838,6 +937,11 @@ const char * key_ssh_name(const Key *k) { + const char* p; + + p = ssh_x509key_name(k); + if (p) return(p); + switch (k->type) { case KEY_RSA: return "ssh-rsa"; @@ -868,6 +972,9 @@ case KEY_DSA_CERT_V00: case KEY_DSA_CERT: return BN_num_bits(k->dsa->p); + case KEY_X509_RSA: + case KEY_X509_DSA: + return ssh_x509_key_size(k); } return 0; } @@ -1002,6 +1109,11 @@ int key_type_from_name(char *name) { + int k; + + k = ssh_x509key_type(name); + if (k != KEY_UNSPEC) return(k); + if (strcmp(name, "rsa1") == 0) { return KEY_RSA1; } else if (strcmp(name, "rsa") == 0) { @@ -1194,10 +1306,14 @@ int rlen, type; char *ktype = NULL; Key *key = NULL; + debug3("key_from_blob(..., %d)", blen); #ifdef DEBUG_PK dump_base64(stderr, blob, blen); #endif + if ((key = x509key_from_blob(blob, blen)) != NULL) { + return key; + } buffer_init(&b); buffer_append(&b, blob, blen); if ((ktype = buffer_get_string_ret(&b, NULL)) == NULL) { @@ -1206,6 +1322,7 @@ } type = key_type_from_name(ktype); + debug3("key_from_blob(..., ...) ktype=%.30s", ktype); switch (type) { case KEY_RSA_CERT: @@ -1296,6 +1413,11 @@ buffer_put_bignum2(&b, key->rsa->e); buffer_put_bignum2(&b, key->rsa->n); break; + case KEY_X509_RSA: + case KEY_X509_DSA: + if (!x509key_to_blob(key, &b)) + return 0; + break; default: error("key_to_blob: unsupported key type %d", key->type); buffer_free(&b); @@ -1328,6 +1450,10 @@ case KEY_RSA_CERT: case KEY_RSA: return ssh_rsa_sign(key, sigp, lenp, data, datalen); + case KEY_X509_RSA: + case KEY_X509_DSA: + return ssh_x509_sign(key, sigp, lenp, data, datalen); + break; default: error("key_sign: invalid key type %d", key->type); return -1; @@ -1356,6 +1482,10 @@ case KEY_RSA_CERT: case KEY_RSA: return ssh_rsa_verify(key, signature, signaturelen, data, datalen); + case KEY_X509_RSA: + case KEY_X509_DSA: + return ssh_x509_verify(key, signature, signaturelen, data, datalen); + break; default: error("key_verify: invalid key type %d", key->type); return -1; @@ -1381,6 +1511,7 @@ /* FALLTHROUGH */ case KEY_RSA1: case KEY_RSA: + case KEY_X509_RSA: if ((pk->rsa = RSA_new()) == NULL) fatal("key_demote: RSA_new failed"); if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL) @@ -1393,6 +1524,7 @@ key_cert_copy(k, pk); /* FALLTHROUGH */ case KEY_DSA: + case KEY_X509_DSA: if ((pk->dsa = DSA_new()) == NULL) fatal("key_demote: DSA_new failed"); if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL) @@ -1405,10 +1537,20 @@ fatal("key_demote: BN_dup failed"); break; default: - fatal("key_free: bad key type %d", k->type); + fatal("key_demote: bad key type %d", k->type); break; } + switch (k->type) { + case KEY_X509_RSA: + case KEY_X509_DSA: + if(k->x509) { + if ((pk->x509 = X509_dup(k->x509)) == NULL) + fatal("key_demote: X509_dup failed"); + } else + fatal("key_demote: no X509 data"); + break; + } return (pk); } diff -ruN openssh-5.6p1/key.h openssh-5.6p1+x509-6.2.3/key.h --- openssh-5.6p1/key.h 2010-04-16 08:56:22.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/key.h 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,9 @@ -/* $OpenBSD: key.h,v 1.30 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * X.509 certificates support, + * Copyright (c) 2002 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,6 +31,7 @@ #include "buffer.h" #include #include +#include typedef struct Key Key; enum types { @@ -39,6 +42,8 @@ KEY_DSA_CERT, KEY_RSA_CERT_V00, KEY_DSA_CERT_V00, + KEY_X509_RSA, + KEY_X509_DSA, KEY_UNSPEC }; enum fp_type { @@ -73,6 +78,7 @@ int flags; RSA *rsa; DSA *dsa; + X509 *x509; struct KeyCert *cert; }; diff -ruN openssh-5.6p1/LICENCE openssh-5.6p1+x509-6.2.3/LICENCE --- openssh-5.6p1/LICENCE 2007-03-12 22:37:49.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/LICENCE 2010-08-24 09:06:00.000000000 +0300 @@ -181,6 +181,7 @@ Per Allansson Nils Nordman Simon Wilkinson + Roumen Petrov Portable OpenSSH additionally includes code from the following copyright holders, also under the 2-term BSD license: @@ -335,4 +336,4 @@ ------ -$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $ +$OpenBSD$ diff -ruN openssh-5.6p1/log.c openssh-5.6p1+x509-6.2.3/log.c --- openssh-5.6p1/log.c 2008-06-10 16:01:51.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/log.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.41 2008/06/10 04:50:25 dtucker Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -324,6 +324,11 @@ #endif } +LogLevel +get_log_level(void) { + return log_level; +} + #define MSGBUFSIZ 1024 void @@ -389,11 +394,11 @@ } else { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); - syslog_r(pri, &sdata, "%.500s", fmtbuf); + syslog_r(pri, &sdata, "%.1000s", fmtbuf); closelog_r(&sdata); #else openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); - syslog(pri, "%.500s", fmtbuf); + syslog(pri, "%.1000s", fmtbuf); closelog(); #endif } diff -ruN openssh-5.6p1/log.h openssh-5.6p1+x509-6.2.3/log.h --- openssh-5.6p1/log.h 2008-06-13 03:22:54.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/log.h 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: log.h,v 1.17 2008/06/13 00:12:02 dtucker Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen @@ -47,6 +47,7 @@ } LogLevel; void log_init(char *, LogLevel, SyslogFacility, int); +LogLevel get_log_level(void); SyslogFacility log_facility_number(char *); const char * log_facility_name(SyslogFacility); diff -ruN openssh-5.6p1/m4/ldap.m4 openssh-5.6p1+x509-6.2.3/m4/ldap.m4 --- openssh-5.6p1/m4/ldap.m4 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/m4/ldap.m4 2007-10-22 23:05:29.000000000 +0300 @@ -0,0 +1,217 @@ +# Options to build with LDAP +# +# Author: Roumen Petrov +# Revision: 22 Oct 2007 +# +dnl The variables provided are : +dnl - build flags: +dnl LDAP_LDFLAGS +dnl LDAP_LIBS +dnl LDAP_CPPFLAGS +dnl - conditional: +dnl LDAP_ON (e.g. '' or '#') +dnl LDAP_OFF (e.g. '#' or '' - oposite of LDAP_ON) +dnl - paths: +dnl LDAP_BINDIR +dnl LDAP_LIBEXECDIR +dnl LDAP_SYSCONFDIR + +AC_DEFUN([AC_WITH_LDAP], +[ +dnl +dnl Get the ldap paths +dnl + +ac_ldap='none' +AC_ARG_ENABLE(ldap, + [ --enable-ldap Enable LDAP queries], + ac_ldap="$enableval" +) + +if test "x$ac_ldap" = xyes; then + ac_ldap_prefix="" + AC_ARG_WITH(ldap-prefix, + [ --with-ldap-prefix=PATH Prefix where LDAP is installed (optional)], + ac_ldap_prefix="$withval" + ) + + AC_ARG_WITH(ldap-bindir, + [ --with-ldap-bindir=PATH Prefix where LDAP user executables are installed (optional)], + [LDAP_BINDIR="$withval"], + [ + if test "x$ac_ldap_prefix" != "x"; then + LDAP_BINDIR="$ac_ldap_prefix/bin" + fi + ] + ) + AC_SUBST(LDAP_BINDIR) + + AC_ARG_WITH(ldap-libexecdir, + [ --with-ldap-libexecdir=PATH Prefix where LDAP program executables are installed (optional)], + [LDAP_LIBEXECDIR="$withval"], + [ + if test "x$ac_ldap_prefix" = "x"; then + LDAP_LIBEXECDIR="/usr/libexec" + else + LDAP_LIBEXECDIR="$ac_ldap_prefix/libexec" + fi + ] + ) + AC_SUBST(LDAP_LIBEXECDIR) +dnl### Check for slapd +dnl if test "x$cross_compiling" = "xyes" ; then +dnl AC_MSG_NOTICE([cannot check for LDAP daemon when cross compiling]) +dnl else +dnl AC_CHECK_FILES( +dnl [ +dnl $LDAP_LIBEXECDIR/slapd +dnl ] +dnl ) +dnl fi + + AC_ARG_WITH(ldap-sysconfdir, + [ --with-ldap-sysconfdir=PATH Prefix where LDAP single-machine data are installed (optional)], + [LDAP_SYSCONFDIR="$withval"], + [LDAP_SYSCONFDIR="$ac_ldap_prefix/etc/openldap"] + ) + AC_SUBST(LDAP_SYSCONFDIR) +dnl### Check for schema files +dnl if test "x$cross_compiling" = "xyes" ; then +dnl AC_MSG_NOTICE([cannot check for schema files existence when cross compiling]) +dnl else +dnl AC_CHECK_FILES( +dnl [ +dnl $LDAP_SYSCONFDIR/schema/core.schema +dnl $LDAP_SYSCONFDIR/schema/cosine.schema +dnl $LDAP_SYSCONFDIR/schema/inetorgperson.schema +dnl ] +dnl ) +dnl fi + + + AC_ARG_WITH(ldap-libdir, + [ --with-ldap-libdir=PATH Prefix where LDAP libaries are installed (optional)], + [LDAP_LDFLAGS="-L$withval"], + [ + if test "x$ac_ldap_prefix" != "x"; then + LDAP_LDFLAGS="-L$ac_ldap_prefix/lib" + else + LDAP_LDFLAGS="" + fi + ] + ) + AC_SUBST(LDAP_LDFLAGS) + + AC_ARG_WITH(ldap-includedir, + [ --with-ldap-includedir=PATH Prefix where LDAP header files are installed (optional)], + [LDAP_CPPFLAGS="-I$withval"], + [ + if test "x$ac_ldap_prefix" != "x"; then + LDAP_CPPFLAGS="-I$ac_ldap_prefix/include" + else + LDAP_CPPFLAGS="" + fi + ] + ) + AC_SUBST(LDAP_CPPFLAGS) + + + ac_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $LDAP_CPPFLAGS" + AC_CHECK_HEADERS( + [lber.h ldap.h], + [], + [ + AC_MSG_ERROR([cannot found LDAP headers]) + ] + ) + CPPFLAGS="$ac_save_CPPFLAGS" + + ac_ldap_libs="" + AC_ARG_WITH(ldap-libs, + [ --with-ldap-libs=LIBS Specify LDAP libraries to link with. + (default is -lldap -llber -lssl -lcrypto)], + [ac_ldap_libs="$withval"] + ) + +### Try to link with LDAP libs + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + + LDFLAGS="$LDAP_LDFLAGS $LDFLAGS" + ac_LDAP_LINK="" + if test "x$ac_ldap_libs" != "x"; then + AC_MSG_CHECKING([to link with specified LDAP libs]) + + LDAP_LIBS="$ac_ldap_libs" + LIBS="$LDAP_LIBS $ac_save_LIBS" + AC_LINK_IFELSE( + [AC_LANG_CALL([], [ldap_init])], + [ac_LDAP_LINK="yes"] + ) + if test "x$ac_LDAP_LINK" != "xyes"; then + AC_MSG_ERROR([cannot link with specified LDAP libs]) + fi + else + AC_MSG_CHECKING([how to link LDAP libs]) + + LDAP_LIBS="-lldap" + for L in lber ssl crypto; do + LDAP_LIBS="$LDAP_LIBS -l$L" + LIBS="$LDAP_LIBS $ac_save_LIBS" + AC_LINK_IFELSE( + [AC_LANG_CALL([], [ldap_init])], + [ac_LDAP_LINK="yes"] + ) + if test "x$ac_LDAP_LINK" = "xyes"; then + break + fi + done + if test "x$ac_LDAP_LINK" != "xyes"; then + AC_MSG_ERROR([cannot link with default LDAP libs]) + fi + fi + AC_MSG_RESULT([done]) + LIBS="$ac_save_LIBS" + LDFLAGS="$ac_save_LDFLAGS" + AC_SUBST([LDAP_LIBS]) +else + AC_MSG_NOTICE([LDAP is disabled]) +fi + +if test "x$ac_ldap" = "xyes"; then + AC_DEFINE_UNQUOTED( + LDAP_ENABLED, 1, + [Define if you want to enable LDAP queries]) + LDAP_ON='' + LDAP_OFF='#' +else + LDAP_ON='#' + LDAP_OFF='' +fi +AC_SUBST(LDAP_ON) +AC_SUBST(LDAP_OFF) +]) + + +# AC_LDAP_FUNCS(FUNCTION...) +# -------------------------------- +AC_DEFUN([AC_LDAP_FUNCS], +[ +dnl +dnl Check ldap functions +dnl +AC_REQUIRE([AC_WITH_LDAP]) +if test "x$ac_ldap" = "xyes"; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $LDAP_CPPFLAGS" + LDFLAGS="$LDFLAGS $LDAP_LDFLAGS" + LIBS="$LDAP_LIBS $LIBS" + AC_CHECK_FUNCS([$1],[],[]) + LIBS="$ac_save_LIBS" + LDFLAGS="$ac_save_LDFLAGS" + CPPFLAGS="$ac_save_CPPFLAGS" +fi +]) diff -ruN openssh-5.6p1/Makefile.in openssh-5.6p1+x509-6.2.3/Makefile.in --- openssh-5.6p1/Makefile.in 2010-05-12 09:51:39.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/Makefile.in 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.310 2010/05/12 06:51:39 dtucker Exp $ +# $Id$ # uncomment if you run a non bourne compatable shell. Ie. csh #SHELL = @SH@ @@ -15,6 +15,7 @@ mandir=@mandir@ mansubdir=@mansubdir@ sysconfdir=@sysconfdir@ +sshcadir=@sshcadir@ piddir=@piddir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ @@ -32,6 +33,7 @@ STRIP_OPT=@STRIP_OPT@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ + -DSSHCADIR=\"$(sshcadir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ @@ -44,10 +46,11 @@ CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ -CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ +CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ @LDAP_CPPFLAGS@ $(PATHS) @DEFS@ LIBS=@LIBS@ SSHDLIBS=@SSHDLIBS@ LIBEDIT=@LIBEDIT@ +LIBLDAP=@LDAP_LDFLAGS@ @LDAP_LIBS@ AR=@AR@ AWK=@AWK@ RANLIB=@RANLIB@ @@ -62,6 +65,15 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ +@LDAP_ON@LDAP_OBJS=x509_by_ldap.o +@LDAP_OFF@LDAP_OBJS= + +@OCSP_ON@OCSP_OBJS=ssh-ocsp.o +@OCSP_OFF@OCSP_OBJS= + +SSHX509_OBJS=ssh-x509.o ssh-xkalg.o x509_nm_cmp.o +X509STORE_OBJS=x509store.o $(LDAP_OBJS) $(OCSP_OBJS) + TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT) LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ @@ -71,13 +83,13 @@ log.o match.o md-sha256.o moduli.o nchan.o packet.o \ readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o $(SSHX509_OBJS) dh.o kexdh.o \ kexgex.o kexdhc.o kexgexc.o msg.o progressmeter.o dns.o \ entropy.o gss-genr.o umac.o jpake.o schnorr.o \ ssh-pkcs11.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o mux.o \ + sshconnect.o sshconnect1.o sshconnect2.o $(X509STORE_OBJS) mux.o \ roaming_common.o roaming_client.o SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ @@ -91,7 +103,7 @@ auth2-gss.o gss-serv.o gss-serv-krb5.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \ - roaming_common.o roaming_serv.o + roaming_common.o roaming_serv.o $(X509STORE_OBJS) MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 @@ -110,6 +122,10 @@ -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \ -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \ -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \ + -e 's|/etc/ssh/ca/ca-bundle.crt|$(sshcadir)/ca-bundle.crt|g' \ + -e 's|/etc/ssh/ca/crt|$(sshcadir)/crt|g' \ + -e 's|/etc/ssh/ca/ca-bundle.crl|$(sshcadir)/ca-bundle.crl|g' \ + -e 's|/etc/ssh/ca/crl|$(sshcadir)/crl|g' \ -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \ -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \ -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \ @@ -139,10 +155,10 @@ $(RANLIB) $@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) - $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBLDAP) $(LIBS) sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) - $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) + $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBLDAP) $(SSHDLIBS) $(LIBS) scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) @@ -156,8 +172,8 @@ ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o - $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o $(X509STORE_OBJS) roaming_dummy.o + $(LD) -o $@ ssh-keysign.o readconf.o $(X509STORE_OBJS) roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBLDAP) $(LIBS) ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) @@ -215,6 +231,7 @@ rm -f survey.sh openbsd-compat/regress/Makefile *~ rm -rf autom4te.cache (cd openbsd-compat && $(MAKE) distclean) + (cd tests/CA && $(MAKE) distclean) if test -d pkg ; then \ rm -fr pkg ; \ fi @@ -253,6 +270,8 @@ $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)5 $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8 $(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir) + $(srcdir)/mkinstalldirs $(DESTDIR)$(sshcadir) + $(srcdir)/mkinstalldirs $(DESTDIR)$(piddir) (umask 022 ; $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH)) $(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT) @@ -386,6 +405,10 @@ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 + +# Target check is more common for the projects using autoXXXX tools +check: tests + tests interop-tests: $(TARGETS) BUILDDIR=`pwd`; \ [ -d `pwd`/regress ] || mkdir -p `pwd`/regress; \ @@ -427,7 +450,22 @@ TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \ TEST_SSH_IPV6="@TEST_SSH_IPV6@" \ EXEEXT="$(EXEEXT)" \ - $@ && echo all tests passed + $@ && echo all mainstream tests passed + $(MAKE) check-certs + +check-certs: $(TARGETS) + @BUILDDIR="`pwd`"; \ + ( cd "tests/CA" && \ + $(MAKE) \ + TEST_SSH_SSH="$${BUILDDIR}/ssh" \ + TEST_SSH_SSHD="$${BUILDDIR}/sshd" \ + TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent" \ + TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add" \ + TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen" \ + TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan" \ + TEST_SSH_SFTP="$${BUILDDIR}/sftp" \ + TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server" \ + $@ ) compat-tests: $(LIBCOMPAT) (cd openbsd-compat/regress && $(MAKE)) @@ -436,6 +474,7 @@ if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \ (cd regress && $(MAKE) clean) \ fi + (cd tests/CA && $(MAKE) clean) survey: survey.sh ssh @$(SHELL) ./survey.sh > survey @@ -451,3 +490,6 @@ sh buildpkg.sh; \ fi +depend: + (cd openbsd-compat && $(MAKE) $@) + makedepend -- $(CPPFLAGS) $(CFLAGS) -- $(srcdir)/*.c diff -ruN openssh-5.6p1/moduli.0 openssh-5.6p1+x509-6.2.3/moduli.0 --- openssh-5.6p1/moduli.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/moduli.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -MODULI(5) OpenBSD Programmer's Manual MODULI(5) +MODULI(5) BSD File Formats Manual MODULI(5) NAME - moduli - Diffie Hellman moduli + moduli -- Diffie Hellman moduli DESCRIPTION The /etc/moduli file contains prime numbers and generators for use by @@ -14,12 +14,11 @@ are prime and are safe for use in Diffie Hellman operations by sshd(8). This moduli format is used as the output from each pass. - The file consists of newline-separated records, one per modulus, - containing seven space separated fields. These fields are as follows: + The file consists of newline-separated records, one per modulus, contain- + ing seven space separated fields. These fields are as follows: - - timestamp The time that the modulus was last processed as - YYYYMMDDHHMMSS. + timestamp The time that the modulus was last processed as YYYYM- + MDDHHMMSS. type Decimal number specifying the internal structure of the prime modulus. Supported types are: @@ -70,4 +69,4 @@ Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, 2006. -OpenBSD 4.8 June 26, 2008 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/monitor.c openssh-5.6p1+x509-6.2.3/monitor.c --- openssh-5.6p1/monitor.c 2010-08-03 08:50:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/monitor.c 2010-08-24 09:06:01.000000000 +0300 @@ -671,6 +671,11 @@ out: buffer_put_string(m, &options, sizeof(options)); + + /* we must sent emtpy string for string options that are not set */ + buffer_put_cstring(m, (options.hostbased_algorithms ? options.hostbased_algorithms : "")); + buffer_put_cstring(m, (options.pubkey_algorithms ? options.pubkey_algorithms : "")); + if (options.banner != NULL) buffer_put_cstring(m, options.banner); debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); diff -ruN openssh-5.6p1/monitor_wrap.c openssh-5.6p1+x509-6.2.3/monitor_wrap.c --- openssh-5.6p1/monitor_wrap.c 2010-03-07 14:05:17.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/monitor_wrap.c 2010-08-24 09:06:01.000000000 +0300 @@ -244,6 +244,18 @@ newopts = buffer_get_string(&m, &len); if (len != sizeof(*newopts)) fatal("%s: option block size mismatch", __func__); + + newopts->hostbased_algorithms = buffer_get_string(&m, NULL); + if (*newopts->hostbased_algorithms == '\0') { + xfree(newopts->hostbased_algorithms); + newopts->hostbased_algorithms = NULL; + } + newopts->pubkey_algorithms = buffer_get_string(&m, NULL); + if (*newopts->pubkey_algorithms == '\0') { + xfree(newopts->pubkey_algorithms); + newopts->pubkey_algorithms = NULL; + } + if (newopts->banner != NULL) newopts->banner = buffer_get_string(&m, NULL); copy_set_server_options(&options, newopts, 1); diff -ruN openssh-5.6p1/openbsd-compat/Makefile.in openssh-5.6p1+x509-6.2.3/openbsd-compat/Makefile.in --- openssh-5.6p1/openbsd-compat/Makefile.in 2010-08-16 06:15:23.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/openbsd-compat/Makefile.in 2010-08-24 09:06:01.000000000 +0300 @@ -40,3 +40,6 @@ distclean: clean rm -f Makefile *~ + +depend: + makedepend -- $(CPPFLAGS) $(CFLAGS) -- $(srcdir)/*.c diff -ruN openssh-5.6p1/pathnames.h openssh-5.6p1+x509-6.2.3/pathnames.h --- openssh-5.6p1/pathnames.h 2010-02-24 08:17:58.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/pathnames.h 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.19 2010/02/11 20:37:47 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen @@ -10,6 +10,29 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X.509 certificates support, + * Copyright (c) 2002 Roumen Petrov. 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. */ #define ETCDIR "/etc" @@ -177,3 +200,20 @@ #ifndef ASKPASS_PROGRAM #define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass" #endif /* ASKPASS_PROGRAM */ + + +#ifndef SSHCADIR +#define SSHCADIR SSHDIR "/ca" +#endif + +/* x509 user store */ +#define _PATH_USERCA_CERTIFICATE_FILE "~/" _PATH_SSH_USER_DIR "/ca-bundle.crt" +#define _PATH_USERCA_CERTIFICATE_PATH "~/" _PATH_SSH_USER_DIR "/crt" +#define _PATH_USERCA_REVOCATION_FILE "~/" _PATH_SSH_USER_DIR "/ca-bundle.crl" +#define _PATH_USERCA_REVOCATION_PATH "~/" _PATH_SSH_USER_DIR "/crl" + +/* x509 system store */ +#define _PATH_CA_CERTIFICATE_FILE SSHCADIR "/ca-bundle.crt" +#define _PATH_CA_CERTIFICATE_PATH SSHCADIR "/crt" +#define _PATH_CA_REVOCATION_FILE SSHCADIR "/ca-bundle.crl" +#define _PATH_CA_REVOCATION_PATH SSHCADIR "/crl" diff -ruN openssh-5.6p1/readconf.c openssh-5.6p1+x509-6.2.3/readconf.c --- openssh-5.6p1/readconf.c 2010-08-03 09:04:46.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/readconf.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.187 2010/07/19 09:15:12 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,6 +10,29 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X509 certificate support, + * Copyright (c) 2002-2006 Roumen Petrov. 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" @@ -41,6 +64,8 @@ #include "misc.h" #include "buffer.h" #include "kex.h" +#include "myproposal.h" +#include "ssh-xkalg.h" #include "mac.h" /* Format of the configuration file: @@ -130,6 +155,18 @@ oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, + oPubkeyAlgorithms, + oX509KeyAlgorithm, + oAllowedServerCertPurpose, + oMandatoryCRL, + oCACertificateFile, oCACertificatePath, + oCARevocationFile, oCARevocationPath, + oCAldapVersion, oCAldapURL, + oUserCACertificateFile, oUserCACertificatePath, + oUserCARevocationFile, oUserCARevocationPath, + oUserCAldapVersion, oUserCAldapURL, + oVAType, oVACertificateFile, + oVAOCSPResponderURL, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, oDeprecated, oUnsupported @@ -228,6 +265,26 @@ { "controlmaster", oControlMaster }, { "controlpersist", oControlPersist }, { "hashknownhosts", oHashKnownHosts }, + { "pubkeyalgorithms", oPubkeyAlgorithms }, + { "x509rsasigtype", oDeprecated }, + { "x509keyalgorithm", oX509KeyAlgorithm }, + { "allowedcertpurpose", oAllowedServerCertPurpose }, + { "mandatorycrl", oMandatoryCRL }, + { "cacertificatefile", oCACertificateFile }, + { "cacertificatepath", oCACertificatePath }, + { "carevocationfile", oCARevocationFile }, + { "carevocationpath", oCARevocationPath }, + { "caldapversion", oCAldapVersion }, + { "caldapurl", oCAldapURL }, + { "usercacertificatefile", oUserCACertificateFile }, + { "usercacertificatepath", oUserCACertificatePath }, + { "usercarevocationfile", oUserCARevocationFile }, + { "usercarevocationpath", oUserCARevocationPath }, + { "usercaldapversion", oCAldapVersion }, + { "usercaldapurl", oCAldapURL }, + { "vatype", oVAType }, + { "vacertificatefile", oVACertificateFile }, + { "vaocspresponderurl", oVAOCSPResponderURL }, { "tunnel", oTunnel }, { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, @@ -703,9 +760,11 @@ arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing argument.", filename, linenum); + /* cannot validate here - depend from X509KeyAlgorithm if (!key_names_valid2(arg)) fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", filename, linenum, arg ? arg : ""); + */ if (*activep && options->hostkeyalgorithms == NULL) options->hostkeyalgorithms = xstrdup(arg); break; @@ -963,11 +1022,180 @@ intptr = &options->use_roaming; goto parse_flag; + case oPubkeyAlgorithms: + charptr = (char**)&options->pubkey_algorithms; + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + /* cannot validate here - depend from X509KeyAlgorithm + if (!key_names_valid2(arg)) + fatal("%.200s line %d: Bad protocol 2 public key algorithms '%s'.", + filename, linenum, arg ? arg : ""); + */ + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + break; + + case oX509KeyAlgorithm: + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + + if (*activep) { + if (ssh_add_x509key_alg(arg) < 0) { + fatal("%.200s line %d: Bad X.509 key algorithm '%.200s'.", + filename, linenum, arg); + } + } + break; + + case oAllowedServerCertPurpose: + intptr = &options->x509flags->allowedcertpurpose; + arg = strdelim(&s); + if (arg && *arg) { + if (strcasecmp(arg, "skip") == 0) goto skip_purpose; + + /* convert string to OpenSSL index */ + value = ssh_get_x509purpose_s (0, arg); + if (value < 0) + fatal("%.200s line %d: Bad certificate purpose '%.30s'.", + filename, linenum, arg); + + if (*activep && *intptr == -1) + *intptr = value; + } else { +skip_purpose: + if (*activep && *intptr == -1) { + *intptr = -2; + verbose("%.200s line %d: option is set to don`t check certificate purpose.", + filename, linenum); + } + } + break; + +#ifndef SSH_X509STORE_DISABLED + case oMandatoryCRL: + intptr = &options->x509flags->mandatory_crl; + goto parse_flag; + + case oCACertificateFile: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.certificate_file; + goto parse_string; + + case oCACertificatePath: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.certificate_path; + goto parse_string; + + case oCARevocationFile: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.revocation_file; + goto parse_string; + + case oCARevocationPath: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.revocation_path; + goto parse_string; + + case oUserCACertificateFile: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->userca.certificate_file; + goto parse_string; + + case oUserCACertificatePath: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->userca.certificate_path; + goto parse_string; + + case oUserCARevocationFile: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->userca.revocation_file; + goto parse_string; + + case oUserCARevocationPath: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->userca.revocation_path; + goto parse_string; +#endif /*ndef SSH_X509STORE_DISABLED*/ + +#ifdef LDAP_ENABLED + case oCAldapVersion: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.ldap_ver; + goto parse_string; + + case oCAldapURL: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.ldap_url; + goto parse_string; + + case oUserCAldapVersion: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->userca.ldap_ver; + goto parse_string; + + case oUserCAldapURL: + /*X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->userca.ldap_url; + goto parse_string; +#endif /*def LDAP_ENABLED*/ + +#ifdef SSH_OCSP_ENABLED + case oVAType: + intptr = &options->va.type; + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + + value = ssh_get_vatype_s(arg); + if (value < 0) { + fatal("%.200s line %d: Bad OCSP responder type '%.30s'.", + filename, linenum, arg); + } + + if (*activep && *intptr == -1) + *intptr = value; + break; + + case oVACertificateFile: + /* VAOptions prefered type is 'const char*' */ + charptr = (char**)&options->va.certificate_file; + goto parse_string; + + case oVAOCSPResponderURL: + /* VAOptions prefered type is 'const char*' */ + charptr = (char**)&options->va.responder_url; + goto parse_string; +#endif /*def SSH_OCSP_ENABLED*/ + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); return 0; +#ifdef SSH_X509STORE_DISABLED + case oMandatoryCRL: + case oCACertificateFile: + case oCACertificatePath: + case oCARevocationFile: + case oCARevocationPath: + case oUserCACertificateFile: + case oUserCACertificatePath: + case oUserCARevocationFile: + case oUserCARevocationPath: +#endif /*def SSH_X509STORE_DISABLED*/ +#ifndef LDAP_ENABLED + case oCAldapVersion: + case oCAldapURL: + case oUserCAldapVersion: + case oUserCAldapURL: +#endif /*ndef LDAP_ENABLED*/ +#ifndef SSH_OCSP_ENABLED + case oVAType: + case oVACertificateFile: + case oVAOCSPResponderURL: +#endif /*ndef SSH_OCSP_ENABLED*/ case oUnsupported: error("%s line %d: Unsupported option \"%s\"", filename, linenum, keyword); @@ -1112,6 +1340,20 @@ options->control_persist = -1; options->control_persist_timeout = 0; options->hash_known_hosts = -1; + options->pubkey_algorithms = NULL; + /* Supported X.509 key algorithms and signatures + are defined is external source. */ + options->x509flags = &ssh_x509flags; + ssh_x509flags_initialize(options->x509flags, 0); +#ifndef SSH_X509STORE_DISABLED + ssh_x509store_initialize(&options->ca); + ssh_x509store_initialize(&options->userca); +#endif /*ndef SSH_X509STORE_DISABLED*/ +#ifdef SSH_OCSP_ENABLED + options->va.type = -1; + options->va.certificate_file = NULL; + options->va.responder_url = NULL; +#endif /*def SSH_OCSP_ENABLED*/ options->tun_open = -1; options->tun_local = -1; options->tun_remote = -1; @@ -1122,6 +1364,22 @@ options->zero_knowledge_password_authentication = -1; } +#ifndef SSH_X509STORE_DISABLED +static int +ssh_x509store_init (Options *options) { + int x509_store_loaded = 0; + + if(ssh_x509store_addlocations(&options->userca)) { + x509_store_loaded = 1; + } + if(ssh_x509store_addlocations(&options->ca)) { + x509_store_loaded = 1; + } + + return x509_store_loaded; +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + /* * Called after processing other sources of option data, this fills those * options for which no value has been specified with their default values. @@ -1192,6 +1450,7 @@ /* options->ciphers, default set in myproposals.h */ /* options->macs, default set in myproposals.h */ /* options->hostkeyalgorithms, default set in myproposals.h */ + /* HostKeyAlgorithms depend from X509KeyAlgorithm options */ if (options->protocol == SSH_PROTO_UNKNOWN) options->protocol = SSH_PROTO_2; if (options->num_identity_files == 0) { @@ -1272,6 +1531,58 @@ /* options->hostname will be set in the main program if appropriate */ /* options->host_key_alias should not be set by default */ /* options->preferred_authentications will be set in ssh */ + + /* options->pubkey_algorithms */ + fill_default_xkalg(); + ssh_x509flags_defaults(options->x509flags); +#ifndef SSH_X509STORE_DISABLED + ssh_x509store_system_defaults(&options->ca); + + { + extern uid_t original_real_uid; + ssh_x509store_user_defaults(&options->userca, original_real_uid); + } + + ssh_x509store_init(options); +#endif /*ndef SSH_X509STORE_DISABLED*/ +#ifdef SSH_OCSP_ENABLED + if (options->va.type == -1) + options->va.type = ssh_get_default_vatype(); + ssh_set_validator(&options->va); +#endif /*def SSH_OCSP_ENABLED*/ + + if (options->hostkeyalgorithms != NULL) { + if (!key_names_valid2(options->hostkeyalgorithms)) + fatal("Bad protocol 2 host key algorithms '%s'.", + options->hostkeyalgorithms); + } else { + Buffer b; + + buffer_init(&b); + ssh_list_xkalg(KEY_X509_RSA, &b); + ssh_list_xkalg(KEY_X509_DSA, &b); + if (buffer_len(&b) > 0) { + /* use defined X.509 "key type name" plus default set in myproposals.h */ + const char *p = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; + + buffer_append(&b, ",", 1); + buffer_append(&b, p, strlen(p)); + buffer_append(&b, "\0", 1); + + options->hostkeyalgorithms = xstrdup(buffer_ptr(&b)); + } else { + /* use default set in myproposals.h */ + } +#ifdef TRACE_XKALG +fprintf(stderr, "TRACE_XKALG hostkeyalgorithms='%s'\n", (options->hostkeyalgorithms ? options->hostkeyalgorithms : "")); +#endif + buffer_free(&b); + } + + if (options->pubkey_algorithms != NULL) + if (!key_names_valid2(options->pubkey_algorithms)) + fatal("Bad protocol 2 public key algorithms '%s'.", + options->pubkey_algorithms); } /* diff -ruN openssh-5.6p1/readconf.h openssh-5.6p1+x509-6.2.3/readconf.h --- openssh-5.6p1/readconf.h 2010-08-03 09:04:46.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/readconf.h 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.86 2010/07/19 09:15:12 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen @@ -11,11 +11,36 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X509 certificate support, + * Copyright (c) 2002-2006 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef READCONF_H #define READCONF_H +#include "x509store.h" + /* Data structure for representing a forwarding request. */ typedef struct { @@ -119,6 +144,24 @@ int hash_known_hosts; + char* pubkey_algorithms; /* Allowed pubkey algorithms. */ + + /* Supported X.509 key algorithms and signatures + are defined is external source. */ + + /* ssh PKI(X509) flags */ + SSH_X509Flags *x509flags; +#ifndef SSH_X509STORE_DISABLED + /* sshd PKI(X509) system store */ + X509StoreOptions ca; + /* sshd PKI(X509) user store */ + X509StoreOptions userca; +#endif /*ndef SSH_X509STORE_DISABLED*/ +#ifdef SSH_OCSP_ENABLED + /* ssh X.509 extra validation */ + VAOptions va; +#endif /*def SSH_OCSP_ENABLED*/ + int tun_open; /* tun(4) */ int tun_local; /* force tun device (optional) */ int tun_remote; /* force tun device (optional) */ diff -ruN openssh-5.6p1/README.x509v3 openssh-5.6p1+x509-6.2.3/README.x509v3 --- openssh-5.6p1/README.x509v3 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/README.x509v3 2009-12-26 17:25:29.000000000 +0200 @@ -0,0 +1,512 @@ + Roumen Petrov + Sofia, Bulgaria + Mon Mar 31 2008 + +How to use X.509 certificates with OpenSSH? + + +Identity or hostkey file for protocol version 2 can contain private key +plus X.509 certificate in PEM format. Note that protocol version 2 keys +are in PEM format. To use X.509 certificate as identity or hostkey user +should convert certificate in PEM format and append to file. After this +with "ssh-keygen -y ..." user must update "pub" file. +File (identity or hostkey) with X.509 certificate (RSA key): +-----BEGIN RSA PRIVATE KEY----- +..... +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +..... +-----END CERTIFICATE----- +Note that to use X.509 certificates in OpenSSH files must contain +private key followed by certificate that match private key! + + +1.) server configuration: + +1.1.) .../sshd_config + +1.1.1.) AllowedCertPurpose sslclient + The intended use off the X.509 client certificate. + +1.1.2.) "X509 store". + Server use "X509 store" to verify and validate client keys. + +1.1.2.1.) CACertificateFile /etc/ssh/ca/ca-bundle.crt + This file contain multiple certificates of certificate signers in PEM +format concatenated together. You can get a copy from openssl, apache, +KDE, mutt, etc. packages. Original file might is exported from Netscape +certificate database and one download URL is: + http://www.modssl.org/contrib/ca-bundle.crt.tar.gz + +1.1.2.2.) CACertificatePath /etc/ssh/ca/crt + "Hash dir" with certificates of certificate signers. Each certificate +should be stored in separate file with name [HASH].[NUMBER], where +[HASH] is certificate hash value and [NUMBER] is an integer starting +from zero. Hash is result from command like this: +$ openssl x509 -in certificate_file_name -noout -hash + +1.1.2.3.) CARevocationFile /etc/ssh/ca/ca-bundle.crl + This file contain multiple "Certificate Revocation List" (CRL) of +certificate signers in PEM format concatenated together. + +1.1.2.4.) CARevocationPath /etc/ssh/ca/crl + "Hash dir" with "Certificate Revocation List" (CRL) of certificate +signers. Each CRL should be stored in separate file with name +[HASH].r[NUMBER], where [HASH] is CRL hash value and [NUMBER] is an +integer starting from zero. Hash is result from command like this: +$ openssl crl -in crl_file_name -noout -hash + +1.1.2.5.) CAldapVersion + LDAP protocol version. Default depend from LDAP library. + +1.1.2.6.) CAldapURL + Hostport and dn of LDAP URL. No default value. + +1.1.3.) HostKey files... + Host key for protocol version 2 can contain private key plus X.509 +certificate in PEM format. + +1.1.4.) X509KeyAlgorithm + This is new option that replace old one X509rsaSigType. + The option list multiple "X509 Key Algorithms Formats" + supported by server. + The format is described in sshd_config(5). + The default for certificates with RSA key is: + X509KeyAlgorithm x509v3-sign-rsa,rsa-md5 + X509KeyAlgorithm x509v3-sign-rsa,rsa-sha1 + The default for certificates with DSA key is: + X509KeyAlgorithm x509v3-sign-dss,dss-asn1 + X509KeyAlgorithm x509v3-sign-dss,dss-raw + The first listed format for each key-type, i.e. RSA or DSA + is used as default in signing. The server will accept + all listed formats. + +1.1.5.) X509rsaSigType=md5 + Deprecated option replaced by X509KeyAlgorithm. + +1.1.6.) VAType none + Specifies whether `Online Certificate Status Protocol' (OCSP) is used + to validate client X.509 certificates. Specified value is used only + when OpenSSH is build with OCSP support. See sshd_config(5) man page + for allowed values and other VA* options. + +1.1.7.) KeyAllowSelfIssued no + Specifies whether self-issued(self-signed) X.509 certificate can be + allowed only by entry in AutorizedKeysFile that contain matching + public key or certificate blob. + +1.2.) user files on the server + Append in USER_HOME/.ssh/authorized_keys a record with following +format: +{|CertBlob} +where: +KEY_TYPE:=x509v3-sign-rsa|x509v3-sign-dss (case sensitive !) +WORDDN:={Distinguished Name| + Distinguished-Name| + Distinguished_Name| + DistinguishedName| + DN| + Subject} +WORDDNSUFF:='='|':'|'' +NOTES: +- WORDDN is case insensitive ! + +- is like output from command: +$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE -nameopt oneline + +- can be in RFC2253 format like output from command: +$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE -nameopt RFC2253 + +IMPORTANT NOTE (if a distinguished name contain non-ascii character): +- for versions 6.+: + ALWAIS use "openssl x509" command option -nameopt ! + The parser don't and won't support output without -nameopt +- for versions prior 6.0: + The program could'not parse non-latin subject. Use "blob" format (see below). + +- Order of items in is not important and separator +can be symbol "/", "," or mixed. All following subjects are equal: +a)CN=dsa test certificate,OU=OpenSSH Testers,O=Test Team,ST=World,C=XX +b)/C=XX/ST=World/O=Test Team/OU=OpenSSH Testers/CN=dsa test certificate +c)/O=Test Team/OU=OpenSSH Testers/C=XX/ST=World/CN=dsa test certificate +d)O=Test Team,OU=OpenSSH Testers/C=XX,ST=World/CN=dsa test certificate + +- CertBlob is base64 encoded sequence of bytes in only one line. + +Shell sample: +- "Distinguished Name" format (rsa key): +$ ( printf 'x509v3-sign-rsa '; + openssl x509 -noout -subject \ + -in A_OPENSSH_IDENTITY_FILE \ + -nameopt oneline \ + ) >> $HOME/.ssh/authorized_keys + +- "blob" format: +$ cat A_OPENSSH_IDENTITY_FILE.pub \ + >> $HOME/.ssh/authorized_keys + +NOTES: +- adjust user authorized_keys file ownership - user must have at least +read access. +- SecSH X.509 key type is "x509v3-sign-rsa" or "x509v3-sign-dss". +- When OpenSSH is build with "--disable-x509store" YOU CANNOT USE +"Distinguished Name" format. You shold use ONLY "blob" format. + + +2.) client settings: +2.1.) IdentityFile + Depends from client. To use X.509 certificate "OpenSSH id-file" must +contain both sections - private key and certificate in PEM format: +Note: Don't forget to update public key file with command: +$ ssh-keygen -y -f IDENTITY_FILE > IDENTITY_FILE.pub +Command ssh-add use public key file! + +2.2.) global ssh_config, $HOME/.ssh/config or command line + +2.2.1.) AllowedCertPurpose sslserver + The intended use of the X.509 server certificate. + +2.2.2.) "X509 store". + Client use "X509 store" to verify and validate server hostkey. + See p. 1.1.2.) and check the options: +- [User]CACertificatePath; +- [User]CACertificateFile; +- [User]CARevocationFile; +- [User]CARevocationPath; +- [User]CAldapVersion; +- [User]CAldapURL. + +Note: When we use own CA we must import CA certificate[s] to +"X509 store". More info on: + http://roumenpetrov.info/domino_CA/#dca2bundle + +2.2.3.) X509KeyAlgorithm + The meaning of options is same as in server. + See p. 1.1.4.) + +2.2.4.) X509rsaSigType=md5 + Deprecated option replaced by X509KeyAlgorithm. + +2.2.5.) VAType none + Specifies whether `Online Certificate Status Protocol' (OCSP) is used + to validate server X.509 certificates. Specified value is used only + when OpenSSH is build with OCSP support. See ssh_config(5) man page + for allowed values and other VA* options. + + +3.) test X.509 certificates. + +3.1.) In openssh build dir run "make check" or "make tests". + Both commands are equivalent and run regression tests. + If you want to test only X.509 certificates you can run +$ make check-certs + + If certificate test scripts fail might you should setup test +configuration in the file OPENSSH_SOURCE_PATH/tests/CA/config or +use some environment variables. Used variables are described +later in the document. + + Output from "make check-certs" is in color and when is redirected to +file later we can see content best with command "less -r ...". + When script run a test command print star '*' followed by simple +information about command. When command succeed script print at right +"done" in GREEN(!) otherwise "failed" in RED(!). After failed command +script show on next lines in RED(!) response, skip execution of next +command/script, print message like this: +.... +Testing OpenSSH client with certificates finished. + status: failed +.... + Note that failed is in RED(!) and exit code is NONZERO(!). + Some command in a test script must fail. Part of "simple information" +about command expected to fail is in RED(!). When command fail script +print "done" (THIS IS CORRECT - COMMAND MUST FAIL) and on next lines +print in GREEN(!) response. Usually this occur when server reject logon. +WHEN ALL TESTS SUCCEED output is: +.... +Testing OpenSSH client with certificates finished. + status: done +.... + Note that "done" is in GREEN(!) and exit code is ZERO(!). + +3.1.1.) Description of variables in Makefile file: + - SHELL + Used shell to run tests. Supported shell are bash, ksh, zsh and ash. + Script might run without porblems on standard unix sh. + Example: + $ make check-certs SHELL=/bin/zsh + +3.1.2.) Description of variables in config file: + +3.1.2.1.) main variables: + - SUDO + (only in config) + on some system sshd must be started as root. + If necessary set variable to sudo and configure sudo'ers. + - TMPDIR + (environment or config) + directory for temporary files. If not set its value is selected + from /tmp, /var/tmp or /usr/tmp. + - SSH_X509TESTS + (environment or config) + list with test scripts. A test script is in file with following + name: test-.sh.inc. + +3.1.2.2.) openssl: + - OPENSSL + (environment or config) + path to openssl binary. The default is result from command: + `which openssl`. + - RSA_DIGEST_LIST + (environment or config) + list with RSA digests in support of openssl. The default value is + build at run time from following digest list "md5 sha1 md2 md4 + rmd160" and contain only supported from openssl. + +3.1.2.3.) server section: + Read sshd_config.5 manual page for valid values. + - SSHD_PORT + (environment or config) + Specifies the port number that server listens on and client connect + to on SSHD_LISTENADDRESS. The default is 20022. + - SSHD_LISTENADDRESS + (only in config) + Same as sshd option "ListenAddress" but without(!) port number. + The default is "127.0.0.1". + - SSHSERVER_USEPRIVILEGESEPARATION="yes": + (only in config) + sshd "UsePrivilegeSeparation" option. + if necessary set to "no", to disable privilege separation. + - SSHSERVER_SYSLOGFACILITY=AUTH + (only in config) + sshd "SyslogFacility" option. + - SSHSERVER_LOGLEVEL=INFO + (only in config) + sshd 'LogLevel' option. + +3.1.2.4.) certificates: + - Variables related to test certificates and CA. + (only in config) + +3.1.2.5.) OCSP responder: + Used only when OpenSSH is build with OCSP support! + Variables related to OCSP tests. + - SSH_VA_BASEPORT + (environment or config) + Test script run one or more OCSP responders at same once. First + responder listen on specified port, second on port plus one and + etc. The default is 20080. + - SSH_OPENSLL_OCSP_TMOUT=60 + (config) + Wait specified number of seconds sockets opened by OCSP responders + to close. After this test script continue with next step. + This is work around for missing SO_REUSEADDR socket option in + OpenSSL OCSP responder. + +3.1.2.5.) LDAP: + In use only when OpenSSH is build with LDAP support! + - SSH_LDAP_DB + (config) + Specifies LDAP database type. The default is ldbm. + - SSH_LDAP_DC + (config) + Specifies domain name component in LDAP distinguished name. + The default is "dc=example,dc=com". + - LDAPD_PORT + (environment or config) + LDAP daemon run by test script run listens on SSHD_LISTENADDRESS + and this port. The default is 20389. + +3.1.3.) Sample commands to run tests: +$ OPENSSL=/usr/local/ssl/bin/openssl make check-certs +$ SSHD_PORT=1122 SSH_X509TESTS="agent blob_auth" make check-certs +$ RSA_DIGEST_LIST="md5 sha1" make check-certs +$ make check-certs SHELL=/bin/ksh + +When check fail see "Troubleshooting" later in document. + + +3.2.) Current test scripts uses only rsa as server hostkey. + To test sshd with X.509 certificate please find in file +openssh_tests.sh variable TEST_SSHD_HOSTKEY and change it. Sample: +TEST_SSH_HOSTKEY="${CWD}/testhostkey_rsa-rsa_md5" + + +3.3.) Test SecSH from "Microsoft Windows OS-es". + This is not part of document. +Tips: use created after "make check-certs" files: +- convert OPENSSH_BUILD_PATH/tests/CA/ca-test/crt/*crt.pem CA + certificates from PEM to DER format and import in + "Windows keystore"; +- import OPENSSH_BUILD_PATH/tests/CA/testid_*.p12 files in + "Windows keystore"; +- setup your client to use certificate[s](see SecSH client manuals). +DON'T FORGET TO REMOVE entries from "Windows keystore" after test! + + +3.4.) Go to OPENSSH_BUILD_PATH/tests/CA and run command "make clean" to +remove all client/server and CA files. + + +3.5.) files in OPENSSH_SOURCE_PATH/tests/CA directory: +config: + Configuration file. + +env.in: + Template file. + Currently contain variables related to LDAP directories. + +shell.rc: + Shell settings. + +1-cre_cadb.sh: + Create "Test CA" directories and files. + +2-cre_cakeys.sh: + Create "Test CA" private keys and certificates. + +3-cre_certs.sh: + Create client/server certificates. + This command create files with mask + "PATH_TO_KEYFILEn-[.]" + , where is in format "rsa_" or "dsa". + DIGEST are form variable "RSA_DIGEST_LIST" specified in "config" + file. Files without extention are openssh identity or hostkey files. + File with .pub extention contain openssh public key (BLOB format). + File with .crt extention contain openssl "text output" for identity + files. Files with .p12 extention are for "Microsoft Windows keystore". + Note: .p12 = .pfx for Windows. + +4-cre_crls.sh: + Revoke part of client certificates. + +5-cre_ldap.sh + Create LDAP ldif files and slapd config. + +verify.sh: + To check certificates against "Test CA". Note: check only + testid_*.crt and testhostkey_*.crt files in current directory. + +functions: + Common usefull functions. + +openssh_tests.sh: + Main test script - call other testscripts. + +test-blob_auth.sh.inc, +test-dn_auth_file.sh.inc, +test-dn_auth_path.sh.inc, +test-agent.sh.inc, +test-crl.sh.inc, +test-self.sh.inc, +test-alg.sh.inc, +test-ocsp.sh.inc, +test-by_ldap.sh.inc: + Test shell scripts. See DESCRIPTION in each file. + +Note that hostbased authentication we cannot test without to install. +Generated testhostkey_* certificates are with sslserver and sslclient +purposes and you can use them to test manually hostbased authentication. + + +4.) Troubleshooting +"make check-certs" fails on: + +4.1.) "generating a new ... private key for the TEST CA ..." +Usually this happen on system without /dev/{u}random. +In file [BUILDDIR]/tests/CA/openssh_ca-2.log we can see a message: +"... PRNG not seeded ...". +Read again WARNING.RNG from OpenSSH sourcedir and/or +http://www.openssl.org/support/faq.html + +4.1.1.) reconfigure your system and/or openssl +4.1.2.) or do next +4.1.2.1.) install OpenSSH :-( otherwise later "make check-certs" +(ssh-keygen) fail with message: +"couldn't exec '.../libexec/ssh-rand-helper': ..." +and second ./ssh-rand-helper fail with message: +"couldn't read entropy commands file ../ssh_prng_cmds: ..." +Tip: configure OpenSSH with prefix for example $HOME/test + +4.1.2.2.) run: +ssh-rand-helper +rm -f $HOME/.rnd +ln -s .ssh/prng_seed $HOME/.rnd + +4.1.2.3.) test openssl with command: +/usr/local/ssl/bin/openssl genrsa -des3 -passout pass:change_it +Tip: before to create every key with OpenSSL run ssh-rand-helper ! + +4.1.2.4.) run again "... make check-certs ..." + +4.2.) fail on first check: "* rsa_md5 valid blob failed" +- Usually SUDO command is not set. See p. 3.1.2.1. +- When you build with tcpwrappers your hosts.allow must permit +connections from localhost, otherwise you can see in failed message +text like this: "... connection closed by remote host ..." + +4.3.) fail on "starting OCSP responder(XXX) on YYY:NNNNN failed" +- Ensure sequence of about six free ports and use SSH_VA_BASEPORT + to specify first of them. +- Ensure enough timeout previous running OCSP responders to free + ports. Increase value of SSH_OPENSLL_OCSP_TMOUT in test config file. + + +5.) FAQ + +Q.) How to convert a certificate from DER to PEM format? +A.) Run command "openssl x509 ..." with command line options +-inform/-outform - you can select one of formats: DER, NET or PEM. +The default is PEM. + +Q.) How to convert pfx to p12 file? +A.) Just change file extension ;-). + +Q.) How to use my p12 file in OpenSSH as identity? +A.) Run commands: +$ openssl pkcs12 -in FILE.p12 -clcerts > id_x509 +$ ssh-keygen -f id_x509 -y > id_x509.pub + Don't forget to set properly permition on file id_x509, as +example "chmod 600 id_x509". + Note name of identity file can be one of defaults: + 'id_rsa' or 'id_dsa'. + Configure client. + +Q.) How to use p12 file in OpenSSH as hostkey? +A.) Note that host keys are password less! + It is similar to client identity. + Remember umask settings. + Run as root commands: +# umask 0077 +# openssl pkcs12 -in FILE.p12 -clcerts > ssh_host_x509 + Note: you must enter export password! +# ssh-keygen -p -f ssh_host_x509 -N '' + Now hostkey file is password less ! +# ssh-keygen -f ssh_host_x509 -y > ssh_host_x509.pub + Restore umask settings. + Note name of hostkey file can be one of defaults: + 'ssh_host_dsa_key' or 'ssh_host_rsa_key'. + Configure server, test configuration with command +# sshd -t ..../sshd_config + and start/restart the server. Don't forget to inform users + that hostkey is changed! + +Q.) How to import CA certificates and/or CRLs in LDAP? +A.) You should create a ldif file with LDAP entries that contains + binary atributes "cACertificate" and/or "certificateRevocationList" + and to specify path to file with certificate or CRL in DER format. + Entry should contain objectClass "pkiCA". See definition in core + LDAP schema. After this to use command ldapadd or ldapmodify to + add/modify LDAP data. See command manual pages. + + As example when you build OpenSSH with ldap queries after + regression test see content of file + $(top_builddir)/tests/CA/ldap/ca.ldif . + This file is created by the script + $(srcdir)/tests/CA/5-cre_ldap.sh + and entries are added to LDAP with command: +# ldapadd -x -w secret -D cn=... -H ldap://... \ + -f .../ca.ldif . + See ldapadd manual page for options meaning. + +Enjoy ;-) diff -ruN openssh-5.6p1/scp.0 openssh-5.6p1+x509-6.2.3/scp.0 --- openssh-5.6p1/scp.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/scp.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SCP(1) OpenBSD Reference Manual SCP(1) +SCP(1) BSD General Commands Manual SCP(1) NAME - scp - secure copy (remote file copy program) + scp -- secure copy (remote file copy program) SYNOPSIS scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] @@ -17,7 +17,7 @@ File names may contain a user and host specification to indicate that the file is to be copied to/from that host. Local file names can be made explicit using absolute or relative pathnames to avoid scp treating file - names containing `:' as host specifiers. Copies between two remote hosts + names containing ':' as host specifiers. Copies between two remote hosts are also permitted. The options are as follows: @@ -33,8 +33,8 @@ -B Selects batch mode (prevents asking for passwords or passphrases). - -C Compression enable. Passes the -C flag to ssh(1) to enable - compression. + -C Compression enable. Passes the -C flag to ssh(1) to enable com- + pression. -c cipher Selects the cipher to use for encrypting the data transfer. This @@ -56,61 +56,11 @@ Can be used to pass options to ssh in the format used in ssh_config(5). This is useful for specifying options for which there is no separate scp command-line flag. For full details of - the options listed below, and their possible values, see - ssh_config(5). - - AddressFamily - BatchMode - BindAddress - ChallengeResponseAuthentication - CheckHostIP - Cipher - Ciphers - Compression - CompressionLevel - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - HostName - IdentityFile - IdentitiesOnly - KbdInteractiveDevices - LogLevel - MACs - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PKCS11Provider - Port - PreferredAuthentications - Protocol - ProxyCommand - PubkeyAuthentication - RekeyLimit - RhostsRSAAuthentication - RSAAuthentication - SendEnv - ServerAliveInterval - ServerAliveCountMax - StrictHostKeyChecking - TCPKeepAlive - UsePrivilegedPort - User - UserKnownHostsFile - VerifyHostKeyDNS + the options and their possible values, see ssh_config(5). -P port Specifies the port to connect to on the remote host. Note that - this option is written with a capital `P', because -p is already + this option is written with a capital 'P', because -p is already reserved for preserving the times and modes of the file in rcp(1). @@ -120,8 +70,8 @@ -q Quiet mode: disables the progress meter as well as warning and diagnostic messages from ssh(1). - -r Recursively copy entire directories. Note that scp follows - symbolic links encountered in the tree traversal. + -r Recursively copy entire directories. Note that scp follows sym- + bolic links encountered in the tree traversal. -S program Name of program to use for the encrypted connection. The program @@ -145,4 +95,4 @@ Timo Rinne Tatu Ylonen -OpenBSD 4.8 February 8, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/scp.1 openssh-5.6p1+x509-6.2.3/scp.1 --- openssh-5.6p1/scp.1 2010-02-12 00:21:03.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/scp.1 2010-08-24 09:06:00.000000000 +0300 @@ -9,7 +9,7 @@ .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" -.\" $OpenBSD: scp.1,v 1.50 2010/02/08 10:50:20 markus Exp $ +.\" $OpenBSD$ .\" .Dd $Mdocdate: February 8 2010 $ .Dt SCP 1 @@ -119,59 +119,8 @@ for which there is no separate .Nm scp command-line flag. -For full details of the options listed below, and their possible values, see +For full details of the options and their possible values, see .Xr ssh_config 5 . -.Pp -.Bl -tag -width Ds -offset indent -compact -.It AddressFamily -.It BatchMode -.It BindAddress -.It ChallengeResponseAuthentication -.It CheckHostIP -.It Cipher -.It Ciphers -.It Compression -.It CompressionLevel -.It ConnectionAttempts -.It ConnectTimeout -.It ControlMaster -.It ControlPath -.It GlobalKnownHostsFile -.It GSSAPIAuthentication -.It GSSAPIDelegateCredentials -.It HashKnownHosts -.It Host -.It HostbasedAuthentication -.It HostKeyAlgorithms -.It HostKeyAlias -.It HostName -.It IdentityFile -.It IdentitiesOnly -.It KbdInteractiveDevices -.It LogLevel -.It MACs -.It NoHostAuthenticationForLocalhost -.It NumberOfPasswordPrompts -.It PasswordAuthentication -.It PKCS11Provider -.It Port -.It PreferredAuthentications -.It Protocol -.It ProxyCommand -.It PubkeyAuthentication -.It RekeyLimit -.It RhostsRSAAuthentication -.It RSAAuthentication -.It SendEnv -.It ServerAliveInterval -.It ServerAliveCountMax -.It StrictHostKeyChecking -.It TCPKeepAlive -.It UsePrivilegedPort -.It User -.It UserKnownHostsFile -.It VerifyHostKeyDNS -.El .It Fl P Ar port Specifies the port to connect to on the remote host. Note that this option is written with a capital diff -ruN openssh-5.6p1/servconf.c openssh-5.6p1+x509-6.2.3/servconf.c --- openssh-5.6p1/servconf.c 2010-06-26 02:38:45.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/servconf.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.209 2010/06/22 04:22:59 djm Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -8,6 +8,29 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X509 certificate support, + * Copyright (c) 2002-2006 Roumen Petrov. 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" @@ -31,6 +54,7 @@ #include "log.h" #include "buffer.h" #include "servconf.h" +#include "ssh-xkalg.h" #include "compat.h" #include "pathnames.h" #include "misc.h" @@ -132,6 +156,18 @@ options->revoked_keys_file = NULL; options->trusted_user_ca_keys = NULL; options->authorized_principals_file = NULL; + + options->hostbased_algorithms = NULL; + options->pubkey_algorithms = NULL; + ssh_x509flags_initialize(&options->x509flags, 1); +#ifndef SSH_X509STORE_DISABLED + ssh_x509store_initialize(&options->ca); +#endif /*ndef SSH_X509STORE_DISABLED*/ +#ifdef SSH_OCSP_ENABLED + options->va.type = -1; + options->va.certificate_file = NULL; + options->va.responder_url = NULL; +#endif /*def SSH_OCSP_ENABLED*/ } void @@ -267,6 +303,21 @@ if (options->zero_knowledge_password_authentication == -1) options->zero_knowledge_password_authentication = 0; + /* options->hostbased_algorithms */ + /* options->pubkey_algorithms */ + fill_default_xkalg(); + ssh_x509flags_defaults(&options->x509flags); + memcpy(&ssh_x509flags, &options->x509flags, sizeof(ssh_x509flags)); +#ifndef SSH_X509STORE_DISABLED + ssh_x509store_system_defaults(&options->ca); + ssh_x509store_addlocations(&options->ca); +#endif /*ndef SSH_X509STORE_DISABLED*/ +#ifdef SSH_OCSP_ENABLED + if (options->va.type == -1) + options->va.type = ssh_get_default_vatype(); + ssh_set_validator(&options->va); +#endif /*def SSH_OCSP_ENABLED*/ + /* Turn privilege separation on by default */ if (use_privsep == -1) use_privsep = 1; @@ -279,7 +330,14 @@ options->compression = 0; } #endif - + if (options->hostbased_algorithms != NULL) + if (!key_names_valid2(options->hostbased_algorithms)) + fatal("Bad protocol 2 hostbased algorithms '%s'.", + options->hostbased_algorithms); + if (options->pubkey_algorithms != NULL) + if (!key_names_valid2(options->pubkey_algorithms)) + fatal("Bad protocol 2 public key algorithms '%s'.", + options->pubkey_algorithms); } /* Keyword tokens. */ @@ -312,6 +370,16 @@ sUsePrivilegeSeparation, sAllowAgentForwarding, sZeroKnowledgePasswordAuthentication, sHostCertificate, sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, + sHostbasedAlgorithms, + sPubkeyAlgorithms, + sX509KeyAlgorithm, + sAllowedClientCertPurpose, + sKeyAllowSelfIssued, sMandatoryCRL, + sCACertificateFile, sCACertificatePath, + sCARevocationFile, sCARevocationPath, + sCAldapVersion, sCAldapURL, + sVAType, sVACertificateFile, + sVAOCSPResponderURL, sDeprecated, sUnsupported } ServerOpCodes; @@ -425,6 +493,22 @@ { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL }, { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, + { "hostbasedalgorithms", sHostbasedAlgorithms, SSHCFG_ALL }, + { "pubkeyalgorithms", sPubkeyAlgorithms, SSHCFG_ALL }, + { "x509rsasigtype", sDeprecated, SSHCFG_GLOBAL }, + { "x509keyalgorithm", sX509KeyAlgorithm, SSHCFG_GLOBAL }, + { "allowedcertpurpose", sAllowedClientCertPurpose, SSHCFG_GLOBAL }, + { "keyallowselfissued", sKeyAllowSelfIssued, SSHCFG_GLOBAL } , + { "mandatorycrl", sMandatoryCRL, SSHCFG_GLOBAL } , + { "cacertificatefile", sCACertificateFile, SSHCFG_GLOBAL }, + { "cacertificatepath", sCACertificatePath, SSHCFG_GLOBAL }, + { "carevocationfile", sCARevocationFile, SSHCFG_GLOBAL }, + { "carevocationpath", sCARevocationPath, SSHCFG_GLOBAL }, + { "caldapversion", sCAldapVersion, SSHCFG_GLOBAL }, + { "caldapurl", sCAldapURL, SSHCFG_GLOBAL }, + { "vatype", sVAType, SSHCFG_GLOBAL }, + { "vacertificatefile", sVACertificateFile, SSHCFG_GLOBAL }, + { "vaocspresponderurl", sVAOCSPResponderURL, SSHCFG_GLOBAL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, { "match", sMatch, SSHCFG_ALL }, { "permitopen", sPermitOpen, SSHCFG_ALL }, @@ -1351,6 +1435,142 @@ charptr = &options->revoked_keys_file; goto parse_filename; + case sHostbasedAlgorithms: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + /* cannot validate here - depend from X509KeyAlgorithm + if (!key_names_valid2(arg)) + fatal("%.200s line %d: Bad protocol 2 hostbased algorithms '%s'.", + filename, linenum, arg ? arg : ""); + */ + if (*activep && options->hostbased_algorithms == NULL) + options->hostbased_algorithms = xstrdup(arg); + break; + + case sPubkeyAlgorithms: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + /* cannot validate here - depend from X509KeyAlgorithm + if (!key_names_valid2(arg)) + fatal("%.200s line %d: Bad protocol 2 public key algorithms '%s'.", + filename, linenum, arg ? arg : ""); + */ + if (*activep && options->pubkey_algorithms == NULL) + options->pubkey_algorithms = xstrdup(arg); + break; + + case sX509KeyAlgorithm: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + if (ssh_add_x509key_alg(arg) < 0) { + fatal("%.200s line %d: Bad X.509 key algorithm '%.200s'.", + filename, linenum, arg); + } + break; + + case sAllowedClientCertPurpose: + intptr = &options->x509flags.allowedcertpurpose; + arg = strdelim(&cp); + if (arg && *arg) { + if (strcasecmp(arg, "skip") == 0) goto skip_purpose; + + /* convert string to OpenSSL index */ + value = ssh_get_x509purpose_s (1, arg); + if (value < 0) + fatal("%.200s line %d: Bad certificate purpose '%.30s'.", + filename, linenum, arg); + + if (*intptr == -1) + *intptr = value; + } else { +skip_purpose: + if (*intptr == -1) { + *intptr = -2; + verbose("%.200s line %d: option is set to don`t check certificate purpose.", + filename, linenum); + } + } + break; + +#ifndef SSH_X509STORE_DISABLED + case sKeyAllowSelfIssued: + intptr = &options->x509flags.key_allow_selfissued; + goto parse_flag; + + case sMandatoryCRL: + intptr = &options->x509flags.mandatory_crl; + goto parse_flag; + + case sCACertificateFile: + /* X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.certificate_file; +parse_string: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + if (*charptr == NULL) + *charptr = xstrdup(arg); + break; + + case sCACertificatePath: + /* X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.certificate_path; + goto parse_string; + + case sCARevocationFile: + /* X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.revocation_file; + goto parse_string; + + case sCARevocationPath: + /* X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.revocation_path; + goto parse_string; +#endif /*ndef SSH_X509STORE_DISABLED*/ + +#ifdef LDAP_ENABLED + case sCAldapVersion: + /* X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.ldap_ver; + goto parse_string; + + case sCAldapURL: + /* X509StoreOptions prefered type is 'const char*' */ + charptr = (char**)&options->ca.ldap_url; + goto parse_string; +#endif /*def LDAP_ENABLED*/ + +#ifdef SSH_OCSP_ENABLED + case sVAType: + intptr = &options->va.type; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + + value = ssh_get_vatype_s(arg); + if (value < 0) { + fatal("%.200s line %d: Bad OCSP responder type '%.30s'.", + filename, linenum, arg); + } + + if (*intptr == -1) + *intptr = value; + break; + + case sVACertificateFile: + /* VAOptions prefered type is 'const char*' */ + charptr = (char**)&options->va.certificate_file; + goto parse_string; + + case sVAOCSPResponderURL: + /* VAOptions prefered type is 'const char*' */ + charptr = (char**)&options->va.responder_url; + goto parse_string; +#endif /*def SSH_OCSP_ENABLED*/ + case sDeprecated: logit("%s line %d: Deprecated option %s", filename, linenum, arg); @@ -1358,6 +1578,23 @@ arg = strdelim(&cp); break; +#ifdef SSH_X509STORE_DISABLED + case sKeyAllowSelfIssued: + case sMandatoryCRL: + case sCACertificateFile: + case sCACertificatePath: + case sCARevocationFile: + case sCARevocationPath: +#endif /*def SSH_X509STORE_DISABLED*/ +#ifndef LDAP_ENABLED + case sCAldapVersion: + case sCAldapURL: +#endif /*ndef LDAP_ENABLED*/ +#ifndef SSH_OCSP_ENABLED + case sVAType: + case sVACertificateFile: + case sVAOCSPResponderURL: +#endif /*ndef SSH_OCSP_ENABLED*/ case sUnsupported: logit("%s line %d: Unsupported option %s", filename, linenum, arg); @@ -1462,6 +1699,9 @@ M_CP_INTOPT(max_sessions); M_CP_INTOPT(max_authtries); + M_CP_STROPT(hostbased_algorithms); + M_CP_STROPT(pubkey_algorithms); + M_CP_STROPT(banner); if (preauth) return; @@ -1541,6 +1781,24 @@ return "clientspecified"; if (code == sCompression && val == COMP_DELAYED) return "delayed"; + if (code == sAllowedClientCertPurpose) { + /* TODO: to use "x509store.{h|c}" - similar to ssh_get_x509purpose_s*/ + if(val > 0) return "ssl client"; + if(val == 0) return "any purpose"; + if(val < -1) return "skip"; + return "unset"; + } +#ifdef SSH_OCSP_ENABLED + if (code == sVAType) { + /* TODO: to use "ssh-ocsp.{h|c}" - similar to ssh_get_vatype_s*/ + switch (val) { + case SSHVA_NONE: return "none"; + case SSHVA_OCSP_CERT: return "ocspcert"; + case SSHVA_OCSP_SPEC: return "ocspspec"; + default: return "UNKNOWN"; + } + } +#endif switch (val) { case -1: return "unset"; @@ -1686,6 +1944,8 @@ dump_cfg_string(sXAuthLocation, o->xauth_location); dump_cfg_string(sCiphers, o->ciphers); dump_cfg_string(sMacs, o->macs); + dump_cfg_string(sHostbasedAlgorithms, o->hostbased_algorithms); + dump_cfg_string(sPubkeyAlgorithms, o->pubkey_algorithms); dump_cfg_string(sBanner, o->banner); dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file); dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2); @@ -1711,6 +1971,33 @@ dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); + /* X.509 certificate arguments */ + /* TODO to implement dump of sX509KeyAlgorithm */ + + /* sshd PKI(X509) flags */ + dump_cfg_fmtint(sAllowedClientCertPurpose, o->x509flags.allowedcertpurpose); +#ifndef SSH_X509STORE_DISABLED + dump_cfg_fmtint(sKeyAllowSelfIssued, o->x509flags.key_allow_selfissued); + dump_cfg_fmtint(sMandatoryCRL , o->x509flags.mandatory_crl ); +#endif /*ndef SSH_X509STORE_DISABLED*/ +#ifndef SSH_X509STORE_DISABLED + /* sshd PKI(X509) system store */ + dump_cfg_string(sCACertificateFile, o->ca.certificate_file); + dump_cfg_string(sCACertificatePath, o->ca.certificate_path); + dump_cfg_string(sCARevocationFile , o->ca.revocation_file ); + dump_cfg_string(sCARevocationPath , o->ca.revocation_path ); +#ifdef LDAP_ENABLED + dump_cfg_string(sCAldapVersion , o->ca.ldap_ver ); + dump_cfg_string(sCAldapURL , o->ca.ldap_url ); +#endif +#endif /*ndef SSH_X509STORE_DISABLED*/ +#ifdef SSH_OCSP_ENABLED + /* ssh X.509 extra validation */ + dump_cfg_fmtint(sVAType , o->va.type ); + dump_cfg_string(sVACertificateFile , o->va.certificate_file); + dump_cfg_string(sVAOCSPResponderURL, o->va.responder_url ); +#endif /*def SSH_OCSP_ENABLED*/ + /* other arguments */ for (i = 0; i < o->num_subsystems; i++) printf("subsystem %s %s\n", o->subsystem_name[i], diff -ruN openssh-5.6p1/servconf.h openssh-5.6p1+x509-6.2.3/servconf.h --- openssh-5.6p1/servconf.h 2010-05-10 04:58:03.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/servconf.h 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.93 2010/05/07 11:30:30 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen @@ -11,11 +11,36 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X509 certificate support, + * Copyright (c) 2002-2006 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SERVCONF_H #define SERVCONF_H +#include "x509store.h" + #define MAX_PORTS 256 /* Max # ports. */ #define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ @@ -149,6 +174,23 @@ int use_pam; /* Enable auth via PAM */ + char* hostbased_algorithms; /* Allowed hostbased algorithms. */ + char* pubkey_algorithms; /* Allowed pubkey algorithms. */ + + /* Supported X.509 key algorithms and signatures + are defined is external source. */ + + /* sshd PKI(X509) flags */ + SSH_X509Flags x509flags; +#ifndef SSH_X509STORE_DISABLED + /* sshd PKI(X509) system store */ + X509StoreOptions ca; +#endif /*ndef SSH_X509STORE_DISABLED*/ +#ifdef SSH_OCSP_ENABLED + /* ssh X.509 extra validation */ + VAOptions va; +#endif /*def SSH_OCSP_ENABLED*/ + int permit_tun; int num_permitted_opens; diff -ruN openssh-5.6p1/sftp.0 openssh-5.6p1+x509-6.2.3/sftp.0 --- openssh-5.6p1/sftp.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sftp.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SFTP(1) OpenBSD Reference Manual SFTP(1) +SFTP(1) BSD General Commands Manual SFTP(1) NAME - sftp - secure file transfer program + sftp -- secure file transfer program SYNOPSIS sftp [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher] @@ -15,20 +15,20 @@ DESCRIPTION sftp is an interactive file transfer program, similar to ftp(1), which performs all operations over an encrypted ssh(1) transport. It may also - use many features of ssh, such as public key authentication and - compression. sftp connects and logs into the specified host, then enters - an interactive command mode. - - The second usage format will retrieve files automatically if a non- - interactive authentication method is used; otherwise it will do so after - successful interactive authentication. + use many features of ssh, such as public key authentication and compres- + sion. sftp connects and logs into the specified host, then enters an + interactive command mode. + + The second usage format will retrieve files automatically if a non-inter- + active authentication method is used; otherwise it will do so after suc- + cessful interactive authentication. The third usage format allows sftp to start in a remote directory. The final usage format allows for automated sessions using the -b option. - In such cases, it is necessary to configure non-interactive - authentication to obviate the need to enter a password at connection time - (see sshd(8) and ssh-keygen(1) for details). The options are as follows: + In such cases, it is necessary to configure non-interactive authentica- + tion to obviate the need to enter a password at connection time (see + sshd(8) and ssh-keygen(1) for details). The options are as follows: -1 Specify the use of protocol version 1. @@ -47,11 +47,11 @@ Batch mode reads a series of commands from an input batchfile instead of stdin. Since it lacks user interaction it should be used in conjunction with non-interactive authentication. A - batchfile of `-' may be used to indicate standard input. sftp + batchfile of '-' may be used to indicate standard input. sftp will abort if any of the following commands fail: get, put, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod, chown, chgrp, lpwd, df, and lmkdir. Termination on error can be suppressed on - a command by command basis by prefixing the command with a `-' + a command by command basis by prefixing the command with a '-' character (for example, -rm /tmp/blah*). -C Enables compression (via ssh's -C flag). @@ -78,57 +78,7 @@ ssh_config(5). This is useful for specifying options for which there is no separate sftp command-line flag. For example, to specify an alternate port use: sftp -oPort=24. For full details - of the options listed below, and their possible values, see - ssh_config(5). - - AddressFamily - BatchMode - BindAddress - ChallengeResponseAuthentication - CheckHostIP - Cipher - Ciphers - Compression - CompressionLevel - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - HostName - IdentityFile - IdentitiesOnly - KbdInteractiveDevices - LogLevel - MACs - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PKCS11Provider - Port - PreferredAuthentications - Protocol - ProxyCommand - PubkeyAuthentication - RekeyLimit - RhostsRSAAuthentication - RSAAuthentication - SendEnv - ServerAliveInterval - ServerAliveCountMax - StrictHostKeyChecking - TCPKeepAlive - UsePrivilegedPort - User - UserKnownHostsFile - VerifyHostKeyDNS + of the options and their possible values, see ssh_config(5). -P port Specifies the port to connect to on the remote host. @@ -144,9 +94,9 @@ Increasing this may slightly improve file transfer speed but will increase memory usage. The default is 64 outstanding requests. - -r Recursively copy entire directories when uploading and - downloading. Note that sftp does not follow symbolic links - encountered in the tree traversal. + -r Recursively copy entire directories when uploading and download- + ing. Note that sftp does not follow symbolic links encountered + in the tree traversal. -S program Name of the program to use for the encrypted connection. The @@ -155,8 +105,8 @@ -s subsystem | sftp_server Specifies the SSH2 subsystem or the path for an sftp server on the remote host. A path is useful for using sftp over protocol - version 1, or when the remote sshd(8) does not have an sftp - subsystem configured. + version 1, or when the remote sshd(8) does not have an sftp sub- + system configured. -v Raise logging level. This option is also passed to ssh. @@ -165,7 +115,7 @@ those of ftp(1). Commands are case insensitive. Pathnames that contain spaces must be enclosed in quotes. Any special characters contained within pathnames that are recognized by glob(3) must be escaped with - backslashes (`\'). + backslashes ('\'). bye Quit sftp. @@ -173,18 +123,16 @@ Change remote directory to path. chgrp grp path - Change group of file path to grp. path may contain glob(3) - characters and may match multiple files. grp must be a numeric - GID. + Change group of file path to grp. path may contain glob(3) char- + acters and may match multiple files. grp must be a numeric GID. chmod mode path Change permissions of file path to mode. path may contain glob(3) characters and may match multiple files. chown own path - Change owner of file path to own. path may contain glob(3) - characters and may match multiple files. own must be a numeric - UID. + Change owner of file path to own. path may contain glob(3) char- + acters and may match multiple files. own must be a numeric UID. df [-hi] [path] Display usage information for the filesystem holding the current @@ -201,11 +149,11 @@ the local path name is not specified, it is given the same name it has on the remote machine. remote-path may contain glob(3) characters and may match multiple files. If it does and - local-path is specified, then local-path must specify a - directory. + local-path is specified, then local-path must specify a direc- + tory. - If either the -P or -p flag is specified, then full file - permissions and access times are copied too. + If either the -P or -p flag is specified, then full file permis- + sions and access times are copied too. If the -r flag is specified then directories will be copied recursively. Note that sftp does not follow symbolic links when @@ -217,10 +165,10 @@ Change local directory to path. lls [ls-options [path]] - Display local directory listing of either path or current - directory if path is not specified. ls-options may contain any - flags supported by the local system's ls(1) command. path may - contain glob(3) characters and may match multiple files. + Display local directory listing of either path or current direc- + tory if path is not specified. ls-options may contain any flags + supported by the local system's ls(1) command. path may contain + glob(3) characters and may match multiple files. lmkdir path Create local directory specified by path. @@ -240,10 +188,10 @@ -1 Produce single columnar output. - -a List files beginning with a dot (`.'). + -a List files beginning with a dot ('.'). - -f Do not sort the listing. The default sort order is - lexicographical. + -f Do not sort the listing. The default sort order is lexi- + cographical. -h When used with a long format option, use unit suffixes: Byte, Kilobyte, Megabyte, Gigabyte, Terabyte, Petabyte, @@ -251,8 +199,8 @@ four or fewer using powers of 2 for sizes (K=1024, M=1048576, etc.). - -l Display additional details including permissions and - ownership information. + -l Display additional details including permissions and own- + ership information. -n Produce a long listing with user and group information presented numerically. @@ -275,13 +223,12 @@ put [-Ppr] local-path [remote-path] Upload local-path and store it on the remote machine. If the remote path name is not specified, it is given the same name it - has on the local machine. local-path may contain glob(3) - characters and may match multiple files. If it does and - remote-path is specified, then remote-path must specify a - directory. + has on the local machine. local-path may contain glob(3) charac- + ters and may match multiple files. If it does and remote-path is + specified, then remote-path must specify a directory. - If ether the -P or -p flag is specified, then full file - permissions and access times are copied too. + If ether the -P or -p flag is specified, then full file permis- + sions and access times are copied too. If the -r flag is specified then directories will be copied recursively. Note that sftp does not follow symbolic links when @@ -317,8 +264,7 @@ ftp(1), ls(1), scp(1), ssh(1), ssh-add(1), ssh-keygen(1), glob(3), ssh_config(5), sftp-server(8), sshd(8) - T. Ylonen, S. Lehtinen, SSH File Transfer Protocol, - draft-ietf-secsh-filexfer-00.txt, January 2001, work in progress - material. + T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- + filexfer-00.txt, January 2001, work in progress material. -OpenBSD 4.8 February 8, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/sftp.1 openssh-5.6p1+x509-6.2.3/sftp.1 --- openssh-5.6p1/sftp.1 2010-02-12 00:21:03.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/sftp.1 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.83 2010/02/08 10:50:20 markus Exp $ +.\" $OpenBSD$ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -168,59 +168,8 @@ command-line flag. For example, to specify an alternate port use: .Ic sftp -oPort=24 . -For full details of the options listed below, and their possible values, see +For full details of the options and their possible values, see .Xr ssh_config 5 . -.Pp -.Bl -tag -width Ds -offset indent -compact -.It AddressFamily -.It BatchMode -.It BindAddress -.It ChallengeResponseAuthentication -.It CheckHostIP -.It Cipher -.It Ciphers -.It Compression -.It CompressionLevel -.It ConnectionAttempts -.It ConnectTimeout -.It ControlMaster -.It ControlPath -.It GlobalKnownHostsFile -.It GSSAPIAuthentication -.It GSSAPIDelegateCredentials -.It HashKnownHosts -.It Host -.It HostbasedAuthentication -.It HostKeyAlgorithms -.It HostKeyAlias -.It HostName -.It IdentityFile -.It IdentitiesOnly -.It KbdInteractiveDevices -.It LogLevel -.It MACs -.It NoHostAuthenticationForLocalhost -.It NumberOfPasswordPrompts -.It PasswordAuthentication -.It PKCS11Provider -.It Port -.It PreferredAuthentications -.It Protocol -.It ProxyCommand -.It PubkeyAuthentication -.It RekeyLimit -.It RhostsRSAAuthentication -.It RSAAuthentication -.It SendEnv -.It ServerAliveInterval -.It ServerAliveCountMax -.It StrictHostKeyChecking -.It TCPKeepAlive -.It UsePrivilegedPort -.It User -.It UserKnownHostsFile -.It VerifyHostKeyDNS -.El .It Fl P Ar port Specifies the port to connect to on the remote host. .It Fl p diff -ruN openssh-5.6p1/sftp-server.0 openssh-5.6p1+x509-6.2.3/sftp-server.0 --- openssh-5.6p1/sftp-server.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sftp-server.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SFTP-SERVER(8) OpenBSD System Manager's Manual SFTP-SERVER(8) +SFTP-SERVER(8) BSD System Manager's Manual SFTP-SERVER(8) NAME - sftp-server - SFTP server subsystem + sftp-server -- SFTP server subsystem SYNOPSIS sftp-server [-ehR] [-f log_facility] [-l log_level] [-u umask] @@ -29,8 +29,8 @@ -h Displays sftp-server usage information. -l log_level - Specifies which messages will be logged by sftp-server. The - possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, + Specifies which messages will be logged by sftp-server. The pos- + sible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. INFO and VERBOSE log transactions that sftp-server performs on behalf of the client. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher @@ -51,9 +51,8 @@ SEE ALSO sftp(1), ssh(1), sshd_config(5), sshd(8) - T. Ylonen, S. Lehtinen, SSH File Transfer Protocol, - draft-ietf-secsh-filexfer-00.txt, January 2001, work in progress - material. + T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- + filexfer-00.txt, January 2001, work in progress material. HISTORY sftp-server first appeared in OpenBSD 2.8. @@ -61,4 +60,4 @@ AUTHORS Markus Friedl -OpenBSD 4.8 January 9, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh.0 openssh-5.6p1+x509-6.2.3/ssh.0 --- openssh-5.6p1/ssh.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSH(1) OpenBSD Reference Manual SSH(1) +SSH(1) BSD General Commands Manual SSH(1) NAME - ssh - OpenSSH SSH client (remote login program) + ssh -- OpenSSH SSH client (remote login program) SYNOPSIS ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] @@ -69,13 +69,13 @@ Protocol version 1 allows specification of a single cipher. The supported values are ``3des'', ``blowfish'', and ``des''. 3des - (triple-des) is an encrypt-decrypt-encrypt triple with three - different keys. It is believed to be secure. blowfish is a fast + (triple-des) is an encrypt-decrypt-encrypt triple with three dif- + ferent keys. It is believed to be secure. blowfish is a fast block cipher; it appears very secure and is much faster than - 3des. des is only supported in the ssh client for - interoperability with legacy protocol 1 implementations that do - not support the 3des cipher. Its use is strongly discouraged due - to cryptographic weaknesses. The default is ``3des''. + 3des. des is only supported in the ssh client for interoperabil- + ity with legacy protocol 1 implementations that do not support + the 3des cipher. Its use is strongly discouraged due to crypto- + graphic weaknesses. The default is ``3des''. For protocol version 2, cipher_spec is a comma-separated list of ciphers listed in order of preference. See the Ciphers keyword @@ -90,8 +90,8 @@ determine where to connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are supported, and ssh will act as a SOCKS server. Only root can forward privileged ports. - Dynamic port forwardings can also be specified in the - configuration file. + Dynamic port forwardings can also be specified in the configura- + tion file. IPv6 addresses can be specified by enclosing the address in square brackets. Only the superuser can forward privileged @@ -99,21 +99,21 @@ the GatewayPorts setting. However, an explicit bind_address may be used to bind the connection to a specific address. The bind_address of ``localhost'' indicates that the listening port - be bound for local use only, while an empty address or `*' - indicates that the port should be available from all interfaces. + be bound for local use only, while an empty address or '*' indi- + cates that the port should be available from all interfaces. -e escape_char - Sets the escape character for sessions with a pty (default: `~'). + Sets the escape character for sessions with a pty (default: '~'). The escape character is only recognized at the beginning of a - line. The escape character followed by a dot (`.') closes the + line. The escape character followed by a dot ('.') closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once. Setting the character to ``none'' disables any escapes and makes the session fully transparent. -F configfile - Specifies an alternative per-user configuration file. If a - configuration file is given on the command line, the system-wide + Specifies an alternative per-user configuration file. If a con- + figuration file is given on the command line, the system-wide configuration file (/etc/ssh/ssh_config) will be ignored. The default for the per-user configuration file is ~/.ssh/config. @@ -137,13 +137,14 @@ -i identity_file Selects a file from which the identity (private key) for RSA or DSA authentication is read. The default is ~/.ssh/identity for - protocol version 1, and ~/.ssh/id_rsa and ~/.ssh/id_dsa for - protocol version 2. Identity files may also be specified on a - per-host basis in the configuration file. It is possible to have - multiple -i options (and multiple identities specified in - configuration files). ssh will also try to load certificate - information from the filename obtained by appending -cert.pub to - identity filenames. + protocol version 1, and ~/.ssh/id_rsa and ~/.ssh/id_dsa for pro- + tocol version 2. For protocol version 2 is possible identity to + contain in addition X.509 certificate that match private key. + Identity files may also be specified on a per-host basis in the + configuration file. It is possible to have multiple -i options + (and multiple identities specified in configuration files). ssh + will also try to load certificate information from the filename + obtained by appending -cert.pub to identity filenames. -K Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI credentials to the server. @@ -155,27 +156,27 @@ Specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side. This works by allocating a socket to listen to port on the local side, - optionally bound to the specified bind_address. Whenever a - connection is made to this port, the connection is forwarded over + optionally bound to the specified bind_address. Whenever a con- + nection is made to this port, the connection is forwarded over the secure channel, and a connection is made to host port hostport from the remote machine. Port forwardings can also be - specified in the configuration file. IPv6 addresses can be - specified by enclosing the address in square brackets. Only the + specified in the configuration file. IPv6 addresses can be spec- + ified by enclosing the address in square brackets. Only the superuser can forward privileged ports. By default, the local - port is bound in accordance with the GatewayPorts setting. - However, an explicit bind_address may be used to bind the - connection to a specific address. The bind_address of - ``localhost'' indicates that the listening port be bound for - local use only, while an empty address or `*' indicates that the - port should be available from all interfaces. + port is bound in accordance with the GatewayPorts setting. How- + ever, an explicit bind_address may be used to bind the connection + to a specific address. The bind_address of ``localhost'' indi- + cates that the listening port be bound for local use only, while + an empty address or '*' indicates that the port should be avail- + able from all interfaces. -l login_name Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file. - -M Places the ssh client into ``master'' mode for connection - sharing. Multiple -M options places ssh into ``master'' mode - with confirmation required before slave connections are accepted. + -M Places the ssh client into ``master'' mode for connection shar- + ing. Multiple -M options places ssh into ``master'' mode with + confirmation required before slave connections are accepted. Refer to the description of ControlMaster in ssh_config(5) for details. @@ -184,8 +185,8 @@ MAC (message authentication code) algorithms can be specified in order of preference. See the MACs keyword for more information. - -N Do not execute a remote command. This is useful for just - forwarding ports (protocol version 2 only). + -N Do not execute a remote command. This is useful for just for- + warding ports (protocol version 2 only). -n Redirects stdin from /dev/null (actually, prevents reading from stdin). This must be used when ssh is run in the background. A @@ -206,76 +207,10 @@ master to exit). -o option - Can be used to give options in the format used in the - configuration file. This is useful for specifying options for - which there is no separate command-line flag. For full details - of the options listed below, and their possible values, see - ssh_config(5). - - AddressFamily - BatchMode - BindAddress - ChallengeResponseAuthentication - CheckHostIP - Cipher - Ciphers - ClearAllForwardings - Compression - CompressionLevel - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - DynamicForward - EscapeChar - ExitOnForwardFailure - ForwardAgent - ForwardX11 - ForwardX11Trusted - GatewayPorts - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - HostName - IdentityFile - IdentitiesOnly - KbdInteractiveDevices - LocalCommand - LocalForward - LogLevel - MACs - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PermitLocalCommand - PKCS11Provider - Port - PreferredAuthentications - Protocol - ProxyCommand - PubkeyAuthentication - RekeyLimit - RemoteForward - RhostsRSAAuthentication - RSAAuthentication - SendEnv - ServerAliveInterval - ServerAliveCountMax - StrictHostKeyChecking - TCPKeepAlive - Tunnel - TunnelDevice - UsePrivilegedPort - User - UserKnownHostsFile - VerifyHostKeyDNS - VisualHostKey - XAuthLocation + Can be used to give options in the format used in the configura- + tion file. This is useful for specifying options for which there + is no separate command-line flag. For full details of the + options and their possible values, see ssh_config(5). -p port Port to connect to on the remote host. This can be specified on @@ -288,9 +223,9 @@ Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side. This works by allocating a socket to listen to port on the remote - side, and whenever a connection is made to this port, the - connection is forwarded over the secure channel, and a connection - is made to host port hostport from the local machine. + side, and whenever a connection is made to this port, the connec- + tion is forwarded over the secure channel, and a connection is + made to host port hostport from the local machine. Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on @@ -298,49 +233,48 @@ the address in square braces. By default, the listening socket on the server will be bound to - the loopback interface only. This may be overridden by - specifying a bind_address. An empty bind_address, or the address - `*', indicates that the remote socket should listen on all - interfaces. Specifying a remote bind_address will only succeed - if the server's GatewayPorts option is enabled (see - sshd_config(5)). + the loopback interface only. This may be overridden by specify- + ing a bind_address. An empty bind_address, or the address '*', + indicates that the remote socket should listen on all interfaces. + Specifying a remote bind_address will only succeed if the + server's GatewayPorts option is enabled (see sshd_config(5)). - If the port argument is `0', the listen port will be dynamically + If the port argument is '0', the listen port will be dynamically allocated on the server and reported to the client at run time. When used together with -O forward the allocated port will be printed to the standard output. -S ctl_path - Specifies the location of a control socket for connection - sharing, or the string ``none'' to disable connection sharing. - Refer to the description of ControlPath and ControlMaster in + Specifies the location of a control socket for connection shar- + ing, or the string ``none'' to disable connection sharing. Refer + to the description of ControlPath and ControlMaster in ssh_config(5) for details. -s May be used to request invocation of a subsystem on the remote system. Subsystems are a feature of the SSH2 protocol which - facilitate the use of SSH as a secure transport for other - applications (eg. sftp(1)). The subsystem is specified as the - remote command. + facilitate the use of SSH as a secure transport for other appli- + cations (eg. sftp(1)). The subsystem is specified as the remote + command. -T Disable pseudo-tty allocation. - -t Force pseudo-tty allocation. This can be used to execute - arbitrary screen-based programs on a remote machine, which can be + -t Force pseudo-tty allocation. This can be used to execute arbi- + trary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty. -V Display the version number and exit. -v Verbose mode. Causes ssh to print debugging messages about its - progress. This is helpful in debugging connection, - authentication, and configuration problems. Multiple -v options - increase the verbosity. The maximum is 3. + progress. This is helpful in debugging connection, authentica- + tion, and configuration problems. Multiple -v options increase + the verbosity. The maximum is 3. -W host:port - Requests that standard input and output on the client be - forwarded to host on port over the secure channel. Implies -N, - -T, ExitOnForwardFailure and ClearAllForwardings and works with - Protocol version 2 only. + Requests that standard input and output on the client be for- + warded to host on port over the secure channel. Implies -N, -T, + ExitOnForwardFailure and ClearAllForwardings and works with Pro- + tocol version 2 only. -w local_tun[:remote_tun] Requests tunnel device forwarding with the specified tun(4) @@ -376,9 +310,9 @@ -y Send log information using the syslog(3) system module. By default this information is sent to stderr. - ssh may additionally obtain configuration data from a per-user - configuration file and a system-wide configuration file. The file format - and configuration options are described in ssh_config(5). + ssh may additionally obtain configuration data from a per-user configura- + tion file and a system-wide configuration file. The file format and con- + figuration options are described in ssh_config(5). ssh exits with the exit status of the remote command or with 255 if an error occurred. @@ -393,11 +327,11 @@ integrity (hmac-md5, hmac-sha1, umac-64, hmac-ripemd160). Protocol 1 lacks a strong mechanism for ensuring the integrity of the connection. - The methods available for authentication are: GSSAPI-based - authentication, host-based authentication, public key authentication, - challenge-response authentication, and password authentication. - Authentication methods are tried in the order specified above, though - protocol 2 has a configuration option to change the default order: + The methods available for authentication are: GSSAPI-based authentica- + tion, host-based authentication, public key authentication, challenge- + response authentication, and password authentication. Authentication + methods are tried in the order specified above, though protocol 2 has a + configuration option to change the default order: PreferredAuthentications. Host-based authentication works as follows: If the machine the user logs @@ -406,73 +340,79 @@ ~/.rhosts or ~/.shosts exist in the user's home directory on the remote machine and contain a line containing the name of the client machine and the name of the user on that machine, the user is considered for login. - Additionally, the server must be able to verify the client's host key - (see the description of /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts, - below) for login to be permitted. This authentication method closes - security holes due to IP spoofing, DNS spoofing, and routing spoofing. - [Note to the administrator: /etc/hosts.equiv, ~/.rhosts, and the - rlogin/rsh protocol in general, are inherently insecure and should be - disabled if security is desired.] - - Public key authentication works as follows: The scheme is based on - public-key cryptography, using cryptosystems where encryption and - decryption are done using separate keys, and it is unfeasible to derive - the decryption key from the encryption key. The idea is that each user - creates a public/private key pair for authentication purposes. The - server knows the public key, and only the user knows the private key. - ssh implements public key authentication protocol automatically, using - either the RSA or DSA algorithms. Protocol 1 is restricted to using only - RSA keys, but protocol 2 may use either. The HISTORY section of ssl(8) - contains a brief discussion of the two algorithms. - - The file ~/.ssh/authorized_keys lists the public keys that are permitted - for logging in. When the user logs in, the ssh program tells the server - which key pair it would like to use for authentication. The client - proves that it has access to the private key and the server checks that - the corresponding public key is authorized to accept the account. + Additionally, the server must be able to verify the client's host key or + certificate (see the description of /etc/ssh/ssh_known_hosts and + ~/.ssh/known_hosts, below) for login to be permitted. This authentica- + tion method closes security holes due to IP spoofing, DNS spoofing, and + routing spoofing. [Note to the administrator: /etc/hosts.equiv, + ~/.rhosts, and the rlogin/rsh protocol in general, are inherently inse- + cure and should be disabled if security is desired.] + + Public key authentication works as follows: The scheme is based on pub- + lic-key cryptography or infrastructure (PKI), using cryptosystems where + encryption and decryption are done using separate keys, and it is unfea- + sible to derive the decryption key from the encryption key. The idea is + that each user creates a public/private key pair for authentication pur- + poses. The server knows the public key or certificate, and only the user + knows the private key. ssh implements public key authentication protocol + automatically, using either the RSA or DSA algorithms. Protocol 1 is + restricted to using only RSA keys, but protocol 2 may use either or X.509 + certificates. The HISTORY section of ssl(8) contains a brief discussion + of the two algorithms. + + The file ~/.ssh/authorized_keys lists the public keys or certificates + that are permitted for logging in. When the user logs in, the ssh pro- + gram tells the server which key pair or certificate it would like to use + for authentication. The client proves that it has access to the private + key and the server checks that the corresponding public key or certifi- + cate is authorized to accept the account. The user creates his/her key pair by running ssh-keygen(1). This stores the private key in ~/.ssh/identity (protocol 1), ~/.ssh/id_dsa (protocol 2 DSA), or ~/.ssh/id_rsa (protocol 2 RSA) and stores the public key in ~/.ssh/identity.pub (protocol 1), ~/.ssh/id_dsa.pub (protocol 2 DSA), or - ~/.ssh/id_rsa.pub (protocol 2 RSA) in the user's home directory. The - user should then copy the public key to ~/.ssh/authorized_keys in his/her - home directory on the remote machine. The authorized_keys file - corresponds to the conventional ~/.rhosts file, and has one key per line, - though the lines can be very long. After this, the user can log in - without giving the password. - - A variation on public key authentication is available in the form of - certificate authentication: instead of a set of public/private keys, - signed certificates are used. This has the advantage that a single - trusted certification authority can be used in place of many - public/private keys. See the CERTIFICATES section of ssh-keygen(1) for - more information. + ~/.ssh/id_rsa.pub (protocol 2 RSA) in the user's home directory. It is + possible protocol version 2 identity file to contain private key followed + by X.509 certificate that match it. In this case *.pub file must contain + that certificate. The user should then copy the public key or certifi- + cate to ~/.ssh/authorized_keys in his/her home directory on the remote + machine. In case with X.509 certificates user can use ``new style'' : + instead to add content of file to authorized_keys user can write certifi- + cate ``Distinguished Name'' - see sshd(8) manual page. The + authorized_keys file corresponds to the conventional ~/.rhosts file, and + has one key or certificate per line, though the lines can be very long. + After this, the user can log in without giving the password. + + A variation on public key authentication is available in the form of cer- + tificate authentication: instead of a set of public/private keys, signed + certificates are used. This has the advantage that a single trusted cer- + tification authority can be used in place of many public/private keys. + See the CERTIFICATES section of ssh-keygen(1) for more information. The most convenient way to use public key or certificate authentication - may be with an authentication agent. See ssh-agent(1) for more - information. + may be with an authentication agent. See ssh-agent(1) for more informa- + tion. Challenge-response authentication works as follows: The server sends an arbitrary "challenge" text, and prompts for a response. Protocol 2 allows multiple challenges and responses; protocol 1 is restricted to - just one challenge/response. Examples of challenge-response - authentication include BSD Authentication (see login.conf(5)) and PAM - (some non-OpenBSD systems). + just one challenge/response. Examples of challenge-response authentica- + tion include BSD Authentication (see login.conf(5)) and PAM (some non- + OpenBSD systems). Finally, if other authentication methods fail, ssh prompts the user for a password. The password is sent to the remote host for checking; however, since all communications are encrypted, the password cannot be seen by someone listening on the network. - ssh automatically maintains and checks a database containing - identification for all hosts it has ever been used with. Host keys are - stored in ~/.ssh/known_hosts in the user's home directory. Additionally, - the file /etc/ssh/ssh_known_hosts is automatically checked for known - hosts. Any new hosts are automatically added to the user's file. If a - host's identification ever changes, ssh warns about this and disables - password authentication to prevent server spoofing or man-in-the-middle - attacks, which could otherwise be used to circumvent the encryption. The + ssh automatically maintains and checks a database containing identifica- + tion for all hosts it has ever been used with. Host keys are stored in + ~/.ssh/known_hosts in the user's home directory. Additionally, the file + /etc/ssh/ssh_known_hosts is automatically checked for known hosts. Any + new hosts are automatically added to the user's file. If a host's iden- + tification ever changes, ssh warns about this and disables password + authentication to prevent server spoofing or man-in-the-middle attacks, + which could otherwise be used to circumvent the encryption. The StrictHostKeyChecking option can be used to control logins to machines whose host key is not known or has changed. @@ -493,16 +433,16 @@ exits and all X11 and TCP connections have been closed. ESCAPE CHARACTERS - When a pseudo-terminal has been requested, ssh supports a number of - functions through the use of an escape character. + When a pseudo-terminal has been requested, ssh supports a number of func- + tions through the use of an escape character. A single tilde character can be sent as ~~ or by following the tilde by a character other than those described below. The escape character must - always follow a newline to be interpreted as special. The escape - character can be changed in configuration files using the EscapeChar - configuration directive or on the command line by the -e option. + always follow a newline to be interpreted as special. The escape charac- + ter can be changed in configuration files using the EscapeChar configura- + tion directive or on the command line by the -e option. - The supported escapes (assuming the default `~') are: + The supported escapes (assuming the default '~') are: ~. Disconnect. @@ -537,8 +477,8 @@ In the example below, we look at encrypting communication between an IRC client and server, even though the IRC server does not directly support encrypted communications. This works as follows: the user connects to - the remote host using ssh, specifying a port to be used to forward - connections to the remote server. After that it is possible to start the + the remote host using ssh, specifying a port to be used to forward con- + nections to the remote server. After that it is possible to start the service which is to be encrypted on the client machine, connecting to the same local port, and ssh will encrypt and forward the connection. @@ -549,11 +489,11 @@ $ irc -c '#users' -p 1234 pinky 127.0.0.1 This tunnels a connection to IRC server ``server.example.com'', joining - channel ``#users'', nickname ``pinky'', using port 1234. It doesn't - matter which port is used, as long as it's greater than 1023 (remember, - only root can open sockets on privileged ports) and doesn't conflict with - any ports already in use. The connection is forwarded to port 6667 on - the remote server, since that's the standard port for IRC services. + channel ``#users'', nickname ``pinky'', using port 1234. It doesn't mat- + ter which port is used, as long as it's greater than 1023 (remember, only + root can open sockets on privileged ports) and doesn't conflict with any + ports already in use. The connection is forwarded to port 6667 on the + remote server, since that's the standard port for IRC services. The -f option backgrounds ssh and the remote command ``sleep 10'' is specified to allow an amount of time (10 seconds, in the example) to @@ -563,13 +503,13 @@ X11 FORWARDING If the ForwardX11 variable is set to ``yes'' (or see the description of the -X, -x, and -Y options above) and the user is using X11 (the DISPLAY - environment variable is set), the connection to the X11 display is - automatically forwarded to the remote side in such a way that any X11 - programs started from the shell (or command) will go through the - encrypted channel, and the connection to the real X server will be made - from the local machine. The user should not manually set DISPLAY. - Forwarding of X11 connections can be configured on the command line or in - configuration files. + environment variable is set), the connection to the X11 display is auto- + matically forwarded to the remote side in such a way that any X11 pro- + grams started from the shell (or command) will go through the encrypted + channel, and the connection to the real X server will be made from the + local machine. The user should not manually set DISPLAY. Forwarding of + X11 connections can be configured on the command line or in configuration + files. The DISPLAY value set by ssh will point to the server machine, but with a display number greater than zero. This is normal, and happens because @@ -614,13 +554,14 @@ $ ssh-keygen -lv -f ~/.ssh/known_hosts If the fingerprint is unknown, an alternative method of verification is - available: SSH fingerprints verified by DNS. An additional resource - record (RR), SSHFP, is added to a zonefile and the connecting client is - able to match the fingerprint with that of the key presented. + available: SSH fingerprints or certificates verified by DNS. An addi- + tional resource record (RR), SSHFP or CERT, is added to a zonefile and + the connecting client is able to match the fingerprint or certificate + with that of the key presented. In this example, we are connecting a client to a server, - ``host.example.com''. The SSHFP resource records should first be added - to the zonefile for host.example.com: + ``host.example.com''. The SSHFP or CERT resource records should first be + added to the zonefile for host.example.com: $ ssh-keygen -r host.example.com. @@ -629,6 +570,10 @@ $ dig -t SSHFP host.example.com + To check that the zone is answering certificate queries: + + $ dig -t CERT host.example.com + Finally the client connects: $ ssh -o "VerifyHostKeyDNS ask" host.example.com @@ -636,14 +581,16 @@ Matching host key fingerprint found in DNS. Are you sure you want to continue connecting (yes/no)? + When host key is a X.509 certificate ``Distinguished Name'' is shown too. + See the VerifyHostKeyDNS option in ssh_config(5) for more information. SSH-BASED VIRTUAL PRIVATE NETWORKS ssh contains support for Virtual Private Network (VPN) tunnelling using the tun(4) network pseudo-device, allowing two networks to be joined securely. The sshd_config(5) configuration option PermitTunnel controls - whether the server supports this, and at what level (layer 2 or 3 - traffic). + whether the server supports this, and at what level (layer 2 or 3 traf- + fic). The following example would connect client network 10.0.50.0/24 with remote network 10.0.99.0/24 using a point-to-point connection from @@ -671,8 +618,8 @@ tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john Since an SSH-based setup entails a fair amount of overhead, it may be - more suited to temporary setups, such as for wireless VPNs. More - permanent VPNs are better provided by tools such as ipsecctl(8) and + more suited to temporary setups, such as for wireless VPNs. More perma- + nent VPNs are better provided by tools such as ipsecctl(8) and isakmpd(8). ENVIRONMENT @@ -682,7 +629,7 @@ X11 server. It is automatically set by ssh to point to a value of the form ``hostname:n'', where ``hostname'' indicates the host where the shell - runs, and `n' is an integer >= 1. ssh uses this + runs, and 'n' is an integer >= 1. ssh uses this special value to forward X11 connections over the secure channel. The user should normally not set DISPLAY explicitly, as that will render the X11 @@ -691,13 +638,13 @@ HOME Set to the path of the user's home directory. - LOGNAME Synonym for USER; set for compatibility with - systems that use this variable. + LOGNAME Synonym for USER; set for compatibility with sys- + tems that use this variable. MAIL Set to the path of the user's mailbox. - PATH Set to the default PATH, as specified when - compiling ssh. + PATH Set to the default PATH, as specified when compil- + ing ssh. SSH_ASKPASS If ssh needs a passphrase, it will read the passphrase from the current terminal if it was run @@ -705,33 +652,32 @@ associated with it but DISPLAY and SSH_ASKPASS are set, it will execute the program specified by SSH_ASKPASS and open an X11 window to read the - passphrase. This is particularly useful when - calling ssh from a .xsession or related script. - (Note that on some machines it may be necessary to - redirect the input from /dev/null to make this - work.) + passphrase. This is particularly useful when call- + ing ssh from a .xsession or related script. (Note + that on some machines it may be necessary to redi- + rect the input from /dev/null to make this work.) SSH_AUTH_SOCK Identifies the path of a UNIX-domain socket used to communicate with the agent. - SSH_CONNECTION Identifies the client and server ends of the - connection. The variable contains four space- - separated values: client IP address, client port - number, server IP address, and server port number. + SSH_CONNECTION Identifies the client and server ends of the con- + nection. The variable contains four space-sepa- + rated values: client IP address, client port num- + ber, server IP address, and server port number. SSH_ORIGINAL_COMMAND This variable contains the original command line if a forced command is executed. It can be used to extract the original arguments. SSH_TTY This is set to the name of the tty (path to the - device) associated with the current shell or - command. If the current session has no tty, this + device) associated with the current shell or com- + mand. If the current session has no tty, this variable is not set. TZ This variable is set to indicate the present time zone if it was set when the daemon was started - (i.e. the daemon passes the value on to new - connections). + (i.e. the daemon passes the value on to new connec- + tions). USER Set to the name of the user logging in. @@ -756,18 +702,27 @@ rlogin/rsh. ~/.ssh/ - This directory is the default location for all user-specific - configuration and authentication information. There is no - general requirement to keep the entire contents of this directory - secret, but the recommended permissions are read/write/execute - for the user, and not accessible by others. + This directory is the default location for all user-specific con- + figuration and authentication information. There is no general + requirement to keep the entire contents of this directory secret, + but the recommended permissions are read/write/execute for the + user, and not accessible by others. ~/.ssh/authorized_keys - Lists the public keys (RSA/DSA) that can be used for logging in - as this user. The format of this file is described in the - sshd(8) manual page. This file is not highly sensitive, but the - recommended permissions are read/write for the user, and not - accessible by others. + Lists the public keys (RSA/DSA) or certificates that can be used + for logging in as this user. The format of this file is + described in the sshd(8) manual page. This file is not highly + sensitive, but the recommended permissions are read/write for the + user, and not accessible by others. + + ~/.ssh/ca/ca-bundle.crt + ~/.ssh/ca/ca-bundle.crl + Part of user ``X.509 store''. Same as systemwide files below. + + ~/.ssh/ca/crt + ~/.ssh/ca/crl + Part of user ``X.509 store''. Same as systemwide directories + below. ~/.ssh/config This is the per-user configuration file. The file format and @@ -782,25 +737,28 @@ ~/.ssh/identity ~/.ssh/id_dsa ~/.ssh/id_rsa - Contains the private key for authentication. These files contain - sensitive data and should be readable by the user but not - accessible by others (read/write/execute). ssh will simply - ignore a private key file if it is accessible by others. It is - possible to specify a passphrase when generating the key which - will be used to encrypt the sensitive part of this file using - 3DES. + Contains the private key for authentication. It is possible pro- + tocol version 2 identity to contain private key followed by X.509 + certificate that match it. These files contain sensitive data + and should be readable by the user but not accessible by others + (read/write/execute). ssh will simply ignore a private key file + if it is accessible by others. It is possible to specify a + passphrase when generating the key which will be used to encrypt + the sensitive part of this file using 3DES. ~/.ssh/identity.pub ~/.ssh/id_dsa.pub ~/.ssh/id_rsa.pub - Contains the public key for authentication. These files are not - sensitive and can (but need not) be readable by anyone. + Contains the public key for authentication. Note for protocol + version 2 if an identity contain private key followed by X.509 + certificate, file must contain that certificate. These files are + not sensitive and can (but need not) be readable by anyone. ~/.ssh/known_hosts - Contains a list of host keys for all hosts the user has logged - into that are not already in the systemwide list of known host - keys. See sshd(8) for further details of the format of this - file. + Contains a list of host keys or certificates for all hosts the + user has logged into that are not already in the systemwide list + of known host keys. See sshd(8) for further details of the for- + mat of this file. ~/.ssh/rc Commands in this file are executed by ssh when the user logs in, @@ -816,6 +774,24 @@ allows host-based authentication without permitting login with rlogin/rsh. + /etc/ssh/ca/ca-bundle.crt + /etc/ssh/ca/ca-bundle.crl + Part of systemwide ``X.509 store''. The first file contain mul- + tiple certificates and the second ``Certificate Revocation List'' + (CRLs) of certificate signers in PEM format concatenated + together. Used in verification and validation of server host + certificate. + + /etc/ssh/ca/crt + /etc/ssh/ca/crl + Part of systemwide ``X.509 store''. ``Hash dirs'' with certifi- + cates, the first directory or CLRs, the second of certificate + signers. Each certificate should be stored in separate file with + name [HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where + [HASH] is certificate or CRL hash value and [NUMBER] is an inte- + ger starting from zero. Used in verification and validation of + server host certificate. + /etc/ssh/ssh_config Systemwide configuration file. The file format and configuration options are described in ssh_config(5). @@ -824,18 +800,25 @@ /etc/ssh/ssh_host_dsa_key /etc/ssh/ssh_host_rsa_key These three files contain the private parts of the host keys and - are used for host-based authentication. If protocol version 1 is - used, ssh must be setuid root, since the host key is readable - only by root. For protocol version 2, ssh uses ssh-keysign(8) to - access the host keys, eliminating the requirement that ssh be - setuid root when host-based authentication is used. By default - ssh is not setuid root. + are used for host-based authentication. It is possible files to + contain private part followed by X.509 certificate that match it + for protocol version 2 keys. If protocol version 1 is used, ssh + must be setuid root, since the host key is readable only by root. + For protocol version 2, ssh uses ssh-keysign(8) to access the + host keys, eliminating the requirement that ssh be setuid root + when host-based authentication is used. By default ssh is not + setuid root. When a certificate is used as host key for host- + based authentication that certificate must have client purpose + too or server configuration must permit connection without client + purpose. For allowed client certificate purposes see + ssh_config(5). /etc/ssh/ssh_known_hosts - Systemwide list of known host keys. This file should be prepared - by the system administrator to contain the public host keys of - all machines in the organization. It should be world-readable. - See sshd(8) for further details of the format of this file. + Systemwide list of known host keys or certificates. This file + should be prepared by the system administrator to contain the + public host keys or certificates of all machines in the organiza- + tion. It should be world-readable. See sshd(8) for further + details of the format of this file. /etc/ssh/sshrc Commands in this file are executed by ssh when the user logs in, @@ -874,15 +857,16 @@ The Secure Shell (SSH) Public Key File Format, RFC 4716, 2006. - A. Perrig, D. Song, Hash Visualization: a New Technique to improve + A. Perrig and D. Song, Hash Visualization: a New Technique to improve Real-World Security, 1999, International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99). AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 4.8 August 4, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh.1 openssh-5.6p1+x509-6.2.3/ssh.1 --- openssh-5.6p1/ssh.1 2010-08-05 06:03:13.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh.1 2010-08-24 09:06:00.000000000 +0300 @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -34,7 +35,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. .\" -.\" $OpenBSD: ssh.1,v 1.308 2010/08/04 05:37:01 djm Exp $ +.\" $OpenBSD$ .Dd $Mdocdate: August 4 2010 $ .Dt SSH 1 .Os @@ -277,6 +278,8 @@ and .Pa ~/.ssh/id_dsa for protocol version 2. +For protocol version 2 is possible identity to contain in addition +X.509 certificate that match private key. Identity files may also be specified on a per-host basis in the configuration file. It is possible to have multiple @@ -399,75 +402,8 @@ Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate command-line flag. -For full details of the options listed below, and their possible values, see +For full details of the options and their possible values, see .Xr ssh_config 5 . -.Pp -.Bl -tag -width Ds -offset indent -compact -.It AddressFamily -.It BatchMode -.It BindAddress -.It ChallengeResponseAuthentication -.It CheckHostIP -.It Cipher -.It Ciphers -.It ClearAllForwardings -.It Compression -.It CompressionLevel -.It ConnectionAttempts -.It ConnectTimeout -.It ControlMaster -.It ControlPath -.It DynamicForward -.It EscapeChar -.It ExitOnForwardFailure -.It ForwardAgent -.It ForwardX11 -.It ForwardX11Trusted -.It GatewayPorts -.It GlobalKnownHostsFile -.It GSSAPIAuthentication -.It GSSAPIDelegateCredentials -.It HashKnownHosts -.It Host -.It HostbasedAuthentication -.It HostKeyAlgorithms -.It HostKeyAlias -.It HostName -.It IdentityFile -.It IdentitiesOnly -.It KbdInteractiveDevices -.It LocalCommand -.It LocalForward -.It LogLevel -.It MACs -.It NoHostAuthenticationForLocalhost -.It NumberOfPasswordPrompts -.It PasswordAuthentication -.It PermitLocalCommand -.It PKCS11Provider -.It Port -.It PreferredAuthentications -.It Protocol -.It ProxyCommand -.It PubkeyAuthentication -.It RekeyLimit -.It RemoteForward -.It RhostsRSAAuthentication -.It RSAAuthentication -.It SendEnv -.It ServerAliveInterval -.It ServerAliveCountMax -.It StrictHostKeyChecking -.It TCPKeepAlive -.It Tunnel -.It TunnelDevice -.It UsePrivilegedPort -.It User -.It UserKnownHostsFile -.It VerifyHostKeyDNS -.It VisualHostKey -.It XAuthLocation -.El .It Fl p Ar port Port to connect to on the remote host. This can be specified on a @@ -697,7 +633,7 @@ Additionally, the server .Em must be able to verify the client's -host key (see the description of +host key or certificate (see the description of .Pa /etc/ssh/ssh_known_hosts and .Pa ~/.ssh/known_hosts , @@ -712,18 +648,18 @@ disabled if security is desired.] .Pp Public key authentication works as follows: -The scheme is based on public-key cryptography, +The scheme is based on public-key cryptography or infrastructure (PKI), using cryptosystems where encryption and decryption are done using separate keys, and it is unfeasible to derive the decryption key from the encryption key. The idea is that each user creates a public/private key pair for authentication purposes. -The server knows the public key, and only the user knows the private key. +The server knows the public key or certificate, and only the user knows the private key. .Nm implements public key authentication protocol automatically, using either the RSA or DSA algorithms. Protocol 1 is restricted to using only RSA keys, -but protocol 2 may use either. +but protocol 2 may use either or X.509 certificates. The .Sx HISTORY section of @@ -732,13 +668,13 @@ .Pp The file .Pa ~/.ssh/authorized_keys -lists the public keys that are permitted for logging in. +lists the public keys or certificates that are permitted for logging in. When the user logs in, the .Nm -program tells the server which key pair it would like to use for +program tells the server which key pair or certificate it would like to use for authentication. The client proves that it has access to the private key -and the server checks that the corresponding public key +and the server checks that the corresponding public key or certificate is authorized to accept the account. .Pp The user creates his/her key pair by running @@ -760,15 +696,26 @@ .Pa ~/.ssh/id_rsa.pub (protocol 2 RSA) in the user's home directory. -The user should then copy the public key +It is possible protocol version 2 identity file to contain +private key followed by X.509 certificate that match it. +In this case *.pub file must contain that certificate. +The user should then copy the public key or certificate to .Pa ~/.ssh/authorized_keys in his/her home directory on the remote machine. +In case with X.509 certificates user can use +.Dq new style +: instead to add content of file to authorized_keys user +can write certificate +.Dq Distinguished Name +- see +.Xr sshd 8 +manual page. The .Pa authorized_keys file corresponds to the conventional .Pa ~/.rhosts -file, and has one key +file, and has one key or certificate per line, though the lines can be very long. After this, the user can log in without giving the password. .Pp @@ -1056,16 +1003,17 @@ .Pp If the fingerprint is unknown, an alternative method of verification is available: -SSH fingerprints verified by DNS. +SSH fingerprints or certificates verified by DNS. An additional resource record (RR), -SSHFP, +SSHFP or CERT, is added to a zonefile and the connecting client is able to match the fingerprint +or certificate with that of the key presented. .Pp In this example, we are connecting a client to a server, .Dq host.example.com . -The SSHFP resource records should first be added to the zonefile for +The SSHFP or CERT resource records should first be added to the zonefile for host.example.com: .Bd -literal -offset indent $ ssh-keygen -r host.example.com. @@ -1076,6 +1024,10 @@ .Pp .Dl $ dig -t SSHFP host.example.com .Pp +To check that the zone is answering certificate queries: +.Pp +.Dl $ dig -t CERT host.example.com +.Pp Finally the client connects: .Bd -literal -offset indent $ ssh -o "VerifyHostKeyDNS ask" host.example.com @@ -1084,6 +1036,10 @@ Are you sure you want to continue connecting (yes/no)? .Ed .Pp +When host key is a X.509 certificate +.Dq Distinguished Name +is shown too. +.Pp See the .Cm VerifyHostKeyDNS option in @@ -1277,13 +1233,25 @@ and not accessible by others. .Pp .It ~/.ssh/authorized_keys -Lists the public keys (RSA/DSA) that can be used for logging in as this user. +Lists the public keys (RSA/DSA) or certificates that can be used for logging in as this user. The format of this file is described in the .Xr sshd 8 manual page. This file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others. .Pp +.It ~/.ssh/ca/ca-bundle.crt +.It ~/.ssh/ca/ca-bundle.crl +Part of user +.Dq "X.509 store" . +Same as systemwide files below. +.Pp +.It ~/.ssh/ca/crt +.It ~/.ssh/ca/crl +Part of user +.Dq "X.509 store" . +Same as systemwide directories below. +.Pp .It ~/.ssh/config This is the per-user configuration file. The file format and configuration options are described in @@ -1300,6 +1268,8 @@ .It ~/.ssh/id_dsa .It ~/.ssh/id_rsa Contains the private key for authentication. +It is possible protocol version 2 identity to contain +private key followed by X.509 certificate that match it. These files contain sensitive data and should be readable by the user but not accessible by others (read/write/execute). @@ -1313,11 +1283,13 @@ .It ~/.ssh/id_dsa.pub .It ~/.ssh/id_rsa.pub Contains the public key for authentication. +Note for protocol version 2 if an identity contain private key +followed by X.509 certificate, file must contain that certificate. These files are not sensitive and can (but need not) be readable by anyone. .Pp .It ~/.ssh/known_hosts -Contains a list of host keys for all hosts the user has logged into +Contains a list of host keys or certificates for all hosts the user has logged into that are not already in the systemwide list of known host keys. See .Xr sshd 8 @@ -1342,6 +1314,28 @@ but allows host-based authentication without permitting login with rlogin/rsh. .Pp +.It /etc/ssh/ca/ca-bundle.crt +.It /etc/ssh/ca/ca-bundle.crl +Part of systemwide +.Dq "X.509 store" . +The first file contain multiple certificates and the second +.Dq "Certificate Revocation List" +(CRLs) of certificate signers in PEM format concatenated together. +Used in verification and validation of server host certificate. +.Pp +.It /etc/ssh/ca/crt +.It /etc/ssh/ca/crl +Part of systemwide +.Dq "X.509 store" . +.Dq "Hash dirs" +with certificates, the first directory or CLRs, the second of +certificate signers. +Each certificate should be stored in separate file with name +[HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where [HASH] is +certificate or CRL hash value and [NUMBER] is an integer starting +from zero. +Used in verification and validation of server host certificate. +.Pp .It Pa /etc/ssh/ssh_config Systemwide configuration file. The file format and configuration options are described in @@ -1352,6 +1346,9 @@ .It /etc/ssh/ssh_host_rsa_key These three files contain the private parts of the host keys and are used for host-based authentication. +It is possible files to contain private part +followed by X.509 certificate that match it +for protocol version 2 keys. If protocol version 1 is used, .Nm must be setuid root, since the host key is readable only by root. @@ -1366,12 +1363,17 @@ By default .Nm is not setuid root. +When a certificate is used as host key for hostbased authentication +that certificate must have client purpose too or server configuration +must permit connection without client purpose. For allowed client +certificate purposes see +.Xr ssh_config 5 . .Pp .It /etc/ssh/ssh_known_hosts -Systemwide list of known host keys. +Systemwide list of known host keys or certificates. This file should be prepared by the -system administrator to contain the public host keys of all machines in the -organization. +system administrator to contain the public host keys or certificates +of all machines in the organization. It should be world-readable. See .Xr sshd 8 @@ -1473,3 +1475,4 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-5.6p1/ssh-add.0 openssh-5.6p1+x509-6.2.3/ssh-add.0 --- openssh-5.6p1/ssh-add.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-add.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSH-ADD(1) OpenBSD Reference Manual SSH-ADD(1) +SSH-ADD(1) BSD General Commands Manual SSH-ADD(1) NAME - ssh-add - adds RSA or DSA identities to the authentication agent + ssh-add -- adds RSA or DSA identities to the authentication agent SYNOPSIS ssh-add [-cDdLlXx] [-t life] [file ...] @@ -10,28 +10,27 @@ DESCRIPTION ssh-add adds RSA or DSA identities to the authentication agent, - ssh-agent(1). When run without arguments, it adds the files - ~/.ssh/id_rsa, ~/.ssh/id_dsa and ~/.ssh/identity. After loading a - private key, ssh-add will try to load corresponding certificate - information from the filename obtained by appending -cert.pub to the name - of the private key file. Alternative file names can be given on the - command line. + ssh-agent(1). It is possible identity to contain in addition correspond- + ing X.509 certificate. When run without arguments, it adds the files + ~/.ssh/id_rsa, ~/.ssh/id_dsa and ~/.ssh/identity. After loading a pri- + vate key, ssh-add will try to load corresponding certificate information + from the filename obtained by appending -cert.pub to the name of the pri- + vate key file. Alternative file names can be given on the command line. If any file requires a passphrase, ssh-add asks for the passphrase from the user. The passphrase is read from the user's tty. ssh-add retries the last passphrase if multiple identity files are given. - The authentication agent must be running and the SSH_AUTH_SOCK - environment variable must contain the name of its socket for ssh-add to - work. + The authentication agent must be running and the SSH_AUTH_SOCK environ- + ment variable must contain the name of its socket for ssh-add to work. The options are as follows: -c Indicates that added identities should be subject to confirmation before being used for authentication. Confirmation is performed - by the SSH_ASKPASS program mentioned below. Successful - confirmation is signaled by a zero exit status from the - SSH_ASKPASS program, rather than text entered into the requester. + by the SSH_ASKPASS program mentioned below. Successful confirma- + tion is signaled by a zero exit status from the SSH_ASKPASS pro- + gram, rather than text entered into the requester. -D Deletes all identities from the agent. @@ -45,8 +44,8 @@ -e pkcs11 Remove keys provided by the PKCS#11 shared library pkcs11. - -L Lists public key parameters of all identities currently - represented by the agent. + -L Lists public key or certificate parameters of all identities cur- + rently represented by the agent. -l Lists fingerprints of all identities currently represented by the agent. @@ -56,8 +55,8 @@ -t life Set a maximum lifetime when adding identities to an agent. The - lifetime may be specified in seconds or in a time format - specified in sshd_config(5). + lifetime may be specified in seconds or in a time format speci- + fied in sshd_config(5). -X Unlock the agent. @@ -85,11 +84,13 @@ ~/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of - the user. + the user. It is possible to contain private key followed by + X.509 certificate that match it. ~/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of - the user. + the user. It is possible to contain private key followed by + X.509 certificate that match it. Identity files should not be readable by anyone but the user. Note that ssh-add ignores identity files if they are accessible by others. @@ -104,8 +105,9 @@ AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 4.8 March 5, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh-add.1 openssh-5.6p1+x509-6.2.3/ssh-add.1 --- openssh-5.6p1/ssh-add.1 2010-03-05 12:31:11.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-add.1 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.52 2010/03/05 10:28:21 djm Exp $ +.\" $OpenBSD$ .\" .\" -*- nroff -*- .\" @@ -16,6 +16,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -56,6 +57,8 @@ .Nm adds RSA or DSA identities to the authentication agent, .Xr ssh-agent 1 . +It is possible identity to contain in addition +corresponding X.509 certificate. When run without arguments, it adds the files .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_dsa @@ -112,8 +115,8 @@ Remove keys provided by the PKCS#11 shared library .Ar pkcs11 . .It Fl L -Lists public key parameters of all identities currently represented -by the agent. +Lists public key or certificate parameters of +all identities currently represented by the agent. .It Fl l Lists fingerprints of all identities currently represented by the agent. .It Fl s Ar pkcs11 @@ -165,8 +168,12 @@ Contains the protocol version 1 RSA authentication identity of the user. .It Pa ~/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. +It is possible to contain private key +followed by X.509 certificate that match it. .It Pa ~/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. +It is possible to contain private key +followed by X.509 certificate that match it. .El .Pp Identity files should not be readable by anyone but the user. @@ -192,3 +199,4 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-5.6p1/ssh-add.c openssh-5.6p1+x509-6.2.3/ssh-add.c --- openssh-5.6p1/ssh-add.c 2010-05-21 07:56:47.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-add.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.96 2010/05/14 00:47:22 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -13,6 +13,8 @@ * * SSH2 implementation, * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * X.509 certificates support, + * Copyright (c) 2002-2005 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -62,6 +64,8 @@ #include "authfile.h" #include "pathnames.h" #include "misc.h" +#include "ssh-x509.h" +#include "ssh-xkalg.h" /* argv0 */ extern char *__progname; @@ -283,9 +287,20 @@ key_size(key), fp, comment, key_type(key)); xfree(fp); } else { +#ifndef SSH_X509STORE_DISABLED + if ((key->type == KEY_X509_RSA) || (key->type == KEY_X509_DSA)) { + /* key_write will print x509 certificate in blob format :-( */ + if(!x509key_write_subject(key, stdout)) + fprintf(stderr, "x509key_write_subject failed"); + fprintf(stdout, "\n"); + } else { +#endif /*ndef SSH_X509STORE_DISABLED*/ if (!key_write(key, stdout)) fprintf(stderr, "key_write failed"); fprintf(stdout, " %s\n", comment); +#ifndef SSH_X509STORE_DISABLED + } +#endif /*ndef SSH_X509STORE_DISABLED*/ } key_free(key); xfree(comment); @@ -373,6 +388,7 @@ seed_rng(); SSLeay_add_all_algorithms(); + fill_default_xkalg(); /* At first, get a connection to the authentication agent. */ ac = ssh_get_authentication_connection(); diff -ruN openssh-5.6p1/ssh-agent.0 openssh-5.6p1+x509-6.2.3/ssh-agent.0 --- openssh-5.6p1/ssh-agent.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-agent.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,17 +1,18 @@ -SSH-AGENT(1) OpenBSD Reference Manual SSH-AGENT(1) +SSH-AGENT(1) BSD General Commands Manual SSH-AGENT(1) NAME - ssh-agent - authentication agent + ssh-agent -- authentication agent SYNOPSIS ssh-agent [-c | -s] [-d] [-a bind_address] [-t life] [command [arg ...]] ssh-agent [-c | -s] -k DESCRIPTION - ssh-agent is a program to hold private keys used for public key - authentication (RSA, DSA). The idea is that ssh-agent is started in the - beginning of an X-session or a login session, and all other windows or - programs are started as clients to the ssh-agent program. Through use of + ssh-agent is a program to hold private keys used for public key authenti- + cation (RSA, DSA). It is possible to contain in addition corresponding + X.509 certificate. The idea is that ssh-agent is started in the begin- + ning of an X-session or a login session, and all other windows or pro- + grams are started as clients to the ssh-agent program. Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using ssh(1). @@ -49,16 +50,17 @@ passphrase, ssh-add(1) asks for the passphrase on the terminal if it has one or from a small X11 program if running under X11. If neither of these is the case then the authentication will fail. It then sends the - identity to the agent. Several identities can be stored in the agent; - the agent can automatically use any of these identities. ssh-add -l - displays the identities currently held by the agent. - - The idea is that the agent is run in the user's local PC, laptop, or - terminal. Authentication data need not be stored on any other machine, - and authentication passphrases never go over the network. However, the - connection to the agent is forwarded over SSH remote logins, and the user - can thus use the privileges given by the identities anywhere in the - network in a secure way. + identity to the agent. Identity can by X.509 certificate that match pri- + vate key. Several identities can be stored in the agent; the agent can + automatically use any of these identities. ssh-add -l displays the iden- + tities currently held by the agent. + + The idea is that the agent is run in the user's local PC, laptop, or ter- + minal. Authentication data need not be stored on any other machine, and + authentication passphrases never go over the network. However, the con- + nection to the agent is forwarded over SSH remote logins, and the user + can thus use the privileges given by the identities anywhere in the net- + work in a secure way. There are two main ways to get an agent set up: The first is that the agent starts a new subcommand into which some environment variables are @@ -68,13 +70,13 @@ Bourne-type shells such as sh(1) or ksh(1) and eval `ssh-agent -c` for csh(1) and derivatives. - Later ssh(1) looks at these variables and uses them to establish a - connection to the agent. + Later ssh(1) looks at these variables and uses them to establish a con- + nection to the agent. The agent will never send a private key over its request channel. Instead, operations that require a private key will be performed by the - agent, and the result will be returned to the requester. This way, - private keys are not exposed to clients using the agent. + agent, and the result will be returned to the requester. This way, pri- + vate keys are not exposed to clients using the agent. A UNIX-domain socket is created and the name of this socket is stored in the SSH_AUTH_SOCK environment variable. The socket is made accessible @@ -93,16 +95,18 @@ ~/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of - the user. + the user. It is possible to contain private key followed by + X.509 certificate that match it. ~/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of - the user. + the user. It is possible to contain private key followed by + X.509 certificate that match it. /tmp/ssh-XXXXXXXXXX/agent. - UNIX-domain sockets used to contain the connection to the - authentication agent. These sockets should only be readable by - the owner. The sockets should get automatically removed when the + UNIX-domain sockets used to contain the connection to the authen- + tication agent. These sockets should only be readable by the + owner. The sockets should get automatically removed when the agent exits. SEE ALSO @@ -111,8 +115,9 @@ AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 4.8 January 17, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh-agent.1 openssh-5.6p1+x509-6.2.3/ssh-agent.1 --- openssh-5.6p1/ssh-agent.1 2010-01-26 03:51:13.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-agent.1 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.50 2010/01/17 21:49:09 tedu Exp $ +.\" $OpenBSD$ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -54,6 +55,7 @@ .Nm is a program to hold private keys used for public key authentication (RSA, DSA). +It is possible to contain in addition corresponding X.509 certificate. The idea is that .Nm is started in the beginning of an X-session or a login session, and @@ -123,6 +125,7 @@ program if running under X11. If neither of these is the case then the authentication will fail. It then sends the identity to the agent. +Identity can by X.509 certificate that match private key. Several identities can be stored in the agent; the agent can automatically use any of these identities. .Ic ssh-add -l @@ -187,8 +190,12 @@ Contains the protocol version 1 RSA authentication identity of the user. .It Pa ~/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. +It is possible to contain private key +followed by X.509 certificate that match it. .It Pa ~/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. +It is possible to contain private key +followed by X.509 certificate that match it. .It Pa /tmp/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt .Ux Ns -domain sockets used to contain the connection to the authentication agent. @@ -209,3 +216,4 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-5.6p1/ssh-agent.c openssh-5.6p1+x509-6.2.3/ssh-agent.c --- openssh-5.6p1/ssh-agent.c 2010-04-16 08:56:22.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-agent.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.166 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,6 +12,8 @@ * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * X.509 certificates support, + * Copyright (c) 2002-2005 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -74,6 +76,8 @@ #include "authfd.h" #include "compat.h" #include "log.h" +#include "ssh-x509.h" +#include "ssh-xkalg.h" #include "misc.h" #ifdef ENABLE_PKCS11 @@ -178,6 +182,25 @@ xfree(id); } +static int/*bool*/ +key_match(const Key *key, Key *found) { + int kt, ret; + + if (key->type == found->type) + return(key_equal(key, found)); + + kt = found->type; + switch(found->type) { + case KEY_X509_RSA: found->type = KEY_RSA; break; + case KEY_X509_DSA: found->type = KEY_DSA; break; + default: return(0); + } + + ret = key_equal(key, found); + found->type = kt; + return(ret); +} + /* return matching private key for given public key */ static Identity * lookup_identity(Key *key, int version) @@ -186,7 +209,7 @@ Idtab *tab = idtab_lookup(version); TAILQ_FOREACH(id, &tab->idlist, next) { - if (key_equal(key, id->key)) + if (key_match(key, id->key)) return (id); } return (NULL); @@ -333,8 +356,12 @@ key = key_from_blob(blob, blen); if (key != NULL) { Identity *id = lookup_identity(key, 2); - if (id != NULL && (!id->confirm || confirm_key(id) == 0)) + if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { + int kt = id->key->type; + id->key->type = key->type; ok = key_sign(id->key, &signature, &slen, data, dlen); + id->key->type = kt; + } key_free(key); } buffer_init(&msg); @@ -493,6 +520,7 @@ xfree(type_name); switch (type) { case KEY_DSA: + case KEY_X509_DSA: k = key_new_private(type); buffer_get_bignum2(&e->request, k->dsa->p); buffer_get_bignum2(&e->request, k->dsa->q); @@ -510,6 +538,7 @@ buffer_get_bignum2(&e->request, k->dsa->priv_key); break; case KEY_RSA: + case KEY_X509_RSA: k = key_new_private(type); buffer_get_bignum2(&e->request, k->rsa->n); buffer_get_bignum2(&e->request, k->rsa->e); @@ -537,10 +566,29 @@ buffer_clear(&e->request); goto send; } + switch (type) { + case KEY_X509_RSA: + case KEY_X509_DSA: { + u_char *blob = NULL; + u_int blen = 0; + Key *key = NULL; + + blob = buffer_get_string(&e->request, &blen); + key = x509key_from_blob(blob, blen); + if(key == NULL) { + fatal("process_add_identity() x509key_from_blob fail"); + } + k->x509 = key->x509; + key->x509 = NULL; + key_free(key); + } + break; + } break; } /* enable blinding */ switch (k->type) { + case KEY_X509_RSA: case KEY_RSA: case KEY_RSA_CERT_V00: case KEY_RSA_CERT: @@ -1093,6 +1141,7 @@ #endif SSLeay_add_all_algorithms(); + fill_default_xkalg(); __progname = ssh_get_progname(av[0]); init_rng(); diff -ruN openssh-5.6p1/ssh.c openssh-5.6p1+x509-6.2.3/ssh.c --- openssh-5.6p1/ssh.c 2010-08-16 18:59:31.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.346 2010/08/12 21:49:44 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -19,6 +19,9 @@ * Modified to work with SSL by Niels Provos * in Canada (German citizen). * + * X.509 certificates support: + * Copyright (c) 2002-2003 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -74,6 +77,10 @@ #include #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" +#ifdef LDAP_ENABLED +/* OpenSSL extension defined in x509_by_ldap.c */ +extern void ERR_load_X509byLDAP_strings(void); +#endif #include "xmalloc.h" #include "ssh.h" @@ -110,6 +117,9 @@ extern char *__progname; +/* ssh-x509.c needs this */ +extern int (*pssh_x509cert_check)(X509 *cert); + /* Flag indicating whether debug mode is on. May be set on the command line. */ int debug_flag = 0; @@ -236,6 +246,7 @@ __progname = ssh_get_progname(av[0]); init_rng(); + pssh_x509cert_check = ssh_x509cert_check; /* * Discard other fds that are hanging around. These can cause problem @@ -601,6 +612,9 @@ SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); +#ifdef LDAP_ENABLED + ERR_load_X509byLDAP_strings(); +#endif /* Initialize the command to execute on remote host. */ buffer_init(&command); diff -ruN openssh-5.6p1/ssh_config openssh-5.6p1+x509-6.2.3/ssh_config --- openssh-5.6p1/ssh_config 2010-01-12 10:40:27.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh_config 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: ssh_config,v 1.26 2010/01/11 01:39:46 dtucker Exp $ +# $OpenBSD$ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -40,6 +40,17 @@ # Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc # MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160 # EscapeChar ~ +# AllowedCertPurpose sslserver +# MandatoryCRL no +# CACertificateFile /etc/ssh/ca/ca-bundle.crt +# CACertificatePath /etc/ssh/ca/crt +# CARevocationFile /etc/ssh/ca/ca-bundle.crl +# CARevocationPath /etc/ssh/ca/crl +# UserCACertificateFile ~/.ssh/ca-bundle.crt +# UserCACertificatePath ~/.ssh/crt +# UserCARevocationFile ~/.ssh/ca-bundle.crl +# UserCARevocationPath ~/.ssh/crl +# VAType none # Tunnel no # TunnelDevice any:any # PermitLocalCommand no diff -ruN openssh-5.6p1/ssh_config.0 openssh-5.6p1+x509-6.2.3/ssh_config.0 --- openssh-5.6p1/ssh_config.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh_config.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,51 +1,51 @@ -SSH_CONFIG(5) OpenBSD Programmer's Manual SSH_CONFIG(5) +SSH_CONFIG(5) BSD File Formats Manual SSH_CONFIG(5) NAME - ssh_config - OpenSSH SSH client configuration files + ssh_config -- OpenSSH SSH client configuration files SYNOPSIS ~/.ssh/config /etc/ssh/ssh_config DESCRIPTION - ssh(1) obtains configuration data from the following sources in the - following order: + ssh(1) obtains configuration data from the following sources in the fol- + lowing order: 1. command-line options 2. user's configuration file (~/.ssh/config) 3. system-wide configuration file (/etc/ssh/ssh_config) - For each parameter, the first obtained value will be used. The - configuration files contain sections separated by ``Host'' - specifications, and that section is only applied for hosts that match one - of the patterns given in the specification. The matched host name is the - one given on the command line. + For each parameter, the first obtained value will be used. The configu- + ration files contain sections separated by ``Host'' specifications, and + that section is only applied for hosts that match one of the patterns + given in the specification. The matched host name is the one given on + the command line. - Since the first obtained value for each parameter is used, more host- - specific declarations should be given near the beginning of the file, and + Since the first obtained value for each parameter is used, more host-spe- + cific declarations should be given near the beginning of the file, and general defaults at the end. The configuration file has the following format: - Empty lines and lines starting with `#' are comments. Otherwise a line + Empty lines and lines starting with '#' are comments. Otherwise a line is of the format ``keyword arguments''. Configuration options may be - separated by whitespace or optional whitespace and exactly one `='; the - latter format is useful to avoid the need to quote whitespace when - specifying configuration options using the ssh, scp, and sftp -o option. + separated by whitespace or optional whitespace and exactly one '='; the + latter format is useful to avoid the need to quote whitespace when speci- + fying configuration options using the ssh, scp, and sftp -o option. Arguments may optionally be enclosed in double quotes (") in order to represent arguments containing spaces. - The possible keywords and their meanings are as follows (note that - keywords are case-insensitive and arguments are case-sensitive): + The possible keywords and their meanings are as follows (note that key- + words are case-insensitive and arguments are case-sensitive): - Host Restricts the following declarations (up to the next Host - keyword) to be only for those hosts that match one of the - patterns given after the keyword. If more than one pattern is - provided, they should be separated by whitespace. A single `*' - as a pattern can be used to provide global defaults for all - hosts. The host is the hostname argument given on the command - line (i.e. the name is not converted to a canonicalized host name - before matching). + Host Restricts the following declarations (up to the next Host key- + word) to be only for those hosts that match one of the patterns + given after the keyword. If more than one pattern is provided, + they should be separated by whitespace. A single '*' as a pat- + tern can be used to provide global defaults for all hosts. The + host is the hostname argument given on the command line (i.e. the + name is not converted to a canonicalized host name before match- + ing). See PATTERNS for more information on patterns. @@ -54,6 +54,18 @@ arguments are ``any'', ``inet'' (use IPv4 only), or ``inet6'' (use IPv6 only). + AllowedCertPurpose + The intended use for the X.509 server certificate. Without this + option no chain verification will be done. Currently accepted + uses are case insensitive: + sslserver | SSL server | SSL_server | server + only SSL-server purpose + any | Any Purpose | Any_Purpose | AnyPurpose + allow any purpose + skip | '' (empty) + do not check purpose + The default is ``sslserver''. + BatchMode If set to ``yes'', passphrase/password querying will be disabled. This option is useful in scripts and other batch jobs where no @@ -66,6 +78,42 @@ one address. Note that this option does not work if UsePrivilegedPort is set to ``yes''. + CACertificateFile + ``X509 store'' option: This file contain multiple certificates of + certificate signers in PEM format concatenated together. The + default is /etc/ssh/ca/ca-bundle.crt. + + CACertificatePath + ``X509 store'' option: ``Hash dir'' with certificates of certifi- + cate signers. Each certificate should be stored in separate file + with name [HASH].[NUMBER], where [HASH] is certificate hash value + and [NUMBER] is an integer starting from zero. The default is + /etc/ssh/ca/crt. + + CAldapVersion + ``X509 store'' option: Specifies LDAP protocol version. The + default depend from LDAP library. + + CAldapURL + ``X509 store'' option: Specifies hostport and dn of LDAP URLs + (Uniform Resource Locators) as detailed in RFC 2255. The rest of + URL is build internally. Because of OpenSSH options parser limi- + tation use '%3D' instead of '=' ! LDAP initialization method may + require URL to be escaped, i.e. use '%2C' instead of ',' (comma). + Escaped URL don't depend from LDAP initialization method. + + CARevocationFile + ``X509 store'' option: This file contain multiple ``Certificate + Revocation List'' (CRL) of certificate signers in PEM format con- + catenated together. The default is /etc/ssh/ca/ca-bundle.crl. + + CARevocationPath + ``X509 store'' option: ``Hash dir'' with ``Certificate Revocation + List'' (CRL) of certificate signers. Each CRL should be stored in + separate file with name [HASH].r[NUMBER], where [HASH] is CRL + hash value and [NUMBER] is an integer starting from zero. The + default is /etc/ssh/ca/crl. + ChallengeResponseAuthentication Specifies whether to use challenge-response authentication. The argument to this keyword must be ``yes'' or ``no''. The default @@ -78,21 +126,20 @@ is set to ``no'', the check will not be executed. The default is ``yes''. - Cipher Specifies the cipher to use for encrypting the session in - protocol version 1. Currently, ``blowfish'', ``3des'', and - ``des'' are supported. des is only supported in the ssh(1) - client for interoperability with legacy protocol 1 - implementations that do not support the 3des cipher. Its use is - strongly discouraged due to cryptographic weaknesses. The - default is ``3des''. + Cipher Specifies the cipher to use for encrypting the session in proto- + col version 1. Currently, ``blowfish'', ``3des'', and ``des'' + are supported. des is only supported in the ssh(1) client for + interoperability with legacy protocol 1 implementations that do + not support the 3des cipher. Its use is strongly discouraged due + to cryptographic weaknesses. The default is ``3des''. Ciphers Specifies the ciphers allowed for protocol version 2 in order of - preference. Multiple ciphers must be comma-separated. The - supported ciphers are ``3des-cbc'', ``aes128-cbc'', - ``aes192-cbc'', ``aes256-cbc'', ``aes128-ctr'', ``aes192-ctr'', - ``aes256-ctr'', ``arcfour128'', ``arcfour256'', ``arcfour'', - ``blowfish-cbc'', and ``cast128-cbc''. The default is: + preference. Multiple ciphers must be comma-separated. The sup- + ported ciphers are ``3des-cbc'', ``aes128-cbc'', ``aes192-cbc'', + ``aes256-cbc'', ``aes128-ctr'', ``aes192-ctr'', ``aes256-ctr'', + ``arcfour128'', ``arcfour256'', ``arcfour'', ``blowfish-cbc'', + and ``cast128-cbc''. The default is: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, @@ -102,10 +149,9 @@ Specifies that all local, remote, and dynamic port forwardings specified in the configuration files or on the command line be cleared. This option is primarily useful when used from the - ssh(1) command line to clear port forwardings set in - configuration files, and is automatically set by scp(1) and - sftp(1). The argument must be ``yes'' or ``no''. The default is - ``no''. + ssh(1) command line to clear port forwardings set in configura- + tion files, and is automatically set by scp(1) and sftp(1). The + argument must be ``yes'' or ``no''. The default is ``no''. Compression Specifies whether to use compression. The argument must be @@ -131,25 +177,25 @@ ControlMaster Enables the sharing of multiple sessions over a single network - connection. When set to ``yes'', ssh(1) will listen for - connections on a control socket specified using the ControlPath - argument. Additional sessions can connect to this socket using - the same ControlPath with ControlMaster set to ``no'' (the - default). These sessions will try to reuse the master instance's - network connection rather than initiating new ones, but will fall - back to connecting normally if the control socket does not exist, - or is not listening. - - Setting this to ``ask'' will cause ssh to listen for control - connections, but require confirmation using the SSH_ASKPASS - program before they are accepted (see ssh-add(1) for details). - If the ControlPath cannot be opened, ssh will continue without - connecting to a master instance. - - X11 and ssh-agent(1) forwarding is supported over these - multiplexed connections, however the display and agent forwarded - will be the one belonging to the master connection i.e. it is not - possible to forward multiple displays or agents. + connection. When set to ``yes'', ssh(1) will listen for connec- + tions on a control socket specified using the ControlPath argu- + ment. Additional sessions can connect to this socket using the + same ControlPath with ControlMaster set to ``no'' (the default). + These sessions will try to reuse the master instance's network + connection rather than initiating new ones, but will fall back to + connecting normally if the control socket does not exist, or is + not listening. + + Setting this to ``ask'' will cause ssh to listen for control con- + nections, but require confirmation using the SSH_ASKPASS program + before they are accepted (see ssh-add(1) for details). If the + ControlPath cannot be opened, ssh will continue without connect- + ing to a master instance. + + X11 and ssh-agent(1) forwarding is supported over these multi- + plexed connections, however the display and agent forwarded will + be the one belonging to the master connection i.e. it is not pos- + sible to forward multiple displays or agents. Two additional options allow for opportunistic multiplexing: try to use a master connection but fall back to creating a new one if @@ -158,30 +204,29 @@ option. ControlPath - Specify the path to the control socket used for connection - sharing as described in the ControlMaster section above or the - string ``none'' to disable connection sharing. In the path, `%l' - will be substituted by the local host name, `%h' will be - substituted by the target host name, `%p' the port, and `%r' by - the remote login username. It is recommended that any - ControlPath used for opportunistic connection sharing include at - least %h, %p, and %r. This ensures that shared connections are - uniquely identified. + Specify the path to the control socket used for connection shar- + ing as described in the ControlMaster section above or the string + ``none'' to disable connection sharing. In the path, '%l' will + be substituted by the local host name, '%h' will be substituted + by the target host name, '%p' the port, and '%r' by the remote + login username. It is recommended that any ControlPath used for + opportunistic connection sharing include at least %h, %p, and %r. + This ensures that shared connections are uniquely identified. ControlPersist When used in conjunction with ControlMaster, specifies that the master connection should remain open in the background (waiting - for future client connections) after the initial client - connection has been closed. If set to ``no'', then the master - connection will not be placed into the background, and will close - as soon as the initial client connection is closed. If set to + for future client connections) after the initial client connec- + tion has been closed. If set to ``no'', then the master connec- + tion will not be placed into the background, and will close as + soon as the initial client connection is closed. If set to ``yes'', then the master connection will remain in the background indefinitely (until killed or closed via a mechanism such as the ssh(1) ``-O exit'' option). If set to a time in seconds, or a time in any of the formats documented in sshd_config(5), then the backgrounded master connection will automatically terminate after - it has remained idle (with no client connections) for the - specified time. + it has remained idle (with no client connections) for the speci- + fied time. DynamicForward Specifies that a TCP port on the local machine be forwarded over @@ -190,11 +235,11 @@ The argument must be [bind_address:]port. IPv6 addresses can be specified by enclosing addresses in square brackets. By default, - the local port is bound in accordance with the GatewayPorts - setting. However, an explicit bind_address may be used to bind - the connection to a specific address. The bind_address of + the local port is bound in accordance with the GatewayPorts set- + ting. However, an explicit bind_address may be used to bind the + connection to a specific address. The bind_address of ``localhost'' indicates that the listening port be bound for - local use only, while an empty address or `*' indicates that the + local use only, while an empty address or '*' indicates that the port should be available from all interfaces. Currently the SOCKS4 and SOCKS5 protocols are supported, and @@ -211,11 +256,11 @@ for more information. EscapeChar - Sets the escape character (default: `~'). The escape character + Sets the escape character (default: '~'). The escape character can also be set on the command line. The argument should be a - single character, `^' followed by a letter, or ``none'' to - disable the escape character entirely (making the connection - transparent for binary data). + single character, '^' followed by a letter, or ``none'' to dis- + able the escape character entirely (making the connection trans- + parent for binary data). ExitOnForwardFailure Specifies whether ssh(1) should terminate the connection if it @@ -237,15 +282,15 @@ the agent. ForwardX11 - Specifies whether X11 connections will be automatically - redirected over the secure channel and DISPLAY set. The argument + Specifies whether X11 connections will be automatically redi- + rected over the secure channel and DISPLAY set. The argument must be ``yes'' or ``no''. The default is ``no''. X11 forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the - user's X11 authorization database) can access the local X11 - display through the forwarded connection. An attacker may then - be able to perform activities such as keystroke monitoring if the + user's X11 authorization database) can access the local X11 dis- + play through the forwarded connection. An attacker may then be + able to perform activities such as keystroke monitoring if the ForwardX11Trusted option is also enabled. ForwardX11Timeout @@ -259,12 +304,11 @@ If this option is set to ``yes'', remote X11 clients will have full access to the original X11 display. - If this option is set to ``no'', remote X11 clients will be - considered untrusted and prevented from stealing or tampering - with data belonging to trusted X11 clients. Furthermore, the - xauth(1) token used for the session will be set to expire after - 20 minutes. Remote clients will be refused access after this - time. + If this option is set to ``no'', remote X11 clients will be con- + sidered untrusted and prevented from stealing or tampering with + data belonging to trusted X11 clients. Furthermore, the xauth(1) + token used for the session will be set to expire after 20 min- + utes. Remote clients will be refused access after this time. The default is ``no''. @@ -275,11 +319,11 @@ Specifies whether remote hosts are allowed to connect to local forwarded ports. By default, ssh(1) binds local port forwardings to the loopback address. This prevents other remote hosts from - connecting to forwarded ports. GatewayPorts can be used to - specify that ssh should bind local port forwardings to the - wildcard address, thus allowing remote hosts to connect to - forwarded ports. The argument must be ``yes'' or ``no''. The - default is ``no''. + connecting to forwarded ports. GatewayPorts can be used to spec- + ify that ssh should bind local port forwardings to the wildcard + address, thus allowing remote hosts to connect to forwarded + ports. The argument must be ``yes'' or ``no''. The default is + ``no''. GlobalKnownHostsFile Specifies a file to use for the global host key database instead @@ -298,9 +342,9 @@ HashKnownHosts Indicates that ssh(1) should hash host names and addresses when they are added to ~/.ssh/known_hosts. These hashed names may be - used normally by ssh(1) and sshd(8), but they do not reveal - identifying information should the file's contents be disclosed. - The default is ``no''. Note that existing names and addresses in + used normally by ssh(1) and sshd(8), but they do not reveal iden- + tifying information should the file's contents be disclosed. The + default is ``no''. Note that existing names and addresses in known hosts files will not be converted automatically, but may be manually hashed using ssh-keygen(1). @@ -313,23 +357,24 @@ HostKeyAlgorithms Specifies the protocol version 2 host key algorithms that the client wants to use in order of preference. The default for this - option is: ``ssh-rsa,ssh-dss''. + option depend from X509KeyAlgorithm. It contain first specified + X509KeyAlgorithm for RSA key, followed by first specified + X509KeyAlgorithm for DSA key, followed by ``,ssh-rsa,ssh-dss''. HostKeyAlias Specifies an alias that should be used instead of the real host - name when looking up or saving the host key in the host key - database files. This option is useful for tunneling SSH - connections or for multiple servers running on a single host. + name when looking up or saving the host key in the host key data- + base files. This option is useful for tunneling SSH connections + or for multiple servers running on a single host. HostName Specifies the real host name to log into. This can be used to specify nicknames or abbreviations for hosts. If the hostname - contains the character sequence `%h', then this will be replaced + contains the character sequence '%h', then this will be replaced with the host name specified on the commandline (this is useful for manipulating unqualified names). The default is the name - given on the command line. Numeric IP addresses are also - permitted (both on the command line and in HostName - specifications). + given on the command line. Numeric IP addresses are also permit- + ted (both on the command line and in HostName specifications). IdentitiesOnly Specifies that ssh(1) should only use the authentication identity @@ -342,21 +387,21 @@ IdentityFile Specifies a file from which the user's RSA or DSA authentication identity is read. The default is ~/.ssh/identity for protocol - version 1, and ~/.ssh/id_rsa and ~/.ssh/id_dsa for protocol - version 2. Additionally, any identities represented by the - authentication agent will be used for authentication. ssh(1) - will try to load certificate information from the filename - obtained by appending -cert.pub to the path of a specified - IdentityFile. + version 1, and ~/.ssh/id_rsa and ~/.ssh/id_dsa for protocol ver- + sion 2. For version 2 is possible identity file to contain key + followed by X.509 certificate that match the key. Additionally, + any identities represented by the authentication agent will be + used for authentication. ssh(1) will try to load certificate + information from the filename obtained by appending -cert.pub to + the path of a specified IdentityFile. The file name may use the tilde syntax to refer to a user's home - directory or one of the following escape characters: `%d' (local - user's home directory), `%u' (local user name), `%l' (local host - name), `%h' (remote host name) or `%r' (remote user name). - - It is possible to have multiple identity files specified in - configuration files; all these identities will be tried in - sequence. + directory or one of the following escape characters: '%d' (local + user's home directory), '%u' (local user name), '%l' (local host + name), '%h' (remote host name) or '%r' (remote user name). + + It is possible to have multiple identity files specified in con- + figuration files; all these identities will be tried in sequence. KbdInteractiveAuthentication Specifies whether to use keyboard-interactive authentication. @@ -372,14 +417,14 @@ and ``skey''. LocalCommand - Specifies a command to execute on the local machine after - successfully connecting to the server. The command string - extends to the end of the line, and is executed with the user's - shell. The following escape character substitutions will be - performed: `%d' (local user's home directory), `%h' (remote host - name), `%l' (local host name), `%n' (host name as provided on the - command line), `%p' (remote port), `%r' (remote user name) or - `%u' (local user name). + Specifies a command to execute on the local machine after suc- + cessfully connecting to the server. The command string extends + to the end of the line, and is executed with the user's shell. + The following escape character substitutions will be performed: + '%d' (local user's home directory), '%h' (remote host name), '%l' + (local host name), '%n' (host name as provided on the command + line), '%p' (remote port), '%r' (remote user name) or '%u' (local + user name). The command is run synchronously and does not have access to the session of the ssh(1) that spawned it. It should not be used for @@ -395,38 +440,42 @@ second argument must be host:hostport. IPv6 addresses can be specified by enclosing addresses in square brackets. Multiple forwardings may be specified, and additional forwardings can be - given on the command line. Only the superuser can forward - privileged ports. By default, the local port is bound in - accordance with the GatewayPorts setting. However, an explicit - bind_address may be used to bind the connection to a specific - address. The bind_address of ``localhost'' indicates that the - listening port be bound for local use only, while an empty - address or `*' indicates that the port should be available from - all interfaces. + given on the command line. Only the superuser can forward privi- + leged ports. By default, the local port is bound in accordance + with the GatewayPorts setting. However, an explicit bind_address + may be used to bind the connection to a specific address. The + bind_address of ``localhost'' indicates that the listening port + be bound for local use only, while an empty address or '*' indi- + cates that the port should be available from all interfaces. LogLevel Gives the verbosity level that is used when logging messages from - ssh(1). The possible values are: QUIET, FATAL, ERROR, INFO, - VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. + ssh(1). The possible values are: QUIET, FATAL, ERROR, INFO, VER- + BOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of verbose output. MACs Specifies the MAC (message authentication code) algorithms in - order of preference. The MAC algorithm is used in protocol - version 2 for data integrity protection. Multiple algorithms - must be comma-separated. The default is: + order of preference. The MAC algorithm is used in protocol ver- + sion 2 for data integrity protection. Multiple algorithms must + be comma-separated. The default is: hmac-md5,hmac-sha1,umac-64@openssh.com, hmac-ripemd160,hmac-sha1-96,hmac-md5-96 + MandatoryCRL + ``X509 store'' option: Specifies whether CRL must present in + store for all certificates in ``certificate chain'' with atribute + ``X509v3 CRL Distribution Points''. The default is ``no''. + NoHostAuthenticationForLocalhost This option can be used if the home directory is shared across machines. In this case localhost will refer to a different - machine on each of the machines and the user will get many - warnings about changed host keys. However, this option disables - host authentication for localhost. The argument to this keyword - must be ``yes'' or ``no''. The default is to check the host key - for localhost. + machine on each of the machines and the user will get many warn- + ings about changed host keys. However, this option disables host + authentication for localhost. The argument to this keyword must + be ``yes'' or ``no''. The default is to check the host key for + localhost. NumberOfPasswordPrompts Specifies the number of password prompts before giving up. The @@ -444,9 +493,8 @@ PKCS11Provider Specifies which PKCS#11 provider to use. The argument to this - keyword is the PKCS#11 shared libary ssh(1) should use to - communicate with a PKCS#11 token providing the user's private RSA - key. + keyword is the PKCS#11 shared libary ssh(1) should use to commu- + nicate with a PKCS#11 token providing the user's private RSA key. Port Specifies the port number to connect on the remote host. The default is 22. @@ -462,25 +510,25 @@ Protocol Specifies the protocol versions ssh(1) should support in order of - preference. The possible values are `1' and `2'. Multiple - versions must be comma-separated. When this option is set to - ``2,1'' ssh will try version 2 and fall back to version 1 if - version 2 is not available. The default is `2'. + preference. The possible values are '1' and '2'. Multiple ver- + sions must be comma-separated. When this option is set to + ``2,1'' ssh will try version 2 and fall back to version 1 if ver- + sion 2 is not available. The default is '2'. ProxyCommand - Specifies the command to use to connect to the server. The - command string extends to the end of the line, and is executed - with the user's shell. In the command string, any occurrence of - `%h' will be substituted by the host name to connect, `%p' by the - port, and `%r' by the remote user name. The command can be - basically anything, and should read from its standard input and - write to its standard output. It should eventually connect an - sshd(8) server running on some machine, or execute sshd -i - somewhere. Host key management will be done using the HostName - of the host being connected (defaulting to the name typed by the - user). Setting the command to ``none'' disables this option - entirely. Note that CheckHostIP is not available for connects - with a proxy command. + Specifies the command to use to connect to the server. The com- + mand string extends to the end of the line, and is executed with + the user's shell. In the command string, any occurrence of '%h' + will be substituted by the host name to connect, '%p' by the + port, and '%r' by the remote user name. The command can be basi- + cally anything, and should read from its standard input and write + to its standard output. It should eventually connect an sshd(8) + server running on some machine, or execute sshd -i somewhere. + Host key management will be done using the HostName of the host + being connected (defaulting to the name typed by the user). Set- + ting the command to ``none'' disables this option entirely. Note + that CheckHostIP is not available for connects with a proxy com- + mand. This directive is useful in conjunction with nc(1) and its proxy support. For example, the following directive would connect via @@ -488,6 +536,16 @@ ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p + PubkeyAlgorithms + Specifies the protocol version 2 algorithms used in ``publickey'' + authentication allowed to sent to the host. The default is all + supported by client and depend from X509KeyAlgorithm, i.e. the + option allow all specified by X509KeyAlgorithm plus ``ssh-rsa'' + and ``ssh-dss''. If a X.509 certificate is used as identity but + corresponding algorithm is not allowed the client will try algo- + rithm ( ``ssh-rsa'' or ``ssh-dss'' ) conforming to certificate + public key if allowed. + PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be ``yes'' or ``no''. The default is @@ -495,10 +553,10 @@ RekeyLimit Specifies the maximum amount of data that may be transmitted - before the session key is renegotiated. The argument is the - number of bytes, with an optional suffix of `K', `M', or `G' to + before the session key is renegotiated. The argument is the num- + ber of bytes, with an optional suffix of 'K', 'M', or 'G' to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The - default is between `1G' and `4G', depending on the cipher. This + default is between '1G' and '4G', depending on the cipher. This option applies to protocol version 2 only. RemoteForward @@ -511,15 +569,14 @@ given on the command line. Privileged ports can be forwarded only when logging in as root on the remote machine. - If the port argument is `0', the listen port will be dynamically + If the port argument is '0', the listen port will be dynamically allocated on the server and reported to the client at run time. If the bind_address is not specified, the default is to only bind - to loopback addresses. If the bind_address is `*' or an empty - string, then the forwarding is requested to listen on all - interfaces. Specifying a remote bind_address will only succeed - if the server's GatewayPorts option is enabled (see - sshd_config(5)). + to loopback addresses. If the bind_address is '*' or an empty + string, then the forwarding is requested to listen on all inter- + faces. Specifying a remote bind_address will only succeed if the + server's GatewayPorts option is enabled (see sshd_config(5)). RhostsRSAAuthentication Specifies whether to try rhosts based authentication with RSA @@ -530,9 +587,9 @@ RSAAuthentication Specifies whether to try RSA authentication. The argument to this keyword must be ``yes'' or ``no''. RSA authentication will - only be attempted if the identity file exists, or an - authentication agent is running. The default is ``yes''. Note - that this option applies to protocol version 1 only. + only be attempted if the identity file exists, or an authentica- + tion agent is running. The default is ``yes''. Note that this + option applies to protocol version 1 only. SendEnv Specifies what variables from the local environ(7) should be sent @@ -540,8 +597,8 @@ for protocol 2. The server must also support it, and the server must be configured to accept these environment variables. Refer to AcceptEnv in sshd_config(5) for how to configure the server. - Variables are specified by name, which may contain wildcard - characters. Multiple environment variables may be separated by + Variables are specified by name, which may contain wildcard char- + acters. Multiple environment variables may be separated by whitespace or spread across multiple SendEnv directives. The default is not to send any environment variables. @@ -554,11 +611,11 @@ being sent, ssh will disconnect from the server, terminating the session. It is important to note that the use of server alive messages is very different from TCPKeepAlive (below). The server - alive messages are sent through the encrypted channel and - therefore will not be spoofable. The TCP keepalive option - enabled by TCPKeepAlive is spoofable. The server alive mechanism - is valuable when the client or server depend on knowing when a - connection has become inactive. + alive messages are sent through the encrypted channel and there- + fore will not be spoofable. The TCP keepalive option enabled by + TCPKeepAlive is spoofable. The server alive mechanism is valu- + able when the client or server depend on knowing when a connec- + tion has become inactive. The default value is 3. If, for example, ServerAliveInterval (see below) is set to 15 and ServerAliveCountMax is left at the @@ -575,27 +632,27 @@ StrictHostKeyChecking If this flag is set to ``yes'', ssh(1) will never automatically - add host keys to the ~/.ssh/known_hosts file, and refuses to - connect to hosts whose host key has changed. This provides - maximum protection against trojan horse attacks, though it can be - annoying when the /etc/ssh/ssh_known_hosts file is poorly - maintained or when connections to new hosts are frequently made. - This option forces the user to manually add all new hosts. If - this flag is set to ``no'', ssh will automatically add new host - keys to the user known hosts files. If this flag is set to - ``ask'', new host keys will be added to the user known host files - only after the user has confirmed that is what they really want - to do, and ssh will refuse to connect to hosts whose host key has - changed. The host keys of known hosts will be verified - automatically in all cases. The argument must be ``yes'', - ``no'', or ``ask''. The default is ``ask''. + add host keys to the ~/.ssh/known_hosts file, and refuses to con- + nect to hosts whose host key has changed. This provides maximum + protection against trojan horse attacks, though it can be annoy- + ing when the /etc/ssh/ssh_known_hosts file is poorly maintained + or when connections to new hosts are frequently made. This + option forces the user to manually add all new hosts. If this + flag is set to ``no'', ssh will automatically add new host keys + to the user known hosts files. If this flag is set to ``ask'', + new host keys will be added to the user known host files only + after the user has confirmed that is what they really want to do, + and ssh will refuse to connect to hosts whose host key has + changed. The host keys of known hosts will be verified automati- + cally in all cases. The argument must be ``yes'', ``no'', or + ``ask''. The default is ``ask''. TCPKeepAlive Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, - this means that connections will die if the route is down - temporarily, and some people find it annoying. + this means that connections will die if the route is down tempo- + rarily, and some people find it annoying. The default is ``yes'' (to send TCP keepalive messages), and the client will notice if the network goes down or the remote host @@ -614,38 +671,83 @@ Specifies the tun(4) devices to open on the client (local_tun) and the server (remote_tun). - The argument must be local_tun [:remote_tun]. The devices may be + The argument must be local_tun[:remote_tun]. The devices may be specified by numerical ID or the keyword ``any'', which uses the next available tunnel device. If remote_tun is not specified, it defaults to ``any''. The default is ``any:any''. UsePrivilegedPort - Specifies whether to use a privileged port for outgoing - connections. The argument must be ``yes'' or ``no''. The - default is ``no''. If set to ``yes'', ssh(1) must be setuid - root. Note that this option must be set to ``yes'' for + Specifies whether to use a privileged port for outgoing connec- + tions. The argument must be ``yes'' or ``no''. The default is + ``no''. If set to ``yes'', ssh(1) must be setuid root. Note + that this option must be set to ``yes'' for RhostsRSAAuthentication with older servers. - User Specifies the user to log in as. This can be useful when a - different user name is used on different machines. This saves - the trouble of having to remember to give the user name on the - command line. + User Specifies the user to log in as. This can be useful when a dif- + ferent user name is used on different machines. This saves the + trouble of having to remember to give the user name on the com- + mand line. + + UserCACertificateFile + ``X509 store'' option: User CACertificateFile , the default is + ~/.ssh/ca-bundle.crt. + + UserCACertificatePath + ``X509 store'' option: User CACertificatePath , the default is + ~/.ssh/crt. + + UserCAldapVersion + ``X509 store'' option: User CAldapVersion. + + UserCAldapURL + ``X509 store'' option: User CAldapURL. + + UserCARevocationFile + ``X509 store'' option: User CARevocationFile , the default is + ~/.ssh/ca-bundle.crl. + + UserCARevocationPath + ``X509 store'' option: User CARevocationPath , the default is + ~/.ssh/crl. UserKnownHostsFile Specifies a file to use for the user host key database instead of ~/.ssh/known_hosts. + VACertificateFile + File with X.509 certificates in PEM format concatenated together. + In use when VAType is set to ``ocspspec''. The default value is + '' (empty). Certificates from that file explicitly trust 'OCSP + Responder' public key. They are used as trusted certificates in + addition to certificates from CACertificateFile , + CACertificatePath , UserCACertificateFile and + UserCACertificatePath to verify responder certificate. + + VAType Specifies whether 'Online Certificate Status Protocol' (OCSP) is + used to validate X.509 certificates. Accepted values are case + insensitive: + none do not use OCSP to validate certificates; + ocspcert validate only certificates that specify 'OCSP + Service Locator' URL; + ocspspec use specified in the configuration 'OCSP + Responder' to validate all certificates. + The default is ``none''. + + VAOCSPResponderURL + 'Access Location' / 'OCSP Service Locator' URL of the OCSP + provider. In use when VAType is set to ``ocspspec''. + VerifyHostKeyDNS - Specifies whether to verify the remote key using DNS and SSHFP - resource records. If this option is set to ``yes'', the client - will implicitly trust keys that match a secure fingerprint from - DNS. Insecure fingerprints will be handled as if this option was - set to ``ask''. If this option is set to ``ask'', information on - fingerprint match will be displayed, but the user will still need - to confirm new host keys according to the StrictHostKeyChecking - option. The argument must be ``yes'', ``no'', or ``ask''. The - default is ``no''. Note that this option applies to protocol - version 2 only. + Specifies whether to verify the remote key using DNS and + CERT/SSHFP resource records. If this option is set to ``yes'', + the client will implicitly trust keys that match a secure finger- + print from DNS. Insecure fingerprints will be handled as if this + option was set to ``ask''. If this option is set to ``ask'', + information on fingerprint match will be displayed, but the user + will still need to confirm new host keys according to the + StrictHostKeyChecking option. The argument must be ``yes'', + ``no'', or ``ask''. The default is ``no''. Note that this + option applies to protocol version 2 only. See also VERIFYING HOST KEYS in ssh(1). @@ -657,16 +759,34 @@ login and only the hex fingerprint string will be printed for unknown host keys. The default is ``no''. + X509KeyAlgorithm + Specifies how X.509 certificates and signatures are used for pro- + tocol version 2. It is possible to have multiple algorithms in + form specified in X509 Key Algorithms Format. sshd use the first + listed for ``rsa'' or ``dsa'' key in signing and accept all + listed. + + The default for certificates with RSA key is: + X509KeyAlgorithm x509v3-sign-rsa,rsa-md5 + X509KeyAlgorithm x509v3-sign-rsa,rsa-sha1 + + The default for certificates with DSA key is: + X509KeyAlgorithm x509v3-sign-dss,dss-asn1 + X509KeyAlgorithm x509v3-sign-dss,dss-raw + + X509rsaSigType + Deprecated option replaced by X509KeyAlgorithm. + XAuthLocation Specifies the full pathname of the xauth(1) program. The default is /usr/X11R6/bin/xauth. PATTERNS - A pattern consists of zero or more non-whitespace characters, `*' (a - wildcard that matches zero or more characters), or `?' (a wildcard that - matches exactly one character). For example, to specify a set of - declarations for any host in the ``.co.uk'' set of domains, the following - pattern could be used: + A pattern consists of zero or more non-whitespace characters, '*' (a + wildcard that matches zero or more characters), or '?' (a wildcard that + matches exactly one character). For example, to specify a set of decla- + rations for any host in the ``.co.uk'' set of domains, the following pat- + tern could be used: Host *.co.uk @@ -677,7 +797,7 @@ A pattern-list is a comma-separated list of patterns. Patterns within pattern-lists may be negated by preceding them with an exclamation mark - (`!'). For example, to allow a key to be used from anywhere within an + ('!'). For example, to allow a key to be used from anywhere within an organisation except from the ``dialup'' pool, the following entry (in authorized_keys) could be used: @@ -688,8 +808,8 @@ This is the per-user configuration file. The format of this file is described above. This file is used by the SSH client. Because of the potential for abuse, this file must have strict - permissions: read/write for the user, and not accessible by - others. + permissions: read/write for the user, and not accessible by oth- + ers. /etc/ssh/ssh_config Systemwide configuration file. This file provides defaults for @@ -703,8 +823,9 @@ AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 4.8 August 4, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh_config.5 openssh-5.6p1+x509-6.2.3/ssh_config.5 --- openssh-5.6p1/ssh_config.5 2010-08-05 06:03:13.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh_config.5 2010-08-24 09:06:00.000000000 +0300 @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2006 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -34,7 +35,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. .\" -.\" $OpenBSD: ssh_config.5,v 1.138 2010/08/04 05:37:01 djm Exp $ +.\" $OpenBSD$ .Dd $Mdocdate: August 4 2010 $ .Dt SSH_CONFIG 5 .Os @@ -124,6 +125,20 @@ (use IPv4 only), or .Dq inet6 (use IPv6 only). +.It Cm AllowedCertPurpose +The intended use for the X.509 server certificate. Without this option +no chain verification will be done. Currently accepted uses are case +insensitive: +.Bl -tag -width Ds -compact +.It Cm sslserver | Cm SSL server | Cm SSL_server | Cm server +only SSL-server purpose +.It Cm any | Cm Any Purpose | Cm Any_Purpose | Cm AnyPurpose +allow any purpose +.It Cm skip | Cm '' Li (empty) +do not check purpose +.El +The default is +.Dq sslserver . .It Cm BatchMode If set to .Dq yes , @@ -144,6 +159,60 @@ .Cm UsePrivilegedPort is set to .Dq yes . +.It Cm CACertificateFile +.Dq X509 store +option: +This file contain multiple certificates of certificate signers in +PEM format concatenated together. The default is +.Pa /etc/ssh/ca/ca-bundle.crt . +.It Cm CACertificatePath +.Dq X509 store +option: +.Dq "Hash dir" +with certificates of certificate signers. Each certificate should be +stored in separate file with name [HASH].[NUMBER], where [HASH] is +certificate hash value and [NUMBER] is an integer starting from zero. +The default is +.Pa /etc/ssh/ca/crt . +.It Cm CAldapVersion +.Dq X509 store +option: +Specifies LDAP protocol version. +The default depend from LDAP library. +.It Cm CAldapURL +.Dq X509 store +option: +Specifies hostport and dn of LDAP URLs (Uniform Resource Locators) +as detailed in RFC 2255. The rest of URL is build internally. +Because of OpenSSH options parser limitation use +.Sq %3D +instead of +.Sq = +! +LDAP initialization method may require URL to be escaped, i.e. use +.Sq %2C +instead of +.Sq \&, +(comma). +Escaped URL don't depend from LDAP initialization method. +.It Cm CARevocationFile +.Dq X509 store +option: +This file contain multiple +.Dq "Certificate Revocation List" +(CRL) of certificate signers in PEM format concatenated together. +The default is +.Pa /etc/ssh/ca/ca-bundle.crl . +.It Cm CARevocationPath +.Dq X509 store +option: +.Dq "Hash dir" +with +.Dq "Certificate Revocation List" +(CRL) of certificate signers. Each CRL should be stored in separate +file with name [HASH].r[NUMBER], where [HASH] is CRL hash value and +[NUMBER] is an integer starting from zero. The default is +.Pa /etc/ssh/ca/crl . .It Cm ChallengeResponseAuthentication Specifies whether to use challenge-response authentication. The argument to this keyword must be @@ -546,8 +615,12 @@ .It Cm HostKeyAlgorithms Specifies the protocol version 2 host key algorithms that the client wants to use in order of preference. -The default for this option is: -.Dq ssh-rsa,ssh-dss . +The default for this option depend from +.Cm X509KeyAlgorithm . +It contain first specified X509KeyAlgorithm for RSA key, +followed by first specified X509KeyAlgorithm for DSA key, +followed by +.Dq ,ssh-rsa,ssh-dss . .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key @@ -592,6 +665,8 @@ and .Pa ~/.ssh/id_dsa for protocol version 2. +For version 2 is possible identity file to contain key +followed by X.509 certificate that match the key. Additionally, any identities represented by the authentication agent will be used for authentication. .Xr ssh 1 @@ -713,6 +788,15 @@ hmac-md5,hmac-sha1,umac-64@openssh.com, hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .Ed +.It Cm MandatoryCRL +.Dq X509 store +option: +Specifies whether CRL must present in store for all certificates in +.Dq certificate chain +with atribute +.Dq X509v3 CRL Distribution Points . +The default is +.Dq no . .It Cm NoHostAuthenticationForLocalhost This option can be used if the home directory is shared across machines. In this case localhost will refer to a different machine on each of @@ -823,6 +907,25 @@ .Bd -literal -offset 3n ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p .Ed +.It Cm PubkeyAlgorithms +Specifies the protocol version 2 algorithms used in +.Dq publickey +authentication allowed to sent to the host. +The default is all supported by client and depend from +.Cm X509KeyAlgorithm , +i.e. the option allow all specified by +.Cm X509KeyAlgorithm +plus +.Dq ssh-rsa +and +.Dq ssh-dss . +If a X.509 certificate is used as identity +but corresponding algorithm is not allowed +the client will try algorithm ( +.Dq ssh-rsa +or +.Dq ssh-dss +) conforming to certificate public key if allowed. .It Cm PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be @@ -1077,12 +1180,99 @@ This can be useful when a different user name is used on different machines. This saves the trouble of having to remember to give the user name on the command line. +.It Cm UserCACertificateFile +.Dq X509 store +option: +User +.Cm CACertificateFile +, the default is +.Pa ~/.ssh/ca-bundle.crt . +.It Cm UserCACertificatePath +.Dq X509 store +option: +User +.Cm CACertificatePath +, the default is +.Pa ~/.ssh/crt . +.It Cm UserCAldapVersion +.Dq X509 store +option: +User +.Cm CAldapVersion . +.It Cm UserCAldapURL +.Dq X509 store +option: +User +.Cm CAldapURL . +.It Cm UserCARevocationFile +.Dq X509 store +option: +User +.Cm CARevocationFile +, the default is +.Pa ~/.ssh/ca-bundle.crl . +.It Cm UserCARevocationPath +.Dq X509 store +option: +User +.Cm CARevocationPath +, the default is +.Pa ~/.ssh/crl . .It Cm UserKnownHostsFile Specifies a file to use for the user host key database instead of .Pa ~/.ssh/known_hosts . +.It Cm VACertificateFile +File with X.509 certificates in PEM format concatenated together. +In use when +.Cm VAType +is set to +.Dq ocspspec . +The default value is +.Sq +.. +(empty). +Certificates from that file explicitly trust +.Sq "OCSP Responder" +public key. +They are used as trusted certificates in addition to certificates from +.Cm CACertificateFile +, +.Cm CACertificatePath +, +.Cm UserCACertificateFile +and +.Cm UserCACertificatePath +to verify responder certificate. +.It Cm VAType +Specifies whether +.Sq "Online Certificate Status Protocol" +(OCSP) is used to validate X.509 certificates. +Accepted values are case insensitive: +.Bl -tag -offset indent -compact +.It none +do not use OCSP to validate certificates; +.It ocspcert +validate only certificates that specify +.Sq "OCSP Service Locator" +URL; +.It ocspspec +use specified in the configuration +.Sq "OCSP Responder" +to validate all certificates. +.El +The default is +.Dq none . +.It Cm VAOCSPResponderURL +.Sq "Access Location" +/ +.Sq "OCSP Service Locator" +URL of the OCSP provider. In use when +.Cm VAType +is set to +.Dq ocspspec . .It Cm VerifyHostKeyDNS -Specifies whether to verify the remote key using DNS and SSHFP resource +Specifies whether to verify the remote key using DNS and CERT/SSHFP resource records. If this option is set to .Dq yes , @@ -1121,6 +1311,48 @@ only the hex fingerprint string will be printed for unknown host keys. The default is .Dq no . +.It Cm X509KeyAlgorithm +Specifies how X.509 certificates and signatures are used for protocol version 2. +It is possible to have multiple algorithms +in form specified in +.Sx X509 Key Algorithms Format . +.Nm sshd +use the first listed for +.Dq rsa +or +.Dq dsa +key in signing and +accept all listed. +.Pp +The default for certificates with RSA key is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-rsa , Ar rsa-md5 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-rsa , Ar rsa-sha1 +.Sm on +.El +.Pp +The default for certificates with DSA key is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-dss , Ar dss-asn1 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-dss , Ar dss-raw +.Sm on +.El +.It Cm X509rsaSigType +Deprecated option replaced by X509KeyAlgorithm. .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 @@ -1189,3 +1421,4 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-5.6p1/sshconnect2.c openssh-5.6p1+x509-6.2.3/sshconnect2.c --- openssh-5.6p1/sshconnect2.c 2010-05-10 04:55:38.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sshconnect2.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,6 +1,7 @@ -/* $OpenBSD: sshconnect2.c,v 1.183 2010/04/26 22:28:24 djm Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2006 Roumen Petrov. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1126,6 +1127,7 @@ /* load the private key from the file */ if ((prv = load_identity_file(id->filename)) == NULL) return (-1); + prv->type = id->key->type; ret = key_sign(prv, sigp, lenp, data, datalen); key_free(prv); return (ret); @@ -1304,6 +1306,7 @@ char *comment; int i, found; + debug2("preparing keys"); TAILQ_INIT(&agent); /* keys from the agent */ TAILQ_INIT(&files); /* keys from the config file */ preferred = &authctxt->keys; @@ -1383,11 +1386,74 @@ } } +static int +get_allowed_keytype(int type) { + static int allowed[KEY_UNSPEC] = { 0 }; + int pktype; + + switch(type) { + case KEY_RSA: + case KEY_DSA: + case KEY_X509_RSA: + case KEY_X509_DSA: + case KEY_RSA_CERT: + case KEY_DSA_CERT: + case KEY_RSA_CERT_V00: + case KEY_DSA_CERT_V00: + break; + default: + return(KEY_UNSPEC); + } + + if (options.pubkey_algorithms == NULL) return(type); + + if (allowed[KEY_UNSPEC] != 1) { + /* prepare allowed key-types flags */ + char *s, *cp, *p; + memset(allowed, 0, sizeof(allowed)); + s = cp = xstrdup(options.pubkey_algorithms); + for (p = strsep(&cp, ","); + p && *p != '\0'; + p = strsep(&cp, ",") + ) { + pktype = key_type_from_name(p); + allowed[pktype] = 1; + } + xfree(s); + allowed[KEY_UNSPEC] = 1; + } + + if (allowed[type]) return(type); + + switch(type) { + case KEY_X509_RSA: type = KEY_RSA; break; + case KEY_X509_DSA: type = KEY_DSA; break; + default: + return(KEY_UNSPEC); + } + + return(allowed[type] ? type : KEY_UNSPEC); +} + +static void +set_keytype(Key *k, int kt) { + const char *n1, *n2; + + if (k->type == kt) return; + + /* key_ssh_name return pointers to statics */ + n1 = key_ssh_name(k); + k->type = kt; + n2 = key_ssh_name(k); + debug("Offering key-type '%s', original was '%s'", n2, n1); +} + int userauth_pubkey(Authctxt *authctxt) { Identity *id; int sent = 0; + int kt_sent; while ((id = TAILQ_FIRST(&authctxt->keys))) { if (id->tried++) @@ -1401,14 +1467,28 @@ * private key instead */ if (id->key && id->key->type != KEY_RSA1) { + kt_sent = get_allowed_keytype(id->key->type); + if (kt_sent == KEY_UNSPEC) { + logit("non-allowed public key: %s", id->filename); + continue; + } debug("Offering %s public key: %s", key_type(id->key), id->filename); + set_keytype(id->key, kt_sent); sent = send_pubkey_test(authctxt, id); } else if (id->key == NULL) { debug("Trying private key: %s", id->filename); id->key = load_identity_file(id->filename); if (id->key != NULL) { id->isprivate = 1; + kt_sent = get_allowed_keytype(id->key->type); + if (kt_sent == KEY_UNSPEC) { + logit("non-allowed private key: %s", id->filename); + key_free(id->key); + id->key = NULL; + continue; + } + set_keytype(id->key, kt_sent); sent = sign_and_send_pubkey(authctxt, id); key_free(id->key); id->key = NULL; diff -ruN openssh-5.6p1/sshconnect.c openssh-5.6p1+x509-6.2.3/sshconnect.c --- openssh-5.6p1/sshconnect.c 2010-04-18 01:08:21.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sshconnect.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.224 2010/04/16 21:14:27 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,6 +11,29 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X.509 certificates support, + * Copyright (c) 2002-2007 Roumen Petrov. 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" @@ -56,6 +79,7 @@ #include "readconf.h" #include "atomicio.h" #include "misc.h" +#include "ssh-x509.h" #include "dns.h" #include "roaming.h" #include "ssh2.h" @@ -618,6 +642,7 @@ char msg[1024]; int len, host_line, ip_line, cancelled_forwarding = 0; const char *host_file = NULL, *ip_file = NULL; + char extramsg[1024], *subject = NULL; /* * Force accepting of the host key for loopback/localhost. The @@ -811,16 +836,30 @@ "No matching host key fingerprint" " found in DNS.\n"); } + if ((host_key->type == KEY_X509_RSA) || (host_key->type == KEY_X509_DSA)) { + subject = x509key_subject(host_key); + snprintf(extramsg, sizeof(extramsg), + "Distinguished name is '%s'.\n", + subject); + } else { + subject = NULL; + *extramsg = '\0'; + } snprintf(msg, sizeof(msg), "The authenticity of host '%.200s (%s)' can't be " "established%s\n" "%s key fingerprint is %s.%s%s\n%s" + "%s" "Are you sure you want to continue connecting " "(yes/no)? ", host, ip, msg1, type, fp, options.visual_host_key ? "\n" : "", options.visual_host_key ? ra : "", - msg2); + msg2, extramsg); + if(subject != NULL) { + xfree(subject); + subject = NULL; + } xfree(ra); xfree(fp); if (!confirm(msg)) @@ -893,7 +932,7 @@ if (readonly == ROQUIET) goto fail; if (options.check_host_ip && host_ip_differ) { - char *key_msg; + const char *key_msg; if (ip_status == HOST_NEW) key_msg = "is unknown"; else if (ip_status == HOST_OK) @@ -1067,9 +1106,15 @@ if (flags & DNS_VERIFY_MATCH) { matching_host_key_dns = 1; } else { + const char *rr = ""; warn_changed_key(host_key); - error("Update the SSHFP RR in DNS with the new " - "host key to get rid of this message."); + if ((host_key->type == KEY_X509_RSA) || (host_key->type == KEY_X509_DSA)) { + rr = "CERT"; + } else { + rr = "SSHFP"; + } + error("Update the %s RR in DNS with the new " + "host key to get rid of this message.", rr); } } } @@ -1173,7 +1218,8 @@ static int show_other_keys(const char *host, Key *key) { - int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, -1}; + int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_X509_RSA, KEY_X509_DSA, -1}; + int i, found = 0; for (i = 0; type[i] != -1; i++) { @@ -1218,6 +1264,11 @@ error("It is also possible that the %s host key has just been changed.", type); error("The fingerprint for the %s key sent by the remote host is\n%s.", type, fp); + if ((host_key->type == KEY_X509_RSA) || (host_key->type == KEY_X509_DSA)) { + char *subject = x509key_subject(host_key); + error("Distinguished name sent by remote host is '%s'.", subject); + xfree(subject); + } error("Please contact your system administrator."); xfree(fp); diff -ruN openssh-5.6p1/sshd.0 openssh-5.6p1+x509-6.2.3/sshd.0 --- openssh-5.6p1/sshd.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sshd.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSHD(8) OpenBSD System Manager's Manual SSHD(8) +SSHD(8) BSD System Manager's Manual SSHD(8) NAME - sshd - OpenSSH SSH daemon + sshd -- OpenSSH SSH daemon SYNOPSIS sshd [-46DdeiqTt] [-b bits] [-C connection_spec] @@ -10,19 +10,19 @@ DESCRIPTION sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these - programs replace rlogin(1) and rsh(1), and provide secure encrypted - communications between two untrusted hosts over an insecure network. + programs replace rlogin(1) and rsh(1), and provide secure encrypted com- + munications between two untrusted hosts over an insecure network. sshd listens for connections from clients. It is normally started at boot from /etc/rc. It forks a new daemon for each incoming connection. - The forked daemons handle key exchange, encryption, authentication, - command execution, and data exchange. + The forked daemons handle key exchange, encryption, authentication, com- + mand execution, and data exchange. sshd can be configured using command-line options or a configuration file - (by default sshd_config(5)); command-line options override values - specified in the configuration file. sshd rereads its configuration file - when it receives a hangup signal, SIGHUP, by executing itself with the - name and options it was started with, e.g. /usr/sbin/sshd. + (by default sshd_config(5)); command-line options override values speci- + fied in the configuration file. sshd rereads its configuration file when + it receives a hangup signal, SIGHUP, by executing itself with the name + and options it was started with, e.g. /usr/sbin/sshd. The options are as follows: @@ -38,17 +38,17 @@ Specify the connection parameters to use for the -T extended test mode. If provided, any Match directives in the configuration file that would apply to the specified user, host, and address - will be set before the configuration is written to standard - output. The connection parameters are supplied as keyword=value + will be set before the configuration is written to standard out- + put. The connection parameters are supplied as keyword=value pairs. The keywords are ``user'', ``host'', and ``addr''. All - are required and may be supplied in any order, either with - multiple -C options or as a comma-separated list. + are required and may be supplied in any order, either with multi- + ple -C options or as a comma-separated list. -c host_certificate_file Specifies a path to a certificate file to identify sshd during key exchange. The certificate file must match a host key file - specified using the -h option or the HostKey configuration - directive. + specified using the -h option or the HostKey configuration direc- + tive. -D When this option is specified, sshd will not detach and does not become a daemon. This allows easy monitoring of sshd. @@ -64,8 +64,8 @@ -f config_file Specifies the name of the configuration file. The default is - /etc/ssh/sshd_config. sshd refuses to start if there is no - configuration file. + /etc/ssh/sshd_config. sshd refuses to start if there is no con- + figuration file. -g login_grace_time Gives the grace time for clients to authenticate themselves @@ -78,10 +78,11 @@ be given if sshd is not run as root (as the normal host key files are normally not readable by anyone but root). The default is /etc/ssh/ssh_host_key for protocol version 1, and - /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_dsa_key for - protocol version 2. It is possible to have multiple host key - files for the different protocol versions and host key - algorithms. + /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_dsa_key for pro- + tocol version 2. It is possible to have multiple host key files + for the different protocol versions and host key algorithms. It + is possible host key for protocol version 2 to contain private + key followed by X.509 certificate that match it. -i Specifies that sshd is being run from inetd(8). sshd is normally not run from inetd because it needs to generate the server key @@ -92,26 +93,25 @@ -k key_gen_time Specifies how often the ephemeral protocol version 1 server key - is regenerated (default 3600 seconds, or one hour). The - motivation for regenerating the key fairly often is that the key - is not stored anywhere, and after about an hour it becomes - impossible to recover the key for decrypting intercepted - communications even if the machine is cracked into or physically - seized. A value of zero indicates that the key will never be - regenerated. + is regenerated (default 3600 seconds, or one hour). The motiva- + tion for regenerating the key fairly often is that the key is not + stored anywhere, and after about an hour it becomes impossible to + recover the key for decrypting intercepted communications even if + the machine is cracked into or physically seized. A value of + zero indicates that the key will never be regenerated. -o option - Can be used to give options in the format used in the - configuration file. This is useful for specifying options for - which there is no separate command-line flag. For full details - of the options, and their values, see sshd_config(5). + Can be used to give options in the format used in the configura- + tion file. This is useful for specifying options for which there + is no separate command-line flag. For full details of the + options, and their values, see sshd_config(5). -p port Specifies the port on which the server listens for connections - (default 22). Multiple port options are permitted. Ports - specified in the configuration file with the Port option are - ignored when a command-line port is specified. Ports specified - using the ListenAddress option override command-line ports. + (default 22). Multiple port options are permitted. Ports speci- + fied in the configuration file with the Port option are ignored + when a command-line port is specified. Ports specified using the + ListenAddress option override command-line ports. -q Quiet mode. Nothing is sent to the system log. Normally the beginning, authentication, and termination of each connection is @@ -119,8 +119,8 @@ -T Extended test mode. Check the validity of the configuration file, output the effective configuration to stdout and then exit. - Optionally, Match rules may be applied by specifying the - connection parameters using one or more -C options. + Optionally, Match rules may be applied by specifying the connec- + tion parameters using one or more -C options. -t Test mode. Only check the validity of the configuration file and sanity of the keys. This is useful for updating sshd reliably as @@ -129,67 +129,68 @@ -u len This option is used to specify the size of the field in the utmp structure that holds the remote host name. If the resolved host name is longer than len, the dotted decimal value will be used - instead. This allows hosts with very long host names that - overflow this field to still be uniquely identified. Specifying - -u0 indicates that only dotted decimal addresses should be put - into the utmp file. -u0 may also be used to prevent sshd from - making DNS requests unless the authentication mechanism or - configuration requires it. Authentication mechanisms that may - require DNS include RhostsRSAAuthentication, - HostbasedAuthentication, and using a from="pattern-list" option - in a key file. Configuration options that require DNS include - using a USER@HOST pattern in AllowUsers or DenyUsers. + instead. This allows hosts with very long host names that over- + flow this field to still be uniquely identified. Specifying -u0 + indicates that only dotted decimal addresses should be put into + the utmp file. -u0 may also be used to prevent sshd from making + DNS requests unless the authentication mechanism or configuration + requires it. Authentication mechanisms that may require DNS + include RhostsRSAAuthentication, HostbasedAuthentication, and + using a from="pattern-list" option in a key file. Configuration + options that require DNS include using a USER@HOST pattern in + AllowUsers or DenyUsers. AUTHENTICATION The OpenSSH SSH daemon supports SSH protocols 1 and 2. The default is to use protocol 2 only, though this can be changed via the Protocol option - in sshd_config(5). Protocol 2 supports both RSA and DSA keys; protocol 1 - only supports RSA keys. For both protocols, each host has a host- - specific key, normally 2048 bits, used to identify the host. + in sshd_config(5). Protocol 2 supports RSA, DSA keys and X.509 certifi- + cates; protocol 1 only supports RSA keys. For both protocols, each host + has a host-specific key, normally 2048 bits, or X.509 certificate used to + identify the host. Forward security for protocol 1 is provided through an additional server key, normally 768 bits, generated when the server starts. This key is normally regenerated every hour if it has been used, and is never stored on disk. Whenever a client connects, the daemon responds with its public host and server keys. The client compares the RSA host key against its - own database to verify that it has not changed. The client then - generates a 256-bit random number. It encrypts this random number using - both the host key and the server key, and sends the encrypted number to - the server. Both sides then use this random number as a session key - which is used to encrypt all further communications in the session. The - rest of the session is encrypted using a conventional cipher, currently - Blowfish or 3DES, with 3DES being used by default. The client selects - the encryption algorithm to use from those offered by the server. + own database to verify that it has not changed. The client then gener- + ates a 256-bit random number. It encrypts this random number using both + the host key and the server key, and sends the encrypted number to the + server. Both sides then use this random number as a session key which is + used to encrypt all further communications in the session. The rest of + the session is encrypted using a conventional cipher, currently Blowfish + or 3DES, with 3DES being used by default. The client selects the encryp- + tion algorithm to use from those offered by the server. For protocol 2, forward security is provided through a Diffie-Hellman key agreement. This key agreement results in a shared session key. The rest of the session is encrypted using a symmetric cipher, currently 128-bit AES, Blowfish, 3DES, CAST128, Arcfour, 192-bit AES, or 256-bit AES. The client selects the encryption algorithm to use from those offered by the - server. Additionally, session integrity is provided through a - cryptographic message authentication code (hmac-md5, hmac-sha1, umac-64 - or hmac-ripemd160). + server. Additionally, session integrity is provided through a crypto- + graphic message authentication code (hmac-md5, hmac-sha1, umac-64 or + hmac-ripemd160). Finally, the server and the client enter an authentication dialog. The - client tries to authenticate itself using host-based authentication, - public key authentication, challenge-response authentication, or password + client tries to authenticate itself using host-based authentication, pub- + lic key authentication, challenge-response authentication, or password authentication. Regardless of the authentication type, the account is checked to ensure that it is accessible. An account is not accessible if it is locked, - listed in DenyUsers or its group is listed in DenyGroups . The - definition of a locked account is system dependant. Some platforms have - their own account database (eg AIX) and some modify the passwd field ( - `*LK*' on Solaris and UnixWare, `*' on HP-UX, containing `Nologin' on - Tru64, a leading `*LOCKED*' on FreeBSD and a leading `!' on most - Linuxes). If there is a requirement to disable password authentication - for the account while allowing still public-key, then the passwd field - should be set to something other than these values (eg `NP' or `*NP*' ). + listed in DenyUsers or its group is listed in DenyGroups . The defini- + tion of a locked account is system dependant. Some platforms have their + own account database (eg AIX) and some modify the passwd field ( '*LK*' + on Solaris and UnixWare, '*' on HP-UX, containing 'Nologin' on Tru64, a + leading '*LOCKED*' on FreeBSD and a leading '!' on most Linuxes). If + there is a requirement to disable password authentication for the account + while allowing still public-key, then the passwd field should be set to + something other than these values (eg 'NP' or '*NP*' ). If the client successfully authenticates itself, a dialog for preparing the session is entered. At this time the client may request things like - allocating a pseudo-tty, forwarding X11 connections, forwarding TCP - connections, or forwarding the authentication agent connection over the + allocating a pseudo-tty, forwarding X11 connections, forwarding TCP con- + nections, or forwarding the authentication agent connection over the secure channel. After this, the client either requests a shell or execution of a command. @@ -197,8 +198,8 @@ data at any time, and such data is forwarded to/from the shell or command on the server side, and the user terminal in the client side. - When the user program terminates and all forwarded X11 and other - connections have been closed, the server sends command exit status to the + When the user program terminates and all forwarded X11 and other connec- + tions have been closed, the server sends command exit status to the client, and both sides exit. LOGIN PROCESS @@ -232,12 +233,11 @@ SSHRC If the file ~/.ssh/rc exists, sh(1) runs it after reading the environment - files but before starting the user's shell or command. It must not - produce any output on stdout; stderr must be used instead. If X11 - forwarding is in use, it will receive the "proto cookie" pair in its - standard input (and DISPLAY in its environment). The script must call - xauth(1) because sshd will not run xauth automatically to add X11 - cookies. + files but before starting the user's shell or command. It must not pro- + duce any output on stdout; stderr must be used instead. If X11 forward- + ing is in use, it will receive the "proto cookie" pair in its standard + input (and DISPLAY in its environment). The script must call xauth(1) + because sshd will not run xauth automatically to add X11 cookies. The primary purpose of this file is to run any initialization routines which may be needed before the user's home directory becomes accessible; @@ -263,36 +263,46 @@ AUTHORIZED_KEYS FILE FORMAT AuthorizedKeysFile specifies the file containing public keys for public key authentication; if none is specified, the default is - ~/.ssh/authorized_keys. Each line of the file contains one key (empty - lines and lines starting with a `#' are ignored as comments). Protocol 1 - public keys consist of the following space-separated fields: options, - bits, exponent, modulus, comment. Protocol 2 public key consist of: - options, keytype, base64-encoded key, comment. The options field is - optional; its presence is determined by whether the line starts with a - number or not (the options field never starts with a number). The bits, - exponent, modulus, and comment fields give the RSA key for protocol - version 1; the comment field is not used for anything (but may be - convenient for the user to identify the key). For protocol version 2 the - keytype is ``ssh-dss'' or ``ssh-rsa''. + ~/.ssh/authorized_keys. It is posible for protocol version 2 to contain + X.509 certificates or certificates ``Distinguished Name''. Each line of + the file contains one key (empty lines and lines starting with a '#' are + ignored as comments). Protocol 1 public keys consist of the following + space-separated fields: options, bits, exponent, modulus, comment. Pro- + tocol 2 public key consist of: options, keytype, base64-encoded key, com- + ment. The options field is optional; its presence is determined by + whether the line starts with a number or not (the options field never + starts with a number). The bits, exponent, modulus, and comment fields + give the RSA key for protocol version 1; the comment field is not used + for anything (but may be convenient for the user to identify the key). + For protocol version 2 the keytype is ``ssh-dss'' or ``ssh-rsa''. In + addition for protocol version 2 user can use X.509 certificates. In that + case keytype is ``x509v3-sign-rsa'' or ``x509v3-sign-dss''. Instead of + ``base64 encoded key'' line must contain base64 encoded certicate (old + style) or a keyword (new style), optional followed by symbol '=' (equal) + or ':' (colon), zero or more spaces and certificate ``Distinguished + Name'' (Subject). Keyword is case insensitive and can be one of 'Subject' + , 'Distinguished Name' , 'Distinguished-Name' , 'Distinguished_Name' , + 'DistinguishedName' or 'DN'. Separator of Subject items can be '/' + (slash), ',' (comma) or mixed and order is not important. Note that lines in this file are usually several hundred bytes long - (because of the size of the public key encoding) up to a limit of 8 - kilobytes, which permits DSA keys up to 8 kilobits and RSA keys up to 16 + (because of the size of the public key encoding) up to a limit of 8 kilo- + bytes, which permits DSA keys up to 8 kilobits and RSA keys up to 16 kilobits. You don't want to type them in; instead, copy the identity.pub, id_dsa.pub, or the id_rsa.pub file and edit it. sshd enforces a minimum RSA key modulus size for protocol 1 and protocol 2 keys of 768 bits. - The options (if present) consist of comma-separated option - specifications. No spaces are permitted, except within double quotes. - The following option specifications are supported (note that option - keywords are case-insensitive): + The options (if present) consist of comma-separated option specifica- + tions. No spaces are permitted, except within double quotes. The fol- + lowing option specifications are supported (note that option keywords are + case-insensitive): cert-authority Specifies that the listed key is a certification authority (CA) - that is trusted to validate signed certificates for user - authentication. + that is trusted to validate signed certificates for user authen- + tication. Certificates may encode access restrictions similar to these key options. If both certificate restrictions and key options are @@ -302,19 +312,19 @@ Specifies that the command is executed whenever this key is used for authentication. The command supplied by the user (if any) is ignored. The command is run on a pty if the client requests a - pty; otherwise it is run without a tty. If an 8-bit clean - channel is required, one must not request a pty or should specify + pty; otherwise it is run without a tty. If an 8-bit clean chan- + nel is required, one must not request a pty or should specify no-pty. A quote may be included in the command by quoting it - with a backslash. This option might be useful to restrict - certain public keys to perform just a specific operation. An - example might be a key that permits remote backups but nothing - else. Note that the client may specify TCP and/or X11 forwarding - unless they are explicitly prohibited. The command originally - supplied by the client is available in the SSH_ORIGINAL_COMMAND - environment variable. Note that this option applies to shell, - command or subsystem execution. Also note that this command may - be superseded by either a sshd_config(5) ForceCommand directive - or a command embedded in a certificate. + with a backslash. This option might be useful to restrict cer- + tain public keys to perform just a specific operation. An exam- + ple might be a key that permits remote backups but nothing else. + Note that the client may specify TCP and/or X11 forwarding unless + they are explicitly prohibited. The command originally supplied + by the client is available in the SSH_ORIGINAL_COMMAND environ- + ment variable. Note that this option applies to shell, command + or subsystem execution. Also note that this command may be + superseded by either a sshd_config(5) ForceCommand directive or a + command embedded in a certificate. environment="NAME=value" Specifies that the string is to be added to the environment when @@ -330,9 +340,9 @@ present in the comma-separated list of patterns. See PATTERNS in ssh_config(5) for more information on patterns. - In addition to the wildcard matching that may be applied to - hostnames or addresses, a from stanza may match IP addresses - using CIDR address/masklen notation. + In addition to the wildcard matching that may be applied to host- + names or addresses, a from stanza may match IP addresses using + CIDR address/masklen notation. The purpose of this option is to optionally increase security: public key authentication by itself does not trust the network or @@ -361,25 +371,25 @@ Any X11 forward requests by the client will return an error. permitopen="host:port" - Limit local ``ssh -L'' port forwarding such that it may only - connect to the specified host and port. IPv6 addresses can be - specified by enclosing the address in square brackets. Multiple - permitopen options may be applied separated by commas. No - pattern matching is performed on the specified hostnames, they - must be literal domains or addresses. + Limit local ``ssh -L'' port forwarding such that it may only con- + nect to the specified host and port. IPv6 addresses can be spec- + ified by enclosing the address in square brackets. Multiple + permitopen options may be applied separated by commas. No pat- + tern matching is performed on the specified hostnames, they must + be literal domains or addresses. principals="principals" - On a cert-authority line, specifies allowed principals for - certificate authentication as a comma-separated list. At least - one name from the list must appear in the certificate's list of - principals for the certificate to be accepted. This option is - ignored for keys that are not marked as trusted certificate - signers using the cert-authority option. + On a cert-authority line, specifies allowed principals for cer- + tificate authentication as a comma-separated list. At least one + name from the list must appear in the certificate's list of prin- + cipals for the certificate to be accepted. This option is + ignored for keys that are not marked as trusted certificate sign- + ers using the cert-authority option. tunnel="n" Force a tun(4) device on the server. Without this option, the - next available device will be used if the client requests a - tunnel. + next available device will be used if the client requests a tun- + nel. An example authorized_keys file: @@ -391,15 +401,17 @@ AAAAC3...51R== example.net permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-dss AAAAB5...21S== + x509v3-sign-dss subject=/C=XX/ST=World/O=OpenSSH Test Team... tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...== jane@example.net SSH_KNOWN_HOSTS FILE FORMAT The /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts files contain host - public keys for all known hosts. The global file should be prepared by - the administrator (optional), and the per-user file is maintained - automatically: whenever the user connects from an unknown host, its key - is added to the per-user file. + public keys, certificates (old style) or certificates ``Distinguished + Name'' for all known hosts. The global file should be prepared by the + administrator (optional), and the per-user file is maintained automati- + cally: whenever the user connects from an unknown host, its key is added + to the per-user file. Each line in these files contains the following fields: markers (optional), hostnames, bits, exponent, modulus, comment. The fields are @@ -411,26 +423,26 @@ on the line is revoked and must not ever be accepted. Only one marker should be used on a key line. - Hostnames is a comma-separated list of patterns (`*' and `?' act as - wildcards); each pattern in turn is matched against the canonical host - name (when authenticating a client) or against the user-supplied name - (when authenticating a server). A pattern may also be preceded by `!' to - indicate negation: if the host name matches a negated pattern, it is not + Hostnames is a comma-separated list of patterns ('*' and '?' act as wild- + cards); each pattern in turn is matched against the canonical host name + (when authenticating a client) or against the user-supplied name (when + authenticating a server). A pattern may also be preceded by '!' to indi- + cate negation: if the host name matches a negated pattern, it is not accepted (by that line) even if it matched another pattern on the line. - A hostname or address may optionally be enclosed within `[' and `]' - brackets then followed by `:' and a non-standard port number. + A hostname or address may optionally be enclosed within '[' and ']' + brackets then followed by ':' and a non-standard port number. Alternately, hostnames may be stored in a hashed form which hides host names and addresses should the file's contents be disclosed. Hashed - hostnames start with a `|' character. Only one hashed hostname may - appear on a single line and none of the above negation or wildcard - operators may be applied. + hostnames start with a '|' character. Only one hashed hostname may + appear on a single line and none of the above negation or wildcard opera- + tors may be applied. Bits, exponent, and modulus are taken directly from the RSA host key; they can be obtained, for example, from /etc/ssh/ssh_host_key.pub. The optional comment field continues to the end of the line, and is not used. - Lines starting with `#' and empty lines are ignored as comments. + Lines starting with '#' and empty lines are ignored as comments. When performing host authentication, authentication is accepted if any matching line has the proper key; either one that matches exactly or, if @@ -442,30 +454,30 @@ The known hosts file also provides a facility to mark keys as revoked, for example when it is known that the associated private key has been stolen. Revoked keys are specified by including the ``@revoked'' marker - at the beginning of the key line, and are never accepted for - authentication or as certification authorities, but instead will produce - a warning from ssh(1) when they are encountered. - - It is permissible (but not recommended) to have several lines or - different host keys for the same names. This will inevitably happen when - short forms of host names from different domains are put in the file. It - is possible that the files contain conflicting information; - authentication is accepted if valid information can be found from either - file. + at the beginning of the key line, and are never accepted for authentica- + tion or as certification authorities, but instead will produce a warning + from ssh(1) when they are encountered. + + It is permissible (but not recommended) to have several lines or differ- + ent host keys for the same names. This will inevitably happen when short + forms of host names from different domains are put in the file. It is + possible that the files contain conflicting information; authentication + is accepted if valid information can be found from either file. Note that the lines in these files are typically hundreds of characters long, and you definitely don't want to type in the host keys by hand. Rather, generate them by a script, ssh-keyscan(1) or by taking /etc/ssh/ssh_host_key.pub and adding the host names at the front. ssh-keygen(1) also offers some basic automated editing for - ~/.ssh/known_hosts including removing hosts matching a host name and - converting all host names to their hashed representations. + ~/.ssh/known_hosts including removing hosts matching a host name and con- + verting all host names to their hashed representations. An example ssh_known_hosts file: # Comments allowed at start of line closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....= + x509host x509v3-sign-rsa Subject:/C=XX..... # A hashed hostname |1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa AAAA1234.....= @@ -484,12 +496,11 @@ ~/.rhosts This file is used for host-based authentication (see ssh(1) for more information). On some machines this file may need to be - world-readable if the user's home directory is on an NFS - partition, because sshd reads it as root. Additionally, this - file must be owned by the user, and must not have write - permissions for anyone else. The recommended permission for most - machines is read/write for the user, and not accessible by - others. + world-readable if the user's home directory is on an NFS parti- + tion, because sshd reads it as root. Additionally, this file + must be owned by the user, and must not have write permissions + for anyone else. The recommended permission for most machines is + read/write for the user, and not accessible by others. ~/.shosts This file is used in exactly the same way as .rhosts, but allows @@ -497,18 +508,19 @@ rlogin/rsh. ~/.ssh/ - This directory is the default location for all user-specific - configuration and authentication information. There is no - general requirement to keep the entire contents of this directory - secret, but the recommended permissions are read/write/execute - for the user, and not accessible by others. + This directory is the default location for all user-specific con- + figuration and authentication information. There is no general + requirement to keep the entire contents of this directory secret, + but the recommended permissions are read/write/execute for the + user, and not accessible by others. ~/.ssh/authorized_keys - Lists the public keys (RSA/DSA) that can be used for logging in - as this user. The format of this file is described above. The - content of the file is not highly sensitive, but the recommended - permissions are read/write for the user, and not accessible by - others. + Lists the public keys (RSA/DSA), certificates or certificates + ``Distinguished Names'' (recommended) that can be used for log- + ging in as this user. The format of this file is described + above. The content of the file is not highly sensitive, but the + recommended permissions are read/write for the user, and not + accessible by others. If this file, the ~/.ssh directory, or the user's home directory are writable by other users, then the file could be modified or @@ -519,17 +531,17 @@ ~/.ssh/environment This file is read into the environment at login (if it exists). It can only contain empty lines, comment lines (that start with - `#'), and assignment lines of the form name=value. The file + '#'), and assignment lines of the form name=value. The file should be writable only by the user; it need not be readable by anyone else. Environment processing is disabled by default and is controlled via the PermitUserEnvironment option. ~/.ssh/known_hosts - Contains a list of host keys for all hosts the user has logged - into that are not already in the systemwide list of known host - keys. The format of this file is described above. This file - should be writable only by root/the owner and can, but need not - be, world-readable. + Contains a list of host keys or certificates for all hosts the + user has logged into that are not already in the systemwide list + of known host keys. The format of this file is described above. + This file should be writable only by root/the owner and can, but + need not be, world-readable. ~/.ssh/rc Contains initialization routines to be run before the user's home @@ -563,34 +575,54 @@ allows host-based authentication without permitting login with rlogin/rsh. + /etc/ssh/ca/ca-bundle.crt + /etc/ssh/ca/ca-bundle.crl + The first file contain multiple certificates and the second + ``Certificate Revocation List'' (CRLs) of certificate signers in + PEM format concatenated together. Used to verify and validate + client certificate. + + /etc/ssh/ca/crt + /etc/ssh/ca/crl + ``Hash dirs'' with certificates, the first directory or CLRs, the + second of certificate signers. Each certificate should be stored + in separate file with name [HASH].[NUMBER] or [HASH].r[NUMBER] + for the CRL, where [HASH] is certificate or CRL hash value and + [NUMBER] is an integer starting from zero. Used to verify and + validate client certificate. + /etc/ssh/ssh_host_key /etc/ssh/ssh_host_dsa_key /etc/ssh/ssh_host_rsa_key - These three files contain the private parts of the host keys. - These files should only be owned by root, readable only by root, - and not accessible to others. Note that sshd does not start if - these files are group/world-accessible. + These three files contain the private parts of the host keys. It + is possible to contain private part followed by X.509 certificate + that match it for protocol version 2 keys. These files should + only be owned by root, readable only by root, and not accessible + to others. Note that sshd does not start if these files are + group/world-accessible. /etc/ssh/ssh_host_key.pub /etc/ssh/ssh_host_dsa_key.pub /etc/ssh/ssh_host_rsa_key.pub These three files contain the public parts of the host keys. These files should be world-readable but writable only by root. - Their contents should match the respective private parts. These - files are not really used for anything; they are provided for the - convenience of the user so their contents can be copied to known - hosts files. These files are created using ssh-keygen(1). + Their contents should match the respective private parts. Note + that when corresponding host key contain X.509 certificate these + files must contains that certificate. These files are not really + used for anything; they are provided for the convenience of the + user so their contents can be copied to known hosts files. These + files are created using ssh-keygen(1). /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared - by the system administrator to contain the public host keys of - all machines in the organization. The format of this file is - described above. This file should be writable only by root/the - owner and should be world-readable. + by the system administrator to contain the public host keys or + certificates of all machines in the organization. The format of + this file is described above. This file should be writable only + by root/the owner and should be world-readable. /etc/ssh/sshd_config - Contains configuration data for sshd. The file format and - configuration options are described in sshd_config(5). + Contains configuration data for sshd. The file format and con- + figuration options are described in sshd_config(5). /etc/ssh/sshrc Similar to ~/.ssh/rc, it can be used to specify machine-specific @@ -607,8 +639,8 @@ Contains the process ID of the sshd listening for connections (if there are several daemons running concurrently for different ports, this contains the process ID of the one started last). - The content of this file is not sensitive; it can be world- - readable. + The content of this file is not sensitive; it can be world-read- + able. SEE ALSO scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), @@ -618,13 +650,14 @@ AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support - for privilege separation. + for privilege separation. Roumen Petrov contributed support for X.509 + certificates. CAVEATS - System security is not improved unless rshd, rlogind, and rexecd are - disabled (thus completely disabling rlogin and rsh into the machine). + System security is not improved unless rshd, rlogind, and rexecd are dis- + abled (thus completely disabling rlogin and rsh into the machine). -OpenBSD 4.8 August 4, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/sshd.8 openssh-5.6p1+x509-6.2.3/sshd.8 --- openssh-5.6p1/sshd.8 2010-08-05 06:03:13.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sshd.8 2010-08-24 09:06:00.000000000 +0300 @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -34,7 +35,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. .\" -.\" $OpenBSD: sshd.8,v 1.257 2010/08/04 05:37:01 djm Exp $ +.\" $OpenBSD$ .Dd $Mdocdate: August 4 2010 $ .Dt SSHD 8 .Os @@ -176,6 +177,8 @@ for protocol version 2. It is possible to have multiple host key files for the different protocol versions and host key algorithms. +It is possible host key for protocol version 2 to contain private key +followed by X.509 certificate that match it. .It Fl i Specifies that .Nm @@ -275,11 +278,12 @@ .Cm Protocol option in .Xr sshd_config 5 . -Protocol 2 supports both RSA and DSA keys; +Protocol 2 supports RSA, DSA keys and X.509 certificates; protocol 1 only supports RSA keys. For both protocols, each host has a host-specific key, normally 2048 bits, +or X.509 certificate used to identify the host. .Pp Forward security for protocol 1 is provided through @@ -466,6 +470,9 @@ public key authentication; if none is specified, the default is .Pa ~/.ssh/authorized_keys . +It is posible for protocol version 2 to contain X.509 certificates +or certificates +.Dq "Distinguished Name" . Each line of the file contains one key (empty lines and lines starting with a .Ql # @@ -486,6 +493,37 @@ .Dq ssh-dss or .Dq ssh-rsa . +In addition for protocol version 2 user can use X.509 certificates. +In that case keytype is +.Dq x509v3-sign-rsa +or +.Dq x509v3-sign-dss . +Instead of +.Dq "base64 encoded key" +line must contain base64 encoded certicate (old style) or +a keyword (new style), optional followed by symbol +.Sq = +(equal) or +.Sq \&: +(colon), zero or more spaces and certificate +.Dq "Distinguished Name" +(Subject). Keyword is case insensitive and can be one of +.Sq Subject +, +.Sq "Distinguished Name" +, +.Sq Distinguished-Name +, +.Sq Distinguished_Name +, +.Sq DistinguishedName +or +.Sq DN . +Separator of Subject items can be +.Sq / +(slash), +.Sq \&, +(comma) or mixed and order is not important. .Pp Note that lines in this file are usually several hundred bytes long (because of the size of the public key encoding) up to a limit of @@ -630,6 +668,7 @@ AAAAC3...51R== example.net permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-dss AAAAB5...21S== +x509v3-sign-dss subject=/C=XX/ST=World/O=OpenSSH Test Team... tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...== jane@example.net .Ed @@ -638,7 +677,9 @@ .Pa /etc/ssh/ssh_known_hosts and .Pa ~/.ssh/known_hosts -files contain host public keys for all known hosts. +files contain host public keys, certificates (old style) or certificates +.Dq "Distinguished Name" +for all known hosts. The global file should be prepared by the administrator (optional), and the per-user file is maintained automatically: whenever the user connects from an unknown host, @@ -741,6 +782,7 @@ # Comments allowed at start of line closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....= +x509host x509v3-sign-rsa Subject:/C=XX..... # A hashed hostname |1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa AAAA1234.....= @@ -792,7 +834,10 @@ and not accessible by others. .Pp .It ~/.ssh/authorized_keys -Lists the public keys (RSA/DSA) that can be used for logging in as this user. +Lists the public keys (RSA/DSA), certificates or certificates +.Dq "Distinguished Names +(recommended) +that can be used for logging in as this user. The format of this file is described above. The content of the file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others. @@ -822,7 +867,7 @@ option. .Pp .It ~/.ssh/known_hosts -Contains a list of host keys for all hosts the user has logged into +Contains a list of host keys or certificates for all hosts the user has logged into that are not already in the systemwide list of known host keys. The format of this file is described above. This file should be writable only by root/the owner and @@ -869,10 +914,31 @@ but allows host-based authentication without permitting login with rlogin/rsh. .Pp +.It /etc/ssh/ca/ca-bundle.crt +.It /etc/ssh/ca/ca-bundle.crl +The first file contain multiple certificates and the second +.Dq "Certificate Revocation List" +(CRLs) of certificate signers in PEM format concatenated together. +Used to verify and validate client certificate. +.Pp +.It /etc/ssh/ca/crt +.It /etc/ssh/ca/crl +.Dq "Hash dirs" +with certificates, the first directory or CLRs, the second of +certificate signers. +Each certificate should be stored in separate file with name +[HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where [HASH] is +certificate or CRL hash value and [NUMBER] is an integer starting +from zero. +Used to verify and validate client certificate. +.Pp .It /etc/ssh/ssh_host_key .It /etc/ssh/ssh_host_dsa_key .It /etc/ssh/ssh_host_rsa_key These three files contain the private parts of the host keys. +It is possible to contain private part +followed by X.509 certificate that match it +for protocol version 2 keys. These files should only be owned by root, readable only by root, and not accessible to others. Note that @@ -886,6 +952,8 @@ These files should be world-readable but writable only by root. Their contents should match the respective private parts. +Note that when corresponding host key contain X.509 certificate +these files must contains that certificate. These files are not really used for anything; they are provided for the convenience of the user so their contents can be copied to known hosts files. @@ -895,7 +963,7 @@ .It /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared by the -system administrator to contain the public host keys of all machines in the +system administrator to contain the public host keys or certificates of all machines in the organization. The format of this file is described above. This file should be writable only by root/the owner and @@ -956,6 +1024,7 @@ protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. +Roumen Petrov contributed support for X.509 certificates. .Sh CAVEATS System security is not improved unless .Nm rshd , diff -ruN openssh-5.6p1/sshd.c openssh-5.6p1+x509-6.2.3/sshd.c --- openssh-5.6p1/sshd.c 2010-04-16 08:56:22.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sshd.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.375 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -21,6 +21,9 @@ * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved. * + * X.509 certificates support: + * Copyright (c) 2002-2005 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -119,6 +122,7 @@ #include "monitor_wrap.h" #include "roaming.h" #include "version.h" +#include "ssh-xkalg.h" #ifdef LIBWRAP #include @@ -139,6 +143,9 @@ extern char *__progname; +/* ssh-x509.c needs this */ +extern int (*pssh_x509cert_check)(X509 *cert); + /* Server configuration options. */ ServerOptions options; @@ -738,6 +745,10 @@ p = key_ssh_name(key); buffer_append(&b, p, strlen(p)); break; + case KEY_X509_RSA: + case KEY_X509_DSA: + ssh_list_xkalg(key->type, &b); + break; } /* If the private key has a cert peer, then list that too */ key = sensitive_data.host_certificates[i]; @@ -1304,6 +1315,7 @@ #endif __progname = ssh_get_progname(av[0]); init_rng(); + pssh_x509cert_check = ssh_x509cert_check; /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; @@ -1576,6 +1588,8 @@ break; case KEY_RSA: case KEY_DSA: + case KEY_X509_RSA: + case KEY_X509_DSA: sensitive_data.have_ssh2_key = 1; break; } diff -ruN openssh-5.6p1/sshd_config openssh-5.6p1+x509-6.2.3/sshd_config --- openssh-5.6p1/sshd_config 2009-10-11 13:51:09.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sshd_config 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.81 2009/10/08 14:03:41 markus Exp $ +# $OpenBSD$ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -24,6 +24,72 @@ #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key +# "key type names" for X.509 certificates with RSA key +# Note first defined is used in signature operations! +#X509KeyAlgorithm x509v3-sign-rsa,rsa-md5 +#X509KeyAlgorithm x509v3-sign-rsa,rsa-sha1 + +# "key type names" for X.509 certificates with DSA key +# Note first defined is used in signature operations! +#X509KeyAlgorithm x509v3-sign-dss,dss-asn1 +#X509KeyAlgorithm x509v3-sign-dss,dss-raw + +# The intended use for the X509 client certificate. Without this option +# no chain verification will be done. Currently accepted uses are case +# insensitive: +# - "sslclient", "SSL client", "SSL_client" or "client" +# - "any", "Any Purpose", "Any_Purpose" or "AnyPurpose" +# - "skip" or ""(empty): don`t check purpose. +#AllowedCertPurpose sslclient + +# Specifies whether self-issued(self-signed) X.509 certificate can be +# allowed only by entry in AutorizedKeysFile that contain matching +# public key or certificate blob. +#KeyAllowSelfIssued no + +# Specifies whether CRL must present in store for all certificates in +# certificate chain with atribute "cRLDistributionPoints" +#MandatoryCRL no + +# A file with multiple certificates of certificate signers +# in PEM format concatenated together. +#CACertificateFile /etc/ssh/ca/ca-bundle.crt + +# A directory with certificates of certificate signers. +# The certificates should have name of the form: [HASH].[NUMBER] +# or have symbolic links to them of this form. +#CACertificatePath /etc/ssh/ca/crt + +# A file with multiple CRL of certificate signers +# in PEM format concatenated together. +#CARevocationFile /etc/ssh/ca/ca-bundle.crl + +# A directory with CRL of certificate signers. +# The CRL should have name of the form: [HASH].r[NUMBER] +# or have symbolic links to them of this form. +#CARevocationPath /etc/ssh/ca/crl + +# LDAP protocol version. +# Example: +# CAldapVersion 2 + +# Note because of OpenSSH options parser limitation +# use %3D instead of = ! +# LDAP initialization may require URL to be escaped, i.e. +# use %2C instead of ,(comma). Escaped URL don't depend from +# LDAP initialization method. +# Example: +# CAldapURL ldap://localhost:389/dc%3Dexample%2Cdc%3Dcom + +# SSH can use "Online Certificate Status Protocol"(OCSP) +# to validate certificate. Set VAType to +# - none : do not use OCSP to validate certificates; +# - ocspcert: validate only certificates that specify `OCSP +# Service Locator' URL; +# - ocspspec: use specified in the configuration 'OCSP Responder' +# to validate all certificates. +#VAType none + # Lifetime and size of ephemeral version 1 server key #KeyRegenerationInterval 1h #ServerKeyBits 1024 diff -ruN openssh-5.6p1/sshd_config.0 openssh-5.6p1+x509-6.2.3/sshd_config.0 --- openssh-5.6p1/sshd_config.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sshd_config.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,28 +1,28 @@ -SSHD_CONFIG(5) OpenBSD Programmer's Manual SSHD_CONFIG(5) +SSHD_CONFIG(5) BSD File Formats Manual SSHD_CONFIG(5) NAME - sshd_config - OpenSSH SSH daemon configuration file + sshd_config -- OpenSSH SSH daemon configuration file SYNOPSIS /etc/ssh/sshd_config DESCRIPTION sshd(8) reads configuration data from /etc/ssh/sshd_config (or the file - specified with -f on the command line). The file contains keyword- - argument pairs, one per line. Lines starting with `#' and empty lines - are interpreted as comments. Arguments may optionally be enclosed in - double quotes (") in order to represent arguments containing spaces. + specified with -f on the command line). The file contains keyword-argu- + ment pairs, one per line. Lines starting with '#' and empty lines are + interpreted as comments. Arguments may optionally be enclosed in double + quotes (") in order to represent arguments containing spaces. - The possible keywords and their meanings are as follows (note that - keywords are case-insensitive and arguments are case-sensitive): + The possible keywords and their meanings are as follows (note that key- + words are case-insensitive and arguments are case-sensitive): AcceptEnv Specifies what environment variables sent by the client will be copied into the session's environ(7). See SendEnv in - ssh_config(5) for how to configure the client. Note that - environment passing is only supported for protocol 2. Variables - are specified by name, which may contain the wildcard characters - `*' and `?'. Multiple environment variables may be separated by + ssh_config(5) for how to configure the client. Note that envi- + ronment passing is only supported for protocol 2. Variables are + specified by name, which may contain the wildcard characters '*' + and '?'. Multiple environment variables may be separated by whitespace or spread across multiple AcceptEnv directives. Be warned that some environment variables could be used to bypass restricted user environments. For this reason, care should be @@ -40,6 +40,18 @@ not improve security unless users are also denied shell access, as they can always install their own forwarders. + AllowedCertPurpose + The intended use for the X.509 client certificate. Without this + option no chain verification will be done. Currently accepted + uses are case insensitive: + sslclient | SSL client | SSL_client | client + only SSL-client purpose + any | Any Purpose | Any_Purpose | AnyPurpose + allow any purpose + skip | '' (empty) + do not check purpose + The default is ``sslclient''. + AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. If specified, login is allowed only for @@ -80,8 +92,8 @@ defined: %% is replaced by a literal '%', %h is replaced by the home directory of the user being authenticated, and %u is replaced by the username of that user. After expansion, - AuthorizedKeysFile is taken to be an absolute path or one - relative to the user's home directory. The default is + AuthorizedKeysFile is taken to be an absolute path or one rela- + tive to the user's home directory. The default is ``.ssh/authorized_keys''. AuthorizedPrincipalsFile @@ -91,7 +103,7 @@ which must appear in the certificate for it to be accepted for authentication. Names are listed one per line preceded by key options (as described in AUTHORIZED_KEYS FILE FORMAT in sshd(8)). - Empty lines and comments starting with `#' are ignored. + Empty lines and comments starting with '#' are ignored. AuthorizedPrincipalsFile may contain tokens of the form %T which are substituted during connection setup. The following tokens @@ -105,16 +117,52 @@ username of the user must appear in a certificate's principals list for it to be accepted. Note that AuthorizedPrincipalsFile is only used when authentication proceeds using a CA listed in - TrustedUserCAKeys and is not consulted for certification - authorities trusted via ~/.ssh/authorized_keys, though the - principals= key option offers a similar facility (see sshd(8) for - details). + TrustedUserCAKeys and is not consulted for certification authori- + ties trusted via ~/.ssh/authorized_keys, though the principals= + key option offers a similar facility (see sshd(8) for details). Banner The contents of the specified file are sent to the remote user before authentication is allowed. If the argument is ``none'' then no banner is displayed. This option is only available for protocol version 2. By default, no banner is displayed. + CACertificateFile + ``X509 store'' option: This file contain multiple certificates of + certificate signers in PEM format concatenated together. The + default is /etc/ssh/ca/ca-bundle.crt. + + CACertificatePath + ``X509 store'' option: ``Hash dir'' with certificates of certifi- + cate signers. Each certificate should be stored in separate file + with name [HASH].[NUMBER], where [HASH] is certificate hash value + and [NUMBER] is an integer starting from zero. The default is + /etc/ssh/ca/crt. + + CAldapVersion + ``X509 store'' option: Specifies LDAP protocol version. The + default is not specified and depend from LDAP library. + + CAldapURL + ``X509 store'' option: Specifies hostport and dn(distinguished + name) of LDAP URLs (Uniform Resource Locators) as detailed in RFC + 2255. The rest of URL is build internally. Because of OpenSSH + options parser limitation use '%3D' instead of '=' ! LDAP ini- + tialization method may require URL to be escaped, i.e. use '%2C' + instead of ',' (comma). Escaped URL don't depend from LDAP ini- + tialization method. + + CARevocationFile + ``X509 store'' option: This file contain multiple ``Certificate + Revocation List'' (CRL) of certificate signers in PEM format con- + catenated together. The default is /etc/ssh/ca/ca-bundle.crl. + + CARevocationPath + ``X509 store'' option: ``Hash dir'' with ``Certificate Revocation + List'' (CRL) of certificate signers. Each CRL should be stored in + separate file with name [HASH].r[NUMBER], where [HASH] is CRL + hash value and [NUMBER] is an integer starting from zero. The + default is /etc/ssh/ca/crl. + ChallengeResponseAuthentication Specifies whether challenge-response authentication is allowed (e.g. via PAM or though authentication styles supported in @@ -130,18 +178,18 @@ The pathname may contain the following tokens that are expanded at runtime once the connecting user has been authenticated: %% is replaced by a literal '%', %h is replaced by the home directory - of the user being authenticated, and %u is replaced by the - username of that user. + of the user being authenticated, and %u is replaced by the user- + name of that user. - The ChrootDirectory must contain the necessary files and - directories to support the user's session. For an interactive - session this requires at least a shell, typically sh(1), and - basic /dev nodes such as null(4), zero(4), stdin(4), stdout(4), - stderr(4), arandom(4) and tty(4) devices. For file transfer - sessions using ``sftp'', no additional configuration of the - environment is necessary if the in-process sftp server is used, - though sessions which use logging do require /dev/log inside the - chroot directory (see sftp-server(8) for details). + The ChrootDirectory must contain the necessary files and directo- + ries to support the user's session. For an interactive session + this requires at least a shell, typically sh(1), and basic /dev + nodes such as null(4), zero(4), stdin(4), stdout(4), stderr(4), + arandom(4) and tty(4) devices. For file transfer sessions using + ``sftp'', no additional configuration of the environment is nec- + essary if the in-process sftp server is used, though sessions + which use logging do require /dev/log inside the chroot directory + (see sftp-server(8) for details). The default is not to chroot(2). @@ -161,27 +209,27 @@ Sets the number of client alive messages (see below) which may be sent without sshd(8) receiving any messages back from the client. If this threshold is reached while client alive messages are - being sent, sshd will disconnect the client, terminating the - session. It is important to note that the use of client alive - messages is very different from TCPKeepAlive (below). The client - alive messages are sent through the encrypted channel and - therefore will not be spoofable. The TCP keepalive option - enabled by TCPKeepAlive is spoofable. The client alive mechanism - is valuable when the client or server depend on knowing when a - connection has become inactive. + being sent, sshd will disconnect the client, terminating the ses- + sion. It is important to note that the use of client alive mes- + sages is very different from TCPKeepAlive (below). The client + alive messages are sent through the encrypted channel and there- + fore will not be spoofable. The TCP keepalive option enabled by + TCPKeepAlive is spoofable. The client alive mechanism is valu- + able when the client or server depend on knowing when a connec- + tion has become inactive. The default value is 3. If ClientAliveInterval (see below) is - set to 15, and ClientAliveCountMax is left at the default, - unresponsive SSH clients will be disconnected after approximately - 45 seconds. This option applies to protocol version 2 only. + set to 15, and ClientAliveCountMax is left at the default, unre- + sponsive SSH clients will be disconnected after approximately 45 + seconds. This option applies to protocol version 2 only. ClientAliveInterval Sets a timeout interval in seconds after which if no data has been received from the client, sshd(8) will send a message through the encrypted channel to request a response from the client. The default is 0, indicating that these messages will - not be sent to the client. This option applies to protocol - version 2 only. + not be sent to the client. This option applies to protocol ver- + sion 2 only. Compression Specifies whether compression is allowed, or delayed until the @@ -192,8 +240,8 @@ This keyword can be followed by a list of group name patterns, separated by spaces. Login is disallowed for users whose primary group or supplementary group list matches one of the patterns. - Only group names are valid; a numerical group ID is not - recognized. By default, login is allowed for all groups. The + Only group names are valid; a numerical group ID is not recog- + nized. By default, login is allowed for all groups. The allow/deny directives are processed in the following order: DenyUsers, AllowUsers, DenyGroups, and finally AllowGroups. @@ -202,13 +250,13 @@ DenyUsers This keyword can be followed by a list of user name patterns, separated by spaces. Login is disallowed for user names that - match one of the patterns. Only user names are valid; a - numerical user ID is not recognized. By default, login is - allowed for all users. If the pattern takes the form USER@HOST - then USER and HOST are separately checked, restricting logins to - particular users from particular hosts. The allow/deny - directives are processed in the following order: DenyUsers, - AllowUsers, DenyGroups, and finally AllowGroups. + match one of the patterns. Only user names are valid; a numeri- + cal user ID is not recognized. By default, login is allowed for + all users. If the pattern takes the form USER@HOST then USER and + HOST are separately checked, restricting logins to particular + users from particular hosts. The allow/deny directives are pro- + cessed in the following order: DenyUsers, AllowUsers, DenyGroups, + and finally AllowGroups. See PATTERNS in ssh_config(5) for more information on patterns. @@ -230,10 +278,10 @@ forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. GatewayPorts can be used to specify that sshd should allow remote port forwardings to - bind to non-loopback addresses, thus allowing other hosts to - connect. The argument may be ``no'' to force remote port - forwardings to be available to the local host only, ``yes'' to - force remote port forwardings to bind to the wildcard address, or + bind to non-loopback addresses, thus allowing other hosts to con- + nect. The argument may be ``no'' to force remote port forward- + ings to be available to the local host only, ``yes'' to force + remote port forwardings to bind to the wildcard address, or ``clientspecified'' to allow the client to select the address to which the forwarding is bound. The default is ``no''. @@ -247,6 +295,14 @@ cache on logout. The default is ``yes''. Note that this option applies to protocol version 2 only. + HostbasedAlgorithms + Specifies the protocol version 2 algorithms used in ``hostbased'' + authentication that the server accept. The default is all sup- + ported by server. Note algorithms that use X.509 certificates + depend from X509KeyAlgorithm and one of names set in + X509KeyAlgorithm for a certain key-type is enough to enable all + form that key-type. + HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is @@ -264,19 +320,21 @@ ``no''. HostCertificate - Specifies a file containing a public host certificate. The - certificate's public key must match a private host key already - specified by HostKey. The default behaviour of sshd(8) is not to + Specifies a file containing a public host certificate. The cer- + tificate's public key must match a private host key already spec- + ified by HostKey. The default behaviour of sshd(8) is not to load any certificates. HostKey Specifies a file containing a private host key used by SSH. The default is /etc/ssh/ssh_host_key for protocol version 1, and - /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_dsa_key for - protocol version 2. Note that sshd(8) will refuse to use a file - if it is group/world-accessible. It is possible to have multiple + /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_dsa_key for pro- + tocol version 2. Note that sshd(8) will refuse to use a file if + it is group/world-accessible. It is possible to have multiple host key files. ``rsa1'' keys are used for version 1 and ``dsa'' - or ``rsa'' are used for version 2 of the SSH protocol. + or ``rsa'' are used for version 2 of the SSH protocol. For ver- + sion 2 is possible file to contain private key followed by X.509 + certificate that match the key. IgnoreRhosts Specifies that .rhosts and .shosts files will not be used in @@ -303,28 +361,43 @@ The default is ``no''. KerberosOrLocalPasswd - If password authentication through Kerberos fails then the - password will be validated via any additional local mechanism - such as /etc/passwd. The default is ``yes''. + If password authentication through Kerberos fails then the pass- + word will be validated via any additional local mechanism such as + /etc/passwd. The default is ``yes''. KerberosTicketCleanup Specifies whether to automatically destroy the user's ticket cache file on logout. The default is ``yes''. + KeyAllowSelfIssued + Specifies whether only public key or certificate blob listed in + AutorizedKeysFile can allow self-issued(self-signed) X.509 cer- + tificate to be used for user authentication. The default is + ``no''. + + A certificate (including self-issued) is accepted for user + authentication if its public key blob, certificate blob or dis- + tinguished name is listed in AutorizedKeysFile, if is valid and + if is verified by certificates from ``X509 store''. See + verify(1). In addition if option is set to ``yes'' self-issued + certificate is accepted when its public key match public key + extracted from entry in AutorizedKeysFile. In this case validity + of certificate is not checked. + KeyRegenerationInterval In protocol version 1, the ephemeral server key is automatically regenerated after this many seconds (if it has been used). The - purpose of regeneration is to prevent decrypting captured - sessions by later breaking into the machine and stealing the - keys. The key is never stored anywhere. If the value is 0, the - key is never regenerated. The default is 3600 (seconds). + purpose of regeneration is to prevent decrypting captured ses- + sions by later breaking into the machine and stealing the keys. + The key is never stored anywhere. If the value is 0, the key is + never regenerated. The default is 3600 (seconds). ListenAddress - Specifies the local addresses sshd(8) should listen on. The - following forms may be used: + Specifies the local addresses sshd(8) should listen on. The fol- + lowing forms may be used: - ListenAddress host | IPv4_addr | IPv6_addr - ListenAddress host | IPv4_addr:port + ListenAddress host|IPv4_addr|IPv6_addr + ListenAddress host|IPv4_addr:port ListenAddress [host|IPv6_addr]:port If port is not specified, sshd will listen on the address and all @@ -334,9 +407,9 @@ port qualified addresses. LoginGraceTime - The server disconnects after this time if the user has not - successfully logged in. If the value is 0, there is no time - limit. The default is 120 seconds. + The server disconnects after this time if the user has not suc- + cessfully logged in. If the value is 0, there is no time limit. + The default is 120 seconds. LogLevel Gives the verbosity level that is used when logging messages from @@ -346,14 +419,19 @@ higher levels of debugging output. Logging with a DEBUG level violates the privacy of users and is not recommended. - MACs Specifies the available MAC (message authentication code) - algorithms. The MAC algorithm is used in protocol version 2 for - data integrity protection. Multiple algorithms must be comma- - separated. The default is: + MACs Specifies the available MAC (message authentication code) algo- + rithms. The MAC algorithm is used in protocol version 2 for data + integrity protection. Multiple algorithms must be comma-sepa- + rated. The default is: hmac-md5,hmac-sha1,umac-64@openssh.com, hmac-ripemd160,hmac-sha1-96,hmac-md5-96 + MandatoryCRL + ``X509 store'' option: Specifies whether CRL must present in + store for all certificates in ``certificate chain'' with atribute + ``X509v3 CRL Distribution Points''. The default is ``no''. + Match Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, @@ -377,13 +455,14 @@ Match keyword. Available keywords are AllowAgentForwarding, AllowTcpForwarding, AuthorizedKeysFile, AuthorizedPrincipalsFile, Banner, ChrootDirectory, ForceCommand, GatewayPorts, - GSSAPIAuthentication, HostbasedAuthentication, - HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication, - KerberosAuthentication, MaxAuthTries, MaxSessions, - PasswordAuthentication, PermitEmptyPasswords, PermitOpen, - PermitRootLogin, PermitTunnel, PubkeyAuthentication, - RhostsRSAAuthentication, RSAAuthentication, X11DisplayOffset, - X11Forwarding and X11UseLocalHost. + GSSAPIAuthentication, HostbasedAlgorithms, + HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, + KbdInteractiveAuthentication, KerberosAuthentication, + MaxAuthTries, MaxSessions, PasswordAuthentication, + PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTunnel, + PubkeyAlgorithms, PubkeyAuthentication, RhostsRSAAuthentication, + RSAAuthentication, X11DisplayOffset, X11Forwarding and + X11UseLocalHost. MaxAuthTries Specifies the maximum number of authentication attempts permitted @@ -391,12 +470,12 @@ value, additional failures are logged. The default is 6. MaxSessions - Specifies the maximum number of open sessions permitted per - network connection. The default is 10. + Specifies the maximum number of open sessions permitted per net- + work connection. The default is 10. MaxStartups - Specifies the maximum number of concurrent unauthenticated - connections to the SSH daemon. Additional connections will be + Specifies the maximum number of concurrent unauthenticated con- + nections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection. The default is 10. @@ -418,26 +497,26 @@ default is ``no''. PermitOpen - Specifies the destinations to which TCP port forwarding is - permitted. The forwarding specification must be one of the - following forms: + Specifies the destinations to which TCP port forwarding is per- + mitted. The forwarding specification must be one of the follow- + ing forms: PermitOpen host:port PermitOpen IPv4_addr:port - PermitOpen [ IPv6_addr ]:port + PermitOpen [IPv6_addr]:port - Multiple forwards may be specified by separating them with - whitespace. An argument of ``any'' can be used to remove all - restrictions and permit any forwarding requests. By default all - port forwarding requests are permitted. + Multiple forwards may be specified by separating them with white- + space. An argument of ``any'' can be used to remove all restric- + tions and permit any forwarding requests. By default all port + forwarding requests are permitted. PermitRootLogin Specifies whether root can log in using ssh(1). The argument must be ``yes'', ``without-password'', ``forced-commands-only'', or ``no''. The default is ``yes''. - If this option is set to ``without-password'', password - authentication is disabled for root. + If this option is set to ``without-password'', password authenti- + cation is disabled for root. If this option is set to ``forced-commands-only'', root login with public key authentication will be allowed, but only if the @@ -448,21 +527,21 @@ If this option is set to ``no'', root is not allowed to log in. PermitTunnel - Specifies whether tun(4) device forwarding is allowed. The - argument must be ``yes'', ``point-to-point'' (layer 3), - ``ethernet'' (layer 2), or ``no''. Specifying ``yes'' permits - both ``point-to-point'' and ``ethernet''. The default is ``no''. + Specifies whether tun(4) device forwarding is allowed. The argu- + ment must be ``yes'', ``point-to-point'' (layer 3), ``ethernet'' + (layer 2), or ``no''. Specifying ``yes'' permits both + ``point-to-point'' and ``ethernet''. The default is ``no''. PermitUserEnvironment Specifies whether ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd(8). The default is ``no''. Enabling environment processing may enable users to - bypass access restrictions in some configurations using - mechanisms such as LD_PRELOAD. + bypass access restrictions in some configurations using mecha- + nisms such as LD_PRELOAD. PidFile - Specifies the file that contains the process ID of the SSH - daemon. The default is /var/run/sshd.pid. + Specifies the file that contains the process ID of the SSH dae- + mon. The default is /var/run/sshd.pid. Port Specifies the port number that sshd(8) listens on. The default is 22. Multiple options of this type are permitted. See also @@ -480,11 +559,19 @@ Protocol Specifies the protocol versions sshd(8) supports. The possible - values are `1' and `2'. Multiple versions must be comma- - separated. The default is `2'. Note that the order of the - protocol list does not indicate preference, because the client - selects among multiple protocol versions offered by the server. - Specifying ``2,1'' is identical to ``1,2''. + values are '1' and '2'. Multiple versions must be comma-sepa- + rated. The default is '2'. Note that the order of the protocol + list does not indicate preference, because the client selects + among multiple protocol versions offered by the server. Specify- + ing ``2,1'' is identical to ``1,2''. + + PubkeyAlgorithms + Specifies the protocol version 2 algorithms used in ``publickey'' + authentication that the server accept. The default is all sup- + ported by server. Note algorithms that use X.509 certificates + depend from X509KeyAlgorithm and one of names set in + X509KeyAlgorithm for a certain key-type is enough to enable all + form that key-type. PubkeyAuthentication Specifies whether public key authentication is allowed. The @@ -545,11 +632,11 @@ Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, - this means that connections will die if the route is down - temporarily, and some people find it annoying. On the other - hand, if TCP keepalives are not sent, sessions may hang - indefinitely on the server, leaving ``ghost'' users and consuming - server resources. + this means that connections will die if the route is down tempo- + rarily, and some people find it annoying. On the other hand, if + TCP keepalives are not sent, sessions may hang indefinitely on + the server, leaving ``ghost'' users and consuming server + resources. The default is ``yes'' (to send TCP keepalive messages), and the server will notice if the network goes down or the client host @@ -559,25 +646,25 @@ ``no''. TrustedUserCAKeys - Specifies a file containing public keys of certificate - authorities that are trusted to sign user certificates for - authentication. Keys are listed one per line; empty lines and - comments starting with `#' are allowed. If a certificate is - presented for authentication and has its signing CA key listed in - this file, then it may be used for authentication for any user - listed in the certificate's principals list. Note that - certificates that lack a list of principals will not be permitted - for authentication using TrustedUserCAKeys. For more details on - certificates, see the CERTIFICATES section in ssh-keygen(1). + Specifies a file containing public keys of certificate authori- + ties that are trusted to sign user certificates for authentica- + tion. Keys are listed one per line; empty lines and comments + starting with '#' are allowed. If a certificate is presented for + authentication and has its signing CA key listed in this file, + then it may be used for authentication for any user listed in the + certificate's principals list. Note that certificates that lack + a list of principals will not be permitted for authentication + using TrustedUserCAKeys. For more details on certificates, see + the CERTIFICATES section in ssh-keygen(1). UseDNS Specifies whether sshd(8) should look up the remote host name and check that the resolved host name for the remote IP address maps back to the very same IP address. The default is ``yes''. UseLogin - Specifies whether login(1) is used for interactive login - sessions. The default is ``no''. Note that login(1) is never - used for remote command execution. Note also, that if this is + Specifies whether login(1) is used for interactive login ses- + sions. The default is ``no''. Note that login(1) is never used + for remote command execution. Note also, that if this is enabled, X11Forwarding will be disabled because login(1) does not know how to handle xauth(1) cookies. If UsePrivilegeSeparation is specified, it will be disabled after authentication. @@ -600,10 +687,32 @@ unprivileged child process to deal with incoming network traffic. After successful authentication, another process will be created that has the privilege of the authenticated user. The goal of - privilege separation is to prevent privilege escalation by - containing any corruption within the unprivileged processes. The + privilege separation is to prevent privilege escalation by con- + taining any corruption within the unprivileged processes. The default is ``yes''. + VACertificateFile + File with X.509 certificates in PEM format concatenated together. + In use when VAType is set to ``ocspspec''. The default value is + '' (empty). Certificates from that file explicitly trust 'OCSP + Responder' public key. They are used as trusted certificates in + addition to certificates from CACertificateFile and + CACertificatePath to verify responder certificate. + + VAType Specifies whether 'Online Certificate Status Protocol' (OCSP) is + used to validate X.509 certificates. Accepted values are case + insensitive: + none do not use OCSP to validate certificates; + ocspcert validate only certificates that specify 'OCSP + Service Locator' URL; + ocspspec use specified in the configuration 'OCSP + Responder' to validate all certificates. + The default is ``none''. + + VAOCSPResponderURL + 'Access Location' / 'OCSP Service Locator' URL of the OCSP + provider. In use when VAType is set to ``ocspspec''. + X11DisplayOffset Specifies the first display number available for sshd(8)'s X11 forwarding. This prevents sshd from interfering with real X11 @@ -616,16 +725,16 @@ When X11 forwarding is enabled, there may be additional exposure to the server and to client displays if the sshd(8) proxy display is configured to listen on the wildcard address (see - X11UseLocalhost below), though this is not the default. - Additionally, the authentication spoofing and authentication data + X11UseLocalhost below), though this is not the default. Addi- + tionally, the authentication spoofing and authentication data verification and substitution occur on the client side. The security risk of using X11 forwarding is that the client's X11 display server may be exposed to attack when the SSH client requests forwarding (see the warnings for ForwardX11 in ssh_config(5)). A system administrator may have a stance in which they want to protect clients that may expose themselves to - attack by unwittingly requesting X11 forwarding, which can - warrant a ``no'' setting. + attack by unwittingly requesting X11 forwarding, which can war- + rant a ``no'' setting. Note that disabling X11 forwarding does not prevent users from forwarding X11 traffic, as users can always install their own @@ -640,19 +749,37 @@ ``localhost''. This prevents remote hosts from connecting to the proxy display. However, some older X11 clients may not function with this configuration. X11UseLocalhost may be set to ``no'' to - specify that the forwarding server should be bound to the - wildcard address. The argument must be ``yes'' or ``no''. The + specify that the forwarding server should be bound to the wild- + card address. The argument must be ``yes'' or ``no''. The default is ``yes''. + X509KeyAlgorithm + Specifies how X.509 certificates and signatures are used for pro- + tocol version 2. It is possible to have multiple algorithms in + form specified in X509 Key Algorithms Format. sshd use the first + listed for ``rsa'' or ``dsa'' key in signing and accept all + listed. + + The default for certificates with RSA key is: + X509KeyAlgorithm x509v3-sign-rsa,rsa-md5 + X509KeyAlgorithm x509v3-sign-rsa,rsa-sha1 + + The default for certificates with DSA key is: + X509KeyAlgorithm x509v3-sign-dss,dss-asn1 + X509KeyAlgorithm x509v3-sign-dss,dss-raw + + X509rsaSigType + Deprecated option replaced by X509KeyAlgorithm. + XAuthLocation Specifies the full pathname of the xauth(1) program. The default is /usr/X11R6/bin/xauth. TIME FORMATS - sshd(8) command-line arguments and configuration file options that - specify time may be expressed using a sequence of the form: time - [qualifier], where time is a positive integer value and qualifier is one - of the following: + sshd(8) command-line arguments and configuration file options that spec- + ify time may be expressed using a sequence of the form: time[qualifier], + where time is a positive integer value and qualifier is one of the fol- + lowing: seconds s | S seconds @@ -670,11 +797,24 @@ 10m 10 minutes 1h30m 1 hour 30 minutes (90 minutes) + X509 Key Algorithms Format + sshd command-line arguments and configuration file options that specify + 'X509 Key Algorithms' expressed using a sequence of the form: + key-type-name,digest-name[,signature-identifier], where key-type-name is + key type name, digest-name is + rsa-md5 : RSA key and signature using the MD5 hash; + rsa-sha1 : RSA key and signature using the SHA-1 hash; + dss-asn1 : DSA key and signature as specified in ``RFC3279'' ; + dss-raw : DSA key and signature in ``ssh-dss'' format specified + in ``SecSH transport'' draft . + and optional signature-identifier. When signature-identifier is omited + key-type-name is used as identifier. + FILES /etc/ssh/sshd_config Contains configuration data for sshd(8). This file should be - writable by root only, but it is recommended (though not - necessary) that it be world-readable. + writable by root only, but it is recommended (though not neces- + sary) that it be world-readable. SEE ALSO sshd(8) @@ -682,9 +822,10 @@ AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support - for privilege separation. + for privilege separation. Roumen Petrov contributed support for X.509 + certificates. -OpenBSD 4.8 June 30, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/sshd_config.5 openssh-5.6p1+x509-6.2.3/sshd_config.5 --- openssh-5.6p1/sshd_config.5 2010-07-02 06:37:17.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/sshd_config.5 2010-08-24 09:06:00.000000000 +0300 @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2006 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -34,7 +35,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. .\" -.\" $OpenBSD: sshd_config.5,v 1.125 2010/06/30 07:28:34 jmc Exp $ +.\" $OpenBSD$ .Dd $Mdocdate: June 30 2010 $ .Dt SSHD_CONFIG 5 .Os @@ -104,6 +105,20 @@ Note that disabling agent forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. +.It Cm AllowedCertPurpose +The intended use for the X.509 client certificate. Without this option +no chain verification will be done. Currently accepted uses are case +insensitive: +.Bl -tag -width Ds -compact +.It Cm sslclient | Cm SSL client | Cm SSL_client | Cm client +only SSL-client purpose +.It Cm any | Cm Any Purpose | Cm Any_Purpose | Cm AnyPurpose +allow any purpose +.It Cm skip | Cm '' Li (empty) +do not check purpose +.El +The default is +.Dq sslclient . .It Cm AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. @@ -220,6 +235,60 @@ then no banner is displayed. This option is only available for protocol version 2. By default, no banner is displayed. +.It Cm CACertificateFile +.Dq X509 store +option: +This file contain multiple certificates of certificate signers in +PEM format concatenated together. The default is +.Pa /etc/ssh/ca/ca-bundle.crt . +.It Cm CACertificatePath +.Dq X509 store +option: +.Dq "Hash dir" +with certificates of certificate signers. Each certificate should be +stored in separate file with name [HASH].[NUMBER], where [HASH] is +certificate hash value and [NUMBER] is an integer starting from zero. +The default is +.Pa /etc/ssh/ca/crt . +.It Cm CAldapVersion +.Dq X509 store +option: +Specifies LDAP protocol version. +The default is not specified and depend from LDAP library. +.It Cm CAldapURL +.Dq X509 store +option: +Specifies hostport and dn(distinguished name) of LDAP URLs (Uniform Resource Locators) as detailed in RFC 2255. +The rest of URL is build internally. +Because of OpenSSH options parser limitation use +.Sq %3D +instead of +.Sq = +! +LDAP initialization method may require URL to be escaped, i.e. use +.Sq %2C +instead of +.Sq \&, +(comma). +Escaped URL don't depend from LDAP initialization method. +.It Cm CARevocationFile +.Dq X509 store +option: +This file contain multiple +.Dq "Certificate Revocation List" +(CRL) of certificate signers in PEM format concatenated together. +The default is +.Pa /etc/ssh/ca/ca-bundle.crl . +.It Cm CARevocationPath +.Dq X509 store +option: +.Dq "Hash dir" +with +.Dq "Certificate Revocation List" +(CRL) of certificate signers. Each CRL should be stored in separate +file with name [HASH].r[NUMBER], where [HASH] is CRL hash value and +[NUMBER] is an integer starting from zero. The default is +.Pa /etc/ssh/ca/crl . .It Cm ChallengeResponseAuthentication Specifies whether challenge-response authentication is allowed (e.g. via PAM or though authentication styles supported in @@ -430,6 +499,16 @@ The default is .Dq yes . Note that this option applies to protocol version 2 only. +.It Cm HostbasedAlgorithms +Specifies the protocol version 2 algorithms used in +.Dq hostbased +authentication that the server accept. +The default is all supported by server. +Note algorithms that use X.509 certificates depend from +.Cm X509KeyAlgorithm +and one of names set in +.Cm X509KeyAlgorithm +for a certain key-type is enough to enable all form that key-type. .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed @@ -484,6 +563,8 @@ or .Dq rsa are used for version 2 of the SSH protocol. +For version 2 is possible file to contain private key +followed by X.509 certificate that match the key. .It Cm IgnoreRhosts Specifies that .Pa .rhosts @@ -536,6 +617,28 @@ file on logout. The default is .Dq yes . +.It Cm KeyAllowSelfIssued +Specifies whether only public key or certificate blob listed in +.Cm AutorizedKeysFile +can allow self-issued(self-signed) X.509 certificate +to be used for user authentication. +The default is +.Dq no . +.Pp +A certificate (including self-issued) is accepted +for user authentication if its public key blob, +certificate blob or distinguished name is listed in +.Cm AutorizedKeysFile , +if is valid and if is verified by certificates from +.Dq X509 store . +See +.Xr verify 1 . +In addition if option is set to +.Dq yes +self-issued certificate is accepted when its public key +match public key extracted from entry in +.Cm AutorizedKeysFile . +In this case validity of certificate is not checked. .It Cm KeyRegenerationInterval In protocol version 1, the ephemeral server key is automatically regenerated after this many seconds (if it has been used). @@ -607,6 +710,15 @@ hmac-md5,hmac-sha1,umac-64@openssh.com, hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .Ed +.It Cm MandatoryCRL +.Dq X509 store +option: +Specifies whether CRL must present in store for all certificates in +.Dq certificate chain +with atribute +.Dq X509v3 CRL Distribution Points . +The default is +.Dq no . .It Cm Match Introduces a conditional block. If all of the criteria on the @@ -660,6 +772,7 @@ .Cm ForceCommand , .Cm GatewayPorts , .Cm GSSAPIAuthentication , +.Cm HostbasedAlgorithms , .Cm HostbasedAuthentication , .Cm HostbasedUsesNameFromPacketOnly , .Cm KbdInteractiveAuthentication , @@ -671,6 +784,7 @@ .Cm PermitOpen , .Cm PermitRootLogin , .Cm PermitTunnel , +.Cm PubkeyAlgorithms , .Cm PubkeyAuthentication , .Cm RhostsRSAAuthentication , .Cm RSAAuthentication , @@ -858,6 +972,16 @@ .Dq 2,1 is identical to .Dq 1,2 . +.It Cm PubkeyAlgorithms +Specifies the protocol version 2 algorithms used in +.Dq publickey +authentication that the server accept. +The default is all supported by server. +Note algorithms that use X.509 certificates depend from +.Cm X509KeyAlgorithm +and one of names set in +.Cm X509KeyAlgorithm +for a certain key-type is enough to enable all form that key-type. .It Cm PubkeyAuthentication Specifies whether public key authentication is allowed. The default is @@ -1021,6 +1145,51 @@ escalation by containing any corruption within the unprivileged processes. The default is .Dq yes . +.It Cm VACertificateFile +File with X.509 certificates in PEM format concatenated together. +In use when +.Cm VAType +is set to +.Dq ocspspec . +The default value is +.Sq +.. +(empty). +Certificates from that file explicitly trust +.Sq "OCSP Responder" +public key. +They are used as trusted certificates in addition to certificates from +.Cm CACertificateFile +and +.Cm CACertificatePath +to verify responder certificate. +.It Cm VAType +Specifies whether +.Sq "Online Certificate Status Protocol" +(OCSP) is used to validate X.509 certificates. +Accepted values are case insensitive: +.Bl -tag -offset indent -compact +.It none +do not use OCSP to validate certificates; +.It ocspcert +validate only certificates that specify +.Sq "OCSP Service Locator" +URL; +.It ocspspec +use specified in the configuration +.Sq "OCSP Responder" +to validate all certificates. +.El +The default is +.Dq none . +.It Cm VAOCSPResponderURL +.Sq "Access Location" +/ +.Sq "OCSP Service Locator" +URL of the OCSP provider. In use when +.Cm VAType +is set to +.Dq ocspspec . .It Cm X11DisplayOffset Specifies the first display number available for .Xr sshd 8 Ns 's @@ -1086,6 +1255,48 @@ .Dq no . The default is .Dq yes . +.It Cm X509KeyAlgorithm +Specifies how X.509 certificates and signatures are used for protocol version 2. +It is possible to have multiple algorithms +in form specified in +.Sx X509 Key Algorithms Format . +.Nm sshd +use the first listed for +.Dq rsa +or +.Dq dsa +key in signing and +accept all listed. +.Pp +The default for certificates with RSA key is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-rsa , Ar rsa-md5 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-rsa , Ar rsa-sha1 +.Sm on +.El +.Pp +The default for certificates with DSA key is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-dss , Ar dss-asn1 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-dss , Ar dss-raw +.Sm on +.El +.It Cm X509rsaSigType +Deprecated option replaced by X509KeyAlgorithm. .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 @@ -1134,6 +1345,43 @@ .It 1h30m 1 hour 30 minutes (90 minutes) .El +.Ss X509 Key Algorithms Format +.Nm sshd +command-line arguments and configuration file options that specify +.Sq X509 Key Algorithms +expressed using a sequence of the form: +.Sm off +.Ar key-type-name , Ar digest-name +.Op Ar \&, signature-identifier , +.Sm on +where +.Ar key-type-name +is key type name, +.Ar digest-name +is +.Bl -tag -compact -offset indent +.It Cm rsa-md5 +: RSA key and signature using the MD5 hash; +.It Cm rsa-sha1 +: RSA key and signature using the SHA-1 hash; +.It Cm dss-asn1 +: DSA key and signature as specified in +.Dq RFC3279 +; +.It Cm dss-raw +: DSA key and signature in +.Dq ssh-dss +format specified in +.Dq SecSH transport +draft . +.El +and optional +.Ar signature-identifier . +When +.Ar signature-identifier +is omited +.Ar key-type-name +is used as identifier. .Sh FILES .Bl -tag -width Ds .It Pa /etc/ssh/sshd_config @@ -1155,3 +1403,4 @@ protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-5.6p1/ssh-keygen.0 openssh-5.6p1+x509-6.2.3/ssh-keygen.0 --- openssh-5.6p1/ssh-keygen.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-keygen.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSH-KEYGEN(1) OpenBSD Reference Manual SSH-KEYGEN(1) +SSH-KEYGEN(1) BSD General Commands Manual SSH-KEYGEN(1) NAME - ssh-keygen - authentication key generation, management and conversion + ssh-keygen -- authentication key generation, management and conversion SYNOPSIS ssh-keygen [-q] [-b bits] -t type [-N new_passphrase] [-C comment] @@ -47,11 +47,11 @@ passphrase may be empty to indicate no passphrase (host keys must have an empty passphrase), or it may be a string of arbitrary length. A passphrase is similar to a password, except it can be a phrase with a - series of words, punctuation, numbers, whitespace, or any string of - characters you want. Good passphrases are 10-30 characters long, are not - simple sentences or otherwise easily guessable (English prose has only 1- - 2 bits of entropy per character, and provides very bad passphrases), and - contain a mix of upper and lowercase letters, numbers, and non- + series of words, punctuation, numbers, whitespace, or any string of char- + acters you want. Good passphrases are 10-30 characters long, are not + simple sentences or otherwise easily guessable (English prose has only + 1-2 bits of entropy per character, and provides very bad passphrases), + and contain a mix of upper and lowercase letters, numbers, and non- alphanumeric characters. The passphrase can be changed later by using the -p option. @@ -61,9 +61,9 @@ For RSA1 keys, there is also a comment field in the key file that is only for convenience to the user to help identify the key. The comment can - tell what the key is for, or whatever is useful. The comment is - initialized to ``user@host'' when the key is created, but can be changed - using the -c option. + tell what the key is for, or whatever is useful. The comment is initial- + ized to ``user@host'' when the key is created, but can be changed using + the -c option. After a key is generated, instructions below detail where the keys should be placed to be activated. @@ -79,16 +79,16 @@ -b bits Specifies the number of bits in the key to create. For RSA keys, - the minimum size is 768 bits and the default is 2048 bits. - Generally, 2048 bits is considered sufficient. DSA keys must be + the minimum size is 768 bits and the default is 2048 bits. Gen- + erally, 2048 bits is considered sufficient. DSA keys must be exactly 1024 bits as specified by FIPS 186-2. -C comment Provides a new comment. -c Requests changing the comment in the private and public key - files. This operation is only supported for RSA1 keys. The - program will prompt for the file containing the private keys, for + files. This operation is only supported for RSA1 keys. The pro- + gram will prompt for the file containing the private keys, for the passphrase if the key has one, and for the new comment. -D pkcs11 @@ -100,8 +100,8 @@ -e This option will read a private or public OpenSSH key file and print to stdout the key in one of the formats specified by the -m option. The default export format is ``RFC4716''. This option - allows exporting OpenSSH keys for use by other programs, - including several commercial SSH implementations. + allows exporting OpenSSH keys for use by other programs, includ- + ing several commercial SSH implementations. -F hostname Search for the specified hostname in a known_hosts file, listing @@ -145,28 +145,29 @@ -l Show fingerprint of specified public key file. Private RSA1 keys are also supported. For RSA and DSA keys ssh-keygen tries to - find the matching public key file and prints its fingerprint. If - combined with -v, an ASCII art representation of the key is - supplied with the fingerprint. + find the matching public key file and prints its fingerprint. + When identity contain X.509 certificate its prints certificate + fingerprint. If combined with -v, an ASCII art representation of + the key is supplied with the fingerprint. -M memory - Specify the amount of memory to use (in megabytes) when - generating candidate moduli for DH-GEX. + Specify the amount of memory to use (in megabytes) when generat- + ing candidate moduli for DH-GEX. -m key_format - Specify a key format for the -i (import) or -e (export) - conversion options. The supported key formats are: ``RFC4716'' - (RFC 4716/SSH2 public or private key), ``PKCS8'' (PEM PKCS8 - public key) or ``PEM'' (PEM public key). The default conversion - format is ``RFC4716''. + Specify a key format for the -i (import) or -e (export) conver- + sion options. The supported key formats are: ``RFC4716'' (RFC + 4716/SSH2 public or private key), ``PKCS8'' (PEM PKCS8 public + key) or ``PEM'' (PEM public key). The default conversion format + is ``RFC4716''. -N new_passphrase Provides the new passphrase. -n principals Specify one or more principals (user or host names) to be - included in a certificate when signing a key. Multiple - principals may be specified, separated by commas. Please see the + included in a certificate when signing a key. Multiple princi- + pals may be specified, separated by commas. Please see the CERTIFICATES section for details. -O option @@ -175,9 +176,9 @@ for details. The options that are valid for user certificates are: - clear Clear all enabled permissions. This is useful for - clearing the default set of permissions so permissions - may be added individually. + clear Clear all enabled permissions. This is useful for clear- + ing the default set of permissions so permissions may be + added individually. force-command=command Forces the execution of command instead of any shell or @@ -216,9 +217,9 @@ source-address=address_list Restrict the source addresses from which the certificate - is considered valid. The address_list is a comma- - separated list of one or more address/netmask pairs in - CIDR format. + is considered valid. The address_list is a comma-sepa- + rated list of one or more address/netmask pairs in CIDR + format. At present, no options are valid for host keys. @@ -239,7 +240,8 @@ -r hostname Print the SSHFP fingerprint resource record named hostname for - the specified public key file. + the specified public key file. In case of X.509 certificates + print CERT resource record. -S start Specify start point (in hex) when generating candidate moduli for @@ -255,14 +257,14 @@ -t type Specifies the type of key to create. The possible values are - ``rsa1'' for protocol version 1 and ``rsa'' or ``dsa'' for - protocol version 2. + ``rsa1'' for protocol version 1 and ``rsa'' or ``dsa'' for proto- + col version 2. -V validity_interval - Specify a validity interval when signing a certificate. A - validity interval may consist of a single time, indicating that - the certificate is valid beginning now and expiring at that time, - or may consist of two times separated by a colon to indicate an + Specify a validity interval when signing a certificate. A valid- + ity interval may consist of a single time, indicating that the + certificate is valid beginning now and expiring at that time, or + may consist of two times separated by a colon to indicate an explicit time interval. The start time may be specified as a date in YYYYMMDD format, a time in YYYYMMDDHHMMSS format or a relative time (to the current time) consisting of a minus sign @@ -279,9 +281,9 @@ 2011). -v Verbose mode. Causes ssh-keygen to print debugging messages - about its progress. This is helpful for debugging moduli - generation. Multiple -v options increase the verbosity. The - maximum is 3. + about its progress. This is helpful for debugging moduli genera- + tion. Multiple -v options increase the verbosity. The maximum + is 3. -W generator Specify desired generator when testing candidate moduli for DH- @@ -299,8 +301,8 @@ ssh-keygen may be used to generate groups for the Diffie-Hellman Group Exchange (DH-GEX) protocol. Generating these groups is a two-step process: first, candidate primes are generated using a fast, but memory - intensive process. These candidate primes are then tested for - suitability (a CPU-intensive process). + intensive process. These candidate primes are then tested for suitabil- + ity (a CPU-intensive process). Generation of primes is performed using the -G option. The desired length of the primes may be specified by the -b option. For example: @@ -308,8 +310,8 @@ # ssh-keygen -G moduli-2048.candidates -b 2048 By default, the search for primes begins at a random point in the desired - length range. This may be overridden using the -S option, which - specifies a different start point (in hex). + length range. This may be overridden using the -S option, which speci- + fies a different start point (in hex). Once a set of candidates have been generated, they must be tested for suitability. This may be performed using the -T option. In this mode @@ -338,8 +340,8 @@ Note that OpenSSH certificates are a different, and much simpler, format to the X.509 certificates used in ssl(8). - ssh-keygen supports two types of certificates: user and host. User - certificates authenticate users to servers, whereas host certificates + ssh-keygen supports two types of certificates: user and host. User cer- + tificates authenticate users to servers, whereas host certificates authenticate server hosts to users. To generate a user certificate: $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub @@ -351,9 +353,9 @@ The host certificate will be output to /path/to/host_key-cert.pub. - It is possible to sign using a CA key stored in a PKCS#11 token by - providing the token library using -D and identifying the CA key by - providing its public half as an argument to -s: + It is possible to sign using a CA key stored in a PKCS#11 token by pro- + viding the token library using -D and identifying the CA key by providing + its public half as an argument to -s: $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub @@ -362,28 +364,28 @@ Certificates may be limited to be valid for a set of principal (user/host) names. By default, generated certificates are valid for all - users or hosts. To generate a certificate for a specified set of - principals: + users or hosts. To generate a certificate for a specified set of princi- + pals: $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub $ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub Additional limitations on the validity and use of user certificates may - be specified through certificate options. A certificate option may - disable features of the SSH session, may be valid only when presented - from particular source addresses or may force the use of a specific - command. For a list of valid certificate options, see the documentation - for the -O option above. + be specified through certificate options. A certificate option may dis- + able features of the SSH session, may be valid only when presented from + particular source addresses or may force the use of a specific command. + For a list of valid certificate options, see the documentation for the -O + option above. Finally, certificates may be defined with a validity lifetime. The -V - option allows specification of certificate start and end times. A - certificate that is presented at a time outside this range will not be - considered valid. By default, certificates have a maximum validity - interval. - - For certificates to be used for user or host authentication, the CA - public key must be trusted by sshd(8) or ssh(1). Please refer to those - manual pages for details. + option allows specification of certificate start and end times. A cer- + tificate that is presented at a time outside this range will not be con- + sidered valid. By default, certificates have a maximum validity inter- + val. + + For certificates to be used for user or host authentication, the CA pub- + lic key must be trusted by sshd(8) or ssh(1). Please refer to those man- + ual pages for details. FILES ~/.ssh/identity @@ -397,45 +399,59 @@ is made. ~/.ssh/identity.pub - Contains the protocol version 1 RSA public key for - authentication. The contents of this file should be added to + Contains the protocol version 1 RSA public key for authentica- + tion. The contents of this file should be added to ~/.ssh/authorized_keys on all machines where the user wishes to log in using RSA authentication. There is no need to keep the contents of this file secret. ~/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of - the user. This file should not be readable by anyone but the - user. It is possible to specify a passphrase when generating the - key; that passphrase will be used to encrypt the private part of - this file using 128-bit AES. This file is not automatically - accessed by ssh-keygen but it is offered as the default file for - the private key. ssh(1) will read this file when a login attempt - is made. + the user. It is possible to contain private key followed by + X.509 certificate that match it. This file should not be read- + able by anyone but the user. It is possible to specify a + passphrase when generating the key; that passphrase will be used + to encrypt the private part of this file using 128-bit AES. This + file is not automatically accessed by ssh-keygen but it is + offered as the default file for the private key. ssh(1) will + read this file when a login attempt is made. ~/.ssh/id_dsa.pub - Contains the protocol version 2 DSA public key for - authentication. The contents of this file should be added to + Contains the protocol version 2 DSA public key for authentica- + tion. The contents of this file should be added to ~/.ssh/authorized_keys on all machines where the user wishes to log in using public key authentication. There is no need to keep - the contents of this file secret. + the contents of this file secret. When file ~/.ssh/id_dsa con- + tain DSA private key followed by X.509 certificate this file must + contain that certificate! Use ssh-keygen with option -y to + regenerate its content. Note in case with X.509 certificate you + can append content to ~/.ssh/authorized_keys or to add certifi- + cate ``Distinguished Name'' / ``Subject'' in corresponding format + to ``authorized keys'' file. See sshd(8). ~/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of - the user. This file should not be readable by anyone but the - user. It is possible to specify a passphrase when generating the - key; that passphrase will be used to encrypt the private part of - this file using 128-bit AES. This file is not automatically - accessed by ssh-keygen but it is offered as the default file for - the private key. ssh(1) will read this file when a login attempt - is made. + the user. It is possible to contain private key followed by + X.509 certificate that match it. This file should not be read- + able by anyone but the user. It is possible to specify a + passphrase when generating the key; that passphrase will be used + to encrypt the private part of this file using 128-bit AES. This + file is not automatically accessed by ssh-keygen but it is + offered as the default file for the private key. ssh(1) will + read this file when a login attempt is made. ~/.ssh/id_rsa.pub - Contains the protocol version 2 RSA public key for - authentication. The contents of this file should be added to + Contains the protocol version 2 RSA public key for authentica- + tion. The contents of this file should be added to ~/.ssh/authorized_keys on all machines where the user wishes to log in using public key authentication. There is no need to keep - the contents of this file secret. + the contents of this file secret. When file ~/.ssh/id_rsa con- + tain RSA private key followed by X.509 certificate this file must + contain that certificate! Use ssh-keygen with option -y to + regenerate its content. Note in case with X.509 certificate you + can append content to ~/.ssh/authorized_keys or to add certifi- + cate ``Distinguished Name'' / ``Subject'' in corresponding format + to ``authorized keys'' file. See sshd(8). /etc/moduli Contains Diffie-Hellman groups used for DH-GEX. The file format @@ -449,8 +465,9 @@ AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 4.8 August 4, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh-keygen.1 openssh-5.6p1+x509-6.2.3/ssh-keygen.1 --- openssh-5.6p1/ssh-keygen.1 2010-08-05 06:05:32.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-keygen.1 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.98 2010/08/04 06:07:11 djm Exp $ +.\" $OpenBSD$ .\" .\" -*- nroff -*- .\" @@ -16,6 +16,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -295,6 +296,7 @@ For RSA and DSA keys .Nm tries to find the matching public key file and prints its fingerprint. +When identity contain X.509 certificate its prints certificate fingerprint. If combined with .Fl v , an ASCII art representation of the key is supplied with the fingerprint. @@ -410,6 +412,7 @@ Print the SSHFP fingerprint resource record named .Ar hostname for the specified public key file. +In case of X.509 certificates print CERT resource record. .It Fl S Ar start Specify start point (in hex) when generating candidate moduli for DH-GEX. .It Fl s Ar ca_key @@ -626,6 +629,8 @@ There is no need to keep the contents of this file secret. .It Pa ~/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. +It is possible to contain private key +followed by X.509 certificate that match it. This file should not be readable by anyone but the user. It is possible to specify a passphrase when generating the key; that passphrase will be @@ -642,8 +647,27 @@ on all machines where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. +When file +.Pa ~/.ssh/id_dsa +contain DSA private key followed by X.509 certificate +this file must contain that certificate! +Use +.Nm +with option -y to regenerate its content. +Note in case with X.509 certificate you can append content to +.Pa ~/.ssh/authorized_keys +or to add certificate +.Dq Distinguished Name +/ +.Dq Subject +in corresponding format to +.Dq authorized keys +file. See +.Xr sshd 8 . .It Pa ~/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. +It is possible to contain private key +followed by X.509 certificate that match it. This file should not be readable by anyone but the user. It is possible to specify a passphrase when generating the key; that passphrase will be @@ -660,6 +684,23 @@ on all machines where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. +When file +.Pa ~/.ssh/id_rsa +contain RSA private key followed by X.509 certificate +this file must contain that certificate! +Use +.Nm +with option -y to regenerate its content. +Note in case with X.509 certificate you can append content to +.Pa ~/.ssh/authorized_keys +or to add certificate +.Dq Distinguished Name +/ +.Dq Subject +in corresponding format to +.Dq authorized keys +file. See +.Xr sshd 8 . .It Pa /etc/moduli Contains Diffie-Hellman groups used for DH-GEX. The file format is described in @@ -685,3 +726,4 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-5.6p1/ssh-keygen.c openssh-5.6p1+x509-6.2.3/ssh-keygen.c --- openssh-5.6p1/ssh-keygen.c 2010-08-05 06:05:32.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-keygen.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.197 2010/08/04 06:07:11 djm Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -10,6 +10,29 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X.509 certificates support, + * Copyright (c) 2005 Roumen Petrov. 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" @@ -49,6 +72,7 @@ #include "hostfile.h" #include "dns.h" #include "ssh2.h" +#include "ssh-xkalg.h" #ifdef ENABLE_PKCS11 #include "ssh-pkcs11.h" @@ -1782,6 +1806,7 @@ __progname = ssh_get_progname(argv[0]); SSLeay_add_all_algorithms(); + fill_default_xkalg(); log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); init_rng(); diff -ruN openssh-5.6p1/ssh-keyscan.0 openssh-5.6p1+x509-6.2.3/ssh-keyscan.0 --- openssh-5.6p1/ssh-keyscan.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-keyscan.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,20 +1,20 @@ -SSH-KEYSCAN(1) OpenBSD Reference Manual SSH-KEYSCAN(1) +SSH-KEYSCAN(1) BSD General Commands Manual SSH-KEYSCAN(1) NAME - ssh-keyscan - gather ssh public keys + ssh-keyscan -- gather ssh public keys SYNOPSIS ssh-keyscan [-46Hv] [-f file] [-p port] [-T timeout] [-t type] [host | addrlist namelist] ... DESCRIPTION - ssh-keyscan is a utility for gathering the public ssh host keys of a - number of hosts. It was designed to aid in building and verifying + ssh-keyscan is a utility for gathering the public ssh host keys of a num- + ber of hosts. It was designed to aid in building and verifying ssh_known_hosts files. ssh-keyscan provides a minimal interface suitable for use by shell and perl scripts. - ssh-keyscan uses non-blocking socket I/O to contact as many hosts as - possible in parallel, so it is very efficient. The keys from a domain of + ssh-keyscan uses non-blocking socket I/O to contact as many hosts as pos- + sible in parallel, so it is very efficient. The keys from a domain of 1,000 hosts can be collected in tens of seconds, even when some of those hosts are down or do not run ssh. For scanning, one does not need login access to the machines that are being scanned, nor does the scanning @@ -32,8 +32,8 @@ read hosts or addrlist namelist pairs from the standard input. -H Hash all hostnames and addresses in the output. Hashed names may - be used normally by ssh and sshd, but they do not reveal - identifying information should the file's contents be disclosed. + be used normally by ssh and sshd, but they do not reveal identi- + fying information should the file's contents be disclosed. -p port Port to connect to on the remote host. @@ -48,20 +48,20 @@ -t type Specifies the type of the key to fetch from the scanned hosts. The possible values are ``rsa1'' for protocol version 1 and - ``rsa'' or ``dsa'' for protocol version 2. Multiple values may - be specified by separating them with commas. The default is - ``rsa''. + ``rsa'' , ``dsa'' , ``x509v3-sign-rsa'' or ``x509v3-sign-dss'' + for protocol version 2. Multiple values may be specified by sep- + arating them with commas. The default are keys for protocol ver- + sion 2. -v Verbose mode. Causes ssh-keyscan to print debugging messages about its progress. SECURITY - If an ssh_known_hosts file is constructed using ssh-keyscan without - verifying the keys, users will be vulnerable to man in the middle - attacks. On the other hand, if the security model allows such a risk, - ssh-keyscan can help in the detection of tampered keyfiles or man in the - middle attacks which have begun after the ssh_known_hosts file was - created. + If an ssh_known_hosts file is constructed using ssh-keyscan without veri- + fying the keys, users will be vulnerable to man in the middle attacks. + On the other hand, if the security model allows such a risk, ssh-keyscan + can help in the detection of tampered keyfiles or man in the middle + attacks which have begun after the ssh_known_hosts file was created. FILES Input format: @@ -78,6 +78,12 @@ Where keytype is either ``ssh-rsa'' or ``ssh-dss''. + Output format for rsa and dsa keys with X.509 certificates: + + host-or-namelist keytype distinguished-name + + Where keytype is either ``x509v3-sign-rsa'' or ``x509v3-sign-dss''. + /etc/ssh/ssh_known_hosts EXAMPLES @@ -88,7 +94,7 @@ Find all hosts from the file ssh_hosts which have new or different keys from those in the sorted file ssh_known_hosts: - $ ssh-keyscan -t rsa,dsa -f ssh_hosts | \ + $ ssh-keyscan -t x509v3-sign-rsa,x509v3-sign-dss,rsa,dsa -f ssh_hosts | \ sort -u - ssh_known_hosts | diff ssh_known_hosts - SEE ALSO @@ -97,7 +103,7 @@ AUTHORS David Mazieres wrote the initial version, and Wayne Davison added support for protocol version - 2. + 2. Roumen Petrov contributed support for X.509 certificates. BUGS It generates "Connection closed by remote host" messages on the consoles @@ -105,4 +111,4 @@ This is because it opens a connection to the ssh port, reads the public key, and drops the connection as soon as it gets the key. -OpenBSD 4.8 January 9, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh-keyscan.1 openssh-5.6p1+x509-6.2.3/ssh-keyscan.1 --- openssh-5.6p1/ssh-keyscan.1 2010-01-10 01:31:12.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-keyscan.1 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.28 2010/01/09 23:04:13 dtucker Exp $ +.\" $OpenBSD$ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" @@ -6,6 +6,29 @@ .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" +.\" X.509 certificates support, +.\" Copyright (c) 2002-2005 Roumen Petrov. 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. +.\" .Dd $Mdocdate: January 9 2010 $ .Dt SSH-KEYSCAN 1 .Os @@ -89,12 +112,15 @@ .Dq rsa1 for protocol version 1 and .Dq rsa -or +, .Dq dsa +, +.Dq x509v3-sign-rsa +or +.Dq x509v3-sign-dss for protocol version 2. Multiple values may be specified by separating them with commas. -The default is -.Dq rsa . +The default are keys for protocol version 2. .It Fl v Verbose mode. Causes @@ -134,6 +160,18 @@ or .Dq ssh-dss . .Pp +.Pa Output format for rsa and dsa keys with X.509 certificates: +.Bd -literal +host-or-namelist keytype distinguished-name +.Ed +.Pp +Where +.Pa keytype +is either +.Dq x509v3-sign-rsa +or +.Dq x509v3-sign-dss . +.Pp .Pa /etc/ssh/ssh_known_hosts .Sh EXAMPLES Print the @@ -149,7 +187,7 @@ which have new or different keys from those in the sorted file .Pa ssh_known_hosts : .Bd -literal -$ ssh-keyscan -t rsa,dsa -f ssh_hosts | \e +$ ssh-keyscan -t x509v3-sign-rsa,x509v3-sign-dss,rsa,dsa -f ssh_hosts | \e sort -u - ssh_known_hosts | diff ssh_known_hosts - .Ed .Sh SEE ALSO @@ -161,6 +199,7 @@ wrote the initial version, and .An Wayne Davison Aq wayned@users.sourceforge.net added support for protocol version 2. +Roumen Petrov contributed support for X.509 certificates. .Sh BUGS It generates "Connection closed by remote host" messages on the consoles of all the machines it scans if the server is older than version 2.9. diff -ruN openssh-5.6p1/ssh-keyscan.c openssh-5.6p1+x509-6.2.3/ssh-keyscan.c --- openssh-5.6p1/ssh-keyscan.c 2010-06-26 02:39:59.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-keyscan.c 2010-08-24 09:06:01.000000000 +0300 @@ -1,10 +1,33 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.82 2010/06/22 04:54:30 djm Exp $ */ +/* $OpenBSD$ */ /* * Copyright 1995, 1996 by David Mazieres . * * Modification and redistribution in source and binary forms is * permitted provided that due credit is given to the author and the * OpenBSD project by leaving this copyright notice intact. + * + * X.509 certificates support, + * Copyright (c) 2002-2005 Roumen Petrov. 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" @@ -35,6 +58,8 @@ #include "ssh1.h" #include "buffer.h" #include "key.h" +#include "ssh-x509.h" +#include "ssh-xkalg.h" #include "cipher.h" #include "kex.h" #include "compat.h" @@ -52,11 +77,7 @@ int ssh_port = SSH_DEFAULT_PORT; -#define KT_RSA1 1 -#define KT_DSA 2 -#define KT_RSA 4 - -int get_keytypes = KT_RSA; /* Get only RSA keys by default */ +char* get_keynames = NULL; int hash_hosts = 0; /* Hash hostname on output */ @@ -90,7 +111,7 @@ int c_plen; /* Packet length field for ssh packet */ int c_len; /* Total bytes which must be read. */ int c_off; /* Length of data read so far. */ - int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ + const char *c_keyname; char *c_namebase; /* Address to free for c_name and c_namelist */ char *c_name; /* Hostname of connection for errors */ char *c_namelist; /* Pointer to other possible addresses */ @@ -170,7 +191,7 @@ * null token for two adjacent separators, so we may have to loop. */ static char * -strnnsep(char **stringp, char *delim) +strnnsep(char **stringp, const char *delim) { char *tok; @@ -244,8 +265,7 @@ packet_set_connection(c->c_fd, c->c_fd); enable_compat20(); - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? - "ssh-dss": "ssh-rsa"; + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = (char*)c->c_keyname; c->c_kex = kex_setup(myproposal); c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; @@ -278,7 +298,16 @@ fatal("host_hash failed"); fprintf(stdout, "%s ", host); +#ifndef SSH_X509STORE_DISABLED + if ((key->type == KEY_X509_RSA) || (key->type == KEY_X509_DSA)) { + /* key_write will print x509 certificate in blob format :-( */ + x509key_write_subject2(key, c->c_keyname, stdout); + } else { +#endif /*ndef SSH_X509STORE_DISABLED*/ key_write(key, stdout); +#ifndef SSH_X509STORE_DISABLED + } +#endif /*ndef SSH_X509STORE_DISABLED*/ fputs("\n", stdout); } @@ -316,7 +345,7 @@ } static int -conalloc(char *iname, char *oname, int keytype) +conalloc(char *iname, char *oname, const char *keyname) { char *namebase, *name, *namelist; int s; @@ -345,7 +374,11 @@ fdcon[s].c_data = (char *) &fdcon[s].c_plen; fdcon[s].c_len = 4; fdcon[s].c_off = 0; - fdcon[s].c_keytype = keytype; +{ + Key *k = key_new(key_type_from_name((char*)keyname)); + fdcon[s].c_keyname = key_ssh_name(k); + key_free(k); +} gettimeofday(&fdcon[s].c_tv, NULL); fdcon[s].c_tv.tv_sec += timeout; TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); @@ -365,7 +398,7 @@ if (fdcon[s].c_status == CS_KEYS) xfree(fdcon[s].c_data); fdcon[s].c_status = CS_UNUSED; - fdcon[s].c_keytype = 0; + fdcon[s].c_keyname = NULL; TAILQ_REMOVE(&tq, &fdcon[s], c_link); FD_CLR(s, read_wait); ncon--; @@ -386,7 +419,7 @@ con *c = &fdcon[s]; int ret; - ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); + ret = conalloc(c->c_namelist, c->c_output_name, c->c_keyname); confree(s); return (ret); } @@ -399,6 +432,7 @@ char remote_version[sizeof buf]; size_t bufsiz; con *c = &fdcon[s]; + int rsa1key; for (;;) { memset(buf, '\0', sizeof(buf)); @@ -438,7 +472,8 @@ compat_datafellows(remote_version); else datafellows = 0; - if (c->c_keytype != KT_RSA1) { + rsa1key = (strcmp(c->c_keyname, "rsa1") == 0); + if (!rsa1key) { if (!ssh2_capable(remote_major, remote_minor)) { debug("%s doesn't support ssh2", c->c_name); confree(s); @@ -451,8 +486,8 @@ } fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", - c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, - c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); + rsa1key ? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, + rsa1key ? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); if (n < 0 || (size_t)n >= sizeof(buf)) { error("snprintf: buffer too small"); confree(s); @@ -463,7 +498,7 @@ confree(s); return; } - if (c->c_keytype != KT_RSA1) { + if (!rsa1key) { keyprint(c, keygrab_ssh2(c)); confree(s); return; @@ -567,16 +602,18 @@ do_host(char *host) { char *name = strnnsep(&host, " \t\n"); - int j; + const char *keyname; if (name == NULL) return; - for (j = KT_RSA1; j <= KT_RSA; j *= 2) { - if (get_keytypes & j) { - while (ncon >= MAXCON) - conloop(); - conalloc(name, *host ? host : name, j); - } + for ( + keyname = strtok(get_keynames, ","); + keyname != NULL; + keyname = strtok(NULL, ",") + ) { + while (ncon >= MAXCON) + conloop(); + conalloc(name, *host ? host : name, keyname); } } @@ -627,6 +664,8 @@ if (argc <= 1) usage(); + fill_default_xkalg(); + get_keynames = xstrdup("x509v3-sign-dss,x509v3-sign-rsa,ssh-rsa,ssh-dss"); /* Get all protocol v2 keys by default */ while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) { switch (opt) { case 'H': @@ -662,23 +701,12 @@ argv[fopt_count++] = optarg; break; case 't': - get_keytypes = 0; + get_keynames = xstrdup(optarg); tname = strtok(optarg, ","); while (tname) { int type = key_type_from_name(tname); - switch (type) { - case KEY_RSA1: - get_keytypes |= KT_RSA1; - break; - case KEY_DSA: - get_keytypes |= KT_DSA; - break; - case KEY_RSA: - get_keytypes |= KT_RSA; - break; - case KEY_UNSPEC: + if (type == KEY_UNSPEC) fatal("unknown key type %s", tname); - } tname = strtok(NULL, ","); } break; diff -ruN openssh-5.6p1/ssh-keysign.0 openssh-5.6p1+x509-6.2.3/ssh-keysign.0 --- openssh-5.6p1/ssh-keysign.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-keysign.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSH-KEYSIGN(8) OpenBSD System Manager's Manual SSH-KEYSIGN(8) +SSH-KEYSIGN(8) BSD System Manager's Manual SSH-KEYSIGN(8) NAME - ssh-keysign - ssh helper program for host-based authentication + ssh-keysign -- ssh helper program for host-based authentication SYNOPSIS ssh-keysign @@ -16,8 +16,8 @@ to ``yes''. ssh-keysign is not intended to be invoked by the user, but from ssh(1). - See ssh(1) and sshd(8) for more information about host-based - authentication. + See ssh(1) and sshd(8) for more information about host-based authentica- + tion. FILES /etc/ssh/ssh_config @@ -28,12 +28,13 @@ generate the digital signature. They should be owned by root, readable only by root, and not accessible to others. Since they are readable only by root, ssh-keysign must be set-uid root if - host-based authentication is used. + host-based authentication is used. It is possible host key to + contain private parts followed by X.509 certificate that match + it. /etc/ssh/ssh_host_dsa_key-cert.pub, /etc/ssh/ssh_host_rsa_key-cert.pub - If these files exist they are assumed to contain public - certificate information corresponding with the private keys - above. + If these files exist they are assumed to contain public certifi- + cate information corresponding with the private keys above. SEE ALSO ssh(1), ssh-keygen(1), ssh_config(5), sshd(8) @@ -44,4 +45,4 @@ AUTHORS Markus Friedl -OpenBSD 4.8 August 4, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh-keysign.8 openssh-5.6p1+x509-6.2.3/ssh-keysign.8 --- openssh-5.6p1/ssh-keysign.8 2010-08-05 06:04:50.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-keysign.8 2010-08-24 09:06:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keysign.8,v 1.10 2010/08/04 05:42:47 djm Exp $ +.\" $OpenBSD$ .\" .\" Copyright (c) 2002 Markus Friedl. All rights reserved. .\" @@ -68,6 +68,8 @@ Since they are readable only by root, .Nm must be set-uid root if host-based authentication is used. +It is possible host key to contain private parts +followed by X.509 certificate that match it. .It Pa /etc/ssh/ssh_host_dsa_key-cert.pub, /etc/ssh/ssh_host_rsa_key-cert.pub If these files exist they are assumed to contain public certificate information corresponding with the private keys above. diff -ruN openssh-5.6p1/ssh-ocsp.c openssh-5.6p1+x509-6.2.3/ssh-ocsp.c --- openssh-5.6p1/ssh-ocsp.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-ocsp.c 2009-12-26 12:34:11.000000000 +0200 @@ -0,0 +1,1059 @@ +/* + * Copyright (c) 2004-2007 Roumen Petrov. 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 "x509store.h" +#ifndef SSH_OCSP_ENABLED +# include "error: OCSP is disabled" +#endif + +#if 1 +# /* not yet fully implemented */ +# define SSH_WITH_SSLOCSP +#endif + +#include + +#include "xmalloc.h" +#include "log.h" +#include +#include +#include +#ifdef SSH_WITH_SSLOCSP +# include +#endif + +#ifdef sk_OPENSSL_STRING_new_null +/* + * STACK_OF(OPENSSL_STRING) is defined for openssl version >= 1.0 + * (OPENSSL_VERSION_NUMBER >= 0x10000000L). + * NOTE: We will test for definition of sk_OPENSSL_STRING_new_null + * instead openssl version number ! + */ +#define ssh_sk_OPENSSL_STRING STACK_OF(OPENSSL_STRING) + +static void OPENSSL_STRING_xfree(OPENSSL_STRING p) { +/* xfree warnings for OpenSSL 1+: +.../ssh-ocsp.c: In function 'ssh_ocsp_validate2': +.../ssh-ocsp.c:845: warning: pointer type mismatch in conditional expression +.../ssh-ocsp.c:845: warning: ISO C forbids conversion of object pointer to function pointer type +*/ + xfree(p); +} + +#else /* !def sk_OPENSSL_STRING_new_null */ + +#ifdef sk_STRING_new_null +/*some OpenSSL 1.0 pre and release candidate */ +# define ssh_sk_OPENSSL_STRING STACK_OF(STRING) +# define sk_OPENSSL_STRING_new_null sk_STRING_new_null +# define sk_OPENSSL_STRING_push sk_STRING_push +# define sk_OPENSSL_STRING_num sk_STRING_num +# define sk_OPENSSL_STRING_value sk_STRING_value +# define sk_OPENSSL_STRING_pop_free sk_STRING_pop_free + +static void OPENSSL_STRING_xfree(STRING p) { + xfree(p); +} + +#else /* !def sk_STRING_new_null */ + +# define ssh_sk_OPENSSL_STRING STACK +# define sk_OPENSSL_STRING_new_null sk_new_null +# define sk_OPENSSL_STRING_push sk_push +# define sk_OPENSSL_STRING_num sk_num +# define sk_OPENSSL_STRING_value sk_value +# define sk_OPENSSL_STRING_pop_free sk_pop_free + +#define OPENSSL_STRING_xfree xfree + +#endif + +#endif + +static VAOptions va = { SSHVA_NONE, NULL, NULL }; + +typedef struct va_type_map_s va_type_map; +struct va_type_map_s { + int id; + const char* code; +}; + +static va_type_map sshva_type_map[] = { + { SSHVA_NONE , "none" }, + { SSHVA_OCSP_CERT, "ocspcert" }, + { SSHVA_OCSP_SPEC, "ocspspec" }, +}; + + +int +ssh_get_default_vatype(void) { + return(SSHVA_NONE); +} + + +int +ssh_get_vatype_s(const char* type) { + int k, n; + + if (type == NULL) return(-1); + + n = sizeof(sshva_type_map) / sizeof(sshva_type_map[0]); + for (k = 0; k < n; k++) { + va_type_map *p = sshva_type_map + k; + if (strcasecmp(type, p->code) == 0) return(p->id); + } + + return(-1); +} + + +static void +ssh_set_vatype(int type) { + switch (type) { + case SSHVA_NONE: + case SSHVA_OCSP_CERT: + case SSHVA_OCSP_SPEC: + va.type = type; + break; + default: + fatal("ssh_set_vatype: invalid type %d", type); + break; + } +} + + +void +ssh_set_validator(const VAOptions *_va) { + if (va.certificate_file != NULL) { + xfree((void*)va.certificate_file); + va.certificate_file = NULL; + } + if (va.responder_url != NULL) { + xfree((void*)va.responder_url); + va.responder_url = NULL; + } + if (_va == NULL) { + debug("ssh_set_validator: NULL options - set vatype to none"); + ssh_set_vatype(SSHVA_NONE); + return; + } + + ssh_set_vatype(_va->type); /*fatal on error*/ + if (_va->certificate_file != NULL) { + switch(va.type) { + case SSHVA_NONE: + case SSHVA_OCSP_CERT: + debug("ssh_set_validator: ignore certificate file"); + break; + case SSHVA_OCSP_SPEC: + va.certificate_file = xstrdup(_va->certificate_file); /*fatal on error*/ + break; + } + } + switch(va.type) { + case SSHVA_NONE: + case SSHVA_OCSP_CERT: + debug("ssh_set_validator: ignore responder url"); + break; + case SSHVA_OCSP_SPEC: + if (_va->responder_url == NULL) { + fatal("ssh_set_validator: responder url is mandatory"); + } + va.responder_url = xstrdup(_va->responder_url); /*fatal on error*/ + break; + } +} + + +static char* +openssl_errormsg(char *buf, size_t len) { + ERR_error_string_n(ERR_get_error(), buf, len); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + return(buf); +} + + +static void +openssl_error(const char *ssh_method, const char *openssl_method) { + char buf[512]; + + ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + + error("%.128s: %.128s fail with errormsg='%.*s'" + , ssh_method + , openssl_method + , (int) sizeof(buf), buf); +} + + +static char* +ssh_ASN1_GENERALIZEDTIME_2_string(ASN1_GENERALIZEDTIME *asn1_time) { + BIO *bio; + int k; + char *p = NULL; + + if (asn1_time == NULL) { + error("ssh_ASN1_GENERALIZEDTIME_2_string: asn1_time is NULL"); + return(NULL); + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + error("ssh_ASN1_GENERALIZEDTIME_2_string: BIO_new fail"); + return(NULL); + } + + ASN1_GENERALIZEDTIME_print(bio, asn1_time); + BIO_flush(bio); + + k = BIO_pending(bio); + p = xmalloc(k + 1); /*fatal on error*/ + k = BIO_read(bio, p, k); + p[k] = '\0'; + BIO_free_all(bio); + return(p); +} + + +static STACK_OF(X509)* +ssh_load_x509certs(const char *certs_file, const char* certs_descrip) { + STACK_OF(X509) *ret_certs = NULL; + BIO *fbio = NULL; + + if (certs_file == NULL) { + error("ssh_load_x509certs: file is NULL"); + goto exit; + } + + ret_certs = sk_X509_new_null(); + if (ret_certs == NULL) { + error("ssh_load_x509certs: sk_X509_new_null fail"); + goto exit; + } + + fbio = BIO_new(BIO_s_file()); + if (fbio == NULL) { + error("ssh_load_x509certs: BIO_new fail"); + goto exit; + } + + if (BIO_read_filename(fbio, certs_file) <= 0) { + openssl_error("ssh_load_x509certs", "BIO_read_filename"); + logit("ssh_load_x509certs:" + " description/filename='%.512s'/'%.512s'" + , certs_descrip + , certs_file); + goto exit; + } + + { + int k; + STACK_OF(X509_INFO) *data; + + data = PEM_X509_INFO_read_bio(fbio, NULL, NULL, NULL); + if (data == NULL) { + error("ssh_load_x509certs: no data."); + goto exit; + } + + for (k = 0; k < sk_X509_INFO_num(data); k++) { + X509_INFO *xi = sk_X509_INFO_value(data, k); + if (xi->x509) { + sk_X509_push(ret_certs, xi->x509); + xi->x509 = NULL; + } + } + sk_X509_INFO_pop_free(data, X509_INFO_free); + } + +exit: + if (fbio != NULL) BIO_free_all(fbio); + if (ret_certs != NULL) { + debug3("ssh_load_x509certs: return %d certs", (int)sk_X509_num(ret_certs)); + } else { + debug("ssh_load_x509certs: return NULL"); + } + return(ret_certs); +} + + +static int/*bool*/ +ssh_ocspreq_addcert( + X509 *cert, + X509_STORE* x509store, + OCSP_REQUEST *req, + STACK_OF(OCSP_CERTID) *ids, + ssh_sk_OPENSSL_STRING *subjs +) { + X509 *issuer = NULL; + OCSP_CERTID *id = NULL; + char *subj = NULL; + + if (cert == NULL) { + error("ssh_ocspreq_addcert: cert is NULL"); + return(0); + } + if (x509store == NULL) { + error("ssh_ocspreq_addcert: x509store is NULL"); + return(0); + } + if (req == NULL) { + error("ssh_ocspreq_addcert: req is NULL"); + return(0); + } + if (ids == NULL) { + error("ssh_ocspreq_addcert: ids is NULL"); + return(0); + } + if (subjs == NULL) { + error("ssh_ocspreq_addcert: subjs is NULL"); + return(0); + } + + { + X509_OBJECT xobj; + memset(&xobj, 0, sizeof(xobj)); + if (ssh_x509store_lookup(x509store, X509_LU_X509, X509_get_issuer_name(cert), &xobj) > 0) { + issuer = xobj.data.x509; + } + X509_OBJECT_free_contents(&xobj); + } + if (issuer == NULL) { + error("ssh_ocspreq_addcert: cannot found issuer certificate"); + return(0); + } + + id = OCSP_cert_to_id(NULL, cert, issuer); + if (id == NULL) { + error("ssh_ocspreq_addcert: OCSP_cert_to_id fail"); + return(0); + } + + if (!OCSP_request_add0_id(req, id)) { + error("ssh_ocspreq_addcert: OCSP_request_add0_id fail"); + return(0); + } + if (!sk_OCSP_CERTID_push(ids, id)) { + error("ssh_ocspreq_addcert: sk_OCSP_CERTID_push fail"); + return(0); + } + subj = ssh_X509_NAME_oneline(X509_get_subject_name(cert)); /*fatal on error*/ + if (!sk_OPENSSL_STRING_push(subjs, subj)) { + error("ssh_ocspreq_addcert: sk_push(..., subj) fail"); + return(0); + } + + return(1); +} + + +struct ssh_ocsp_conn_s { + const char *url; + +#ifdef SSH_WITH_SSLOCSP + int use_ssl; +#endif + /*pointers inside data buffer*/ + /*const*/ char *host; + const char *port; + const char *path; + + /*data buffer to hold all connection info*/ + char *data; +}; + +typedef struct ssh_ocsp_conn_s ssh_ocsp_conn; + + +static void +ssh_ocsp_conn_free(ssh_ocsp_conn **pconn) { + ssh_ocsp_conn *conn = *pconn; + + if (conn == NULL) return; + *pconn = NULL; + + /* we don't need to clean items */ + if (conn->path != NULL) xfree((void*)conn->path); + if (conn->data != NULL) xfree(conn->data); + if (conn->url != NULL) xfree((void*)conn->url ); + xfree(conn); +} + + +static int/*bool*/ +ssh_ocsp_set_protocol(ssh_ocsp_conn *conn, const char *protocol) { + if (strcmp(protocol, "http") == 0) { +#ifdef SSH_WITH_SSLOCSP + conn->use_ssl = 0; +#endif + return(1); + } + +#ifdef SSH_WITH_SSLOCSP + if (strcmp(protocol, "https") == 0) { + conn->use_ssl = 1; + return(1); + } +#endif + +#ifdef SSH_WITH_SSLOCSP + conn->use_ssl = -1; +#endif + return(0); +} + + +static ssh_ocsp_conn* +ssh_ocsp_conn_new(const char *url) { + ssh_ocsp_conn *conn = NULL; + char *p = NULL; + char *q = NULL; + + if (url == NULL) { + error("ssh_ocsp_conn_new: url is NULL"); + return(NULL); + } + + conn = xmalloc(sizeof(*conn)); /*fatal on error*/ + memset(conn, 0, sizeof(*conn)); + + conn->url = xstrdup(url); /*fatal on error*/ + conn->data = xstrdup(url); /*fatal on error*/ + + /* chech for protocol */ + p = conn->data; + q = strchr(p, ':'); + if (q == NULL) goto error; + *q = '\x0'; + + if (!ssh_ocsp_set_protocol(conn, p)) { + error("ssh_ocsp_conn_new:" + " unsupported protocol '%.16s'" + , p); + goto error; + } + + p = q; + if (*++p != '/') { /*this symbol is inside data */ + error("ssh_ocsp_conn_new: expected first slash," + " got char with code %d" + , (int)*p); + goto error; + } + if (*++p != '/') { /*this symbol is inside data */ + error("ssh_ocsp_conn_new: expected second slash," + " got char with code %d" + , (int)*p); + goto error; + } + + /* chech for host and port */ + if (*++p == '\x0') { + error("ssh_ocsp_conn_new: missing host in url '%.512s'", url); + goto error; + } + conn->host = p; + q = strchr(p, '/'); + if (q != NULL) { + if (q[1] != '\x0') conn->path = xstrdup(q); /*fatal on error*/ + *q = '\x0'; + /* now p(conn->host) point only to host{:port} */ + } + /*else q is NULL !!!*/ + + /* chech for port */ + p = strrchr(conn->host, ':'); + if (p != NULL) { + *p = '\x0'; + if (*++p != '\x0') conn->port = p; + } + if (conn->port == NULL) { +#ifdef SSH_WITH_SSLOCSP + conn->port = conn->use_ssl ? "443" : "80"; +#else + conn->port = "80"; +#endif + } + +exit: + return(conn); +error: + ssh_ocsp_conn_free(&conn); + goto exit; +} + + +static OCSP_RESPONSE* +ssh_ocsp_get_response(const ssh_ocsp_conn *conn, OCSP_REQUEST *req) { + OCSP_RESPONSE *resp = NULL; + BIO *bio_conn = NULL; +#ifdef SSH_WITH_SSLOCSP + SSL_CTX *ctx = NULL; +#endif + + if (conn == NULL) { + error("ssh_ocsp_get_response: conn is NULL"); + return(NULL); + } + if (req == NULL) { + error("ssh_ocsp_get_response: req is NULL"); + return(NULL); + } + +#ifndef OPENSSL_NO_SOCK + bio_conn = BIO_new_connect(conn->host); + if (bio_conn == NULL) { + openssl_error("ssh_ocsp_get_response", "BIO_new_connect"); + goto exit; + } +#else + error("ssh_ocsp_get_response: sockets are not supported in OpenSSL"); + goto exit; +#endif + if (conn->port != NULL) { + BIO_set_conn_port(bio_conn, conn->port); + } + +#ifdef SSH_WITH_SSLOCSP + if (conn->use_ssl == 1) { + BIO *bio_sslconn; +#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) + ctx = SSL_CTX_new(SSLv23_client_method()); +#elif !defined(OPENSSL_NO_SSL3) + ctx = SSL_CTX_new(SSLv3_client_method()); +#elif !defined(OPENSSL_NO_SSL2) + ctx = SSL_CTX_new(SSLv2_client_method()); +#else + error("ssh_ocsp_get_response: SSL is disabled"); + goto exit; +#endif + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + bio_sslconn = BIO_new_ssl(ctx, 1); + bio_conn = BIO_push(bio_sslconn, bio_conn); + } +#endif /*def SSH_WITH_SSLOCSP*/ + + if (BIO_do_connect(bio_conn) <= 0) { + openssl_error("ssh_ocsp_get_response", "BIO_do_connect"); + goto exit; + } + + /* + * OCSP_sendreq_bio accept null as path argument but if path + * is null http request will contain what is incorrect. + */ + resp = OCSP_sendreq_bio(bio_conn, (char*)(conn->path ? conn->path : "/") , req); + if (resp == NULL) { + openssl_error("ssh_ocsp_get_response", "OCSP_sendreq_bio"); + } + +exit: + if (bio_conn != NULL) BIO_free_all(bio_conn); +#ifdef SSH_WITH_SSLOCSP + if (ctx != NULL) SSL_CTX_free(ctx); +#endif + + return(resp); +} + + +static OCSP_BASICRESP* +ssh_ocsp_get_basicresp( + OCSP_REQUEST *req, + OCSP_RESPONSE *resp, + STACK_OF(X509) *vacrts, + X509_STORE *x509store +) { + OCSP_BASICRESP *br = NULL; + unsigned long basic_verify_flags = 0/*NO:OCSP_NOEXPLICIT*/; + int flag; + + if (req == NULL) { + error("ssh_ocsp_get_basicresp: req is NULL"); + return(NULL); + } + if (resp == NULL) { + error("ssh_ocsp_get_basicresp: resp is NULL"); + return(NULL); + } + if (x509store == NULL) { + error("ssh_ocsp_get_basicresp: x509store is NULL"); + return(NULL); + } + + br = OCSP_response_get1_basic(resp); + if (br == NULL) { + openssl_error("ssh_ocsp_get_basicresp", "OCSP_response_get1_basic"); + return(NULL); + } + + flag = OCSP_check_nonce(req, br); + if (flag <= 0) { + if (flag == -1) { + logit("ssh_ocsp_get_basicresp: WARNING - no nonce in response"); + } else { + openssl_error("ssh_ocsp_get_basicresp", "OCSP_check_nonce"); + goto error; + } + } + +#ifdef SSHOCSPTEST +{ +int k; +logit("ssh_ocsp_get_basicresp: VA certs num=%d", sk_X509_num(vacrts)); +for (k = 0; k < sk_X509_num(vacrts); k++) { + char *buf; + X509 *x = sk_X509_value(vacrts, k); + buf = ssh_X509_NAME_oneline(X509_get_subject_name(x)); /*fatal on error*/ + logit("ssh_ocsp_get_basicresp: VA[%d] subject='%s'", k, buf); + xfree(buf); +} +} +#endif /*def SSHOCSPTEST*/ + +/* + * RFC2560: + * ... + * All definitive response messages SHALL be digitally signed. The key + * used to sign the response MUST belong to one of the following: + * + * -- the CA who issued the certificate in question + * -- a Trusted Responder whose public key is trusted by the requester + * -- a CA Designated Responder (Authorized Responder) who holds a + * specially marked certificate issued directly by the CA, indicating + * that the responder may issue OCSP responses for that CA + * ... + * + * TODO: to check OpenSLL implementation + */ + if ((vacrts == NULL) || (sk_X509_num(vacrts) <= 0)) { + flag = -1; + } else { + /* + * With flag OCSP_TRUSTOTHER: + * - we never get error 'without missing ocspsigning + * usage' for VA certificate !!! + * Without flag OCSP_TRUSTOTHER: + * - we can get OCSP_basic_verify error "root ca not trusted" + */ +#if 0 + flag = OCSP_basic_verify(br, vacrts, x509store, basic_verify_flags | OCSP_TRUSTOTHER); +#else + flag = OCSP_basic_verify(br, vacrts, x509store, basic_verify_flags); +#endif + } + if (flag < 0) { + flag = OCSP_basic_verify(br, NULL, x509store, basic_verify_flags); + } + if (flag <= 0) { + openssl_error("ssh_ocsp_get_basicresp", "OCSP_basic_verify"); + logit("ssh_ocsp_get_basicresp: flag=%d", flag); + goto error; + } + + debug3("ssh_ocsp_get_basicresp: OK"); + return(br); + +error: + debug3("ssh_ocsp_get_basicresp: FAIL"); + if (br != NULL) OCSP_BASICRESP_free(br); + return(NULL); +} + + +/* + * Method return value: + * 1 - all cert.-s are good + * -1 - error or at least one cert. with status unknow + * 0 - otherwise, i.e. at least one cert. is revoked and rest are good + */ +static int +ssh_ocsp_check_validity( + OCSP_REQUEST *req, + OCSP_BASICRESP *br, + STACK_OF(OCSP_CERTID) *ids, + ssh_sk_OPENSSL_STRING *subjs +) { + int ret = 1; + /* Maximum leeway in validity period: default 5 minutes */ + const long nsec = (5 * 60); + const long maxage = -1; + + int k; + int status, reason; + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + + if (req == NULL) { + error("ssh_ocsp_check_validity: req is NULL"); + return(-1); + } + if (br == NULL) { + error("ssh_ocsp_check_validity: br is NULL"); + return(-1); + } + if (sk_OCSP_CERTID_num(ids) <= 0) { + error("ssh_ocsp_check_validity:" + " number of ids is %d" + , sk_OCSP_CERTID_num(ids)); + return(-1); + } + if (sk_OPENSSL_STRING_num(subjs) <= 0) { + error("ssh_ocsp_check_validity:" + " number of subjs is %d" + , sk_OPENSSL_STRING_num(subjs)); + return(-1); + } + if (sk_OCSP_CERTID_num(ids) != sk_OPENSSL_STRING_num(subjs)) { + error("ssh_ocsp_check_validity:" + " ids(%d) != subjs(%d)" + , sk_OCSP_CERTID_num(ids) + , sk_OPENSSL_STRING_num(subjs)); + return(-1); + } + + for (k = 0; k < sk_OCSP_CERTID_num(ids); k++) { + OCSP_CERTID *id = sk_OCSP_CERTID_value(ids, k); + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *subject = sk_OPENSSL_STRING_value(subjs, k); + debug3("ssh_ocsp_check_validity: cert[%d]='%s'", k, subject); + } + + if (!OCSP_resp_find_status( + br, id, &status, &reason, + &rev, &thisupd, &nextupd) + ) { + ret = -1; + error("ssh_ocsp_check_validity: cannot found status"); + break; + } + + if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) { + char ebuf[512]; + ret = -1; + logit("ssh_ocsp_check_validity: " + " WARNING-invalid status time." + " OCSP_check_validity fail with errormsg='%.512s'" + , openssl_errormsg(ebuf, sizeof(ebuf))); + break; + } + debug("ssh_ocsp_check_validity: status=%.32s", OCSP_cert_status_str(status)); + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *p = ssh_ASN1_GENERALIZEDTIME_2_string(thisupd); + debug3("ssh_ocsp_check_validity: This Update=%.128s", p); + xfree(p); + if (nextupd != NULL) { + p = ssh_ASN1_GENERALIZEDTIME_2_string(nextupd); + debug3("ssh_ocsp_check_validity: Next Update=%.128s", p); + xfree(p); + } + } + + if (status == V_OCSP_CERTSTATUS_GOOD) continue; + + if (status != V_OCSP_CERTSTATUS_REVOKED) { + ret = -1; + error("ssh_ocsp_check_validity: unknow certificate status"); + break; + } + + ret = 0; + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *p = ssh_ASN1_GENERALIZEDTIME_2_string(rev); + debug3("ssh_ocsp_check_validity: Revocation Time=%.128s", p); + xfree(p); + if (reason != -1) { + debug3("ssh_ocsp_check_validity:" + " Revocation Reason='%.128s'" + , OCSP_crl_reason_str(reason)); + } + } + break; + } + debug3("ssh_ocsp_check_validity: return %d", ret); + return(ret); +} + + +static int +ssh_ocsp_validate2( + X509 *cert, + X509_STORE *x509store, + const ssh_ocsp_conn *ocsp +) { + int ret = -1; + int add_nonce = 0; + + STACK_OF(X509) *vacrts = NULL; + OCSP_REQUEST *req = OCSP_REQUEST_new(); + STACK_OF(OCSP_CERTID) *ids = sk_OCSP_CERTID_new_null(); + ssh_sk_OPENSSL_STRING *subjs = sk_OPENSSL_STRING_new_null(); + OCSP_RESPONSE *resp = NULL; + OCSP_BASICRESP *br = NULL; + + if ((va.type == SSHVA_OCSP_SPEC) && + (va.certificate_file != NULL)) { + vacrts = ssh_load_x509certs(va.certificate_file, "'OCSP Responder' trusted certificates"); + if (vacrts == NULL) goto exit; + debug("ssh_ocsp_validate2: VA certs num=%d", sk_X509_num(vacrts)); + } + + if (!ssh_ocspreq_addcert(cert, x509store, req, ids, subjs)) { + goto exit; + } + + if (req && add_nonce) { + OCSP_request_add1_nonce(req, NULL, -1); + } + + resp = ssh_ocsp_get_response(ocsp, req); + if (resp == NULL) goto exit; + + { /*check OCSP response status*/ + int flag = OCSP_response_status(resp); + if (flag != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + error("ssh_ocsp_validate2:" + " responder error=%d(%.256s)" + , flag + , OCSP_response_status_str((long/*???*/)flag)); + goto exit; + } + } + + br = ssh_ocsp_get_basicresp(req, resp, vacrts, x509store); + if (br == NULL) goto exit; + + ret = ssh_ocsp_check_validity(req, br, ids, subjs); + +exit: + if (br != NULL) OCSP_BASICRESP_free(br); + if (resp != NULL) OCSP_RESPONSE_free(resp); + if (subjs != NULL) sk_OPENSSL_STRING_pop_free(subjs, OPENSSL_STRING_xfree); + if (ids != NULL) sk_OCSP_CERTID_free(ids); + if (req != NULL) OCSP_REQUEST_free(req); + if (vacrts != NULL) sk_X509_pop_free(vacrts, X509_free); + + return(ret); +} + + +static AUTHORITY_INFO_ACCESS* +ssh_aia_get(X509_EXTENSION *ext) { + X509V3_EXT_METHOD *method = NULL; + void *ext_str = NULL; + const unsigned char *p; + int len; + + if (ext == NULL) { + error("ssh_aia_get: ext is NULL"); + return(NULL); + } + + method = (X509V3_EXT_METHOD*) X509V3_EXT_get(ext); + if (method == NULL) { + debug("ssh_aia_get: cannot get method"); + return(NULL); + } + + p = ext->value->data; + len = ext->value->length; + if (method->it) { + ext_str = ASN1_item_d2i(NULL, &p, len, ASN1_ITEM_ptr(method->it)); + } else { + ext_str = method->d2i(NULL, &p, len); + } + if (ext_str == NULL) { + debug("ssh_aia_get: null ext_str!"); + return(NULL); + } + + return((AUTHORITY_INFO_ACCESS*)ext_str); +} + + +static void +ssh_aia_free(X509_EXTENSION *ext, AUTHORITY_INFO_ACCESS* aia) { + X509V3_EXT_METHOD *method = NULL; + + if (ext == NULL) { + error("ssh_aia_free: ext is NULL"); + return; + } + + method = (X509V3_EXT_METHOD*) X509V3_EXT_get(ext); + if (method == NULL) return; + + if (method->it) { + ASN1_item_free((void*)aia, ASN1_ITEM_ptr(method->it)); + } else { + method->ext_free(aia); + } +} + + +static int +ssh_aiaocsp_validate( + X509 *cert, + X509_STORE *x509store, + AUTHORITY_INFO_ACCESS *aia, + int *has_ocsp_url +) { + int ret = -1; + int k; + if (has_ocsp_url == NULL) { + fatal("ssh_aiaocsp_validate: has_ocsp_url is NULL"); + return(-1); /*;-)*/ + } + + *has_ocsp_url = 0; + for (k = 0; k < sk_ACCESS_DESCRIPTION_num(aia); k++) { + ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(aia, k); + GENERAL_NAME *gn; + ASN1_IA5STRING *uri; + ssh_ocsp_conn *conn; + + if (OBJ_obj2nid(ad->method) != NID_ad_OCSP) continue; + + gn = ad->location; +#if 0 +{ +BIO *bio = BIO_new_fp(stderr, BIO_NOCLOSE); +if (bio != NULL) { + BIO_puts(bio, "gn->type:"); + switch (gn->type) { + case GEN_OTHERNAME : BIO_puts(bio, "GEN_OTHERNAME"); break; + case GEN_EMAIL : BIO_puts(bio, "GEN_EMAIL" ); break; + case GEN_DNS : BIO_puts(bio, "GEN_DNS" ); break; + case GEN_X400 : BIO_puts(bio, "GEN_X400" ); break; + case GEN_DIRNAME : BIO_puts(bio, "GEN_DIRNAME" ); break; + case GEN_EDIPARTY : BIO_puts(bio, "GEN_EDIPARTY" ); break; + case GEN_URI : BIO_puts(bio, "GEN_URI" ); break; + case GEN_IPADD : BIO_puts(bio, "GEN_IPADD" ); break; + case GEN_RID : BIO_puts(bio, "GEN_RID" ); break; + default : BIO_puts(bio, "[unsupported]"); break; + } + BIO_puts(bio, "\n"); + BIO_free(bio); +} +} +#endif + if (gn->type != GEN_URI) continue; + + uri = gn->d.uniformResourceIdentifier; + *has_ocsp_url = 1; + + conn = ssh_ocsp_conn_new((const char*)uri->data); + if (conn == NULL) { + debug("ssh_aiaocsp_validate: cannot create ocsp connection"); + continue; + } + ret = ssh_ocsp_validate2(cert, x509store, conn); + ssh_ocsp_conn_free(&conn); + + if (ret >= 0) break; + } + + return(*has_ocsp_url ? ret : 1); +} + + +static int +ssh_ocsp_validate4cert(X509 *cert, X509_STORE *x509store) { + int found = 0; + int ret = -1; + int loc = -1; + + if (cert == NULL) return(0); + + for ( loc = X509_get_ext_by_NID(cert, NID_info_access, loc); + loc >= 0; + loc = X509_get_ext_by_NID(cert, NID_info_access, loc) + ) { + X509_EXTENSION *xe; + + xe = X509_get_ext(cert, loc); + if (xe == NULL) { + debug("ssh_ocsp_validate4cert: cannot get x509 extension"); + continue; + } + + {/*validate from AIA*/ + AUTHORITY_INFO_ACCESS *aia = ssh_aia_get(xe); + if (aia == NULL) continue; + + ret = ssh_aiaocsp_validate(cert, x509store, aia, &found); + + ssh_aia_free(xe, aia); + } + + if (ret >= 0) break; + } + + if (found) { + debug3("ssh_ocsp_validate4cert: validation result=%d", ret); + } else { + debug3("ssh_ocsp_validate4cert: no OCSP 'Service Locator' URL"); + } + return(found ? ret : 1); +} + + +int +ssh_ocsp_validate(X509 *cert, X509_STORE *x509store) { + int ret = -1; + ssh_ocsp_conn *conn = NULL; + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *buf = ssh_X509_NAME_oneline(X509_get_subject_name(cert)); /*fatal on error*/ + debug3("ssh_ocsp_validate: for '%s'", buf); + xfree(buf); + } + + switch (va.type) { + default: + /*when something is missing*/ + fatal("ssh_ocsp_validate: invalid validator type %d", va.type); + break; /*;-)*/ + case SSHVA_NONE: + debug3("ssh_ocsp_validate: none"); + ret = 1; + break; + case SSHVA_OCSP_CERT: + ret = ssh_ocsp_validate4cert(cert, x509store); + break; + case SSHVA_OCSP_SPEC: + conn = ssh_ocsp_conn_new(va.responder_url); + if (conn != NULL) { + ret = ssh_ocsp_validate2(cert, x509store, conn); + ssh_ocsp_conn_free(&conn); + } + break; + } + + return(ret); +} diff -ruN openssh-5.6p1/ssh-pkcs11-helper.0 openssh-5.6p1+x509-6.2.3/ssh-pkcs11-helper.0 --- openssh-5.6p1/ssh-pkcs11-helper.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-pkcs11-helper.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSH-PKCS11-HELPER(8) OpenBSD System Manager's Manual SSH-PKCS11-HELPER(8) +SSH-PKCS11-HELPER(8) BSD System Manager's Manual SSH-PKCS11-HELPER(8) NAME - ssh-pkcs11-helper - ssh-agent helper program for PKCS#11 support + ssh-pkcs11-helper -- ssh-agent helper program for PKCS#11 support SYNOPSIS ssh-pkcs11-helper @@ -22,4 +22,4 @@ AUTHORS Markus Friedl -OpenBSD 4.8 February 10, 2010 OpenBSD 4.8 +BSD August 23, 2010 BSD diff -ruN openssh-5.6p1/ssh-pkcs11-helper.c openssh-5.6p1+x509-6.2.3/ssh-pkcs11-helper.c --- openssh-5.6p1/ssh-pkcs11-helper.c 2010-03-13 23:37:49.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-pkcs11-helper.c 2010-08-24 09:06:01.000000000 +0300 @@ -365,6 +365,8 @@ { extern char *__progname; + init_rng(); + seed_rng(); __progname = ssh_get_progname(argv[0]); log_init(__progname, SYSLOG_LEVEL_ERROR, SYSLOG_FACILITY_AUTH, 0); fatal("PKCS#11 support disabled at compile time"); diff -ruN openssh-5.6p1/ssh-rand-helper.0 openssh-5.6p1+x509-6.2.3/ssh-rand-helper.0 --- openssh-5.6p1/ssh-rand-helper.0 2010-08-23 06:24:16.000000000 +0300 +++ openssh-5.6p1+x509-6.2.3/ssh-rand-helper.0 2010-08-24 09:06:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSH-RAND-HELPER(8) OpenBSD System Manager's Manual SSH-RAND-HELPER(8) +SSH-RAND-HELPER(8) BSD System Manager's Manual SSH-RAND-HELPER(8) NAME - ssh-rand-helper - random number gatherer for OpenSSH + ssh-rand-helper -- random number gatherer for OpenSSH SYNOPSIS ssh-rand-hlper [-vxXh] [-b bytes] @@ -27,8 +27,8 @@ random numbers from a EGD/PRNGd server via a unix domain or localhost tcp socket. - This program is not intended to be run by the end-user, so the few - commandline options are for debugging purposes only. + This program is not intended to be run by the end-user, so the few com- + mandline options are for debugging purposes only. -b bytes Specify the number of random bytes to include in the output. @@ -48,4 +48,4 @@ SEE ALSO ssh(1), ssh-add(1), ssh-keygen(1), sshd(8) -OpenBSD 4.8 April 14, 2002 OpenBSD 4.8 +BSD April 14, 2002 BSD diff -ruN openssh-5.6p1/ssh-x509.c openssh-5.6p1+x509-6.2.3/ssh-x509.c --- openssh-5.6p1/ssh-x509.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-x509.c 2010-02-27 17:44:37.000000000 +0200 @@ -0,0 +1,1182 @@ +/* + * Copyright (c) 2002-2007 Roumen Petrov. 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 "ssh-x509.h" +#include +#include + +#include "ssh-xkalg.h" +#include "log.h" +#include +#include "xmalloc.h" +#include "uuencode.h" +#include +#include "x509store.h" +#include "compat.h" + +#ifndef ISSPACE +# define ISSPACE(ch) (isspace((int)(unsigned char)(ch))) +#endif + +int (*pssh_x509cert_check)(X509 *_cert) = NULL; + + +static char* +openssl_errormsg(char *buf, size_t len) { + ERR_error_string_n(ERR_get_error(), buf, len); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + return(buf); +} + + +static inline int +ssh_EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type) { +#ifdef OPENSSL_EVP_DIGESTUPDATE_VOID + /* OpenSSL < 0.9.7 */ + EVP_VerifyInit(ctx, type); + return(1); +#else + return(EVP_VerifyInit(ctx, type)); +#endif +} + + +static inline int +ssh_EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt) { +#ifdef OPENSSL_EVP_DIGESTUPDATE_VOID + /* OpenSSL < 0.9.7 */ + EVP_VerifyUpdate(ctx, d, cnt); + return(1); +#else + return(EVP_VerifyUpdate(ctx, d, cnt)); +#endif +} + + +int +ssh_X509_NAME_print(BIO* bio, X509_NAME *xn) { + static u_long print_flags = ((XN_FLAG_ONELINE & \ + ~XN_FLAG_SPC_EQ & \ + ~XN_FLAG_SEP_MASK) | \ + XN_FLAG_SEP_COMMA_PLUS); + + if (xn == NULL) return(-1); + + X509_NAME_print_ex(bio, xn, 0, print_flags); + BIO_flush(bio); + + return(BIO_pending(bio)); +} + + +char* +ssh_X509_NAME_oneline(X509_NAME *xn) { + char *buf = NULL; + int size; + BIO* mbio = NULL; + + if (xn == NULL) return(NULL); + + mbio = BIO_new(BIO_s_mem()); + if (mbio == NULL) return(buf); + + size = ssh_X509_NAME_print(mbio, xn); + if (size <= 0) { + error("ssh_X509_NAME_oneline: no data in buffer"); + goto done; + } + + buf = xmalloc(size + 1); /*fatal on error*/ + + /* we should request one byte more !?!? */ + if (size != BIO_gets(mbio, buf, size + 1)) { + error("ssh_X509_NAME_oneline: cannot get data from buffer"); + goto done; + } + buf[size] = '\0'; + +done: + /* This call will walk the chain freeing all the BIOs */ + BIO_free_all(mbio); + + return(buf); +} + + +#ifndef SSH_X509STORE_DISABLED +static const char* +x509key_find_subject(const char* s) { + static const char *keywords[] = { + "subject", + "distinguished name", + "distinguished-name", + "distinguished_name", + "distinguishedname", + "dn", + NULL + }; + const char **q, *p; + size_t len; + + if (s == NULL) { + error("x509key_find_subject: no input data"); + return(NULL); + } + for (; *s && ISSPACE(*s); s++) + {/*skip space*/} + + for (q=keywords; *q; q++) { + len = strlen(*q); + if (strncasecmp(s, *q, len) != 0) continue; + + for (p = s + len; *p && ISSPACE(*p); p++) + {/*skip space*/} + if (!*p) { + error("x509key_find_subject: no data after keyword"); + return(NULL); + } + if (*p == ':' || *p == '=') { + for (p++; *p && ISSPACE(*p); p++) + {/*skip space*/} + if (!*p) { + error("x509key_find_subject: no data after separator"); + return(NULL); + } + } + if (*p == '/' || *p == ',') { + /*skip leading [Relative]DistinguishedName elements separator*/ + for (p++; *p && ISSPACE(*p); p++) + {/*skip space*/} + if (!*p) { + error("x509key_find_subject: no data"); + return(NULL); + } + } + return(p); + } + return(NULL); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +#ifndef SSH_X509STORE_DISABLED +static unsigned long +ssh_hctol(u_char ch) { +/* '0'-'9' = 0x30 - 0x39 (ascii) */ +/* 'A'-'F' = 0x41 - 0x46 (ascii) */ +/* 'a'-'f' = 0x61 - 0x66 (ascii) */ +/* should work for EBCDIC */ + if (('0' <= ch) && (ch <= '9')) { + return((long)(ch - '0')); + } + if (('A' <= ch) && (ch <= 'F')) { + return((long)(ch - ('A' - 10))); + } + if (('a' <= ch) && (ch <= 'f')) { + return((long)(ch - ('a' - 10))); + } + + return(-1); +} + + +static unsigned long +ssh_hatol(const u_char *str, size_t maxsize) { + int k; + long v, ret = 0; + + for(k = maxsize; k > 0; k--, str++) { + v = ssh_hctol(*str); + if (v < 0) return(-1); + ret = (ret << 4) + v; + } + return(ret); +} + + +static int +get_escsymbol(const u_char* str, size_t len, u_long *value) { + const char ch = *str; + long v; + + if (len < 1) { + error("get_escsymbol:" + " missing characters in escape sequence"); + return(-1); + } + + /*escape formats: + "{\\}\\W%08lX" + "{\\}\\U%04lX" + "{\\}\\%02X" + "{\\}\\x%02X" - X509_NAME_oneline format + */ + if (ch == '\\') { + if (value) *value = ch; + return(1); + } + if (ch == 'W') { + if (len < 9) { + error("get_escsymbol:" + " to short 32-bit escape sequence"); + return(-1); + } + v = ssh_hatol(++str, 8); + if (v < 0) { + error("get_escsymbol:" + " invalid character in 32-bit hex sequence"); + return(-1); + } + if (value) *value = v; + return(9); + } + if (ch == 'U') { + if (len < 5) { + error("get_escsymbol:" + " to short 16-bit escape sequence"); + return(-1); + } + v = ssh_hatol(++str, 4); + if (v < 0) { + error("get_escsymbol:" + " invalid character in 16-bit hex sequence"); + return(-1); + } + if (value) *value = v; + return(5); + } +#if 0 +/* +The code bellow isn't correct. Let 'O' is not 8-bit string(as example +BMPString) then "X509_NAME_oneline" will output "\x00O"(!). +The X509_NAME_oneline output format will left unsupported, i.e.: +Unsupported: +$ openssl x509 -in cert_file -subject -noout +Supported: + v0.9.7+ +$ openssl x509 -in cert_file -subject -noout -nameopt oneline[,] + v0.9.6 +$ openssl x509 -in cert_file -subject -noout -nameopt oneline [-nameopt ] +*/ + if ((ch == 'x') || (ch == 'X')) { + if (len < 3) { + error("get_escsymbol:" + " to short 8-bit hex sequence"); + return(-1); + } + v = ssh_hatol(++str, 2); + if (v < 0) { + error("get_escsymbol:" + " invalid character in 8-bit hex sequence"); + return(-1); + } + if (value) *value = v; + return(3); + } +#endif + v = ssh_hctol(*str); + if (v < 0) { + /*a character is escaped ?*/ + if (*str > 127) { /*ASCII comparision !*/ + /* there is no reason symbol above 127 + to be escaped in this way */ + error("get_escsymbol:" + " non-ascii character in escape sequence"); + return(-1); + } + if (value) *value = *str; + return(1); + } + + /*two hex numbers*/ + { + long vlo; + if (len < 2) { + error("get_escsymbol:" + " to short 8-bit escape sequence"); + return(-1); + } + vlo = ssh_hctol(*++str); + if (vlo < 0) { + error("get_escsymbol:" + " invalid character in 8-bit hex sequence"); + return(-1); + } + v = (v << 4) + vlo; + } + if (value) *value = v; + return(2); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +#ifndef SSH_X509STORE_DISABLED +static int/*bool*/ +ssh_X509_NAME_add_entry_by_NID(X509_NAME* name, int nid, const u_char* str, size_t len) { +/* default maxsizes: + C: 2 + L, ST: 128 + O, OU, CN: 64 + emailAddress: 128 +*/ + u_char buf[129*6+1]; /*enough for 128 UTF-8 symbols*/ + int ret = 0; + int type = MBSTRING_ASC; + u_long ch; + u_char *p; + const u_char *q; + size_t k; + + /*this is internal method and we don't check validity of some arguments*/ + + p = buf; + q = str; + k = sizeof(buf); + + while ((len > 0) && (k > 0)) { + int ch_utf8 = 1; + if (*q == '\0') { + error("ssh_X509_NAME_add_entry_by_NID:" + " unsupported zero(NIL) symbol in name"); + return(0); + } + if (*q == '\\') { + len--; + if (len <= 0) { + error("ssh_X509_NAME_add_entry_by_NID:" + " escape sequence without data"); + return(0); + } + + ret = get_escsymbol(++q, len, &ch); + if (ret < 0) return(0); + if (ret == 2) { + /*escaped two hex numbers*/ + ch_utf8 = 0; + } + } else { + ret = UTF8_getc(q, len, &ch); + if(ret < 0) { + error("ssh_X509_NAME_add_entry_by_NID:" + " cannot get next symbol(%.32s)" + , q); + return(0); + } + } + len -= ret; + q += ret; + + if (ch_utf8) { + /* UTF8_putc return negative if buffer is too short */ + ret = UTF8_putc(p, k, ch); + if (ret < 0) { + error("ssh_X509_NAME_add_entry_by_NID:" + " UTF8_putc fail for symbol %ld", ch); + return(0); + } + } else { + *p = (u_char)ch; + ret = 1; + } + k -= ret; + p += ret; + } + if (len > 0) { + error("ssh_X509_NAME_add_entry_by_NID:" + " too long data"); + return(0); + } + *p = '\0'; + + for (p = buf; *p; p++) { + if (*p > 127) { + type = MBSTRING_UTF8; + break; + } + } + k = strlen((char*)buf); + + debug3("ssh_X509_NAME_add_entry_by_NID:" + " type=%s, k=%d" + , ((type == MBSTRING_ASC) ? "ASCII" : "UTF-8") + , k + ); + + /* this method will fail if string exceed max size limit for nid */ + ret = X509_NAME_add_entry_by_NID(name, nid, type, buf, (int)k, -1, 0); + if (!ret) { + char ebuf[256]; + error("ssh_X509_NAME_add_entry_by_NID: X509_NAME_add_entry_by_NID" + " fail with errormsg='%.*s'" + " for nid=%d/%.32s" + " and data='%.512s'" + , sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf)) + , nid, OBJ_nid2ln(nid) + , str); + } + return(ret); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +#ifndef SSH_X509STORE_DISABLED +static int/*bool*/ +x509key_str2X509NAME(const char* _str, X509_NAME *_name) { + int ret = 1; + char *str = NULL; + char *p, *q, *token; + int has_more = 0; + + str = xmalloc(strlen(_str) + 1); /*fatal on error*/ + strcpy(str, _str); + + p = (char*)str; + while (*p) { + int nid; + for (; *p && ISSPACE(*p); p++) + {/*skip space*/} + if (!*p) break; + + /* get shortest token */ + { + char *tokenA = strchr(p, ','); + char *tokenB = strchr(p, '/'); + + if (tokenA == NULL) { + token = tokenB; + } else if (tokenB == NULL) { + token = tokenA; + } else { + token = (tokenA < tokenB) ? tokenA : tokenB; + } + } + if (token) { + has_more = 1; + *token = 0; + } else { + has_more = 0; + token = p + strlen(p); + } + q = strchr(p, '='); + if (!q) { + error("x509key_str2X509NAME: cannot parse '%.200s' ...", p); + ret = 0; + break; + } + { + char *s = q; + for(--s; ISSPACE(*s) && (s > p); s--) + {/*skip trailing space*/} + *++s = 0; + } + nid = OBJ_txt2nid(p); +#ifdef SSH_OPENSSL_DN_WITHOUT_EMAIL + if (nid == NID_undef) { + /* work around for OpenSSL 0.9.7+ */ + if (strcasecmp(p, "Email") == 0) { + nid = OBJ_txt2nid("emailAddress"); + } + } +#endif /* def SSH_OPENSSL_DN_WITHOUT_EMAIL */ + if (nid == NID_undef) { + error("x509key_str2X509NAME: cannot get nid from string '%.200s'", p); + ret = 0; + break; + } + + p = q + 1; + if (!*p) { + error("x509key_str2X509NAME: no data"); + ret = 0; + break; + } + + for (; *p && ISSPACE(*p); p++) + {/*skip space*/} + for (q = token - 1; (q >= p) && ISSPACE(*q); q--) + {/*skip unexpected \n, etc. from end*/} + *++q = 0; + + ret = ssh_X509_NAME_add_entry_by_NID(_name, nid, (u_char*)p, (size_t)(q - p)); + if (!ret) { + break; + } + + p = token; + if (has_more) p++; + } + + if (str) xfree(str); + debug3("x509key_str2X509NAME: return %d", ret); + return(ret); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +#ifndef SSH_X509STORE_DISABLED +Key* +x509key_from_subject(int _keytype, const char* _cp) { + int ret = 1; + Key* key = NULL; + X509_NAME *subj; + const char *subject; + + if (_keytype != KEY_X509_RSA && + _keytype != KEY_X509_DSA) { + debug3("x509key_from_subject: %d is not x509 key", _keytype); + return(NULL); + } + debug3("x509key_from_subject(%d, [%.1024s]) called", + _keytype, (_cp ? _cp : "")); + subject = x509key_find_subject(_cp); + if (subject == NULL) + return(NULL); + + debug3("x509key_from_subject: subject=[%.1024s]", subject); + key = key_new(_keytype); + if (key == NULL) { + error("x509key_from_subject: out of memory"); + return(NULL); + } + + if (ret > 0) { + subj = X509_get_subject_name(key->x509); + if (subj == NULL) { + error("x509key_from_subject: new x509 key without subject"); + ret = 0; + } + } + + if (ret > 0) { + ret = x509key_str2X509NAME(subject, subj); + } + + if (ret <= 0) { + if (key != NULL) { + key_free(key); + key = NULL; + } + } + debug3("x509key_from_subject: return %p", (void*)key); + return(key); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +static Key* +x509_to_key(X509 *x509) { + Key *key = NULL; + EVP_PKEY *env_pkey; + + env_pkey = X509_get_pubkey(x509); + if (env_pkey == NULL) { + char ebuf[256]; + error("x509_to_key: X509_get_pubkey fail %.*s", + sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); + return(NULL); + } + /*else*/ + debug3("x509_to_key: X509_get_pubkey done!"); + + switch (env_pkey->type) { + case EVP_PKEY_RSA: + key = key_new(KEY_UNSPEC); + key->x509 = x509; + key->rsa = EVP_PKEY_get1_RSA(env_pkey); + key->type = KEY_X509_RSA; +#ifdef DEBUG_PK + RSA_print_fp(stderr, key->rsa, 8); +#endif + break; + + case EVP_PKEY_DSA: + key = key_new(KEY_UNSPEC); + key->x509 = x509; + key->dsa = EVP_PKEY_get1_DSA(env_pkey); + key->type = KEY_X509_DSA; +#ifdef DEBUG_PK + DSA_print_fp(stderr, key->dsa, 8); +#endif + break; + + default: + fatal("ssh_x509_key_size: unknow env_pkey->type %d", env_pkey->type); + /*unreachable code*/ + } + + return(key); +} + + +Key* +x509key_from_blob(const u_char *blob, int blen) { + Key* key = NULL; + BIO *mbio; + + /* convert blob data to BIO certificate data */ + mbio = BIO_new(BIO_s_mem()); + if (mbio == NULL) return(NULL); + BIO_write(mbio, blob, blen); + BIO_flush(mbio); + + debug3("x509key_from_blob: We have %d bytes available in BIO", BIO_pending(mbio)); + + { /* read X509 certificate from BIO data */ + X509* x509 = NULL; + x509 = d2i_X509_bio(mbio, NULL); + if (x509 == NULL) { + /* We will print only debug info !!! + * This method is used in place where we can only check incomming data. + * If data contain x506 certificate blob we will return a key otherwise NULL. + */ + char ebuf[256]; + debug3("x509key_from_blob: read X509 from BIO fail %.*s", + sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); + } else { + key = x509_to_key(x509); + if (key == NULL) + X509_free(x509); + } + } + + /* This call will walk the chain freeing all the BIOs */ + BIO_free_all(mbio); + return(key); +} + + +static int +x509key_check(const char* method, const Key *key) { + if (key == NULL) + { error("%.50s: no key", method); return(0); } + + if (key->type != KEY_X509_RSA && + key->type != KEY_X509_DSA ) + { error("%.50s: cannot handle key type %d", method, key->type); return(0); } + + if (key->x509 == NULL) + { error("%.50s: no X509 key", method); return(0); } + + return(1); +} + + +int +x509key_to_blob(const Key *key, Buffer *b) { + int len; + void *str; + u_char *p; + + if (!x509key_check("x509key_to_blob", key)) return(0); + + len = i2d_X509(key->x509, NULL); + str = xmalloc(len); /*fatal on error*/ + p = str; + i2d_X509(key->x509, &p); + buffer_append(b, str, len); + xfree(str); + return(1); +} + + +char* +x509key_subject(const Key *key) { + X509_NAME *dn; + + if (!x509key_check("x509key_subject", key)) return(NULL); + + /* it is better to match format used in x509key_write_subject */ + dn = X509_get_subject_name(key->x509); + return(ssh_X509_NAME_oneline(dn)); /*fatal on error*/ +} + + +int +x509key_write(const Key *key, FILE *f) { + int ret = 0; + Buffer b; + size_t n; + + if (!x509key_check("x509key_write_blob", key)) return(ret); + + buffer_init(&b); + ret = x509key_to_blob(key, &b); + if (ret) { + /* write ssh key name */ + const char *ktype = key_ssh_name(key); + n = strlen(ktype); + ret = ( fwrite(ktype, 1, n, f) == n ) && + ( fwrite(" ", 1, 1, f) == 1 ); + } + if (ret) { + char uu[1<<12]; /* 4096 bytes */ + + n = uuencode(buffer_ptr(&b), buffer_len(&b), uu, sizeof(uu)); + ret = n > 0; + if (ret) { + ret = (fwrite(uu, 1, n, f) == n); + } + } + buffer_free(&b); + return(ret); +} + + +#ifndef SSH_X509STORE_DISABLED +int +x509key_write_subject(const Key *key, FILE *f) { + return(x509key_write_subject2(key, key_ssh_name(key), f)); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +#ifndef SSH_X509STORE_DISABLED +int +x509key_write_subject2(const Key *key, const char *keyname, FILE *f) { + BIO *out; + + if (!x509key_check("x509key_write_subject2", key)) return(0); + if (keyname == NULL) return(0); + + out = BIO_new_fp(f, BIO_NOCLOSE); + if (out == NULL) return(0); +#ifdef VMS + { + BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + out = BIO_push(tmpbio, out); + } +#endif + + BIO_puts(out, keyname); + BIO_puts(out, " Subject:"); + ssh_X509_NAME_print(out, X509_get_subject_name(key->x509)); + + BIO_free_all(out); + return(1); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +Key* +x509key_load_cert(Key *key, FILE *fp) { + if (key == NULL) return(NULL); + + if ( (key->type == KEY_RSA) || + (key->type == KEY_DSA) ) { + key->x509 = PEM_read_X509(fp, NULL, NULL, NULL); + if (key->x509 == NULL) { + char ebuf[256]; + debug3("x509key_load_cert: PEM_read_X509 fail %.*s", + sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); + } + else { + key->type = (key->type == KEY_RSA) ? KEY_X509_RSA : KEY_X509_DSA; + debug("read X509 certificate done: type %.40s", key_type(key)); + } + } + return(key); +} + + +static int +x509key_save_cert(FILE *fp, X509 *x509) { + int ret = 0; + BIO *out; + + out = BIO_new_fp(fp, BIO_NOCLOSE); + if (out == NULL) return(0); +#ifdef VMS + { + BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + out = BIO_push(tmpbio, out); + } +#endif + + BIO_puts(out, "issuer= "); + ssh_X509_NAME_print(out, X509_get_issuer_name(x509)); + BIO_puts(out, "\n"); + + BIO_puts(out, "subject= "); + ssh_X509_NAME_print(out, X509_get_subject_name(x509)); + BIO_puts(out, "\n"); + + { + const char *alstr = (const char*)X509_alias_get0(x509, NULL); + if (alstr == NULL) alstr = ""; + BIO_puts(out, alstr); + BIO_puts(out, "\n"); + } + + ret = PEM_write_bio_X509(out, x509); + if (!ret) { + char ebuf[256]; + error("x509key_save_cert: PEM_write_bio_X509 fail %.*s", + sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); + } + + BIO_free_all(out); + return(ret); +} + + +int +x509key_save_pem( + FILE *fp, + const Key *key, + const EVP_CIPHER *cipher, + u_char *passphrase, + int len +) { + if (!x509key_check("x509key_save_pem", key)) return(0); + + switch (key->type) { + case KEY_X509_DSA: + if (PEM_write_DSAPrivateKey(fp, key->dsa, cipher, passphrase, len, NULL, NULL)) + return(x509key_save_cert(fp, key->x509)); + break; + case KEY_X509_RSA: + if (PEM_write_RSAPrivateKey(fp, key->rsa, cipher, passphrase, len, NULL, NULL)) + return(x509key_save_cert(fp, key->x509)); + break; + } + return(0); +} + + +#ifndef SSH_X509STORE_DISABLED +/* + * We can check only by Subject (Distinguished Name): + * - sshd receive from client only x509 certificate !!! + * - sshadd -d ... send only x509 certificate !!! + * - otherwise Key might contain private key + */ +int +ssh_x509_equal(const Key *a, const Key *b) { + if (!x509key_check("ssh_x509_equal", a)) return(1); + if (!x509key_check("ssh_x509_equal", b)) return(-1); + +#if 1 +/* + * We must use own method to compare two X509_NAMEs instead of OpenSSL + * function[s]! See notes before body of "ssh_X509_NAME_cmp()". + */ + { + X509_NAME *nameA = X509_get_subject_name(a->x509); + X509_NAME *nameB = X509_get_subject_name(b->x509); + return(ssh_X509_NAME_cmp(nameA, nameB)); + } +#else + return(X509_subject_name_cmp(a->x509, b->x509)); +#endif +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +int +ssh_x509key_type(const char *name) { + SSHX509KeyAlgs *p; + int k; + + if (name == NULL) { + fatal("ssh_x509key_type: name is NULL"); + return(KEY_UNSPEC); /*unreachable code*/ + } + + k = ssh_xkalg_nameind(name, &p, -1); + return((k >= 0) ? p->type : KEY_UNSPEC); +} + + +static SSHX509KeyAlgs* +ssh_first_xkalg(int type) { + SSHX509KeyAlgs *p; + int k; + + k = ssh_xkalg_typeind(type, &p, -1); + return((k >= 0) ? p : NULL); +} + + +const char* +ssh_x509key_name(const Key *k) { + int type; + SSHX509KeyAlgs *p; + + if (k == NULL) { + fatal("ssh_x509key_name: key is NULL"); + return(NULL); /*unreachable code*/ + } + + type = k->type; + if ((type != KEY_X509_RSA) && (type != KEY_X509_DSA)) return(NULL); + + p = ssh_first_xkalg(type); + if (p != NULL) return(p->name); + + error("ssh_x509key_name: cannot handle type %d", type); + return(NULL); +} + + +int +ssh_x509_sign( + const Key *key, + u_char **psignature, u_int *psignaturelen, + const u_char *data, u_int datalen +) { + int ret = -1; + SSHX509KeyAlgs *xkalg = NULL; + int keylen = 0; + u_char *sigret = NULL; + u_int siglen; + + if (!x509key_check("ssh_x509_sign", key)) return(ret); + if ((key->rsa == NULL) && (key->dsa == NULL)) { + error("ssh_x509_sign: missing private key"); + return(ret); + } + + debug3("ssh_x509_sign: key_type=%.20s, key_ssh_name=%.40s", key_type(key), key_ssh_name(key)); + ret = 1; + { + EVP_PKEY *privkey = EVP_PKEY_new(); + if (privkey == NULL) { + error("ssh_x509_sign: out of memory"); + ret = -1; + } + else { + ret = (key->rsa) + ? EVP_PKEY_set1_RSA(privkey, key->rsa) + : EVP_PKEY_set1_DSA(privkey, key->dsa); + + if (ret <= 0) { + char ebuf[256]; + error("ssh_x509_sign: EVP_PKEY_set1_XXX: failed %.*s", + sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); + } + } + + if (ret > 0) { + xkalg = ssh_first_xkalg(key->type); + if (xkalg == NULL) { + error("ssh_x509_sign: cannot handle type %d", key->type); + ret = -1; + } + } + + if (ret > 0) { + keylen = EVP_PKEY_size(privkey); + if (keylen > 0) { + sigret = xmalloc(keylen); /*fatal on error*/ + } else { + error("ssh_x509_sign: cannot get key size for type %d", key->type); + ret = -1; + } + } + if (ret > 0) { + EVP_MD_CTX ctx; + + debug3("ssh_x509_sign: alg=%.50s, md=%.30s", xkalg->name, xkalg->dgst.name); + EVP_SignInit(&ctx, xkalg->dgst.evp); + EVP_SignUpdate(&ctx, data, datalen); + ret = EVP_SignFinal(&ctx, sigret, &siglen, privkey); + debug3("ssh_x509_sign: keylen=%d, siglen=%u", keylen, siglen); + if (ret <= 0) { + char ebuf[256]; + error("ssh_x509_sign: digest failed: %.*s", + sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); + } + } + EVP_PKEY_free(privkey); + } + if (ret > 0) { + Buffer b; + const char *signame; + + buffer_init(&b); + signame = X509PUBALG_SIGNAME(xkalg); + debug3("ssh_x509_sign: signame=%.50s", signame); + buffer_put_cstring(&b, signame); + buffer_put_string(&b, sigret, siglen); + + { + u_int len = buffer_len(&b); + if (psignaturelen != NULL) + *psignaturelen = len; + + if (psignature != NULL) { + *psignature = xmalloc(len); /*fatal on error*/ + memcpy(*psignature, buffer_ptr(&b), len); + } + } + buffer_free(&b); + } + if (sigret) { + memset(sigret, 's', keylen); + xfree(sigret); + } + ret = ret > 0 ? 0 : -1; + debug3("ssh_x509_sign: return %d", ret); + return(ret); +} + + +int +ssh_x509_verify( + const Key *key, + const u_char *signature, u_int signaturelen, + const u_char *data, u_int datalen +) { + int ret = -1; + u_char *sigblob = NULL; + uint len = 0; + + if (!x509key_check("ssh_x509_verify", key)) return(ret); + + { /* get signature data only */ + Buffer b; + + ret = 1; + buffer_init(&b); + buffer_append(&b, signature, signaturelen); + + { /* check signature format */ + char *sigformat = buffer_get_string(&b, NULL); + + debug3("ssh_x509_verify: signature format = %.40s", sigformat); + if (!ssh_is_x509signame(sigformat)) { + error("ssh_x509_verify: cannot handle signature format %.40s", sigformat); + ret = 0; + } + xfree(sigformat); + } + + if (ret > 0) { + int rlen; + + sigblob = buffer_get_string(&b, &len); + rlen = buffer_len(&b); + if (rlen != 0) { + error("ssh_x509_verify: remaining bytes in signature %d", rlen); + ret = -1; + } + } + buffer_free(&b); + } + + if (ret > 0 ) { + EVP_PKEY* pubkey = X509_get_pubkey(key->x509); + SSHX509KeyAlgs *xkalg; + int loc; + + if (pubkey == NULL) { + error("ssh_x509_verify: no 'X509 Public Key'"); + ret = -1; + } + if (ret > 0) { + loc = ssh_xkalg_typeind(key->type, &xkalg, -1); + if (loc < 0) { + error("ssh_x509_verify: cannot handle type %d", key->type); + ret = -1; + } + } + if (ret > 0) { + for (; loc >= 0; loc = ssh_xkalg_typeind(key->type, &xkalg, loc)) { + EVP_MD_CTX ctx; + + debug3("ssh_x509_verify: md=%.30s, loc=%d", xkalg->dgst.name, loc); + ret = ssh_EVP_VerifyInit(&ctx, xkalg->dgst.evp); + if (ret <= 0) { + char ebuf[256]; + error("ssh_x509_verify: EVP_VerifyInit" + " fail with errormsg='%.*s'" + , sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); + continue; + } + ret = ssh_EVP_VerifyUpdate(&ctx, data, datalen); + if (ret <= 0) { + char ebuf[256]; + error("ssh_x509_verify: EVP_VerifyUpdate" + " fail with errormsg='%.*s'" + , sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); + continue; + } + ret = EVP_VerifyFinal(&ctx, sigblob, len, pubkey); + if (ret > 0) break; + } + if (ret <= 0) { + debug3("ssh_x509_verify: failed for all digests"); + ret = 0; + } + } + EVP_PKEY_free(pubkey); + } + if (sigblob) { + memset(sigblob, 's', len); + xfree(sigblob); + sigblob = NULL; + } + if (ret > 0) { + if (pssh_x509cert_check != NULL) { + ret = pssh_x509cert_check(key->x509); + } else { + error("ssh_x509_verify: pssh_x509cert_check is NULL"); + ret = -1; + } + } + ret = ret > 0 ? 1 : (ret < 0 ? -1 : 0); + debug3("ssh_x509_verify: return %d", ret); + return(ret); +} + + +u_int +ssh_x509_key_size(const Key *key) { + EVP_PKEY *pkey; + int k = 0; + + if (!x509key_check("key_size", key)) goto done; + + pkey = X509_get_pubkey(key->x509); + if (pkey == NULL) goto done; + + switch(pkey->type) { + case EVP_PKEY_RSA: + /* BN_num_bits return int (!): XXX */ + k = BN_num_bits(pkey->pkey.rsa->n); + break; + case EVP_PKEY_DSA: + /*OpenSSH like this*/ + k = BN_num_bits(pkey->pkey.dsa->p); + break; + default: + fatal("ssh_x509_key_size: unknow pkey->type %d", pkey->type); + /*unreachable code*/ + } + EVP_PKEY_free(pkey); +done: + return((u_int) k); +} diff -ruN openssh-5.6p1/ssh-x509.h openssh-5.6p1+x509-6.2.3/ssh-x509.h --- openssh-5.6p1/ssh-x509.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-x509.h 2007-10-04 22:56:18.000000000 +0300 @@ -0,0 +1,73 @@ +#ifndef SSH_X509_H +#define SSH_X509_H +/* + * Copyright (c) 2002-2005 Roumen Petrov. 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" +#include "key.h" +#include "buffer.h" + + +#ifndef SSH_X509STORE_DISABLED +/* + * Method return a key(x509) only with "Subject"("Distinguished Name") ! + */ +Key* x509key_from_subject(int _keytype, const char* _cp); +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +Key* x509key_from_blob(const u_char *blob, int blen); +int x509key_to_blob(const Key *key, Buffer *b); + +char* x509key_subject(const Key *key); + +/* + * Method write x509 certificate as blob. + */ +int x509key_write(const Key *key, FILE *f); +#ifndef SSH_X509STORE_DISABLED +/* + * Method write x509 certificate subject. + */ +int x509key_write_subject(const Key *key, FILE *f); +int x509key_write_subject2(const Key *key, const char *keyname, FILE *f); +#endif /*ndef SSH_X509STORE_DISABLED*/ + +Key* x509key_load_cert(Key *key, FILE *fp); + +int x509key_save_pem(FILE *fp, const Key *key, const EVP_CIPHER *cipher, u_char *passphrase, int len); + +#ifndef SSH_X509STORE_DISABLED +int ssh_x509_equal(const Key *a, const Key *b); +#endif /*ndef SSH_X509STORE_DISABLED*/ + +int ssh_x509key_type(const char *name); +const char* ssh_x509key_name(const Key *k); + +int ssh_x509_sign(const Key *key, u_char **psignature, u_int *psignaturelen, const u_char *data, u_int datalen); +int ssh_x509_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen); +u_int ssh_x509_key_size(const Key *key); + + +#endif /* SSH_X509_H */ diff -ruN openssh-5.6p1/ssh-xkalg.c openssh-5.6p1+x509-6.2.3/ssh-xkalg.c --- openssh-5.6p1/ssh-xkalg.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-xkalg.c 2009-10-15 22:42:37.000000000 +0300 @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2005 Roumen Petrov. 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 "ssh-xkalg.h" +#include + +#include "log.h" +#include "key.h" +#include "xmalloc.h" + + +#define SHARAW_DIGEST_LENGTH (2*SHA_DIGEST_LENGTH) + + +#ifdef OPENSSL_NO_DSA +# error "OPENSSL_NO_DSA" +#endif +#ifdef OPENSSL_NO_SHA +# error "OPENSSL_NO_SHA" +#endif + + +#if OPENSSL_VERSION_NUMBER >= 0x00908000L +#define EVP_PKEY_DSARAW_method \ + (evp_sign_method *)DSARAW_sign, \ + (evp_verify_method *)DSARAW_verify, \ + {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3,EVP_PKEY_DSA4,0} +#else +#define EVP_PKEY_DSARAW_method \ + DSARAW_sign,DSARAW_verify, \ + {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3,EVP_PKEY_DSA4,0} +#endif + + +static int/*bool*/ +DSARAW_sign( + int type, + const unsigned char *dgst, + int dlen, + unsigned char *sigret, unsigned int *siglen, + DSA *dsa +) { + int ret = 0; + DSA_SIG *sig = NULL; + + (void) type; +#ifdef TRACE_XKALG +fprintf(stderr, "TRACE_XKALG DSARAW_sign:\n"); +#endif + sig = DSA_do_sign(dgst, dlen, dsa); + if (sig == NULL) { + *siglen=0; + return(ret); + } + + *siglen = SHARAW_DIGEST_LENGTH; + if (sigret != NULL) { + u_int rlen, slen; + rlen = BN_num_bytes(sig->r); + slen = BN_num_bytes(sig->s); + if (rlen > SHA_DIGEST_LENGTH || slen > SHA_DIGEST_LENGTH) { + error("DSARAW_sign: bad sig size %u %u", rlen, slen); + goto done; + } + memset(sigret, 0, SHARAW_DIGEST_LENGTH); + BN_bn2bin(sig->r, sigret + SHARAW_DIGEST_LENGTH - SHA_DIGEST_LENGTH - rlen); + BN_bn2bin(sig->s, sigret + SHARAW_DIGEST_LENGTH - slen); + } + ret = 1; + +done: + DSA_SIG_free(sig); + return(ret); +} + + +static int +DSARAW_verify( + int type, + const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int siglen, + DSA *dsa +) { + int ret = -1; + DSA_SIG *sig = NULL; + + (void) type; +#ifdef TRACE_XKALG +fprintf(stderr, "TRACE_XKALG DSARAW_verify: siglen=%d\n", siglen); +#endif + if (siglen != SHARAW_DIGEST_LENGTH) return(ret); + + sig = DSA_SIG_new(); + if (sig == NULL) return(ret); + + sig->r = BN_new(); + if (sig->r == NULL) + fatal("DSARAW_verify: BN_new failed"); + sig->s = BN_new(); + if (sig->s == NULL) + fatal("DSARAW_verify: BN_new failed"); + + BN_bin2bn(sigbuf , SHA_DIGEST_LENGTH, sig->r); + BN_bin2bn(sigbuf+SHA_DIGEST_LENGTH, SHA_DIGEST_LENGTH, sig->s); + + ret = DSA_do_verify(dgst, dgst_len, sig, dsa); + + DSA_SIG_free(sig); + return(ret); +} + + +#ifdef HAVE_EVP_MD_CTX_MD_DATA +static int +init(EVP_MD_CTX *ctx) { + return(SHA1_Init(ctx->md_data)); +} + + +static int +#if OPENSSL_VERSION_NUMBER >= 0x00908000L +update(EVP_MD_CTX *ctx, const void *data, size_t count) { +#else +update(EVP_MD_CTX *ctx, const void *data, unsigned long count) { +#endif + return(SHA1_Update(ctx->md_data, data, count)); +} + + +static int +final(EVP_MD_CTX *ctx, unsigned char *md) { + return(SHA1_Final(md, ctx->md_data)); +} +#endif /*def HAVE_EVP_MD_CTX_MD_DATA*/ + + +#ifdef HAVE_EVP_MD_FLAGS +#ifndef EVP_MD_FLAG_FIPS +# define EVP_MD_FLAG_FIPS 0 +#endif +#endif /*def HAVE_EVP_MD_FLAGS*/ + +static const +EVP_MD dss1_md = { + NID_dsa, + NID_dsaWithSHA1, + SHA_DIGEST_LENGTH, +#ifdef HAVE_EVP_MD_FLAGS + EVP_MD_FLAG_FIPS, +#endif /*def HAVE_EVP_MD_FLAGS*/ +#ifdef HAVE_EVP_MD_CTX_MD_DATA + init, + update, + final, +#else + SHA1_Init, + SHA1_Update, + SHA1_Final, +#endif /*ndef HAVE_EVP_MD_CTX_MD_DATA*/ +#ifdef HAVE_EVP_MD_COPY + NULL, +#endif /*def HAVE_EVP_MD_COPY*/ +#ifdef HAVE_EVP_MD_CLEANUP + NULL, +#endif /*def HAVE_EVP_MD_CLEANUP*/ + EVP_PKEY_DSARAW_method, + SHA_CBLOCK, + sizeof(EVP_MD *)+sizeof(SHA_CTX), +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + NULL /*md_ctrl*/ +#endif +}; + + +extern const EVP_MD* +EVP_dss1raw(void); + + +const EVP_MD* +EVP_dss1raw(void) { + return(&dss1_md); +} + + +/* SSH X509 public key algorithms*/ +static int x509keyalgs_initialized = 0; +static SSHX509KeyAlgs x509keyalgs[10]; + + +static void +initialize_xkalg(void) { + SSHX509KeyAlgs *p = x509keyalgs; + int k; + + if (x509keyalgs_initialized) return; + +#ifdef TRACE_XKALG +fprintf(stderr, "TRACE_XKALG initialize_xkalg:\n"); +#endif + k = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + for (; k > 0; k--, p++) { + p->type = KEY_UNSPEC; + p->name = NULL; + p->dgst.name = NULL; + p->dgst.evp = NULL; + p->signame = NULL; + } + x509keyalgs_initialized = 1; +} + + +static void +add_default_xkalg(void) { +#ifdef TRACE_XKALG +fprintf(stderr, "TRACE_XKALG add_default_xkalg:\n"); +#endif + + /*RSA public key algorithm*/ + /* OpenSSH defaults note that + * draft-ietf-secsh-transport-NN.txt where NN <= 12 + * don't define signature format + */ + if (ssh_add_x509key_alg("x509v3-sign-rsa,rsa-md5") < 0) + fatal("ssh_init_xkalg: oops"); + if (ssh_add_x509key_alg("x509v3-sign-rsa,rsa-sha1") < 0) + fatal("ssh_init_xkalg: oops"); + +#if 0 + /* "draft-ietf-secsh-x509-NN.txt" where NN <= 03 */ +/* NOT YET FULLY IMPLEMENTED */ + if (ssh_add_x509key_alg("x509v3-sign-rsa-sha1,rsa-sha1,ssh-rsa") < 0) + fatal("ssh_init_xkalg: oops"); +#endif + + /*DSA public key algorithm*/ + /* OpenSSH default compatible with + * draft-ietf-secsh-transport-NN.txt where NN <= 12 + */ + if (ssh_add_x509key_alg("x509v3-sign-dss,dss-asn1") < 0) + fatal("ssh_init_xkalg: oops"); + /* some non OpenSSH implementations incompatible with + * draft-ietf-secsh-transport-NN.txt where NN <= 12 + */ + if (ssh_add_x509key_alg("x509v3-sign-dss,dss-raw") < 0) + fatal("ssh_init_xkalg: oops"); + +#if 0 + /* draft-ietf-secsh-x509-NN.txt where NN <= 03 */ +/* NOT YET FULLY IMPLEMENTED */ + if (ssh_add_x509key_alg("x509v3-sign-dss-sha1,dss-raw,ssh-dss") < 0) + fatal("ssh_init_xkalg: oops"); +#endif +} + + +void +fill_default_xkalg(void) { + SSHX509KeyAlgs *p = x509keyalgs; + +#ifdef TRACE_XKALG +fprintf(stderr, "TRACE_XKALG fill_default_xkalg:\n"); +#endif + initialize_xkalg(); + if (p[0].name == NULL) add_default_xkalg(); +} + + +static const EVP_MD* +ssh_evp_md(const char *dgstname) { + if (dgstname == NULL) { + fatal("ssh_get_md: dgstname is NULL"); + return(NULL); /*unreachable code*/ + } + + if (strcasecmp("rsa-sha1", dgstname) == 0) return(EVP_sha1()); + if (strcasecmp("rsa-md5" , dgstname) == 0) return(EVP_md5()); +/*?: if (strcasecmp("ssh-rsa" , dgstname) == 0) return(EVP_sha1());*/ + + if (strcasecmp("dss-asn1", dgstname) == 0) return(EVP_dss1()); + if (strcasecmp("dss-raw" , dgstname) == 0) return(EVP_dss1raw()); +/*?: if (strcasecmp("ssh-dss" , dgstname) == 0) return(EVP_dss1raw());*/ + +#if 0 + fatal("ssh_get_md: invalid sigformat '%.10s'", dgstname); +#endif + return(NULL); /*unreachable code*/ +} + + +int +ssh_add_x509key_alg(const char *data) { + char *name, *mdname, *signame; + SSHX509KeyAlgs* p; + const EVP_MD* md; + + if (data == NULL) { + error("ssh_add_x509pubkey_alg: data is NULL"); + return(-1); + } + + name = xstrdup(data); /*fatal on error*/ + + mdname = strchr(name, ','); + if (mdname == NULL) { + error("ssh_add_x509pubkey_alg: cannot get digest"); + goto err; + } + *mdname++ = '\0'; + + signame = strchr(mdname, ','); + if (signame != NULL) *signame++ = '\0'; + + md = ssh_evp_md(mdname); + if (md == NULL) { + error("ssh_add_x509pubkey_alg: unsupported digest"); + goto err; + } + + initialize_xkalg(); + p = x509keyalgs; + { + int k = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + + for (; k > 0; k--, p++) { + if (p->name == NULL) break; + } + if (k <= 0) { + error("ssh_add_x509pubkey_alg: insufficient slots"); + goto err; + } + } + + if ((md == EVP_dss1()) || (md == EVP_dss1raw())) { + p->type = KEY_X509_DSA; + } else { + p->type = KEY_X509_RSA; + } + p->name = name; + p->dgst.name = mdname; + p->dgst.evp = md; + p->signame = signame; + + return (1); + +err: + xfree((void*)name); + return (-1); +} + + +int/*bool*/ +ssh_is_x509signame(const char *signame) { + SSHX509KeyAlgs *xkalg; + int k; + + if (signame == NULL) { + fatal("ssh_is_x509signame: signame is NULL"); + return(0); /*unreachable code*/ + } + + initialize_xkalg(); + xkalg = x509keyalgs; + k = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + + for (; k > 0; k--, xkalg++) { + if (xkalg->name == NULL) return(0); + if (strcmp(signame, X509PUBALG_SIGNAME(xkalg)) == 0) return(1); + } + return(0); +} + + +int +ssh_xkalg_nameind(const char *name, SSHX509KeyAlgs **q, int loc) { + int k, n; + SSHX509KeyAlgs *p; + + if (name == NULL) return (-1); + + initialize_xkalg(); + k = (loc < 0) ? 0 : (loc + 1); + n = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + if (k < n) p = &x509keyalgs[k]; + + for (; k < n; k++, p++) { + if (p->name == NULL) return(-1); + if (strcmp(p->name, name) == 0) { + if (q) *q = p; + return(k); + } + } + return(-1); +} + + +int +ssh_xkalg_typeind(int type, SSHX509KeyAlgs **q, int loc) { + int k, n; + SSHX509KeyAlgs *p; + + initialize_xkalg(); + k = (loc < 0) ? 0 : (loc + 1); + n = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + if (k < n) p = &x509keyalgs[k]; + + for (; k < n; k++, p++) { + if (p->name == NULL) return(-1); + if (p->type == type) { + if (q) *q = p; + return(k); + } + } + return(-1); +} + + +void +ssh_list_xkalg(int type, Buffer *b) { + SSHX509KeyAlgs *xkalg; + int loc; + + if ((type != KEY_X509_RSA) && (type != KEY_X509_DSA)) { + error("ssh_list_xkalg: %d is not x509 key", type); + return; + } + if (b == NULL) { + error("ssh_list_xkalg: buffer is NULL"); + return; + } + +#if 1 + /* add only(!) first found */ + loc = ssh_xkalg_typeind(type, &xkalg, -1); + if (loc < 0) return; + + if (buffer_len(b) > 0) buffer_append(b, ",", 1); + buffer_append(b, xkalg->name, strlen(xkalg->name)); +#else +IMPORTANT NOTE: + For every unique "key name" we MUST define unique "key type" +otherwise cannot distinguish them ! +As example structure Kex contain integer attribute "kex_type" +and kex use method "load_host_key" to find hostkey. When client +request hostkey algorithms (comma separated list with names) +server should be able to find first hostkey that match one of them. +Note to "load_host_key" is assigned method "get_hostkey_by_type" +defined in "sshd.c". + + for ( + loc = ssh_xkalg_typeind(type, &xkalg, -1); + loc >= 0; + loc = ssh_xkalg_typeind(type, &xkalg, loc) + ) { + const char *p; + int dupl, k; + + p = xkalg->name; + + dupl = 0; + + for ( + k = ssh_xkalg_typeind(type, &xkalg, -1); + (k >= 0) && (k < loc); + k = ssh_xkalg_typeind(type, &xkalg, k) + ) { + if (strcmp(p, xkalg->name) == 0) { + dupl = 1; + break; + } + } + if (dupl) continue; + + if (buffer_len(b) > 0) buffer_append(b, ",", 1); + buffer_append(b, p, strlen(p)); + } +#endif +} diff -ruN openssh-5.6p1/ssh-xkalg.h openssh-5.6p1+x509-6.2.3/ssh-xkalg.h --- openssh-5.6p1/ssh-xkalg.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/ssh-xkalg.h 2005-08-13 14:59:26.000000000 +0300 @@ -0,0 +1,58 @@ +#ifndef SSH_XKALG_H +#define SSH_XKALG_H +/* + * Copyright (c) 2005 Roumen Petrov. 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" +#include +#include "buffer.h" + + +typedef struct { + int type; + const char *name; + struct { + const char *name; + const EVP_MD *evp; + } dgst; + const char *signame; +} SSHX509KeyAlgs; +#define X509PUBALG_SIGNAME(p) (p->signame ? p->signame : p->name) + + +void fill_default_xkalg(void); + /* format "name,dgst_name[,sig_name]" */ +int ssh_add_x509key_alg(const char *data); + + +int/*bool*/ ssh_is_x509signame(const char *signame); + +int ssh_xkalg_nameind(const char *name, SSHX509KeyAlgs **q, int loc); +int ssh_xkalg_typeind(int type, SSHX509KeyAlgs **q, int loc); + +void ssh_list_xkalg(int type, Buffer *b); + + +#endif /* SSH_XKALG_H */ diff -ruN openssh-5.6p1/tests/CA/1-cre_cadb.sh openssh-5.6p1+x509-6.2.3/tests/CA/1-cre_cadb.sh --- openssh-5.6p1/tests/CA/1-cre_cadb.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/1-cre_cadb.sh 2007-02-27 23:22:48.000000000 +0200 @@ -0,0 +1,339 @@ +#! /bin/sh +# Copyright (c) 2002-2006 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Create a new certificate authority config and database. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/1-cre_cadb.sh$//'` +. "${SCRIPTDIR}shell.rc" +. "${SCRIPTDIR}functions" +. "${SCRIPTDIR}config" + + +# === +# args: +# $1 - type +echo_CA_common_options () { +cat < "$1" +[ ca ] +default_ca = CA_OpenSSH_rsa_md5 + + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + + +[ req ] +default_bits = 1024 +distinguished_name = req_distinguished_name +attributes = req_attributes +#prompt = no + +# The extensions to add to a certificate request: +#???req_extensions = usr_cert + + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = $SSH_DN_C +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = $SSH_DN_ST + +localityName = Locality Name (eg, city) +localityName_default = $SSH_DN_L + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = $SSH_DN_O + +0.organizationalUnitName = Organizational Unit1 Name (eg, section1 - optional) +0.organizationalUnitName_default = ${SSH_DN_OU}-1 + +1.organizationalUnitName = Organizational Unit2 Name (eg, section2 - optional) +1.organizationalUnitName_default = ${SSH_DN_OU}-2 + +2.organizationalUnitName = Organizational Unit3 Name (eg, section3 - optional) +2.organizationalUnitName_default = ${SSH_DN_OU}-3 + +commonName = Common Name (eg, YOUR name) +commonName_min = 2 +commonName_max = 64 + +emailAddress = Email Address (optional) +emailAddress_max = 40 +emailAddress_default = $SSH_DN_EM + + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + + +[ ca_cert ] +# PKIX recommendation. + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +# Since we generate OpenSSH test CA we comment next line. +#basicConstraints=CA:true + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated OpenSSH Test CA Certificate" + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# Since we verify CRL signatures cRLSign must present +keyUsage = keyCertSign, cRLSign + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always + +# To test CRL presence this extension should exist +crlDistributionPoints = URI:attribute_only_exist +EOF + + +# X.509 extensions: SSH client certificates +cat << EOF >> "$1" + + +[ usr_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints = CA:FALSE +nsCertType = client, email + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated OpenSSH Test Client Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +EOF + +echo_CA_ocsp_options >> "$1" + + +# X.509 extensions: SSH server certificates +cat << EOF >> "$1" + + +[ srv_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints = CA:FALSE + +# To test OpenSSH hostbased authentication we need +# following certificate purposes: +nsCertType = server,client +# Normal for server certificate is: +#nsCertType = server +# but in last case me must disable check of certificate purposes +# in sshd_config otherwise hostbased fail. + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated OpenSSH Test Server Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always + +# Some SSH clients require server certificate to contain +# correct alternate name of type DNS (FQDN) +subjectAltName = DNS:localhost +EOF + +echo_CA_ocsp_options >> "$1" + + +# X.509 extensions: OCSP Validator certificates +if test "x$SSH_OCSP" = "xyes"; then +cat << EOF >> "$1" + + +[ ocsp_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints = CA:FALSE + +# Normal for validator certificate is: +nsCertType = objsign + +# This is typical in keyUsage for a validator certificate. +keyUsage = nonRepudiation, digitalSignature + +# This should present for a validator certificate. +extendedKeyUsage = OCSPSigning + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated OpenSSH Test OCSP Responder Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +EOF +fi + + +for DIGEST in ${RSA_DIGEST_LIST}; do +( cat << EOF + + +[ CA_OpenSSH_rsa_${DIGEST} ] +EOF + echo_CA_common_options "rsa_${DIGEST}" + cat << EOF +# which md to use: +default_md = ${DIGEST} + +# The private key (!) +private_key = "${SSH_CAKEYDIR}/${CAKEY_PREFIX}-rsa.key" + +#The CA certificate (!) +certificate = "${SSH_CACERTDIR}/${CAKEY_PREFIX}-rsa_${DIGEST}.crt.pem" +EOF +) >> "$1" +done + +( cat << EOF + + +[ CA_OpenSSH_dsa ] +EOF + echo_CA_common_options "dsa" + cat << EOF +# which md to use: +default_md = sha1 + +# The private key (!) +private_key = "${SSH_CAKEYDIR}/${CAKEY_PREFIX}-dsa.key" + +#The CA certificate (!) +certificate = "${SSH_CACERTDIR}/${CAKEY_PREFIX}-dsa.crt.pem" +EOF +) >> "$1" +} + + +# === +cre_db () { +( + var="${SSH_CAROOT}" + + if test ! -d "$var"; then + mkdir -p "$var" || exit $? + else + count=`getNextDirName "${var}"` || exit $? + if test -d "${var}"; then + printf '%s' "saving old directoty as ${attn}${var}.${warn}${count}${norm} ... " + mv "${var}" "${var}.${count}"; show_status $? || exit $? + fi + fi + + mkdir -p "$var" && + mkdir "$var/crt" && + mkdir "$var/crl" || + exit $? + + for type in ${SSH_SIGN_TYPES}; do + create_empty_file "$var/index-${type}.txt" || exit $? + done + + mkdir "$var/newcerts" && + echo '200402160906000001' > "$var/serial" +) +} + + +# === + +cre_config "${TMPDIR}/${CACONFIG}" && +cre_db && +update_file "${TMPDIR}/${CACONFIG}" "${SSH_CACFGFILE}"; retval=$? + +show_status $retval "${extd}Creating${norm} ${warn}TEST${norm} ${attn}Certificate Authority Database${norm}" diff -ruN openssh-5.6p1/tests/CA/2-cre_cakeys.sh openssh-5.6p1+x509-6.2.3/tests/CA/2-cre_cakeys.sh --- openssh-5.6p1/tests/CA/2-cre_cakeys.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/2-cre_cakeys.sh 2006-03-12 23:01:31.000000000 +0200 @@ -0,0 +1,253 @@ +#! /bin/sh +# Copyright (c) 2002-2006 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Create "Test Certificate Authority" private keys and certificates. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/2-cre_cakeys.sh$//'` +. "${SCRIPTDIR}shell.rc" +. "${SCRIPTDIR}functions" +. "${SCRIPTDIR}config" + + +OPENSSH_LOG="$CWD/openssh_ca-2.log" +create_empty_file .delmy && +update_file .delmy "$OPENSSH_LOG" > /dev/null || exit $? + + +# === +echo_SSH_CA_DN () { +cat </dev/null + +$OPENSSL genrsa ${RSA_OPT} \ + -passout pass:${KEY_PASS} \ + -out "${TMPDIR}/${CAKEY_PREFIX}-rsa.key" 1024 \ + 2>> "$OPENSSH_LOG" \ +; show_status $? "generating ${extd}TEST CA${norm} ${attn}rsa${norm} private key" \ +|| return $? + +for DIGEST in ${RSA_DIGEST_LIST}; do + +rm -f "${TMPDIR}/${CAKEY_PREFIX}-rsa_${DIGEST}.crt" 2>/dev/null + +echo_SSH_CA_DN "rsa_${DIGEST}" | +$OPENSSL req \ + -new -x509 \ + -config "${SSH_CACFGFILE}" \ + $SSH_DN_UTF8_FLAG \ + -days $SSH_CACERTDAYS \ + -passin pass:${KEY_PASS} \ + -key "${TMPDIR}/${CAKEY_PREFIX}-rsa.key" \ + -${DIGEST} \ + -out "${TMPDIR}/${CAKEY_PREFIX}-rsa_${DIGEST}.crt" \ + -extensions ca_cert \ + 2>> "$OPENSSH_LOG" \ +; show_status $? "generating ${extd}TEST CA${norm} ${attn}rsa-${DIGEST}${norm} certificate" \ +|| return $? + +done + +return 0 +} + + +# === +gen_dsa () { +DSA_OPT="" +if [ -f /etc/random-seed ]; then + DSA_OPT="${DSA_OPT} -rand /etc/random-seed" +fi + +rm -f "${TMPDIR}/${CAKEY_PREFIX}-dsa.prm" 2>/dev/null +$OPENSSL dsaparam ${DSA_OPT} \ + -out "${TMPDIR}/${CAKEY_PREFIX}-dsa.prm" 1024\ + 2>> "$OPENSSH_LOG";\ +show_status $? "generating ${extd}DSA parameter file${norm}" \ +|| return $? + +rm -f "${TMPDIR}/${CAKEY_PREFIX}-dsa.key" 2>/dev/null +DSA_OPT="${DSA_OPT} -des3" +$OPENSSL gendsa ${DSA_OPT} \ + -passout pass:${KEY_PASS} \ + -out "${TMPDIR}/${CAKEY_PREFIX}-dsa.key" \ + "${TMPDIR}/${CAKEY_PREFIX}-dsa.prm" \ + 2>> "$OPENSSH_LOG" \ +; show_status $? "generating ${extd}TEST CA${norm} ${attn}dsa${norm} private key" \ +|| return $? + + +#request & ceritificate +rm -f "${TMPDIR}/${CAKEY_PREFIX}-dsa.crt" 2>/dev/null + +echo_SSH_CA_DN "dsa" | +$OPENSSL req \ + -new -x509 \ + -config "${SSH_CACFGFILE}" \ + $SSH_DN_UTF8_FLAG \ + -days $SSH_CACERTDAYS \ + -passin pass:${KEY_PASS} \ + -key "${TMPDIR}/${CAKEY_PREFIX}-dsa.key" \ + -out "${TMPDIR}/${CAKEY_PREFIX}-dsa.crt" \ + -extensions ca_cert \ + 2>> "$OPENSSH_LOG" \ +; show_status $? "generating ${extd}TEST CA${norm} ${attn}dsa-sha1${norm} certificate" \ +|| return $? + +return 0 +} + + +# === +crt2bundle () { +( + val="$1" + test -z "${val}" && { echo ${warn}missing DN${norm} >&2; return 1; } + + echo + echo ${val} + echo ${val} | sed -e 's/./=/g' + $OPENSSL x509 -inform PEM -in "${2}" -fingerprint -noout || exit $? + echo PEM data: + $OPENSSL x509 -inform PEM -in "${2}" -trustout || exit $? + echo Certificate Ingredients: + $OPENSSL x509 -inform PEM -in "${2}" -text -noout || exit $? + + exit 0 +) +} + + +# === +install () { +( + for D in \ + "${SSH_CAROOT}" \ + "${SSH_CAKEYDIR}" \ + "${SSH_CACERTDIR}" \ + ; do + if test ! -d "$D"; then + mkdir -p "${D}" || exit $? + fi + done + chmod 700 "${SSH_CAKEYDIR}" || exit $? + + update_file "${TMPDIR}/${CAKEY_PREFIX}-dsa.prm" "${SSH_CAROOT}/${CAKEY_PREFIX}-dsa.prm" && + for type in rsa dsa; do + F="${CAKEY_PREFIX}-${type}.key" + update_file "${TMPDIR}/${F}" "${SSH_CAKEYDIR}/${F}" && + chmod 400 "${SSH_CAKEYDIR}/${F}" || exit $? + done + + for type in ${SSH_SIGN_TYPES}; do + F="${CAKEY_PREFIX}-${type}.crt" + update_file "${TMPDIR}/${F}" "${SSH_CACERTDIR}/${F}.pem" || exit $? + done + + create_empty_file "${TMPDIR}/${CACERTFILE}" && + for type in ${SSH_SIGN_TYPES}; do + F="${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" + crt2bundle "${SSH_DN_O}-${type}" "${F}" >> "${TMPDIR}/${CACERTFILE}" || exit $? + done + + update_file "${TMPDIR}/${CACERTFILE}" "${SSH_CAROOT}/${CACERTFILE}" +) +} + + +# === +cre_hash_link () { +( +#option -noout problem: +#exit code from .../openssl ... -noout ... is sometime nonzero !!! +#might only by .../openssl x509 ... -noout ... exit code is zero +#sample: +#a) exit code is one - INCORRECT +# .../openssl crl -in a_crl_file -hash -noout +#b) exit code is zero - correct +# .../openssl crl -in a_crl_file -hash -out /dev/null +# +#work around might is to use -out /dev/null :-/ + HASH=`$OPENSSL x509 -in "$1" -noout -hash` || exit $? + NAME=`getNextFreeName ${HASH}.` || exit $? + + echo "creating link ${attn}${NAME}${norm} to ${attn}$1${norm}" + rm -f "${NAME}" && + ln -s "$1" "${NAME}" || exit $? + #link might never fail ;-( + test -h "${NAME}" +) +} + + +cre_hashs () { +#(!) openssl script "c_rehash" is missing in some installations :-( +# c_rehash "${SSH_CACERTDIR}" +( + cd "${SSH_CACERTDIR}" || exit $? + + for F in [0-9a-f]*.[0-9]; do + # we must use test -L, but on ?-OSes ... :-( + if test -h "$F"; then + rm -f "$F" || exit $? + fi + done + + for type in ${SSH_SIGN_TYPES}; do + cre_hash_link "${CAKEY_PREFIX}-${type}.crt.pem" || exit $? + done + + exit 0 +) +} + + +# === + +gen_rsa && +gen_dsa && +install && +cre_hashs; retval=$? + +show_status $retval "${extd}Creating${norm} ${warn}TEST${norm} ${attn}Certificate Authority${norm}" +echo "${warn}password for all private keys is ${attn}${KEY_PASS}${norm}" +exit $retval diff -ruN openssh-5.6p1/tests/CA/3-cre_certs.sh openssh-5.6p1+x509-6.2.3/tests/CA/3-cre_certs.sh --- openssh-5.6p1/tests/CA/3-cre_certs.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/3-cre_certs.sh 2007-02-17 20:35:58.000000000 +0200 @@ -0,0 +1,274 @@ +#! /bin/sh +# Copyright (c) 2002-2006 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Create certificate(s). +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/3-cre_certs.sh$//'` +. "${SCRIPTDIR}shell.rc" +. "${SCRIPTDIR}functions" +. "${SCRIPTDIR}config" + +usage () { + cat < + -f[ile] [ssh]key_file_name + -t[ype] certificate type: client, server, ocsp(if enabled) + -n[ame] "base" common name +EOF + exit 1 +} + +test "x$TEST_SSH_SSHKEYGEN" = "x" && { echo "Please define TEST_SSH_SSHKEYGEN"; exit 1; } +test -z "$1" && usage + +while test -n "$1"; do + case $1 in + -f|\ + -file) + shift + if test -z "$1"; then + usage + fi + if test -n "${SSH_BASE_KEY}"; then + usage + fi + SSH_BASE_KEY="$1" + shift + ;; + + -t|\ + -type) + shift + if test -z "$1"; then + usage + fi + if test -n "$SSH_CERT_TYPE"; then + usage + fi + SSH_CERT_TYPE="$1" + shift + case $SSH_CERT_TYPE in + client) + SSH_X509V3_EXTENSIONS="usr_cert" + ;; + server) + SSH_X509V3_EXTENSIONS="srv_cert" + ;; + ocsp) + if test "x$SSH_OCSP" = "xyes"; then + SSH_X509V3_EXTENSIONS="ocsp_cert" + else + echo "${warn}unsupported type${norm}" + usage + fi + ;; + *) + echo "${warn}wrong type${norm}" + usage + ;; + esac + ;; + + -n|\ + -name) + shift + if test -z "$1"; then + usage + fi + if test -n "${SSH_BASE_DN_CN}"; then + usage + fi + SSH_BASE_DN_CN="$1" + shift + ;; + + *) + usage + ;; + esac +done + +test -z "${SSH_BASE_KEY}" && usage +test ! -r "${SSH_BASE_KEY}" && { error_file_not_readable; exit 1; } +test -z "${SSH_BASE_DN_CN}" && usage +test -z "${SSH_CERT_TYPE}" && usage + + +OPENSSH_LOG="$CWD/openssh_ca-3.${SSH_BASE_KEY}.${SSH_X509V3_EXTENSIONS}.log" +create_empty_file .delmy && +update_file .delmy "$OPENSSH_LOG" > /dev/null || exit $? + + +# === +cre_csr () { + echo "=== create a new CSR ===" >> "$OPENSSH_LOG" + ( + if test "$SSH_X509V3_EXTENSIONS" != "usr_cert"; then + SSH_DN_EM="." + fi + + cat <> "$OPENSSH_LOG" \ + ; show_status $? "- ${extd}CSR${norm}" +} + + +# === +cre_crt () { + echo "=== create a new CRT ===" >> "$OPENSSH_LOG" + $OPENSSL ca \ + -config "${SSH_CACFGFILE}" \ + -batch \ + -in "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.csr" \ + -name "CA_OpenSSH_${type}" \ + -passin pass:$KEY_PASS \ + -out "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.crt" \ + -extensions ${SSH_X509V3_EXTENSIONS} \ + 2>> "$OPENSSH_LOG" \ + ; show_status $? "- ${extd}CRT${norm}" || + { retval=$? + printf '%s' "${warn}" + grep 'ERROR:' "$OPENSSH_LOG" + printf '%s' "${norm}" + return $retval + } + + sync + $OPENSSL verify \ + -CAfile "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" \ + "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.crt" && + rm -f "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.csr" || + return $? + + printf '%s' '- ' && + update_file \ + "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.crt" \ + "${SSH_BASE_KEY}-${type}${subtype}.crt" +} + + +# === +cre_OpenSSH_Crt () { + printf '%s' "- ${extd}OpenSSH certificate${norm}" + ( cat "${SSH_BASE_KEY}" + $OPENSSL x509 -in "${SSH_BASE_KEY}-${type}${subtype}.crt" -subject -issuer -alias + ) > "${SSH_BASE_KEY}-${type}${subtype}" && + chmod 600 "${SSH_BASE_KEY}-${type}${subtype}" \ + ; show_status $? +} + + +cre_OpenSSH_PubKey () { + printf '%s' "- ${extd}OpenSSH public key${norm}" + "$TEST_SSH_SSHKEYGEN" -y -f "${SSH_BASE_KEY}-${type}${subtype}" \ + > "${SSH_BASE_KEY}-${type}${subtype}.pub" \ + ; show_status $? +} + + +cre_P12_Crt () { + printf '%s' "- ${extd}PKCS #12${norm} file" + $OPENSSL pkcs12 \ + -passin pass:"" \ + -passout pass:"" \ + -in "${SSH_BASE_KEY}-${type}${subtype}" \ + -out "${SSH_BASE_KEY}-${type}${subtype}".p12 \ + -export \ + ; show_status $? +} + + +revoke_crt () { + echo "=== revoke a CRT ===" >> "$OPENSSH_LOG" + printf '%s' "- ${extd}revoke${norm} certificate" + $OPENSSL ca \ + -config "${SSH_CACFGFILE}" \ + -name "CA_OpenSSH_${type}" \ + -passin pass:$KEY_PASS \ + -revoke "${SSH_BASE_KEY}-${type}${subtype}.crt" \ + 2>> "$OPENSSH_LOG" \ + ; show_status $? +} + + +# === +cre_all2 () { + echo + printf '%s\n' "creating ${extd}${SSH_X509V3_EXTENSIONS}${norm} for ${extd}${SSH_BASE_DN_CN}${norm}(${attn}${type}${norm}${warn}${subtype}${norm}) ..." + + cre_csr && + cre_crt || return $? + + test "$SSH_X509V3_EXTENSIONS" = "ocsp_cert" && return 0 + + cre_OpenSSH_Crt && + cre_OpenSSH_PubKey && + cre_P12_Crt +} + + +# === +cre_all () { +( + subtype="" + for type in ${SSH_SIGN_TYPES}; do + cre_all2 || exit $? + done + + test "$SSH_X509V3_EXTENSIONS" = "srv_cert" && exit 0 + + subtype="-revoked" + for type in ${SSH_SIGN_TYPES}; do + cre_all2 && + revoke_crt || exit $? + done + + exit 0 +) +} + +# === + +cre_all; retval=$? + +echo +show_status $retval "${extd}Creating${norm} ${attn}${SSH_BASE_DN_CN}${norm} group of ${warn}test${norm} certificates" diff -ruN openssh-5.6p1/tests/CA/4-cre_crls.sh openssh-5.6p1+x509-6.2.3/tests/CA/4-cre_crls.sh --- openssh-5.6p1/tests/CA/4-cre_crls.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/4-cre_crls.sh 2006-02-16 22:07:09.000000000 +0200 @@ -0,0 +1,113 @@ +#! /bin/sh +# Copyright (c) 2002-2004 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Create "Test Certificate Authority" CRLs. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/4-cre_crls.sh$//'` +. "${SCRIPTDIR}shell.rc" +. "${SCRIPTDIR}functions" +. "${SCRIPTDIR}config" + + +OPENSSH_LOG="$CWD/openssh_ca-4.log" +create_empty_file .delmy && +update_file .delmy "$OPENSSH_LOG" > /dev/null || exit $? + + +# === +cre_crlfile() { +( + type="$1" + + cd "${SSH_CACRLDIR}" || exit $? + + FILE="${CAKEY_PREFIX}-${type}.crl.pem" + + printf '%s' "- ${attn}${type}${norm} certificates" + ${OPENSSL} ca \ + -config "${SSH_CACFGFILE}" \ + -name "CA_OpenSSH_${type}" \ + -passin pass:${KEY_PASS} \ + -gencrl \ + -out "${FILE}" \ + 2>> "$OPENSSH_LOG" \ + ; show_status $? || exit $? + + HASH=`${OPENSSL} crl -out /dev/null -in "${FILE}" -hash 2>> "$OPENSSH_LOG"` || exit $? + + NAME=`getNextFreeName "${HASH}.r"` || exit $? + + ln -s "${FILE}" "${NAME}" + #link might never fail :-( + test -h "${NAME}" +) +} + + +# === +cre_crlindir () { + echo "=== create a new CRL ===" >> "$OPENSSH_LOG" + rm -f "${SSH_CACRLDIR}"/* 2>/dev/null + + printf '%s\n' "creating ${extd}CA CRL file${norm} for ..." + for type in ${SSH_SIGN_TYPES}; do + cre_crlfile "${type}" || return $? + done + + return 0 +} + + +# === +cre_CAcrlfile () { +( + crlfile="${SSH_CAROOT}/${CACRLFILE}" + + create_empty_file "${crlfile}" && + for type in ${SSH_SIGN_TYPES}; do + ( ${OPENSSL} crl \ + -in "${SSH_CACRLDIR}/${CAKEY_PREFIX}-${type}.crl.pem" \ + -text \ + 2>> "$OPENSSH_LOG" + echo; echo + ) >> "${crlfile}" || exit $? + done + + exit 0 +) +} + + +# === +cre_all () { + cre_crlindir || return $? + + printf '%s' "creating ${extd}CA CRL ${attn}common${norm} ${extd}file${norm} ..." + cre_CAcrlfile; show_status $? +} + + +# === +cre_all; retval=$? + +show_status $retval "${extd}Creating${norm} ${warn}TEST${norm} ${attn}Certificate Authority${norm} CRL files" diff -ruN openssh-5.6p1/tests/CA/5-cre_ldap.sh openssh-5.6p1+x509-6.2.3/tests/CA/5-cre_ldap.sh --- openssh-5.6p1/tests/CA/5-cre_ldap.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/5-cre_ldap.sh 2007-08-28 01:08:11.000000000 +0300 @@ -0,0 +1,127 @@ +#! /bin/sh +# Copyright (c) 2004-2007 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Create LDAP files. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/5-cre_ldap.sh$//'` +. "${SCRIPTDIR}shell.rc" +. "${SCRIPTDIR}functions" +. "${SCRIPTDIR}config" +. ./env + + +if test ! -d ldap/data; then + mkdir -p ldap/data || exit $? +fi + + +# === +cre_base_ldif() { +( + cat < ldap/base.ldif +} + + +# === +cre_slapdconf () { +( + cat < ldap/slapd.conf.tmpl + +} + + +# === + +cre_base_ldif && +cre_slapdconf && +: ; retval=$? + +show_status $retval "${extd}Creating${norm} ${warn}LDAP${norm} ${attn}files${norm}" diff -ruN openssh-5.6p1/tests/CA/config openssh-5.6p1+x509-6.2.3/tests/CA/config --- openssh-5.6p1/tests/CA/config 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/config 2010-02-28 00:49:36.000000000 +0200 @@ -0,0 +1,201 @@ +# Copyright (c) 2002-2006 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: OpenSSH CA configuration. +# + + +# === main variables: +# on some system (with pam?, AIX?, when port is below 1024, etc.) we +# might use sudo command to start sshd when current user isn`t root or +# to run tests as root. +# Prefered user for tests is NOT root :-) ! +SUDO= +#SUDO=sudo + + +#Old BSD shells, including the Ultrix `sh', don't accept the colon +#for any shell substitution, and complain and die. +##TMPDIR="${TMPDIR:-/tmp}" + +if test -n "$TMPDIR"; then + if test ! -d "$TMPDIR"; then + echo "error: $TMPDIR is not directory" + exit 1 + fi + if test ! -w "$TMPDIR"; then + echo "error: $TMPDIR is not writable" + exit 1 + fi +else + for D in /tmp /var/tmp /usr/tmp; do + test -d $D || continue + test -w $D || continue + TMPDIR=$D + break + done + if test -z "$TMPDIR"; then + echo "error: cannot set TMPDIR" + exit 1 + fi +fi + + +if test -z "${SSH_X509TESTS}"; then +SSH_X509TESTS="\ + blob_auth + dn_auth_file + dn_auth_path + agent + crl + self + alg + ocsp + by_ldap +" +fi + + +# === openssl: + +if test -z "${OPENSSL}"; then + OPENSSL=`which openssl 2>/dev/null` + if test -z "${OPENSSL}"; then + echo "error:cannot find openssl is your path !" >&2 + exit 1 + fi +fi + +printf 'OpenSSL executable version: ' +"${OPENSSL}" version || exit $? + +# These are the known patent issues with OpenSSL: +# name # expires +# mdc2: 4,908,861 13/03/2007 - enabled in OpenSSL 1.x branches from 2009-08-12 +# idea: 5,214,703 25/05/2010 +# rc5: 5,724,428 03/03/2015 +# +# Note the MD2 hash algorithm is considered as weak (2009) and +# most vendors disable it in openssl. Also from 2009-07-08 +# OpenSSL team disable md2 by default in 0.9.8 and 1.x branches. +# This is reason md2 to be removed from list starting with +# "X.509 certificate support version 6.3". + +if test -z "${RSA_DIGEST_LIST}"; then + for DIGEST in md5 sha1 mdc2 md4 rmd160; do + if "${OPENSSL}" dgst -${DIGEST} "${OPENSSL}" >/dev/null 2>&1; then + RSA_DIGEST_LIST="${RSA_DIGEST_LIST} ${DIGEST}" + fi + done +fi +if test -z "${RSA_DIGEST_LIST}"; then + echo "RSA_DIGEST_LIST is empty" >&2 + exit 1 +fi +echo "RSA digest list: ${RSA_DIGEST_LIST}" + + +SSH_SIGN_TYPES="" +for DIGEST in ${RSA_DIGEST_LIST}; do + SSH_SIGN_TYPES="${SSH_SIGN_TYPES} rsa_${DIGEST}" +done + SSH_SIGN_TYPES="${SSH_SIGN_TYPES} dsa" + + +# === server section: + +if test -z "${SSHD_PORT}"; then + SSHD_PORT=20022 +fi + +SSHD_LISTENADDRESS=127.0.0.1 +#SSHD_LISTENADDRESS=::1 + +#"yes" or "no" +SSHSERVER_USEPRIVILEGESEPARATION="yes" +#SSHSERVER_USEPRIVILEGESEPARATION="no" + +SSHSERVER_SYSLOGFACILITY=AUTH +SSHSERVER_LOGLEVEL=FATAL +#SSHSERVER_SYSLOGFACILITY=LOCAL3 +#SSHSERVER_LOGLEVEL=DEBUG3 + + +# === certificates: + +KEY_PASS="change_it" +CAKEY_PREFIX="catest" + +SSH_CAROOT="`pwd`/ca-test" +SSH_CAKEYDIR="${SSH_CAROOT}/keys" + +CACERTFILE="catest-bundle.crt" +CACRLFILE="catest-bundle.crl" + +SSH_CACERTDIR="${SSH_CAROOT}/crt" +SSH_CACRLDIR="${SSH_CAROOT}/crl" + +CACONFIG="catest.config" +SSH_CACFGFILE="${SSH_CAROOT}/${CACONFIG}" + +SSH_CACERTDAYS=60 + +SSH_DN_C="XX" +SSH_DN_ST="World" +SSH_DN_L="Somewhere" +SSH_DN_O="OpenSSH Test Team" +SSH_DN_OU="OpenSSH Testers" +SSH_DN_EM="email@not.set" + +SSH_DN_UTF8_FLAG='-utf8' +# '-utf8' flag is added in OpenSSL 0.9.7 +case "`${OPENSSL} version`" in + *0.9.6*) + SSH_DN_UTF8_FLAG= + ;; + *);; +esac +if test -n "${SSH_DN_UTF8_FLAG}"; then + SSH_DN_L="$SSH_DN_L cyrillic-АБВГабвг greek-ΑΒΓΔαβγδ" + SSH_DN_O="$SSH_DN_O cyrillic-АБВГабвг greek-ΑΒΓΔαβγδ" + SSH_DN_OU="$SSH_DN_OU cyrillic-АБВГабвг greek-ΑΒΓΔαβγδ" +fi + +# OpenSSL OCSP test responders listen on BASE, BASE+1, ... +if test -z "${SSH_VA_BASEPORT}"; then + SSH_VA_BASEPORT=20080 +fi + +# OpenSSL OCSP responder don't use SO_REUSEADDR :-(, so ocsp tests +# must wait socket to close. +SSH_OPENSLL_OCSP_TMOUT=60 + +# === LDAP: +SSH_LDAP_DB=bdb +# "hdb" backend since openldap 2.2+ +#SSH_LDAP_DB=hdb +# openldap 2.4+ deprecate "ldbm" backend +#SSH_LDAP_DB=ldbm +SSH_LDAP_DC="dc=example,dc=com" + +if test -z "${LDAPD_PORT}"; then + LDAPD_PORT=20389 +fi +LDAPD_URL="ldap://${SSHD_LISTENADDRESS}:${LDAPD_PORT}" diff -ruN openssh-5.6p1/tests/CA/env.in openssh-5.6p1+x509-6.2.3/tests/CA/env.in --- openssh-5.6p1/tests/CA/env.in 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/env.in 2004-10-29 22:52:46.000000000 +0300 @@ -0,0 +1,4 @@ +# LDAP environment: +@LDAP_ON@LDAP_SYSCONFDIR="@LDAP_SYSCONFDIR@" +@LDAP_ON@LDAP_LIBEXECDIR="@LDAP_LIBEXECDIR@" +@LDAP_ON@LDAP_BINDIR="@LDAP_BINDIR@" diff -ruN openssh-5.6p1/tests/CA/functions openssh-5.6p1+x509-6.2.3/tests/CA/functions --- openssh-5.6p1/tests/CA/functions 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/functions 2007-02-11 18:29:44.000000000 +0200 @@ -0,0 +1,287 @@ +# Copyright (c) 2002-2004 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Usefull functions. +# + + +# === +# +# define colors and more for echo commands +# +# \033 ascii ESCape +# \033[G move to column (linux console, xterm, not vt100) +# \033[C move columns forward but only upto last column +# \033[D move columns backward but only upto first column +# \033[A move rows up +# \033[B move rows down +# \033[1m switch bold on +# \033[31m switch red on +# \033[32m switch green on +# \033[33m switch yellow on +# \033[m switch color/bold off +# \017 exit alternate mode (xterm, vt100, linux console) +# \033[10m exit alternate mode (linux console) +# \015 carriage return (without newline) +# + +if test -z "${LINES}" -o -z "${COLUMNS}" ; then + eval `stty size 2>/dev/null | (read L C; \ + if test x${L} = x; then L=24; fi; \ + if test x${C} = x; then C=80; fi; \ + echo LINES=${L} COLUMNS=${C} )` +fi +test ${LINES} -eq 0 && LINES=24 +test ${COLUMNS} -eq 0 && COLUMNS=80 +export LINES COLUMNS + +if test "${TERM}" != "dumb" ; then + esc=`printf '\033'` + extd="${esc}[1m" + warn="${esc}[1;31m" + done="${esc}[1;32m" + attn="${esc}[1;34m" + norm=`printf '%s\017' "${esc}[m"` + stat=`printf '\015%s' "${esc}[${COLUMNS}C${esc}[10D"` + + msg_done="${stat}${done}done${norm}" + msg_failed="${stat}${warn}failed${norm}" + +else + esc="" + extd="" + warn="" + done="" + attn="" + norm="" + stat="" + + msg_done="..done" + msg_failed="..failed" + +fi + + +# === +error_file_not_found () { + echo "${warn}file ${attn}${1}${warn} not found${norm}" + return 1 +} + + +# === +error_file_not_readable () { + echo "${warn}file ${attn}${1}${warn} not found or not readable${norm}" + return 1 +} + + +# === +error_dir_not_found () { + echo "${warn}directory ${attn}${1}${warn} not found${norm}" + return 1 +} + + +# === +printSeparator() { + echo "=======================================================================" +} + + +# === +show_status () { + if test -n "$2"; then + printf '%s' "$2" + fi + if test $1 -eq 0; then + echo "$msg_done" + else + echo "$msg_failed" + fi + return $1 +} + + +# === +getNextFreeName() { + var="$1" + limit="$2" + + if test -z "${limit}"; then + limit=10 + fi + + count=0 + while true; do + test ! -f "${var}${count}" && break + count=`expr ${count} + 1` + if test ${count} -ge ${limit}; then + echo "getNextFreeName: ${warn}limit reached${norm} for file ${attn}${var}${norm}" >&2 + + echo "" + return 33 + fi + done + + echo "${var}${count}" + return 0 +} + + +# === +getNextDirName() { + var="$1" + count=0 + while true; do + test ! -d "${var}.${count}" && break + count=`expr ${count} + 1` + done + if test ${count} -ge 10; then + echo "${warn}please remove ${attn}${var}${warn} backup directories !${norm}" >&2 + return 33 + fi + echo $count + return 0 +} + + +# === +create_empty_file () { + cat /dev/null > "$1" +} + + +# === +update_file () { + var_new="$1" + var_old="$2" + + if test ! -f "${var_old}"; then + printf '%s' "creating file ${attn}${var_old}${norm}" + mv "${var_new}" "${var_old}"; show_status $? + return $? + fi + test -r "${var_new}" || { error_file_not_readable "${var_new}"; return 1; } + + if diff "${var_old}" "${var_new}" >/dev/null 2>&1; then + echo "no changes in ${attn}${var_old}${norm}" + rm -f "${var_new}" + return 0 + fi + + backup=`getNextFreeName "${var_old}."` || return $? + printf '%s' "saving old file as ${attn}${backup}${norm}" + cp -p "${var_old}" "${backup}"; show_status $? || return $? + + printf '%s' "updating file ${attn}${var_old}${norm}" + if test ! -w "${var_old}"; then + chmod u+w "${var_old}" + not_writable="yes" + fi + cat "${var_new}" > "${var_old}"; show_status $? || return $? + if test "$not_writable" = "yes"; then + chmod u-w "${var_old}" + fi + rm -f "${var_new}" + return 0 +} + + +# === +getSSHkeyType () { + identity_file="$1" + if test ! -r "$identity_file"; then + error_file_not_readable "${identity_file}" >&2; return $? + fi + + sshkeytype="unspec" + retval=0 + + sshkeytype=`"${TEST_SSH_SSHKEYGEN}" -f "${identity_file}" -y 2>/dev/null`; retval=$? + if test $retval -ne 0 ; then + echo "${warn}command${norm} ${TEST_SSH_SSHKEYGEN} ${warn}fail${norm}" >&2 + return $retval + fi + echo "${sshkeytype}" | cut -d ' ' -f 1 + return 0 +} + + +# === +getSubject () { + identity_file="$1" +#rest of arguments passed to openssl + + if test ! -r "$identity_file"; then + error_file_not_readable "${identity_file}" >&2 + return 1 + fi + shift + + retval=0 + +#SHELL bug or ?: when we assign command result to "local xxx=..." retval is always zero :-/ !!! +#unix sh don't like local :-) +# local subject=`"${OPENSSL}" x509 -noout -subject -in "${identity_file}" $*`; retval=$? +# + if test -n "${SSH_DN_UTF8_FLAG}"; then + NAMEOPT="-nameopt utf8,sep_comma_plus" #ok + #NAMEOPT="-nameopt esc_2253,esc_ctrl,esc_msb,utf8,dump_nostr,dump_der,use_quote,sep_comma_plus_space,sname" #fail - esc_msb should be removed + #NAMEOPT="-nameopt esc_2253,esc_ctrl,utf8,dump_nostr,dump_der,use_quote,sep_comma_plus_space,sname" #ok + #NAMEOPT="-nameopt esc_2253,esc_ctrl,-esc_msb,utf8,dump_nostr,dump_der,use_quote,sep_comma_plus_space,sname" #ok + #NAMEOPT="-nameopt esc_2253,esc_ctrl,esc_msb,utf8,dump_nostr,dump_der,use_quote,sep_comma_plus_space,sname,-esc_msb" #ok + #NAMEOPT="-nameopt oneline,-esc_msb,-space_eq" #ok + #NAMEOPT="-nameopt oneline,-esc_msb" #now ok (spaces around '=') + else + NAMEOPT= + fi + subject=`"${OPENSSL}" x509 -noout -subject ${NAMEOPT} -in "${identity_file}" $* 2>/dev/null`; retval=$? + if test $retval -ne 0 ; then + echo "${warn}cannot get certificate subject${norm}" >&2 + return $retval + fi + echo "$subject" | cut -d ' ' -f 2- +} + + +#=== +creX509AuthorizedKeysFile () { + identity_file="$1" + + sshkeytype=`getSSHkeyType "${identity_file}"` || return $? + subject=`getSubject "${identity_file}"` || return $? + echo "${sshkeytype} subject ${subject}" > "${AUTHORIZEDKEYSFILE}" +} + + +# === +utf8base64() { + if test -n "${SSH_DN_UTF8_FLAG}"; then + printf ':' + printf "$1" | ${OPENSSL} enc -a -e | xargs printf ' %s\n' + else + printf " $1" + fi +} + + +# === +FUNCTIONS_INCLUDED="yes" diff -ruN openssh-5.6p1/tests/CA/Makefile.in openssh-5.6p1+x509-6.2.3/tests/CA/Makefile.in --- openssh-5.6p1/tests/CA/Makefile.in 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/Makefile.in 2007-01-27 16:59:16.000000000 +0200 @@ -0,0 +1,134 @@ +srcdir=@srcdir@ +@OCSP_ON@SSH_OCSP=yes +@OCSP_OFF@SSH_OCSP=no +RSAKEYBITS=2048 + + +all: + + +clean: ldap_clean + rm -f testhostkey_* + rm -f testid_* + rm -f testocsp_* + rm -fr ca-test/ + rm -f openssh_ca-?.log* + rm -f openssh_ca-3.*.log* + rm -f va-*.log + rm -f sshd_x509.log + +distclean: clean + rm -f env + rm -f Makefile + +# === + +check-certs: ca_files hostkeys identities ocsp_certs crl_files ldap_files + @echo + $(SHELL) $(srcdir)/openssh_tests.sh + +# === +ca_files: ca-test/catest.config ca-test/catest-bundle.crt + +#user is responsible to recreate X.509 tests files !!! +#ca-test/catest.config: $(srcdir)/config +ca-test/catest.config: + @echo + SSH_OCSP=$(SSH_OCSP) \ + $(SHELL) $(srcdir)/1-cre_cadb.sh + +ca-test/catest-bundle.crt: ca-test/catest.config + @echo + $(SHELL) $(srcdir)/2-cre_cakeys.sh + + +# === +hostkeys: testhostkey_rsa testhostkey_rsa-rsa_md5 testhostkey_dsa testhostkey_dsa-rsa_md5 + +testhostkey_rsa: + @echo + @echo "generating RSA 'hostkey'" + $(TEST_SSH_SSHKEYGEN) -t rsa -b $(RSAKEYBITS) -f $@ -N "" + +testhostkey_rsa-rsa_md5: testhostkey_rsa ca-test/catest-bundle.crt + @echo + @echo "generating RSA server certificates, keys, etc." + $(SHELL) $(srcdir)/3-cre_certs.sh -f testhostkey_rsa -t server -n "localhost RSA" + +testhostkey_dsa: + @echo + @echo "generating DSA 'hostkey'" + $(TEST_SSH_SSHKEYGEN) -t dsa -f $@ -N "" + +testhostkey_dsa-rsa_md5: testhostkey_dsa ca-test/catest-bundle.crt + @echo + @echo "generating DSA server certificates, keys, etc." + $(SHELL) $(srcdir)/3-cre_certs.sh -f testhostkey_dsa -t server -n "localhost DSA" + + +# === +identities: testid_rsa testid_rsa-rsa_md5 testid_dsa testid_dsa-rsa_md5 + +testid_rsa: + @echo + @echo "generating RSA 'Identity'" + $(TEST_SSH_SSHKEYGEN) -t rsa -b $(RSAKEYBITS) -f $@ -N "" + +testid_rsa-rsa_md5: testid_rsa ca-test/catest-bundle.crt + @echo + @echo "generating RSA client certificates, keys, etc." + $(SHELL) $(srcdir)/3-cre_certs.sh -f testid_rsa -t client -n "OpenSSH RSA test certificate" + +testid_dsa: + @echo + @echo "generating DSA 'Identity'" + $(TEST_SSH_SSHKEYGEN) -t dsa -f $@ -N "" + +testid_dsa-rsa_md5: testid_dsa ca-test/catest-bundle.crt + @echo + @echo "generating DSA client certificates, keys, etc." + $(SHELL) $(srcdir)/3-cre_certs.sh -f testid_dsa -t client -n "OpenSSH DSA test certificate" + + +# === +@OCSP_OFF@ocsp_certs: +@OCSP_ON@ocsp_certs: testocsp_rsa-rsa_md5.crt testocsp_dsa-rsa_md5.crt + +@OCSP_ON@testocsp_rsa-rsa_md5.crt: testocsp_rsa ca-test/catest-bundle.crt +@OCSP_ON@ @echo; echo "generating RSA ocsp responder certificates." +@OCSP_ON@ SSH_OCSP=$(SSH_OCSP) \ +@OCSP_ON@ $(SHELL) $(srcdir)/3-cre_certs.sh -f testocsp_rsa -t ocsp -n "validator RSA" + +@OCSP_ON@testocsp_rsa: +@OCSP_ON@ @echo; echo "generating RSA 'ocspkey'" +@OCSP_ON@ $(TEST_SSH_SSHKEYGEN) -t rsa -b $(RSAKEYBITS) -f $@ -N "" + +@OCSP_ON@testocsp_dsa-rsa_md5.crt: testocsp_dsa ca-test/catest-bundle.crt +@OCSP_ON@ @echo; echo "generating DSA ocsp responder certificates." +@OCSP_ON@ SSH_OCSP=$(SSH_OCSP) \ +@OCSP_ON@ $(SHELL) $(srcdir)/3-cre_certs.sh -f testocsp_dsa -t ocsp -n "validator DSA" + +@OCSP_ON@testocsp_dsa: +@OCSP_ON@ @echo; echo "generating DSA 'ocspkey'" +@OCSP_ON@ $(TEST_SSH_SSHKEYGEN) -t dsa -f $@ -N "" + + +# === +crl_files: ca-test/catest-bundle.crl + +ca-test/catest-bundle.crl: testid_rsa-rsa_md5 testid_dsa-rsa_md5 + @echo + $(SHELL) $(srcdir)/4-cre_crls.sh + +# === +@LDAP_OFF@ldap_files: +@LDAP_ON@ldap_files: ldap/slapd.conf.tmpl + +@LDAP_ON@ldap/slapd.conf.tmpl: env +@LDAP_ON@ @echo +@LDAP_ON@ $(SHELL) $(srcdir)/5-cre_ldap.sh + +@LDAP_OFF@ldap_clean: +@LDAP_ON@ldap_clean: +@LDAP_ON@ rm -f ldap_setup.log +@LDAP_ON@ rm -fr ldap diff -ruN openssh-5.6p1/tests/CA/openssh_tests.sh openssh-5.6p1+x509-6.2.3/tests/CA/openssh_tests.sh --- openssh-5.6p1/tests/CA/openssh_tests.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/openssh_tests.sh 2010-02-28 00:38:06.000000000 +0200 @@ -0,0 +1,368 @@ +#! /bin/sh +# Copyright (c) 2002-2006 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Test OpenSSH client and server with x509 certificates. +# + + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/openssh_tests.sh//'` +. "${SCRIPTDIR}shell.rc" +. "${SCRIPTDIR}functions" +. "${SCRIPTDIR}config" +. "./env" + +test "x$TEST_SSH_SSH" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSH${norm}" ; exit 1; } +test "x$TEST_SSH_SSHD" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHD${norm}" ; exit 1; } +test "x$TEST_SSH_SSHAGENT" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHAGENT${norm}" ; exit 1; } +test "x$TEST_SSH_SSHADD" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHADD${norm}" ; exit 1; } +test "x$TEST_SSH_SSHKEYGEN" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHKEYGEN${norm}"; exit 1; } +#TEST_SSH_SSHKEYSCAN +#TEST_SSH_SFTP +#TEST_SSH_SFTPSERVER + +# prevent user environment influence +unset SSH_AGENT_PID +unset SSH_AUTH_SOCK + +# regression test files +SSHD_LOG="${CWD}/sshd_x509.log" +SSHD_PID="${CWD}/.sshd_x509.pid" +SSHD_CFG="${CWD}/sshd_config-certTests" +SSH_CFG="${CWD}/ssh_config-certTests" + +SSH_ERRLOG="${CWD}/.ssh_x509.err.log" +SSH_REPLY="${CWD}/.ssh_x509.reply" +SSH_EXTRA_OPTIONS="" + + +TEST_SSH_CLIENTKEYS="\ + testid_rsa + testid_dsa +" + +#OpenSSL OCSP limitation: only rsa keys +#TEST_OCSP_RESPKEYS="\ +# testocsp_rsa +# testocsp_dsa +#" +TEST_OCSP_RESPKEYS="testocsp_rsa" + +#TEST_SSHD_HOSTKEY="${CWD}/testhostkey_rsa-rsa_md5" +TEST_SSHD_HOSTKEY="${CWD}/testhostkey_rsa" + + +USERDIR="${HOME}/.ssh" +if test ! -d "${USERDIR}"; then + mkdir "${USERDIR}" || exit 1 + chmod 700 "${USERDIR}" || exit 1 +fi + +AUTHORIZEDKEYSFILE="${USERDIR}/authorized_keys-certTests" +USERKNOWNHOSTSFILE="${USERDIR}/known_hosts-certTests" + + +# === +# remove unsupported tests + +cat > "$SSHD_CFG" < "${SSHD_LOG}" 2>&1 +if grep 'Unsupported.*CACertificateFile' "${SSHD_LOG}" > /dev/null; then + SSH_X509STORE_DISABLED="yes" +else + SSH_X509STORE_DISABLED="no" +fi +if grep 'Unsupported.*CAldapURL' "${SSHD_LOG}" > /dev/null; then + SSH_LDAP_ENABLED="no" +else + SSH_LDAP_ENABLED="yes" +fi +if grep 'Unsupported.*VAType' "${SSHD_LOG}" > /dev/null; then + SSH_OCSP_ENABLED="no" +else + SSH_OCSP_ENABLED="yes" +fi + +echo SSH_X509STORE_DISABLED=${SSH_X509STORE_DISABLED} +if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then + SSH_X509TESTS=`echo "${SSH_X509TESTS}" | \ + sed \ + -e 's|dn_auth_file||g' \ + -e 's|dn_auth_path||g' \ + -e 's|crl||g' \ + -e 's|self||g'` +fi +echo SSH_LDAP_ENABLED=${SSH_LDAP_ENABLED} +if test "x${SSH_LDAP_ENABLED}" = "xno"; then + SSH_X509TESTS=`echo "${SSH_X509TESTS}" | sed -e 's|by_ldap||g'` +fi +echo SSH_OCSP_ENABLED=${SSH_OCSP_ENABLED} +if test "x${SSH_OCSP_ENABLED}" = "xno"; then + SSH_X509TESTS=`echo "${SSH_X509TESTS}" | sed -e 's|ocsp||g'` +fi +echo SSH_X509TESTS=$SSH_X509TESTS + + +# === +runSSHdaemon() { + echo "=======================================================================" >> "${SSHD_LOG}" + + if test -f "${SSHD_PID}"; then + echo "${warn}sshd pid file exist!${norm}" >&2 + fi + + #NOTES: + #- without -d option sshd run in daemon mode and this command always return 0 !!! + #- bug or ?: with option -e no log to stderr in daemon mode + $SUDO "$TEST_SSH_SSHD" -f "${SSHD_CFG}" \ + -o PidFile="${SSHD_PID}" \ + -o SyslogFacility="${SSHSERVER_SYSLOGFACILITY}" \ + -o LogLevel="${SSHSERVER_LOGLEVEL}" \ + >> "${SSHD_LOG}" 2>&1 + + sleep 3 + if test ! -f "${SSHD_PID}"; then + printf "${warn}cannot start sshd:${norm} " >&2 + error_file_not_readable "${SSHD_PID}" + return 33 + fi +} + + +# === +killSSHdaemon() { +( + $SUDO kill `cat "${SSHD_PID}" 2>/dev/null` > /dev/null 2>&1 + K=0 + while test $K -le 9; do + if test ! -f "${SSHD_PID}"; then + break + fi + sleep 1 + K=`expr $K + 1` + done + rm -f "${SSHD_CFG}" + if test -f "${SSHD_PID}"; then + $SUDO kill -9 `cat "${SSHD_PID}" 2>/dev/null` > /dev/null 2>&1 + sleep 1 + $SUDO rm -f "${SSHD_PID}" > /dev/null 2>&1 + fi + exit 0 +) +} + + +# === +testEND() { + ( echo + echo "*=- The END -=*" + ) >> "${SSHD_LOG}" + + rm -f "${SSH_ERRLOG}" + rm -f "${SSH_REPLY}" + rm -f "${AUTHORIZEDKEYSFILE}" + rm -f "${USERKNOWNHOSTSFILE}" + rm -f "${SSH_CFG}" +} + +testBREAK() { + ( echo + echo "*=- BREAK -=*" + ) >> "${SSHD_LOG}" + killSSHdaemon +} + +trap testBREAK INT QUIT ABRT KILL TERM || exit 1 +trap testEND EXIT || exit 1 + + +# === +creTestSSHDcfgFile() { + cat > "${SSHD_CFG}" < "${SSH_CFG}" <> "${SSH_CFG}" < "${SSH_ERRLOG}" > "${SSH_REPLY}"; retval=$? + + if test "x$must_fail" = "x1"; then + if test $retval -ne 0; then + retval=0 + else + retval=1 + fi + fi + + show_status $retval + if test $retval -ne 0; then + printf '%s' "${warn}" + cat "${SSH_ERRLOG}"; printf '%s' "${norm}" + else + if test "x$must_fail" = "x1"; then + if fgrep 'Permission denied (publickey)' "${SSH_ERRLOG}" > /dev/null; then + printf '%s' "${done}" + else + retval=33 + printf '%s' "${warn}" + fi + cat "${SSH_ERRLOG}"; printf '%s' "${norm}" + else + if fgrep "$msg" "${SSH_REPLY}" > /dev/null; then + : + else + retval=33 + printf '%s' "${warn}" + cat "${SSH_REPLY}"; printf '%s' "${norm}" + fi + fi + fi + + exit $retval +) +} + + +# === +do_all () { + create_empty_file "${AUTHORIZEDKEYSFILE}" && + chmod 644 "${AUTHORIZEDKEYSFILE}" || return $? + + create_empty_file "${SSHD_LOG}" || return $? + + if test ! -f "${TEST_SSHD_HOSTKEY}.pub"; then + echo "${warn}Public host file ${attn}${TEST_SSHD_HOSTKEY}.pub${warn} not found !${norm}" + return 3 + fi + ( printf '%s' "${SSHD_LISTENADDRESS} " + cat "${TEST_SSHD_HOSTKEY}.pub" + ) > "${USERKNOWNHOSTSFILE}" && + chmod 644 "${USERKNOWNHOSTSFILE}" || return $? + + # call the test scripts + for LTEST in ${SSH_X509TESTS}; do + ( + echo + echo "using: ${attn}${SCRIPTDIR}test-${LTEST}.sh.inc${norm}" + . ${SCRIPTDIR}test-${LTEST}.sh.inc && + do_test + ) || return $? + done + + printSeparator + return 0 +} + + +# === +echo +printSeparator +echo "${extd}Testing OpenSSH client and server with certificates:${norm}" +printSeparator + +do_all; retval=$? + +echo +printSeparator +echo "${extd}Testing OpenSSH client and server with certificates finished.${norm}" +show_status $retval " ${extd}status${norm}:" +printSeparator +echo + +exit $retval diff -ruN openssh-5.6p1/tests/CA/shell.rc openssh-5.6p1+x509-6.2.3/tests/CA/shell.rc --- openssh-5.6p1/tests/CA/shell.rc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/shell.rc 2006-02-16 22:40:27.000000000 +0200 @@ -0,0 +1,34 @@ +# Copyright (c) 2003-2006 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Shell settings. +# + + +# Be Bourne compatible (as autoconf do it) +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi diff -ruN openssh-5.6p1/tests/CA/test-agent.sh.inc openssh-5.6p1+x509-6.2.3/tests/CA/test-agent.sh.inc --- openssh-5.6p1/tests/CA/test-agent.sh.inc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/test-agent.sh.inc 2007-02-27 22:56:10.000000000 +0200 @@ -0,0 +1,165 @@ +# +# Copyright (c) 2002-2004 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Test OpenSSH client authentication: +# - add a key to agent; +# - list agent keys; +# - try to connect with key from agent; +# - remove the key from agent. +# + + +# === +#env. vars: +# SSH_CLIENTKEY +# type +testAgent () { + identity_file="${SSH_CLIENTKEY}-${type}" + if test ! -r "${identity_file}"; then + error_file_not_readable "${identity_file}"; return $? + fi + + ( + if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then + cat "${identity_file}.pub" + else + sshkeytype=`getSSHkeyType "${identity_file}"` || exit $? + subject=`getSubject "${identity_file}"` || exit $? + + echo "${sshkeytype} Subject: ${subject}" + fi + ) > "${AUTHORIZEDKEYSFILE}" || return $? + +( +killAgent () { + "${TEST_SSH_SSHAGENT}" -k > /dev/null + sleep 1 + exit $1 +} + +checkEmptyListResponse () { + case $1 in + 1) return 0;; + 0) killAgent 99;; + *) killAgent $1;; + esac + return 33 +} + +showAgentMsg() { + show_status $1 "$2" + if test $1 -ne 0; then + printf '%s' "${warn}" + cat "${SSH_ERRLOG}" + printf '%s' "${norm}" + if test $1 -ne 2; then + killAgent $1 + fi + exit $1 + fi + + if test "x$3" != "x"; then + printf '%s' "${done}" + cat "$3" + printf '%s' "${norm}" + fi + return 0 +} + + eval `"${TEST_SSH_SSHAGENT}"` > /dev/null + + "${TEST_SSH_SSHADD}" -L >/dev/null; checkEmptyListResponse $? + + "${TEST_SSH_SSHADD}" "${identity_file}" 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + showAgentMsg $? " add identity ${extd}${SSH_CLIENTKEY}-${attn}${type}${norm} to agent ..." + + "${TEST_SSH_SSHADD}" -L 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + retval=$? + if test $retval -ne 0; then + showAgentMsg ${retval} + else + printf " ${done}-${norm} " + if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then + printf '%s.......\n' "`cut -c -60 \"${SSH_REPLY}\"`" + else + cat "${SSH_REPLY}" + fi + fi + +# TODO +# Note the current script run ssh with -i option, +# but ssh check existence of file and when file +# don't exit it is excluded from list of identity +# files. When the list is empty ssh will use +# default file names. To avoid this we will +# use /dev/null, until method runTest run ssh +# with -i option +#!!! "use-only-key-from-agent" \ + runTest "${type}" \ + "/dev/null" \ + "key from agent ..." || + killAgent $? + + "${TEST_SSH_SSHADD}" -d "${identity_file}".pub \ + 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + showAgentMsg $? " remove identity ${extd}${SSH_CLIENTKEY}-${attn}${type}${norm} from agent ..." + + "${TEST_SSH_SSHADD}" -L > /dev/null; checkEmptyListResponse $? + + killAgent 0 +) +} + + +# === + +do_test () { + retval=0 + if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then + echo "* ${extd}with x509 identity from ${attn}agent${norm}:" + else + echo "* ${extd}against ${attn}CACertificateFile${norm} and x509 identity from ${attn}agent${norm}:" + fi + + creTestSSHDcfgFile + if test "x${SSH_X509STORE_DISABLED}" != "xyes"; then + cat >> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" </dev/null > "${AUTHORIZEDKEYSFILE}" || exit $? + + if test -n "$must_fail"; then + typemsg="${identity_file} ${warn}!${norm}" + else + typemsg="${identity_file}" + fi + runTest "${typemsg}" \ + "${identity_file}" "" "$must_fail" || exit $? + + for type in ${SSH_SIGN_TYPES}; do + if test -n "$withcert"; then + must_fail="" + case $alg in + x509v3-sign-rsa*) test "$keytype" = "rsa" || must_fail="yes";; + x509v3-sign-dss*) test "$keytype" = "dsa" || must_fail="yes";; + *) echo "${warn}unknown X.509 alg${norm}" + exit 1;; + esac + else + must_fail="yes" + fi + + identity_file="${SSH_CLIENTKEY}-${type}" + "$TEST_SSH_SSHKEYGEN" -f "${identity_file}" -y 2>/dev/null > "${AUTHORIZEDKEYSFILE}" || exit $? + + if test -n "$must_fail"; then + typemsg="${identity_file} ${warn}!${norm}" + else + typemsg="${identity_file}" + fi + runTest "${typemsg}" \ + "${identity_file}" "" "$must_fail" || exit $? + done + done + ); retval=$? + killSSHdaemon + + return $retval +} + + +# === + +do_test () { + retval=0 + if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then + echo "* ${extd}with different publickey ${attn}algorithms${norm}:" + else + echo "* ${extd}against ${attn}CACertificateFile${norm} and different publickey ${attn}algorithms${norm}:" + fi + + for alg in \ + "ssh-rsa" \ + "ssh-dss" \ + "x509v3-sign-rsa" \ + "x509v3-sign-dss" \ + ; do + testAlg; retval=$? + if test $retval -ne 0; then + break + fi + done + return $retval +} diff -ruN openssh-5.6p1/tests/CA/test-blob_auth.sh.inc openssh-5.6p1+x509-6.2.3/tests/CA/test-blob_auth.sh.inc --- openssh-5.6p1/tests/CA/test-blob_auth.sh.inc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/test-blob_auth.sh.inc 2004-03-08 23:30:24.000000000 +0200 @@ -0,0 +1,84 @@ +# +# Copyright (c) 2002-2004 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Test OpenSSH client authentication: +# - "IdentityFile" contain private key and x509 certificate; +# - "AuthorizedKeysFile" contain certificate BLOB. +# + + +# === +#env. vars: +# SSH_CLIENTKEY +# type +testBLOBautorization () { + identity_file="${SSH_CLIENTKEY}-${type}" + if test ! -r "${identity_file}"; then + error_file_not_readable "${identity_file}"; return $? + fi + + echo " using identity file ${identity_file}" + echo " creating AuthorizedKeysFile" + "$TEST_SSH_SSHKEYGEN" -f "${identity_file}" -y 2>/dev/null > "${AUTHORIZEDKEYSFILE}" || return $? + runTest "${type}" "${identity_file}"\ + "${extd}valid${norm} blob" || return $? + + blob=`cat "${AUTHORIZEDKEYSFILE}"` + echo $blob | cut -c 1-50 > "${AUTHORIZEDKEYSFILE}" + runTest "${type}" "${identity_file}"\ + "${warn}invalid${norm} blob" "Yes" || return $? +} + + +# === + +do_test () { + retval=0 + if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then + echo "* ${extd}with autorization by x509 ${attn}blob${norm}:" + else + echo "* ${extd}against ${attn}CACertificateFile${norm} and autorization by x509 ${attn}blob${norm}:" + fi + + creTestSSHDcfgFile + if test "x${SSH_X509STORE_DISABLED}" != "xyes"; then + cat >> "$SSHD_CFG" < ${LDAPD_CFG} +} + + +# === +creTestLDAPDCAldifFile() { +( + for type in ${SSH_SIGN_TYPES}; do + N="${CAKEY_PREFIX}-${type}.crt" + if test ! -f "ldap/${N}.der"; then + ${OPENSSL} x509 \ + -in "${SSH_CACERTDIR}/${N}".pem \ + -out "ldap/${N}.der" -outform DER \ + || exit $? + fi + + N="${CAKEY_PREFIX}-${type}.crl" + if test ! -f "ldap/${N}.der"; then + ${OPENSSL} crl \ + -in "${SSH_CACRLDIR}/${N}".pem \ + -out "ldap/${N}.der" -outform DER \ + || exit $? + fi + done +) || return $? + +( + for type in ${SSH_SIGN_TYPES}; do + cat < ldap/ca.ldif +} + + +# === +runLDAPdaemon() { + if test -f "${LDAPD_PID}"; then + echo "${warn}slapd pid file exist!${norm}" >&2 + fi + + printf ' %s' "starting ${extd}LDAP${norm} server on ${attn}${LDAPD_URL}${norm}" + #for errors check syslog files(LOCAL4 facility) + $SUDO "${LDAP_LIBEXECDIR}/slapd" \ + -f "${LDAPD_CFG}" \ + -h "${LDAPD_URL}" \ + > /dev/null 2>&1 + + sleep 2 + K=0 + while test $K -le 5; do + if test -f "${LDAPD_PID}"; then + break + fi + sleep 1 + K=`expr $K + 1` + done + + test -r "${LDAPD_PID}"; show_status $? + if test ! -r "${LDAPD_PID}"; then + printf "${warn}cannot start slapd:${norm} " >&2 + error_file_not_readable "${LDAPD_PID}" + return 33 + fi + return 0 +} + + +killLDAPdaemon() { +( + $SUDO kill `cat "${LDAPD_PID}" 2>/dev/null` > /dev/null 2>&1 + K=0 + while test $K -le 9; do + if test ! -f "${LDAPD_PID}"; then + break + fi + sleep 1 + K=`expr $K + 1` + done + if test -f "${LDAPD_PID}"; then + $SUDO kill -9 `cat "${LDAPD_PID}" 2>/dev/null` > /dev/null 2>&1 + sleep 1 + $SUDO rm -f "${LDAPD_PID}" > /dev/null 2>&1 + $SUDO rm -f "${LDAPD_ARGS}" > /dev/null 2>&1 + fi + rm -f "${LDAPD_CFG}" + exit 0 +) +} + + +initLDAPdb() { + create_empty_file "${LDAP_SETUP_LOG}" || return $? + + "${LDAPADD}" \ + -x -w secret -D "cn=Manager,${SSH_LDAP_DC}" \ + -H "${LDAPD_URL}" \ + -f "${CWD}/ldap/base.ldif" \ + >> "${LDAP_SETUP_LOG}" 2>&1 || return $? + + "${LDAPADD}" \ + -x -w secret -D "cn=Manager,${SSH_LDAP_DC}" \ + -H "${LDAPD_URL}" \ + -f "${CWD}/ldap/ca.ldif" \ + >> "${LDAP_SETUP_LOG}" 2>&1 || return $? + + return 0 +} + + +# === +# $1 - LDAP version +testLDAP() { + printSeparator + echo "Begin test with LDAP ${extd}version${norm} ${attn}$1${norm}" + + creTestLDAPDcfgFile + creTestLDAPDCAldifFile + creTestSSHDcfgFile + +#openssh config parser limitation +SSH_CONF_LDAP_DC=`echo ${SSH_LDAP_DC} | sed -e 's|=|%3D|g' -e 's|,|%2C|'` + cat >> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" < /dev/null + FILE="${SSH_CACRLDIR}/${CAKEY_PREFIX}-${crltype}.crl.pem" + HASH=`${OPENSSL} crl -out /dev/null -in "${FILE}" -hash`; retval=$? + if test ${retval} -eq 0; then + hashfile="${CRL_TEST_DIR}/${HASH}.r0" + ln -s "${FILE}" "${hashfile}" + #link might never fail :-( + test -h "${hashfile}"; retval=$? + fi + #printf "${norm}" + show_status ${retval} || return $? + + ( + for type in ${SSH_SIGN_TYPES}; do + for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do + identity_file="${SSH_CLIENTKEY}-${type}-revoked" + + creX509AuthorizedKeysFile "${identity_file}" || exit $? + + if test "${type}" = "${crltype}"; then + runTest "${SSH_CLIENTKEY}-${warn}${type}-revoked${norm}" \ + "${identity_file}" "" "Yes" + else + runTest "${identity_file}" \ + "${identity_file}" "" "" + fi || exit $? + done + done + exit 0 + ); retval=$? + + if test ${retval} -eq 0; then + rm -f "${hashfile}"; retval=$? + else + rm -f "${hashfile}" + fi + return ${retval} +} + + +# === +test_onlyonecrl () { + retval=0 + CRL_TEST_DIR="${SSH_CAROOT}/crl-test" + + printSeparator + echo "Check ${extd}revoked${norm} with only ${attn}one CRL${norm} in ${attn}CARevocationPath${norm} ..." + + mkdir -p "${CRL_TEST_DIR}" || return $? + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" < /dev/null + if test ${retval} -eq 0; then + rmdir "${CRL_TEST_DIR}"; retval=$? + else + rmdir "${CRL_TEST_DIR}" + fi + return ${retval} +} + + +# === +test_crlpresence_yes () { + printSeparator + echo "Begin test with mandatory ${extd}CRL presence ${attn}with${norm} CRL ..." + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" < "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${subtype}" "${identity_file}" "" || return $? + done + + subtype="subject" + subject=`getSubject "${identity_file}" -nameopt RFC2253 -nameopt -esc_msb` || return $? + echo "${sshkeytype} ${subtype} ${subject}" > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${subtype} in ${attn}RFC2253${norm} format" "${identity_file}" "" || return $? + + echo "${sshkeytype} ${subtype} ${subject}" | sed -e 's/,/\//'> "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${subtype} and mixed item-separator symbol" "${identity_file}" "" || return $? + + for subtype in \ + "Invalid" \ + "Subject-" \ + ; do + echo "${sshkeytype} ${subtype} ${subject}" > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${warn}${subtype}${norm}" "${identity_file}" \ + "autorization type" "Yes" || return $? + done + + subtype="Subject" + printf "${sshkeytype} ${subtype}," > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${warn}empty${norm} ${subtype}" "${identity_file}" \ + "" "Yes" || return $? + + subtype="Subject" + ( printf "${sshkeytype} ${subtype}" + echo "${subject}" | cut -c -40 + ) > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${warn}invalid${norm} ${subtype}" "${identity_file}" \ + "" "Yes" || return $? + + return 0 +} + + +# === + +do_test () { + if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then + echo "* ${extd}X.509 store${norm} is ${attn}disabled${norm}" + return 1 + fi + echo "* ${extd}against ${attn}CACertificateFile${norm} and autorization by x509 ${attn}'Distinguished Name'${norm}:" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" </dev/null + + for catype in ${SSH_SIGN_TYPES}; do + F="${SSH_CACERTDIR}/${CAKEY_PREFIX}-${catype}.crt.pem" + HASH=`$OPENSSL x509 -in "${F}" -noout -hash` + ( cd "${CRT_TEST_DIR}" || exit $? + ln -s "${F}" "$HASH.0" + #link might never fail :-( + test -h "$HASH.0" + ) && + do_test_catype; retval=$? + rm -f "${CRT_TEST_DIR}/$HASH.0" + if test $retval -ne 0; then + break + fi + done + + rmdir "${CRT_TEST_DIR}" + if test $retval -ne 0; then + exit $retval + fi + done + + exit 0 + ); retval=$? + killSSHdaemon + return $retval +} diff -ruN openssh-5.6p1/tests/CA/test-ocsp.sh.inc openssh-5.6p1+x509-6.2.3/tests/CA/test-ocsp.sh.inc --- openssh-5.6p1/tests/CA/test-ocsp.sh.inc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/tests/CA/test-ocsp.sh.inc 2006-09-01 00:35:03.000000000 +0300 @@ -0,0 +1,255 @@ +# +# Copyright (c) 2004 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 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. +# +# DESCRIPTION: Test OpenSSH client authentication: +# - "IdentityFile" contain private key and x509 certificate; +# - "AuthorizedKeysFile" contain certificate Subject; +# - validation against: +# - OCSP provider from certificate +# - specified in configuration OCSP provider +# - TODO:specified OCSP provider with revoked provider certificate +# Note: +# Due OpenSSL limitation no one of tests start OCSP provider with dsa key. +# + + +# === +openssl_ocsp_tmout() { +( + if test -z "${SSH_OPENSLL_OCSP_TMOUT}"; then + sleep 1 + exit 0 + fi + + count=${SSH_OPENSLL_OCSP_TMOUT} + echo "OpenSSL OCSP responder socket timeout ${count}[sec.]" >&2 + while test ${count} -gt 0; do + printf 'O' + sleep 1 + count=`expr ${count} - 1` + done + printf 'X\n' +) +} + + +# === +killResponders() { +( + if test -z "${SSH_OPENSLL_OCSP_TMOUT}"; then + ( + has="" + for pidfile in va-*.pid; do + if test -r "${pidfile}"; then + kill `cat "${pidfile}"` > /dev/null 2>&1 + has="yes" + fi + done + if test -n "${has}"; then + openssl_ocsp_tmout + fi + ) + fi + ( + has="" + for pidfile in va-*.pid; do + if test -r "${pidfile}"; then + kill -9 `cat "${pidfile}"` > /dev/null 2>&1 + rm -f "${pidfile}" + has="yes" + fi + done + if test -n "${has}"; then + openssl_ocsp_tmout + fi + ) + : +) +} + + +# === +OCSPtestBREAK() { + echo + killResponders + testBREAK +} + +trap OCSPtestBREAK INT QUIT ABRT KILL TERM || exit 1 + + +# === +#args: +# $1 - port +#env. vars: +# OCSP_RESPKEY +# type +runResponder() { +( + port=$1 + + pidfile="va-${port}.pid" + test -r "${pidfile}" && exit 1 + + printf ' %s' "starting OCSP ${extd}responder${norm}(${attn}${type}${norm}) on ${attn}${SSHD_LISTENADDRESS}:${port}${norm}" + ( + ${OPENSSL} ocsp \ + -CA "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" \ + -rsigner "${OCSP_RESPKEY}-${type}.crt" \ + -rkey "${OCSP_RESPKEY}" \ + -index "${SSH_CAROOT}/index-${type}.txt" \ + -host ${SSHD_LISTENADDRESS} \ + -port ${port} 2> va-${type}.log & + pid=$! + echo ${pid} > "${pidfile}" + wait ${pid} + rm -f "${pidfile}" + ) 2> /dev/null & + + sleep 1 + test -r "${pidfile}"; show_status $? +) +} + + +# === +test_ocsp_cert () { +( + printSeparator + echo "Begin test ${extd}against${norm} OCSP provider from ${attn}certificate${norm} ..." + + retval=1 + for OCSP_RESPKEY in ${TEST_OCSP_RESPKEYS}; do + printSeparator + echo " respoder key base ${attn}${OCSP_RESPKEY}${norm} ..." + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" < "${SSH_CLIENTKEY}" && + chmod 600 "${SSH_CLIENTKEY}" && + "$TEST_SSH_SSHKEYGEN" -f "${SSH_CLIENTKEY}" -p -P "${KEY_PASS}" -N "" \ + > /dev/null && + "$TEST_SSH_SSHKEYGEN" -f "${SSH_CLIENTKEY}" -y \ + > "${SSH_CLIENTKEY}.pub" && + + for type in ${SSH_SIGN_TYPES}; do + case $keytype in + rsa) + case $type in + *dsa*) continue;; + esac + ;; + dsa) + case $type in + *rsa*) continue;; + esac + ;; + esac + + identity_file="${SSH_CLIENTKEY}-${type}" + ( cat "${SSH_CLIENTKEY}" + $OPENSSL x509 -in "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" \ + -subject -issuer -alias + ) > "${identity_file}" && + chmod 600 "${identity_file}" || return $? + done + done +} + +# === +#args: +# $1 - request to fail flag for blob +# $2 - request to fail flag for DN +test_self() { + + case $1 in + Y|y|Yes|yes|YES|1) + blob_msg="${warn}blob${norm}";; + *) + blob_msg="${extd}blob${norm}";; + esac + case $2 in + Y|y|Yes|yes|YES|1) + dn_msg="${warn}DN${norm}";; + *) + dn_msg="${extd}DN${norm}";; + esac + + for keytype in rsa dsa; do + SSH_CLIENTKEY="selfid_${keytype}" + + for type in ${SSH_SIGN_TYPES}; do + case $keytype in + rsa) + case $type in + *dsa*) continue;; + esac + ;; + dsa) + case $type in + *rsa*) continue;; + esac + ;; + esac + + identity_file="${SSH_CLIENTKEY}-${type}" + + cat "${SSH_CLIENTKEY}.pub" > "${AUTHORIZEDKEYSFILE}" && + runTest "" "${identity_file}" \ + "${type} ${blob_msg}" "$1" \ + || return $? + + sshkeytype=`getSSHkeyType "${identity_file}"` || return $? + subject=`getSubject "${identity_file}"` || return $? + + echo "${sshkeytype} Subject: ${subject}" > "${AUTHORIZEDKEYSFILE}" && + runTest "" "${identity_file}" \ + "${type} ${dn_msg}" "$2" \ + || return $? + done + done +} + +# === + +test_store () { + retval=0 + echo " - ${attn}with${norm} self-issued trusted by ${extd}x509store${norm}:" + printSeparator + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" < +#ifndef LDAP_DEPRECATED + /* to suppress warnings in some 2.3x versions */ +# define LDAP_DEPRECATED 0 +#endif +#include + + +/* ================================================================== */ +/* ERRORS */ +#ifndef OPENSSL_NO_ERR +static ERR_STRING_DATA X509byLDAP_str_functs[] = { + { ERR_PACK(0, X509byLDAP_F_LOOKUPCRTL, 0) , "LOOKUPCRTL" }, + { ERR_PACK(0, X509byLDAP_F_LDAPHOST_NEW, 0) , "LDAPHOST_NEW" }, + { ERR_PACK(0, X509byLDAP_F_SET_PROTOCOL, 0) , "SET_PROTOCOL" }, + { ERR_PACK(0, X509byLDAP_F_RESULT2STORE, 0) , "RESULT2STORE" }, + { ERR_PACK(0, X509byLDAP_F_GET_BY_SUBJECT, 0) , "GET_BY_SUBJECT" }, + { 0, NULL } +}; + + +static ERR_STRING_DATA X509byLDAP_str_reasons[] = { + { X509byLDAP_R_INVALID_CRTLCMD , "invalid control command" }, + { X509byLDAP_R_NOT_LDAP_URL , "not ldap url" }, + { X509byLDAP_R_INVALID_URL , "invalid ldap url" }, + { X509byLDAP_R_INITIALIZATION_ERROR , "ldap initialization error" }, + { X509byLDAP_R_UNABLE_TO_GET_PROTOCOL_VERSION , "unable to get ldap protocol version" }, + { X509byLDAP_R_UNABLE_TO_SET_PROTOCOL_VERSION , "unable to set ldap protocol version" }, + { X509byLDAP_R_UNABLE_TO_COUNT_ENTRIES , "unable to count ldap entries" }, + { X509byLDAP_R_WRONG_LOOKUP_TYPE , "wrong lookup type" }, + { X509byLDAP_R_UNABLE_TO_GET_FILTER , "unable to get ldap filter" }, + { X509byLDAP_R_UNABLE_TO_BIND , "unable to bind to ldap server" }, + { X509byLDAP_R_SEARCH_FAIL , "search failure" }, + { 0, NULL } +}; +#endif /*ndef OPENSSL_NO_ERR*/ + + +void +ERR_load_X509byLDAP_strings(void) { + static int init = 1; + + if (init) { + init = 0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(ERR_LIB_X509byLDAP, X509byLDAP_str_functs); + ERR_load_strings(ERR_LIB_X509byLDAP, X509byLDAP_str_reasons); +#endif + } +} + + +static char* +ldap_errormsg(char *buf, size_t len, int err) { + snprintf(buf, len, "ldaperror=0x%x(%.256s)", err, ldap_err2string(err)); + return(buf); +} + + +static void +openssl_add_ldap_error(int err) { + char buf[512]; + ERR_add_error_data(1, ldap_errormsg(buf, sizeof(buf), err)); +} + + +/* ================================================================== */ +/* wrappers to some depricated functions */ +static void +ldaplookup_parse_result ( + LDAP *ld, + LDAPMessage *res +) { + static const int freeit = 0; + int result; +#ifdef HAVE_LDAP_PARSE_RESULT + int ret; + char *matcheddn; + char *errmsg; + + ret = ldap_parse_result(ld, res, &result, &matcheddn, &errmsg, NULL, NULL, freeit); + if (ret == LDAP_SUCCESS) { + if (errmsg) ERR_add_error_data(1, errmsg); + } + if (matcheddn) ldap_memfree(matcheddn); + if (errmsg) ldap_memfree(errmsg); +#else + result = ldap_result2error(ld, res, freeit); + openssl_add_ldap_error(result); +#endif +} + + +static int +ldaplookup_bind_s(LDAP *ld) { + int result; + + /* anonymous bind - data must be retrieved by anybody */ +#ifdef HAVE_LDAP_SASL_BIND_S +{ + static struct berval cred = { 0, (char*)"" }; + + result = ldap_sasl_bind_s( + ld, NULL/*dn*/, LDAP_SASL_SIMPLE, &cred, + NULL, NULL, NULL); +} +#else + result = ldap_simple_bind_s(ld, NULL/*binddn*/, NULL/*bindpw*/); +#endif + +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_bind_s:" +" ldap_XXX_bind_s return 0x%x(%s)\n" +, result, ldap_err2string(result)); +#endif + return(result); +} + + +static int +ldaplookup_search_s( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPMessage **res +) { + int result; +#ifdef HAVE_LDAP_SEARCH_EXT_S + result = ldap_search_ext_s(ld, base, + scope, filter, attrs, attrsonly, + NULL, NULL, NULL, 0, res); +#else + result = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res); +#endif + +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_search_s:" +"\n base=%s\n filter=%s\n" +" ldap_search_{XXX}s return 0x%x(%s)\n" +, base, filter +, result, ldap_err2string(result)); +#endif + return(result); +} + + +/* ================================================================== */ +/* LOOKUP by LDAP */ + +static const char ATTR_CACERT[] = "cACertificate"; +static const char ATTR_CACRL[] = "certificateRevocationList"; + +typedef struct ldaphost_s ldaphost; +struct ldaphost_s { + char *url; + char *binddn; + char *bindpw; + LDAPURLDesc *ldapurl; + LDAP *ld; + ldaphost *next; +}; + + +static ldaphost* ldaphost_new(const char *url); +static void ldaphost_free(ldaphost *p); + + +static int ldaplookup_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret); +static int ldaplookup_new(X509_LOOKUP *ctx); +static void ldaplookup_free(X509_LOOKUP *ctx); +static int ldaplookup_init(X509_LOOKUP *ctx); +static int ldaplookup_shutdown(X509_LOOKUP *ctx); +static int ldaplookup_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, X509_OBJECT *ret); + +static int ldaplookup_add_search(X509_LOOKUP *ctx, const char *url); +static int ldaplookup_set_protocol(X509_LOOKUP *ctx, const char *ver); + + +X509_LOOKUP_METHOD x509_ldap_lookup = { + "Load certs and crls from LDAP server", + ldaplookup_new, /* new */ + ldaplookup_free, /* free */ + ldaplookup_init, /* init */ + ldaplookup_shutdown, /* shutdown */ + ldaplookup_ctrl, /* ctrl */ + ldaplookup_by_subject, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + + +X509_LOOKUP_METHOD* +X509_LOOKUP_ldap(void) { + return(&x509_ldap_lookup); +} + + +static int +ldaplookup_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **retp) { + int ret = 0; + + (void)argl; + (void)retp; +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_ctrl: cmd=%d, argc=%s\n", cmd, argc); +#endif + switch (cmd) { + case X509_L_LDAP_HOST: + ret = ldaplookup_add_search(ctx, argc); + break; + case X509_L_LDAP_VERSION: + ret = ldaplookup_set_protocol(ctx, argc); + break; + default: + X509byLDAPerr(X509byLDAP_F_LOOKUPCRTL, X509byLDAP_R_INVALID_CRTLCMD); + break; + } + return(ret); +} + + +static int +ldaplookup_new(X509_LOOKUP *ctx) { +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_new:\n"); +#endif + if (ctx == NULL) + return(0); + + ctx->method_data = NULL; + return(1); +} + + +static void +ldaplookup_free(X509_LOOKUP *ctx) { + ldaphost *p; +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_free:\n"); +#endif + + if (ctx == NULL) + return; + + p = (ldaphost*) ctx->method_data; + while (p != NULL) { + ldaphost *q = p; + p = p->next; + ldaphost_free(q); + } +} + + +static int +ldaplookup_init(X509_LOOKUP *ctx) { +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_init:\n"); +#endif + (void)ctx; + return(1); +} + + +static int +ldaplookup_shutdown(X509_LOOKUP *ctx) { +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_shutdown:\n"); +#endif + (void)ctx; + return(1); +} + + +static ldaphost* +ldaphost_new(const char *url) { + ldaphost *p; + int ret; + + p = OPENSSL_malloc(sizeof(ldaphost)); + if (p == NULL) return(NULL); + + memset(p, 0, sizeof(ldaphost)); + + p->url = OPENSSL_malloc(strlen(url) + 1); + if (p->url == NULL) goto error; + strcpy(p->url, url); + + /*ldap://hostport/dn[?attrs[?scope[?filter[?exts]]]] */ + ret = ldap_is_ldap_url(url); + if (ret < 0) { + X509byLDAPerr(X509byLDAP_F_LDAPHOST_NEW, X509byLDAP_R_NOT_LDAP_URL); + goto error; + } + + ret = ldap_url_parse(p->url, &p->ldapurl); + if (ret != 0) { + X509byLDAPerr(X509byLDAP_F_LDAPHOST_NEW, X509byLDAP_R_INVALID_URL); + openssl_add_ldap_error(ret); + goto error; + } +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaphost_new: ldap_url_desc2str=%s\n", ldap_url_desc2str(p->ldapurl)); +fprintf(stderr, "TRACE_BY_LDAP ldaphost_new: ldapurl->%s://%s:%d\n", p->ldapurl->lud_scheme, p->ldapurl->lud_host, p->ldapurl->lud_port); +#endif + + /* open ldap connection */ +#ifdef HAVE_LDAP_INITIALIZE + ret = ldap_initialize(&p->ld, p->url); + if (ret != LDAP_SUCCESS) { + X509byLDAPerr(X509byLDAP_F_LDAPHOST_NEW, X509byLDAP_R_INITIALIZATION_ERROR); + openssl_add_ldap_error(ret); + goto error; + } +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaphost_new: ldap_initialize(..., url=%s)\n", p->url); +#endif +#else /*ndef HAVE_LDAP_INITIALIZE*/ + p->ld = ldap_init(p->ldapurl->lud_host, p->ldapurl->lud_port); + if(p->ld == NULL) { + X509byLDAPerr(X509byLDAP_F_LDAPHOST_NEW, X509byLDAP_R_INITIALIZATION_ERROR); + goto error; + } +#endif /*ndef HAVE_LDAP_INITIALIZE*/ + + { + int version = -1; + + ret = ldap_get_option(p->ld, LDAP_OPT_PROTOCOL_VERSION, &version); + if (ret != LDAP_OPT_SUCCESS) { + X509byLDAPerr(X509byLDAP_F_LDAPHOST_NEW, X509byLDAP_R_UNABLE_TO_GET_PROTOCOL_VERSION ); + goto error; + } +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaphost_new: using ldap v%d protocol\n", version); +#endif + } + + return(p); +error: + ldaphost_free(p); + return(NULL); +} + + +static void +ldaphost_free(ldaphost *p) { +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaphost_free:\n"); +#endif + if (p == NULL) return; + if (p->url != NULL) OPENSSL_free(p->url); + if (p->binddn != NULL) OPENSSL_free(p->binddn); + if (p->bindpw != NULL) OPENSSL_free(p->bindpw); + if (p->ldapurl != NULL) { + ldap_free_urldesc(p->ldapurl); + p->ldapurl = NULL; + } + if (p->ld != NULL) { + /* how to free ld ???*/ + p->ld = NULL; + } + OPENSSL_free(p); +} + + +static int/*bool*/ +ldaplookup_add_search(X509_LOOKUP *ctx, const char *url) { + ldaphost *p, *q; + + if (ctx == NULL) return(0); + if (url == NULL) return(0); + + q = ldaphost_new(url); + if (q == NULL) return(0); + + p = (ldaphost*) ctx->method_data; + if (p == NULL) { + ctx->method_data = (void*) q; + return(1); + } + + for(; p->next != NULL; p = p->next) { + /*find list end*/ + } + p->next = q; + + return(1); +} + + +static int/*bool*/ +ldaplookup_set_protocol(X509_LOOKUP *ctx, const char *ver) { + ldaphost *p; + char *q = NULL; + int n; + +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_set_protocol(..., %s)\n", ver); +#endif + if (ctx == NULL) return(0); + if (ver == NULL) return(0); + + p = (ldaphost*) ctx->method_data; +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_set_protocol(..., %s) p=%p\n", ver, (void*)p); +#endif + if (p == NULL) return(0); + + n = (int) strtol(ver, &q, 10); + if (*q != '\0') return(0); + if ((n < LDAP_VERSION_MIN) || (n > LDAP_VERSION_MAX)) return(0); + + for(; p->next != NULL; p = p->next) { + /*find list end*/ + } +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_set_protocol(...): ver=%d\n", n); +#endif + { + int ret; + const int version = n; + + ret = ldap_set_option(p->ld, LDAP_OPT_PROTOCOL_VERSION, &version); + if (ret != LDAP_OPT_SUCCESS) { + X509byLDAPerr(X509byLDAP_F_SET_PROTOCOL, X509byLDAP_R_UNABLE_TO_SET_PROTOCOL_VERSION); + openssl_add_ldap_error(ret); + return(0); + } + } + + return(1); +} + + +static char* +ldaplookup_attr(ASN1_STRING *nv) { + char *p = NULL; + int k; + BIO *mbio; + + mbio = BIO_new(BIO_s_mem()); + if (mbio == NULL) return(NULL); + + k = ASN1_STRING_print_ex(mbio, nv, XN_FLAG_RFC2253); + p = OPENSSL_malloc(k + 1); + if (p == NULL) goto done; + + k = BIO_read(mbio, p, k); + p[k] = '\0'; + +done: + BIO_free_all(mbio); + return(p); +} + + +static char* +ldaplookup_filter(X509_NAME *name, const char *attribute) { + char *p = NULL; + int k; + BIO *mbio; + + mbio = BIO_new(BIO_s_mem()); + if (mbio == NULL) return(NULL); + + BIO_puts(mbio, "(&"); + + k = sk_X509_NAME_ENTRY_num(name->entries); + for (--k; k >= 0; k--) { + X509_NAME_ENTRY *ne; + ASN1_STRING *nv; + int nid; + + ne = sk_X509_NAME_ENTRY_value(name->entries, k); + nid = OBJ_obj2nid(ne->object); + + if ( + (nid != NID_organizationName) && + (nid != NID_organizationalUnitName) && + (nid != NID_commonName) + ) continue; + + BIO_puts(mbio, "("); + BIO_puts(mbio, OBJ_nid2sn(nid)); + BIO_puts(mbio, "="); + nv = ne->value; +#if 0 + /* + TODO: + we must escape '(' and ')' symbols and might to check for other symbols (>=128?) + BIO_puts(mbio, M_ASN1_STRING_data(nv)); + */ + { /* escape '(' and ')' */ + p = (char*)M_ASN1_STRING_data(nv); + for (; *p; p++) { + if ((*p == '(') || (*p == ')')) + BIO_write(mbio, "\\", 1); + BIO_write(mbio, p, 1); + } + } +#else + { + char *q, *s; + + q = ldaplookup_attr(nv); + if (q == NULL) goto done; +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_filter: ldaplookup_attr(nv) return '%.512s'\n", q); +#endif + /* escape some charecters according to RFC2254 */ + for (s=q; *s; s++) { + if ((*s == '*') || + (*s == '(') || + (*s == ')') + /* character '\' should be already escaped ! */ + ) { + /* RFC2254 recommendation */ + BIO_printf(mbio, "\\%02X", (int)*s); + continue; + } + BIO_write(mbio, s, 1); + } + + OPENSSL_free(q); + } +#endif + BIO_puts(mbio, ")"); + } + + BIO_puts(mbio, "("); + BIO_puts(mbio, attribute); + BIO_puts(mbio, "=*)"); + + BIO_puts(mbio, ")"); + BIO_flush(mbio); + + k = BIO_pending(mbio); + p = OPENSSL_malloc(k + 1); + if (p == NULL) goto done; + + k = BIO_read(mbio, p, k); + p[k] = '\0'; +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_filter: p=%.512s\n", p); +#endif + +done: + BIO_free_all(mbio); + return(p); +} + + +static int/*bool*/ +ldaplookup_check_attr( + int type, + const char *attr +) { + if (type == X509_LU_X509) + return(strncmp(attr, ATTR_CACERT, sizeof(ATTR_CACERT)) != 0); + + if (type == X509_LU_CRL) + return(strncmp(attr, ATTR_CACRL, sizeof(ATTR_CACRL)) != 0); + + return(0); +} + + +/* + * We will put into store X509 object from passed data in buffer only + * when object name match passed. To compare both names we use our + * method "ssh_X509_NAME_cmp"(it is more general). + */ +static int/*bool*/ +ldaplookup_data2store( + int type, + X509_NAME* name, + void* buf, + int len, + X509_STORE* store +) { + int ok = 0; + BIO *mbio; + + if (name == NULL) return(0); + if (buf == NULL) return(0); + if (len <= 0) return(0); + if (store == NULL) return(0); + + mbio = BIO_new_mem_buf(buf, len); + if (mbio == NULL) return(0); + + switch (type) { + case X509_LU_X509: { + X509 *x509 = d2i_X509_bio(mbio, NULL); + if(x509 == NULL) goto exit; + + /*This is correct since lookup method is by subject*/ + if (ssh_X509_NAME_cmp(name, X509_get_subject_name(x509)) != 0) goto exit; + + ok = X509_STORE_add_cert(store, x509); + } break; + case X509_LU_CRL: { + X509_CRL *crl = d2i_X509_CRL_bio(mbio, NULL); + if(crl == NULL) goto exit; + + if (ssh_X509_NAME_cmp(name, X509_CRL_get_issuer(crl)) != 0) goto exit; + + ok = X509_STORE_add_crl(store, crl); + } break; + } + +exit: + if (mbio != NULL) BIO_free_all(mbio); +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_data2store: ok=%d\n", ok); +#endif + return(ok); +} + + +static int +ldaplookup_result2store( + int type, + X509_NAME* name, + LDAP* ld, + LDAPMessage* res, + X509_STORE* store +) { + int count = 0; + int result; + LDAPMessage *entry; + + result = ldap_count_entries(ld, res); + if (result < 0) { + X509byLDAPerr(X509byLDAP_F_RESULT2STORE, X509byLDAP_R_UNABLE_TO_COUNT_ENTRIES); + ldaplookup_parse_result (ld, res); + goto done; + } +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_result2store: ldap_count_entries=%d\n", result); +#endif + + for(entry = ldap_first_entry(ld, res); + entry != NULL; + entry = ldap_next_entry(ld, entry) + ) { + char *attr; + BerElement *ber; +#ifdef TRACE_BY_LDAP +{ +char *dn = ldap_get_dn(ld, entry); +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_result2store(): ldap_get_dn=%s\n", dn); +ldap_memfree(dn); +} +#endif + for(attr = ldap_first_attribute(ld, entry, &ber); + attr != NULL; + attr = ldap_next_attribute(ld, entry, ber) + ) { + struct berval **vals; + struct berval **p; + +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_result2store: attr=%s\n", attr); +#endif + if (!ldaplookup_check_attr(type, attr)) continue; + + vals = ldap_get_values_len(ld, entry, attr); + if (vals == NULL) continue; + + for(p = vals; *p; p++) { + struct berval *q = *p; + if (ldaplookup_data2store(type, name, q->bv_val, q->bv_len, store)) { + count++; + } + } + ldap_value_free_len(vals); + } + ber_free(ber, 0); + } +done: +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_result2store: count=%d\n", count); +#endif + return(count); +} + + +static int +ldaplookup_by_subject( + X509_LOOKUP *ctx, + int type, + X509_NAME *name, + X509_OBJECT *ret +) { + int count = 0; + ldaphost *lh; + const char *attrs[2]; + char *filter = NULL; + + + if (ctx == NULL) return(0); + if (name == NULL) return(0); + + lh = (ldaphost*) ctx->method_data; + if (lh == NULL) return(0); + + switch(type) { + case X509_LU_X509: { + attrs[0] = ATTR_CACERT; + } break; + case X509_LU_CRL: { + attrs[0] = ATTR_CACRL; + } break; + default: { + X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_WRONG_LOOKUP_TYPE); + goto done; + } + } + attrs[1] = NULL; + + filter = ldaplookup_filter(name, attrs[0]); + if (filter == NULL) { + X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_UNABLE_TO_GET_FILTER); + goto done; + } +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: filter=%s\n", filter); +#endif + + for (; lh != NULL; lh = lh->next) { + LDAPMessage *res = NULL; + int result; + +#ifdef TRACE_BY_LDAP +{ +int version = -1; + +ldap_get_option(lh->ld, LDAP_OPT_PROTOCOL_VERSION, &version); +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject:" +" bind to \"%s://%s:%d\"" +" using ldap v%d protocol\n" +, lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port +, version +); +} +#endif + + result = ldaplookup_bind_s(lh->ld); + if (result != LDAP_SUCCESS) { + X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_UNABLE_TO_BIND); + { + char buf[1024]; + snprintf(buf, sizeof(buf), + " url=\"%s://%s:%d\"" + " ldaperror=0x%x(%.256s)" + , lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port + , result, ldap_err2string(result) + ); + ERR_add_error_data(1, buf); + } + continue; + } + + result = ldaplookup_search_s(lh->ld, lh->ldapurl->lud_dn, + LDAP_SCOPE_SUBTREE, filter, (char**)attrs, 0, &res); + if (result != LDAP_SUCCESS) { + X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_SEARCH_FAIL); + ldap_msgfree(res); + continue; + } + + result = ldaplookup_result2store(type, name, lh->ld, res, ctx->store_ctx); + if (result > 0) count += result; + + ldap_msgfree(res); + + /*do not call ldap_unbind_s*/ + } + +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: count=%d\n", count); +#endif + if (count > 0) { + /* + * we have added at least one to the cache so now pull one out again + */ + union { + struct { + X509_CINF st_x509_cinf; + X509 st_x509; + } x509; + struct { + X509_CRL_INFO st_crl_info; + X509_CRL st_crl; + } crl; + } data; + + X509_OBJECT stmp, *tmp; + int k; + + memset(&data, 0, sizeof(data)); + stmp.type = type; + switch(type) { + case X509_LU_X509: { + data.x509.st_x509_cinf.subject = name; + data.x509.st_x509.cert_info = &data.x509.st_x509_cinf; + stmp.data.x509 = &data.x509.st_x509; + } break; + case X509_LU_CRL: { + data.crl.st_crl_info.issuer = name; + data.crl.st_crl.crl = &data.crl.st_crl_info; + stmp.data.crl = &data.crl.st_crl; + } break; + default: + count = 0; + goto done; + } + + CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); + k = sk_X509_OBJECT_find(ctx->store_ctx->objs, &stmp); + if (k >= 0) + tmp = sk_X509_OBJECT_value(ctx->store_ctx->objs, k); + else + tmp = NULL; + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); +#ifdef TRACE_BY_LDAP +fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: k=%d, tmp=%p\n", k, (void*)tmp); +#endif + + if (tmp == NULL) { + count = 0; + goto done; + } + + ret->type = tmp->type; + memcpy(&ret->data, &tmp->data, sizeof(ret->data)); + } + +done: + if (filter != NULL) OPENSSL_free(filter); + return(count > 0); +} diff -ruN openssh-5.6p1/x509_by_ldap.h openssh-5.6p1+x509-6.2.3/x509_by_ldap.h --- openssh-5.6p1/x509_by_ldap.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/x509_by_ldap.h 2004-11-19 09:06:00.000000000 +0200 @@ -0,0 +1,98 @@ +#ifndef X509_BY_LDAP_H +#define X509_BY_LDAP_H +/* + * Copyright (c) 2004 Roumen Petrov. 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. + */ + +/* openssh specific includes */ +#include "includes.h" +#ifndef LDAP_ENABLED +# include "error: LDAP is disabled" +#endif + +/* required includes */ +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +X509_LOOKUP_METHOD* X509_LOOKUP_ldap(void); + +#define X509_L_LDAP_HOST 1 +#define X509_L_LDAP_VERSION 2 + +#define X509_LOOKUP_add_ldap(x,value) \ + X509_LOOKUP_ctrl((x),X509_L_LDAP_HOST,(value),(long)(0),NULL) +#define X509_LOOKUP_set_protocol(x,value) \ + X509_LOOKUP_ctrl((x),X509_L_LDAP_VERSION,(value),(long)(0),NULL) + + +/* Error codes for the X509byLDAP functions. */ +#ifdef NO_ERR /* openssl < 0.7.x */ +# define OPENSSL_NO_ERR /* openssl >= 0.7.x */ +#endif + +#ifndef OPENSSL_NO_ERR + +void ERR_load_X509byLDAP_strings(void); + +/* library */ +#define ERR_LIB_X509byLDAP ERR_LIB_USER + +#define X509byLDAPerr(f,r) ERR_PUT_error(ERR_LIB_X509byLDAP,(f),(r),__FILE__,__LINE__) + +/* BEGIN ERROR CODES */ + +/* Function codes. */ +#define X509byLDAP_F_LOOKUPCRTL 100 +#define X509byLDAP_F_LDAPHOST_NEW 101 +#define X509byLDAP_F_SET_PROTOCOL 102 +#define X509byLDAP_F_RESULT2STORE 103 +#define X509byLDAP_F_GET_BY_SUBJECT 104 + +/* Reason codes. */ +#define X509byLDAP_R_INVALID_CRTLCMD 100 +#define X509byLDAP_R_NOT_LDAP_URL 101 +#define X509byLDAP_R_INVALID_URL 102 +#define X509byLDAP_R_INITIALIZATION_ERROR 103 +#define X509byLDAP_R_UNABLE_TO_GET_PROTOCOL_VERSION 104 +#define X509byLDAP_R_UNABLE_TO_SET_PROTOCOL_VERSION 105 +#define X509byLDAP_R_UNABLE_TO_COUNT_ENTRIES 106 +#define X509byLDAP_R_WRONG_LOOKUP_TYPE 107 +#define X509byLDAP_R_UNABLE_TO_GET_FILTER 108 +#define X509byLDAP_R_UNABLE_TO_BIND 109 +#define X509byLDAP_R_SEARCH_FAIL 110 + +#endif /*ndef OPENSSL_NO_ERR*/ + + +#ifdef __cplusplus +} +#endif + + +#endif /*ndef X509_BY_LDAP_H*/ diff -ruN openssh-5.6p1/x509_nm_cmp.c openssh-5.6p1+x509-6.2.3/x509_nm_cmp.c --- openssh-5.6p1/x509_nm_cmp.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/x509_nm_cmp.c 2007-10-21 19:48:55.000000000 +0300 @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2005-2007 Roumen Petrov. 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. + */ + +/* initial code is moved from ssh-x509.c */ +#include "includes.h" + +#ifndef SSH_X509STORE_DISABLED +#include +#include + +#include "x509store.h" +#include "log.h" +#include "xmalloc.h" + + +static int +ssh_ASN1_OBJECT_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { + int lmin = MIN(a->length, b->length); + + int ret = memcmp(a->data, b->data, lmin); + + return((ret == 0) + ? (b->length - a->length) + : ret); +} + + +static int +ssh_ASN1_STRING_casecmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ + int la = M_ASN1_STRING_length(a); + int lb = M_ASN1_STRING_length(b); + const char *sa = (const char *)M_ASN1_STRING_data(a); + const char *sb = (const char *)M_ASN1_STRING_data(b); + + return((strncasecmp(sa, sb, MIN(la, lb)) != 0) ? (lb - la) : 0); +} + + +/* from RFC3280 and oldest RFC2459 + * (d) attribute values in PrintableString are compared after + * removing leading and trailing white space and converting internal + * substrings of one or more consecutive white space characters to a + * single space. + */ +static int +ssh_printable_casecmp(const u_char *pa, int la, const u_char *pb, int lb) +{ +/* + * Be careful: this method work fine only in "C(POSIX)" locale. + * Since OpenSSH now run without to set locale, i.e. + * following comparision is OK. + * This implementation should be changed for other locales !!! + * + * Note pa or pb may contain utf8 characters ! + */ + /* skip leading spaces */ + for (; la > 0 && isspace((int)*pa); la--, pa++); + for (; lb > 0 && isspace((int)*pb); lb--, pb++); + + /* skip trailing spaces */ + { + const u_char *p; + for (p = pa + la - 1; la > 0 && isspace((int)*p); la--, p--); + for (p = pb + lb - 1; lb > 0 && isspace((int)*p); lb--, p--); + } + + while (la > 0 && lb > 0) + { + int chA = tolower((int)*pa); + int chB = tolower((int)*pb); + + if (chA != chB) + return(chB - chA); + + pa++; pb++; + la--; lb--; + if (isspace(chA)) { + for (; la > 0 && isspace((int)*pa); la--, pa++); + for (; lb > 0 && isspace((int)*pb); lb--, pb++); + } + } + return(lb - la); +} + + +static int +ssh_ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) { +/* + * Note before OpenSSL versions 0.7.e method ASN1_STRING_to_UTF8 + * fail when ASN1_STRING is utf8String ! + */ + int tag; + int l; + + if (!in) return(-1); + + tag = M_ASN1_STRING_type(in); + if (tag != V_ASN1_UTF8STRING) { + /*OpenSSL method surprisingly require non-const(!?) ASN1_STRING!*/ + return(ASN1_STRING_to_UTF8(out, in)); + } + + l = M_ASN1_STRING_length(in); + if (out) { + u_char *p; + + if (*out) { + error("ssh_ASN1_STRING_to_UTF8: *out is not NULL"); + return(-1); + } + /* we MUST allocate memory with OPENSSL method! */ + p = OPENSSL_malloc(l + 1); + if (p == NULL) { + fatal("ssh_ASN1_STRING_to_UTF8: out of memory (allocating %d bytes)", (l + 1)); + } + memcpy(p, M_ASN1_STRING_data(in), l); + p[l] = 0; + *out = p; + } + return(l); +} + + +static int +ssh_ASN1_PRINTABLESTRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ + int n = -1; + int tagA, tagB; + int la, lb; + u_char *pa, *pb; + u_char *ua = NULL, *ub = NULL; + + tagA = M_ASN1_STRING_type(a); + tagB = M_ASN1_STRING_type(b); + if (tagA != V_ASN1_PRINTABLESTRING) { + debug3("ssh_ASN1_PRINTABLESTRING_cmp: a->type=%d(%.30s) is not PrintableString", tagA, ASN1_tag2str(tagA)); + /* just in case - see caling methods */ + if (tagB != V_ASN1_PRINTABLESTRING) { + error("ssh_ASN1_PRINTABLESTRING_cmp: b is not PrintableString too"); + return(-1); + } + } + if (tagB != V_ASN1_PRINTABLESTRING) { + debug3("ssh_ASN1_PRINTABLESTRING_cmp: b->type=%d(%.30s) is not PrintableString", tagB, ASN1_tag2str(tagB)); + /* just in case - see caling methods */ + if (tagA != V_ASN1_PRINTABLESTRING) { + error("ssh_ASN1_PRINTABLESTRING_cmp: a is not PrintableString too"); + return(1); + } + } + + if (tagA == tagB) { + /*both are PrintableString*/ + la = M_ASN1_STRING_length(a); + pa = M_ASN1_STRING_data(a); + lb = M_ASN1_STRING_length(b); + pb = M_ASN1_STRING_data(b); + } else { + /*convert strings to utf8*/ + la = ssh_ASN1_STRING_to_UTF8(&ua, a); + if (la <= 0) { + /*first string is lower in case of error or zero length*/ + n = -1; + goto done; + } + lb = ssh_ASN1_STRING_to_UTF8(&ub, b); + if (lb <= 0) { + /*second string is greater in case of error or zero length*/ + n = 1; + goto done; + } + pa = ua; + pb = ub; + } + + n = ssh_printable_casecmp(pa, la, pb, lb); + +done: + if(ua) OPENSSL_free(ua); + if(ub) OPENSSL_free(ub); +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "ssh_ASN1_PRINTABLESTRING_cmp: return %d\n", n); +#endif + return(n); +} + + +/* + * ===================================================================== + * from RFC3280 and oldest 2459: + * DirectoryString ::= CHOICE { + * teletexString TeletexString (SIZE (1..MAX)), + * printableString PrintableString (SIZE (1..MAX)), + * universalString UniversalString (SIZE (1..MAX)), + * utf8String UTF8String (SIZE (1..MAX)), + * bmpString BMPString (SIZE (1..MAX)) } + *..... + * The DirectoryString type is defined as a choice of PrintableString, + * TeletexString, BMPString, UTF8String, and UniversalString. The + * UTF8String encoding is the preferred encoding, and all certificates + * issued after December 31, 2003 MUST use the UTF8String encoding of + * DirectoryString (except as noted below). Until that date, conforming + * CAs MUST choose from the following options when creating a + * distinguished name, including their own: + * (a) if the character set is sufficient, the string MAY be + * represented as a PrintableString; + * (b) failing (a), if the BMPString character set is sufficient the + * string MAY be represented as a BMPString; and + * (c) failing (a) and (b), the string MUST be represented as a + * UTF8String. If (a) or (b) is satisfied, the CA MAY still choose + * to represent the string as a UTF8String. + *..... + * later in RFCs: + * (a) attribute values encoded in different types (e.g., + * PrintableString and BMPString) may be assumed to represent + * different strings; + * (b) attribute values in types other than PrintableString are case + * sensitive (this permits matching of attribute values as binary + * objects); + * (c) attribute values in PrintableString are not case sensitive + * (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and + * (d) attribute values in PrintableString are compared after + * removing leading and trailing white space and converting internal + * substrings of one or more consecutive white space characters to a + * single space. + * ===================================================================== + * + * OpenSSH implementation: + * - assume that all DirectoryStrings represent same strings regardless + * of type. When strings are from different types they will be converted + * to utf8 before comparison. + * - when one of the strings is PrintableString they will be compared + * with method that ignore cases and spaces and convert to utf8 + * if necessary. + * + * Note calling method shoud ensure that both strings are + * DirectoryString !!! + */ +static int +ssh_ASN1_DIRECTORYSTRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ + int n = -1; + int tagA, tagB; + int la, lb; + const char *pa, *pb; + u_char *ua = NULL, *ub = NULL; + + tagA = M_ASN1_STRING_type(a); + tagB = M_ASN1_STRING_type(b); + + /* just in case of PrintableString - see caling method ;-) */ + if ((tagA == V_ASN1_PRINTABLESTRING) || + (tagB == V_ASN1_PRINTABLESTRING) ) { + /* + * one is PrintableString and we will compare + * according rules for PrintableString. + */ + return(ssh_ASN1_PRINTABLESTRING_cmp(a, b)); + } +/*....*/ + if (tagA == tagB) { + la = M_ASN1_STRING_length(a); + pa = (const char *)M_ASN1_STRING_data(a); + lb = M_ASN1_STRING_length(b); + pb = (const char *)M_ASN1_STRING_data(b); + } else { + /*convert both string to utf8*/ + la = ssh_ASN1_STRING_to_UTF8(&ua, a); + if (la <= 0) { + /*first string is lower in case of error or zero length*/ + n = -1; + goto done; + } + lb = ssh_ASN1_STRING_to_UTF8(&ub, b); + if (lb <= 0) { + /*second string is greater in case of error or zero length*/ + logit("ssh_ASN1_DIRECTORYSTRING_cmp lb=%d", lb); + n = 1; + goto done; + } +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "ssh_ASN1_DIRECTORYSTRING_cmp ua='%s'\n", ua); +fprintf(stderr, "ssh_ASN1_DIRECTORYSTRING_cmp ub='%s'\n", ub); +#endif + pa = (const char *)ua; + pb = (const char *)ub; + } + + n = memcmp(pa, pb, (size_t)MIN(la, lb)); +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "ssh_ASN1_DIRECTORYSTRING_cmp n=%d, la=%d, lb=%d\n", n, la, lb); +#endif + if (n == 0) n = (lb - la); + +done: + if(ua) OPENSSL_free(ua); + if(ub) OPENSSL_free(ub); +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "ssh_ASN1_DIRECTORYSTRING_cmp: return %d\n", n); +#endif + return(n); +} + + +static int/*bool*/ +ssh_is_DirectoryString(const ASN1_STRING* s) { + int tag = M_ASN1_STRING_type(s); + + switch(tag) { + case V_ASN1_T61STRING: /*==V_ASN1_TELETEXSTRING*/ + case V_ASN1_PRINTABLESTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_BMPSTRING: + return(1); + default: + return(0); + } +} + + +/* + * 1.) + * Since version 0.9.7.beta4 and 0.9.6h OpenSSL function X509_NAME_cmp + * is more restrictive but more correct (!). + * Problem is that some x509 implementation set X509_NAME entry + * incorrectly to "Printable String" :-[ . + * Work around: when one entry is "Printable String" method compare + * to corresponding entry as "Printable String". + * 2.) + * OpenSSL functions X509_NAME_cmp check nids order in X509_NAME. + * i.e. X509_NAME{"/C=XX/O=YY"} is not equal to X509_NAME{"/O=YY/C=XX"} + */ +int +ssh_X509_NAME_cmp(X509_NAME *_a, X509_NAME *_b) { + int k, n; + X509_NAME *b; + +#if 1 + /*XXX: to call fatal when _a or _b is NULL or to use next*/ + if (_a == NULL) { + return((_b == NULL) ? 0 : 1); + } else { + if (_b == NULL) return(-1); + } +#else + if (_a == NULL) { + fatal("ssh_X509_NAME_cmp: first name is NULL"); + } + if (_b == NULL) { + fatal("ssh_X509_NAME_cmp: second name is NULL"); + } +#endif + + k = sk_X509_NAME_ENTRY_num(_a->entries); + n = sk_X509_NAME_ENTRY_num(_b->entries); + + if (k != n) + return(n - k); + + b = X509_NAME_dup(_b); + n = 0; + for (--k; k >= 0; k--) { + X509_NAME_ENTRY *neA; + ASN1_STRING *nvA; + int nid; + X509_NAME_ENTRY *neB; + ASN1_STRING *nvB; + int loc; + + neA = sk_X509_NAME_ENTRY_value(_a->entries, k); + nvA = neA->value; + nid = OBJ_obj2nid(neA->object); + loc = X509_NAME_get_index_by_NID(b, nid, -1); + if (loc < 0) { + char *buf1, *buf2; + + buf1 = ssh_X509_NAME_oneline(_a); /*fatal on error*/ + buf2 = ssh_X509_NAME_oneline(_b); /*fatal on error*/ + debug3("ssh_X509_NAME_cmp: insufficient entries with nid=%d(%.40s) in second name." + " na=%s, nb=%s", + nid, OBJ_nid2ln(nid), + buf1, buf2); + xfree(buf1); + xfree(buf2); + n = -1; + break; + } +trynextentry: + neB = sk_X509_NAME_ENTRY_value(b->entries, loc); + nvB = neB->value; +#ifdef SSHX509TEST_DBGCMP +{ + int l, tag; + + l = M_ASN1_STRING_length(nvA); + tag = M_ASN1_STRING_type (nvA); + fprintf(stderr, "nvA(%.40s:%d)='", ASN1_tag2str(tag), l); + ASN1_STRING_print_ex_fp(stderr, nvA, /*flags*/0); + fputs("'\n", stderr); + + l = M_ASN1_STRING_length(nvB); + tag = M_ASN1_STRING_type (nvB); + fprintf(stderr, "nvA(%.40s:%d)='", ASN1_tag2str(tag), l); + ASN1_STRING_print_ex_fp(stderr, nvB, /*flags*/0); + fputs("'\n", stderr); +} +#endif + + if (nid == NID_pkcs9_emailAddress) { + int tag; + + tag = M_ASN1_STRING_type(nvA); + if (tag != V_ASN1_IA5STRING) { + /* to be strict and return nonzero or ... ? XXX + n = -1; + break; + */ + error("ssh_X509_NAME_cmp: incorrect type for emailAddress(a) %d(%.30s)", tag, ASN1_tag2str(tag)); + } + + tag = M_ASN1_STRING_type(nvB); + if (tag != V_ASN1_IA5STRING) { + /* to be strict and return nonzero or ... ? XXX + n = 1; + break; + */ + error("ssh_X509_NAME_cmp: incorrect type for emailAddress(b) %d(%.30s)", tag, ASN1_tag2str(tag)); + } + + n = ssh_ASN1_STRING_casecmp(nvA, nvB); + if (n == 0) goto entryisok; + + goto getnextentry; + } + if ((M_ASN1_STRING_type(nvA) == V_ASN1_PRINTABLESTRING) || + (M_ASN1_STRING_type(nvB) == V_ASN1_PRINTABLESTRING) ) { + n = ssh_ASN1_PRINTABLESTRING_cmp(nvA, nvB); + if (n == 0) goto entryisok; + + goto getnextentry; + } + if (ssh_is_DirectoryString(nvA) && + ssh_is_DirectoryString(nvB)) { + n = ssh_ASN1_DIRECTORYSTRING_cmp(nvA, nvB); + if (n == 0) goto entryisok; + + goto getnextentry; + } + + n = M_ASN1_STRING_length(nvA) - M_ASN1_STRING_length(nvB); + if (n != 0) goto getnextentry; + + n = M_ASN1_STRING_length(nvA); + n = memcmp(nvA->data, nvB->data, n); + if (n != 0) goto getnextentry; + + /* openssl check object too */ + n = ssh_ASN1_OBJECT_cmp(neA->object, neB->object); + if (n != 0) goto getnextentry; + +entryisok: + { + X509_NAME_ENTRY *ne = X509_NAME_delete_entry(b, loc); + X509_NAME_ENTRY_free(ne); + } + continue; +getnextentry: + loc = X509_NAME_get_index_by_NID(b, nid, loc); + if (loc < 0) { + break; + } + goto trynextentry; + } + + X509_NAME_free(b); +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "ssh_X509_NAME_cmp: return %d\n", n); +#endif + return(n); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ diff -ruN openssh-5.6p1/x509store.c openssh-5.6p1+x509-6.2.3/x509store.c --- openssh-5.6p1/x509store.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/x509store.c 2009-12-26 12:22:45.000000000 +0200 @@ -0,0 +1,1011 @@ +/* + * Copyright (c) 2002-2007 Roumen Petrov. 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 "x509store.h" +#include +#include "log.h" + +#ifndef SSH_X509STORE_DISABLED +#include + +#include "xmalloc.h" +#include "pathnames.h" +#include "misc.h" +#include +#include +/* struct X509_VERIFY_PARAM is defined in OpenSSL 0.9.8x */ +#ifdef HAVE_X509_STORE_CTX_PARAM +# define SSH_X509_VERIFY_PARAM(ctx,member) ctx->param->member +#else +# define SSH_X509_VERIFY_PARAM(ctx,member) ctx->member +#endif +#ifdef LDAP_ENABLED +# include "x509_by_ldap.h" +#endif +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +SSH_X509Flags +ssh_x509flags = { + 0, /* is_server */ + -1, /* allowedcertpurpose */ +#ifndef SSH_X509STORE_DISABLED + -1, /* key_allow_selfissued */ + -1 /* mandatory_crl */ +#endif /*ndef SSH_X509STORE_DISABLED*/ +}; + + +#ifndef SSH_X509STORE_DISABLED +static X509_STORE *x509store = NULL; +#if OPENSSL_VERSION_NUMBER < 0x00907000L +/* void X509_STORE_CTX_init() */ +static int ssh_X509_STORE_CTX_init ( + X509_STORE_CTX *ctx, + X509_STORE *store, + X509 *x509, + STACK_OF(X509) *chain) +{ + X509_STORE_CTX_init(ctx, store, x509, chain); + return(1); +} + +#define X509_STORE_CTX_init ssh_X509_STORE_CTX_init +#endif + +#if 1 +# define SSH_CHECK_REVOKED +#endif + + +#ifdef SSH_CHECK_REVOKED +static X509_STORE *x509revoked = NULL; +static int ssh_x509revoked_cb(int ok, X509_STORE_CTX *ctx); + + +static char * +ssh_ASN1_INTEGER_2_string(ASN1_INTEGER *_asni) { + BIO *bio; + int k; + char *p; + + if (_asni == NULL) { + error("ssh_ASN1_INTEGER_2_string: _asni is NULL"); + return(NULL); + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + fatal("ssh_ASN1_INTEGER_2_string: out of memory"); + return(NULL); /* ;-) */ + } + + i2a_ASN1_INTEGER(bio, _asni); + k = BIO_pending(bio); + p = xmalloc(k + 1); /*fatal on error*/ + k = BIO_read(bio, p, k); + p[k] = '\0'; + BIO_free_all(bio); + + return(p); +} +#endif /*def SSH_CHECK_REVOKED*/ + + +int +ssh_x509store_lookup(X509_STORE *store, int type, X509_NAME *name, X509_OBJECT *xobj) { + X509_STORE_CTX ctx; + int ret; + + if (X509_STORE_CTX_init(&ctx, store, NULL, NULL) <= 0) { + /*memory allocation error*/ + error("ssh_x509store_lookup: cannot initialize x509store context"); + return(-1); + } + ret = X509_STORE_get_by_subject(&ctx, type, name, xobj); + X509_STORE_CTX_cleanup(&ctx); + + return(ret); +} + + +static int +ssh_x509store_cb(int ok, X509_STORE_CTX *ctx) { + int ctx_error = X509_STORE_CTX_get_error(ctx); + X509 *ctx_cert = X509_STORE_CTX_get_current_cert(ctx); + + if ((!ok) && + (ctx_error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) + ) { + if (ssh_x509flags.key_allow_selfissued) + ok = ssh_is_selfsigned(ctx_cert); + } + if (!ok) { + char *buf; + buf = ssh_X509_NAME_oneline(X509_get_subject_name(ctx_cert)); /*fatal on error*/ + error("ssh_x509store_cb: subject='%s', error %d at %d depth lookup:%.200s", + buf, + ctx_error, + X509_STORE_CTX_get_error_depth(ctx), + X509_verify_cert_error_string(ctx_error)); + xfree(buf); + } +#ifdef SSH_CHECK_REVOKED + if (ok) { + ok = ssh_x509revoked_cb(ok, ctx); + } +#endif + return(ok); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +typedef struct { + const char **synonyms; +} CertPurposes; + + +static const char *__purpose_any[] = { + "any", "any purpose", "any_purpose", "anypurpose", NULL +}; + + +static const char *__purpose_sslclient[] = { + "sslclient", "ssl client", "ssl_client", "client", NULL +}; + + +static const char *__purpose_sslserver[] = { + "sslserver", "ssl server", "ssl_server", "server", NULL +}; + + +static CertPurposes +sslclient_purposes[] = { + { __purpose_sslclient }, + { __purpose_any }, + { NULL } +}; + + +static CertPurposes +sslserver_purposes [] = { + { __purpose_sslserver }, + { __purpose_any }, + { NULL } +}; + + +static const char* +get_cert_purpose(const char* _purpose_synonym, CertPurposes *_purposes) { + int i; + + for (i = 0; _purposes[i].synonyms; i++) { + const char *q = _purposes[i].synonyms[0]; + if (strcasecmp(_purpose_synonym, q) == 0 ) { + return(q); + } else { + const char **p; + for (p = (_purposes[i].synonyms) + 1; *p; p++) { + if (strcasecmp(_purpose_synonym, *p) == 0 ) { + return(q); + } + } + } + } + return(NULL); +} + + +void +ssh_x509flags_initialize(SSH_X509Flags *flags, int is_server) { + flags->is_server = is_server; + flags->allowedcertpurpose = -1; +#ifndef SSH_X509STORE_DISABLED + flags->key_allow_selfissued = -1; + flags->mandatory_crl = -1; +#endif /*ndef SSH_X509STORE_DISABLED*/ +} + + +void +ssh_x509flags_defaults(SSH_X509Flags *flags) { + if (flags->allowedcertpurpose == -1) { + int is_server = flags->is_server; + const char* purpose_synonym = is_server ? __purpose_sslclient[0] : __purpose_sslserver[0]; + + flags->allowedcertpurpose = ssh_get_x509purpose_s(is_server, purpose_synonym); + } +#ifndef SSH_X509STORE_DISABLED + if (flags->key_allow_selfissued == -1) { + flags->key_allow_selfissued = 0; + } +#ifdef SSH_CHECK_REVOKED + if (flags->mandatory_crl == -1) { + flags->mandatory_crl = 0; + } +#else + if (flags->mandatory_crl != -1) { + logit("useless option: mandatory_crl"); + } +#endif +#endif /*ndef SSH_X509STORE_DISABLED*/ +} + + +int +ssh_get_x509purpose_s(int _is_server, const char* _purpose_synonym) { + const char * sslpurpose; + + sslpurpose = get_cert_purpose(_purpose_synonym, + (_is_server ? sslclient_purposes : sslserver_purposes)); + if (sslpurpose != NULL) { + int purpose_index = X509_PURPOSE_get_by_sname((char*)sslpurpose); + if (purpose_index < 0) + fatal( "ssh_get_x509purpose_s(%.10s): " + "X509_PURPOSE_get_by_sname fail for argument '%.30s(%.40s)'", + (_is_server ? "server" : "client"), + sslpurpose, _purpose_synonym); + return(purpose_index); + } + return(-1); +} + + +#ifndef SSH_X509STORE_DISABLED +int/*bool*/ +ssh_is_selfsigned(X509 *_cert) { + X509_NAME *issuer, *subject; + + issuer = X509_get_issuer_name(_cert); + subject = X509_get_subject_name(_cert); + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *buf; + + buf = ssh_X509_NAME_oneline(issuer); /*fatal on error*/ + debug3("ssh_is_selfsigned: issuer='%s'", buf); + xfree(buf); + + buf = ssh_X509_NAME_oneline(subject); /*fatal on error*/ + debug3("ssh_is_selfsigned: subject='%s'", buf); + xfree(buf); + } + + return (ssh_X509_NAME_cmp(issuer, subject) == 0); +} + + +void +ssh_x509store_initialize(X509StoreOptions *options) { + options->certificate_file = NULL; + options->certificate_path = NULL; + options->revocation_file = NULL; + options->revocation_path = NULL; +#ifdef LDAP_ENABLED + options->ldap_ver = NULL; + options->ldap_url = NULL; +#endif +} + + +void +ssh_x509store_system_defaults(X509StoreOptions *options) { + if (options->certificate_file == NULL) + options->certificate_file = _PATH_CA_CERTIFICATE_FILE; + if (options->certificate_path == NULL) + options->certificate_path = _PATH_CA_CERTIFICATE_PATH; + if (options->revocation_file == NULL) + options->revocation_file = _PATH_CA_REVOCATION_FILE; + if (options->revocation_path == NULL) + options->revocation_path = _PATH_CA_REVOCATION_PATH; +#ifdef LDAP_ENABLED + /*nothing to do ;-)*/ +#endif +} + + +static void +tilde_expand_filename2(const char **_fn, const char* _default, uid_t uid) { + if (*_fn == NULL) { + *_fn = tilde_expand_filename(_default, uid); + } else { + const char *p = *_fn; + *_fn = tilde_expand_filename(p, uid); + xfree((void*)p); + } +} + + +void +ssh_x509store_user_defaults(X509StoreOptions *options, uid_t uid) { + tilde_expand_filename2(&options->certificate_file, _PATH_USERCA_CERTIFICATE_FILE, uid); + tilde_expand_filename2(&options->certificate_path, _PATH_USERCA_CERTIFICATE_PATH, uid); + tilde_expand_filename2(&options->revocation_file , _PATH_USERCA_REVOCATION_FILE , uid); + tilde_expand_filename2(&options->revocation_path , _PATH_USERCA_REVOCATION_PATH , uid); +#ifdef LDAP_ENABLED + /*nothing to do ;-)*/ +#endif +} + + +static void +ssh_x509store_initcontext(void) { + if (x509store == NULL) { + x509store = X509_STORE_new(); + if (x509store == NULL) { + fatal("cannot create x509store context"); + } + X509_STORE_set_verify_cb_func(x509store, ssh_x509store_cb); + } +#ifdef SSH_CHECK_REVOKED + if (x509revoked == NULL) { + x509revoked = X509_STORE_new(); + if (x509revoked == NULL) { + fatal("cannot create x509revoked context"); + } + } +#endif +} + + +int/*bool*/ +ssh_x509store_addlocations(const X509StoreOptions *_locations) { + int flag; + + if (_locations == NULL) { + error("ssh_x509store_addlocations: _locations is NULL"); + return(0); + } + if ((_locations->certificate_path == NULL) && + (_locations->certificate_file == NULL)) { + error("ssh_x509store_addlocations: certificate path and file are NULLs"); + return(0); + } +#ifdef SSH_CHECK_REVOKED + if ((_locations->revocation_path == NULL) && + (_locations->revocation_file == NULL)) { + error("ssh_x509store_addlocations: revocation path and file are NULLs"); + return(0); + } +#endif + ssh_x509store_initcontext(); + + flag = 0; + /* + * Note: + * After X509_LOOKUP_{add_dir|load_file} calls we must call + * ERR_clear_error() otherwise when the first call to + * X509_LOOKUP_XXXX fail the second call fail too ! + */ + if (_locations->certificate_path != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations: cannot add hash dir lookup !"); + return(0); /* ;-) */ + } + if (X509_LOOKUP_add_dir(lookup, _locations->certificate_path, X509_FILETYPE_PEM)) { + debug2("hash dir '%.400s' added to x509 store", _locations->certificate_path); + flag = 1; + } + ERR_clear_error(); + } + if (_locations->certificate_file != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509store, X509_LOOKUP_file()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations: cannot add file lookup !"); + return(0); /* ;-) */ + } + if (X509_LOOKUP_load_file(lookup, _locations->certificate_file, X509_FILETYPE_PEM)) { + debug2("file '%.400s' added to x509 store", _locations->certificate_file); + flag = 1; + } + ERR_clear_error(); + } + /*at least one lookup should succeed*/ + if (flag == 0) return(0); + + flag = 0; +#ifdef SSH_CHECK_REVOKED + if (_locations->revocation_path != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509revoked, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations: cannot add hash dir revocation lookup !"); + return(0); /* ;-) */ + } + if (X509_LOOKUP_add_dir(lookup, _locations->revocation_path, X509_FILETYPE_PEM)) { + debug2("hash dir '%.400s' added to x509 revocation store", _locations->revocation_path); + flag = 1; + } + ERR_clear_error(); + } + if (_locations->revocation_file != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509revoked, X509_LOOKUP_file()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations: cannot add file revocation lookup !"); + return(0); /* ;-) */ + } + if (X509_LOOKUP_load_file(lookup, _locations->revocation_file, X509_FILETYPE_PEM)) { + debug2("file '%.400s' added to x509 revocation store", _locations->revocation_file); + flag = 1; + } + ERR_clear_error(); + } +#else /*ndef SSH_CHECK_REVOKED*/ + if (_locations->revocation_path != NULL) { + logit("useless option: revocation_path"); + } + if (_locations->revocation_file != NULL) { + logit("useless option: revocation_file"); + } + flag = 1; +#endif /*ndef SSH_CHECK_REVOKED*/ + /*at least one revocation lookup should succeed*/ + if (flag == 0) return(0); + +#ifdef LDAP_ENABLED + if (_locations->ldap_url != NULL) { + X509_LOOKUP *lookup; + + lookup = X509_STORE_add_lookup(x509store, X509_LOOKUP_ldap()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations: cannot add ldap lookup !"); + return(0); /* ;-) */ + } + if (X509_LOOKUP_add_ldap(lookup, _locations->ldap_url)) { + debug2("ldap url '%.400s' added to x509 store", _locations->ldap_url); + } + if (_locations->ldap_ver != NULL) { + if (!X509_LOOKUP_set_protocol(lookup, _locations->ldap_ver)) { + fatal("ssh_x509store_addlocations: cannot set ldap version !"); + return(0); /* ;-) */ + } + } + /*ERR_clear_error();*/ + +#ifdef SSH_CHECK_REVOKED + lookup = X509_STORE_add_lookup(x509revoked, X509_LOOKUP_ldap()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations: cannot add ldap lookup(revoked) !"); + return(0); /* ;-) */ + } + if (X509_LOOKUP_add_ldap(lookup, _locations->ldap_url)) { + debug2("ldap url '%.400s' added to x509 store(revoked)", _locations->ldap_url); + } + if (_locations->ldap_ver != NULL) { + if (!X509_LOOKUP_set_protocol(lookup, _locations->ldap_ver)) { + fatal("ssh_x509store_addlocations: cannot set ldap version(revoked) !"); + return(0); /* ;-) */ + } + } + /*ERR_clear_error();*/ +#endif /*def SSH_CHECK_REVOKED*/ + } +#endif /*def LDAP_ENABLED*/ + + return(1); +} + + +static int +ssh_verify_cert(X509_STORE_CTX *_csc, X509 *_cert) { + int flag; + if (X509_STORE_CTX_init(_csc, x509store, _cert, NULL) <= 0) { + /*memory allocation error*/ + error("ssh_verify_cert: cannot initialize x509store context"); + return(-1); + } + + if (ssh_x509flags.allowedcertpurpose >= 0) { + int def_purpose = ( ssh_x509flags.is_server + ? X509_PURPOSE_SSL_CLIENT + : X509_PURPOSE_SSL_SERVER + ); + X509_PURPOSE *xptmp = X509_PURPOSE_get0(ssh_x509flags.allowedcertpurpose); + int purpose; + if (xptmp == NULL) { + fatal("ssh_verify_cert: cannot get purpose from index"); + return(-1); /* ;-) */ + } + purpose = X509_PURPOSE_get_id(xptmp); + flag = X509_STORE_CTX_purpose_inherit(_csc, def_purpose, purpose, 0); + if (flag <= 0) { + /* + * By default openssl applications don't check return code from + * X509_STORE_CTX_set_purpose or X509_STORE_CTX_purpose_inherit. + * + * Both methods return 0 (zero) and don't change purpose in context when: + * -X509_STORE_CTX_set_purpose(...) + * purpose is X509_PURPOSE_ANY + * -X509_STORE_CTX_purpose_inherit(...) + * purpose is X509_PURPOSE_ANY and default purpose is zero (!) + * + * Take note when purpose is "any" check method in current + * OpenSSL code just return 1. This openssl behavior is same + * as ssh option "AllowedCertPurpose=skip". + */ + int ecode; + char ebuf[256]; + + ecode = X509_STORE_CTX_get_error(_csc); + error("ssh_verify_cert: context purpose error, code=%d, msg='%.200s'" + , ecode + , X509_verify_cert_error_string(ecode)); + + ecode = ERR_get_error(); + ERR_error_string_n(ecode, ebuf, sizeof(ebuf)); + error("ssh_verify_cert: X509_STORE_CTX_purpose_inherit failed with '%.256s'" + , ebuf); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + return(-1); + } + } + + /* + if (issuer_checks) + X509_STORE_CTX_set_flags(_csc, X509_V_FLAG_CB_ISSUER_CHECK); + */ + + flag = X509_verify_cert(_csc); + if (flag < 0) { + /* NOTE: negative result is returned only if certificate to check + * is not set in context. This function is called if _cert is non + * NULL, i.e. certificate has to be set in context! + * Lets log (posible in future) cases with negative value. + */ + logit("ssh_verify_cert: X509_verify_cert return unexpected negative value: '%d'", flag); + return(-1); + } + if (flag == 0) { + int ecode = X509_STORE_CTX_get_error(_csc); + error("ssh_verify_cert: verify error, code=%d, msg='%.200s'" + , ecode + , X509_verify_cert_error_string(ecode)); + return(-1); + } + + return(1); +} +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +int +ssh_x509cert_check(X509 *_cert) { + int ret = 1; +#ifndef SSH_X509STORE_DISABLED + X509_STORE_CTX *csc; +#else /*def SSH_X509STORE_DISABLED*/ + X509_PURPOSE *xptmp; +#endif /*def SSH_X509STORE_DISABLED*/ + +#ifndef SSH_X509STORE_DISABLED + if (_cert == NULL) { + /*already checked but ...*/ + error("ssh_x509cert_check: cert is NULL"); + ret = -1; + goto done; + } + if (x509store == NULL) { + error("ssh_x509cert_check: context is NULL"); + ret = -1; + goto done; + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *buf; + buf = ssh_X509_NAME_oneline(X509_get_subject_name(_cert)); /*fatal on error*/ + debug3("ssh_x509cert_check: for '%s'", buf); + xfree(buf); + } + + csc = X509_STORE_CTX_new(); + if (csc == NULL) { + int ecode = ERR_get_error(); + char ebuf[256]; + ERR_error_string_n(ecode, ebuf, sizeof(ebuf)); + error("ssh_x509cert_check: X509_STORE_CTX_new failed with '%.256s'", ebuf); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + ret = -1; + goto done; + } + + ret = ssh_verify_cert(csc, _cert); + X509_STORE_CTX_free(csc); +#ifdef SSH_OCSP_ENABLED + if (ret > 0) { +/* + * OpenSSH implementation first verify and validate certificate by + * "X.509 store" with certs and crls from file system. It is fast + * check. After this when certificate chain is correct and + * certificate is not revoked we send a status request to an OCSP + * responder if configured. + * + * RFC2560(OCSP): + * ... + * 2.7 CA Key Compromise + * If an OCSP responder knows that a particular CA's private key + * has been compromised, it MAY return the revoked state for all + * certificates issued by that CA. + * ... + * 5. Security Considerations + * For this service to be effective, certificate using systems must + * connect to the certificate status service provider. In the event + * such a connection cannot be obtained, certificate-using systems + * could implement CRL processing logic as a fall-back position. + * ... + * RFC2560(OCSP)^ + * + * About OpenSSH implementation: + * 1.) We preffer to delegate validation of issuer certificates to + * 'OCSP Provider'. It is easy and simple to configure an OCSP + * responder to return revoked state for all certificates issued + * by a CA. Usually 'OCSP Provider' admins shall be first informed + * for certificates with changed state. In each case this simplify + * 'OCSP client'. + * 2.) To conform to RFC2560 we should use OCSP to check status of + * all certificates in the chain. Since this is network request it + * is good to implement a cache and to save status with lifetime. + * Might is good to have an OCSP cache server ;-). + * + * To minimize network latency and keeping in mind 1.) we send + * 'OCSP request' only for the last certificate in the chain, i.e. + * sended client or server certificate. + * + * Therefore instead to send OCSP request in ssh_x509revoked_cb() + * we do this here. + */ + ret = ssh_ocsp_validate(_cert, x509store); + } +#endif /*def SSH_OCSP_ENABLED*/ + +#else /*def SSH_X509STORE_DISABLED*/ + if (ssh_x509flags.allowedcertpurpose >= 0) { + xptmp = X509_PURPOSE_get0(ssh_x509flags.allowedcertpurpose); + if (xptmp == NULL) { + fatal("ssh_x509cert_check: cannot get purpose from index"); + return(-1); /* ;-) */ + } + ret = X509_check_purpose(_cert, X509_PURPOSE_get_id(xptmp), 0); + if (ret < 0) { + logit("ssh_x509cert_check: X509_check_purpose return %d", ret); + ret = 0; + } + } +#endif /*def SSH_X509STORE_DISABLED*/ +done: +{ + const char *msg = (ret > 0) ? "trusted" : (ret < 0 ? "error" : "rejected"); + debug3("ssh_x509cert_check: return %d(%s)", ret, msg); +} + return(ret); +} + + +#ifndef SSH_X509STORE_DISABLED +#ifdef SSH_CHECK_REVOKED +static void +ssh_get_namestr_and_hash( + X509_NAME *name, + char **buf, + u_long *hash +) { + if (name == NULL) { + debug("ssh_get_namestr_and_hash: name is NULL"); + if (buf ) *buf = NULL; + if (hash) *hash = 0; /* not correct but :-( */ + return; + } + + if (buf ) *buf = ssh_X509_NAME_oneline(name); /*fatal on error*/ + if (hash) *hash = X509_NAME_hash(name); +} + + +static int/*bool*/ +ssh_check_crl(X509_STORE_CTX *_ctx, X509* _issuer, X509_CRL *_crl) { + time_t *pcheck_time; + int k; + u_long hash; + + if (_issuer == NULL) { + error("ssh_check_crl: issuer is NULL"); + return(0); + } + if (_crl == NULL) { + debug("ssh_check_crl: crl is NULL"); + return(1); + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + BIO *bio; + char *p; + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + fatal("ssh_check_crl: out of memory"); + return(0); /* ;-) */ + } + + ssh_X509_NAME_print(bio, X509_CRL_get_issuer(_crl)); + + BIO_printf(bio, "; Last Update: "); + ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(_crl)); + + BIO_printf(bio, "; Next Update: "); + ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(_crl)); + + k = BIO_pending(bio); + p = xmalloc(k + 1); /*fatal on error*/ + k = BIO_read(bio, p, k); + p[k] = '\0'; + + debug3("ssh_check_crl: Issuer: %s", p); + + xfree(p); + BIO_free(bio); + } + +/* RFC 3280: + * The cRLSign bit is asserted when the subject public key is used + * for verifying a signature on certificate revocation list (e.g., a + * CRL, delta CRL, or an ARL). This bit MUST be asserted in + * certificates that are used to verify signatures on CRLs. + */ + if (/*???(_issuer->ex_flags & EXFLAG_KUSAGE) &&*/ + !(_issuer->ex_kusage & KU_CRL_SIGN) + ) { + char *buf; + #ifdef X509_V_ERR_KEYUSAGE_NO_CRL_SIGN + /*first defined in OpenSSL 0.9.7d*/ + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_KEYUSAGE_NO_CRL_SIGN); + #endif + ssh_get_namestr_and_hash(X509_get_subject_name(_issuer), &buf, &hash); + error("ssh_check_crl:" + " to verify crl signature key usage 'cRLSign'" + " must present in issuer certificate '%s' with hash=0x%08lx" + , buf, hash + ); + xfree(buf); + return(0); + } + + { + EVP_PKEY *pkey = X509_get_pubkey(_issuer); + if (pkey == NULL) { + error("ssh_check_crl: unable to decode issuer public key"); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY); + return(0); + } + + if (X509_CRL_verify(_crl, pkey) <= 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error("ssh_check_crl: CRL has invalid signature" + ": issuer='%s', hash=0x%08lx" + , buf, hash + ); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE); + xfree(buf); + return(0); + } + EVP_PKEY_free(pkey); + } + + + if (SSH_X509_VERIFY_PARAM(_ctx,flags) & X509_V_FLAG_USE_CHECK_TIME) + pcheck_time = &SSH_X509_VERIFY_PARAM(_ctx,check_time); + else + pcheck_time = NULL; + + k = X509_cmp_time(X509_CRL_get_lastUpdate(_crl), pcheck_time); + if (k == 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error("ssh_check_crl: CRL has invalid lastUpdate field" + ": issuer='%s', hash=0x%08lx" + , buf, hash + ); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD); + xfree(buf); + return(0); + } + if (k > 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error("ssh_check_crl: CRL is not yet valid" + ": issuer='%s', hash=0x%08lx" + , buf, hash + ); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_NOT_YET_VALID); + xfree(buf); + return(0); + } + + k = X509_cmp_time(X509_CRL_get_nextUpdate(_crl), pcheck_time); + if (k == 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error("ssh_check_crl: CRL has invalid nextUpdate field" + ": issuer='%s', hash=0x%08lx" + , buf, hash + ); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); + xfree(buf); + return(0); + } +#if 0 + /*test "extend time limit"*/ + if (k < 0) { + time_t tm; + if (pcheck_time == NULL) { + tm = time(NULL); + pcheck_time = &tm; + } + *pcheck_time -= convtime("1w"); + k = X509_cmp_time(X509_CRL_get_nextUpdate(_crl), pcheck_time); + } +#endif + if (k < 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error("ssh_check_crl: CRL is expired" + ": issuer='%s', hash=0x%08lx" + , buf, hash + ); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_HAS_EXPIRED); + xfree(buf); + return(0); + } + + return(1); +} + + +static int/*bool*/ +ssh_is_cert_revoked(X509_STORE_CTX *_ctx, X509_CRL *_crl, X509 *_cert) { + X509_REVOKED revoked; + int k; + char *dn, *ser, *in; + + if (_crl == NULL) return(1); + revoked.serialNumber = X509_get_serialNumber(_cert); + k = sk_X509_REVOKED_find(_crl->crl->revoked, &revoked); + if (k < 0) return(0); + + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CERT_REVOKED); + /* yes, revoked. print log and ...*/ + dn = ssh_X509_NAME_oneline(X509_get_subject_name(_cert)); /*fatal on error*/ + ser = ssh_ASN1_INTEGER_2_string(revoked.serialNumber); + in = ssh_X509_NAME_oneline(X509_CRL_get_issuer (_crl )); /*fatal on error*/ + + error("certificate '%s' with serial '%.40s' revoked from issuer '%s'" + , dn, ser, in); + xfree(dn); + xfree(ser); + xfree(in); + + return(1); +} + + +static int +ssh_x509revoked_cb(int ok, X509_STORE_CTX *ctx) { + X509 *cert; + X509_OBJECT xobj; + + if (!ok) return(0); + if (x509revoked == NULL) + return(ok); /* XXX:hmm */ + + cert = X509_STORE_CTX_get_current_cert(ctx); + if (cert == NULL) { + error("ssh_x509revoked_cb: missing current certificate in x509store context"); + return(0); + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *buf; + + buf = ssh_X509_NAME_oneline(X509_get_issuer_name(cert)); /*fatal on error*/ + debug3("ssh_x509revoked_cb: Issuer: %s", buf); + xfree(buf); + + buf = ssh_X509_NAME_oneline(X509_get_subject_name(cert)); /*fatal on error*/ + debug3("ssh_x509revoked_cb: Subject: %s", buf); + xfree(buf); + } + + memset(&xobj, 0, sizeof(xobj)); +/* TODO: + * NID_crl_distribution_points may contain one or more + * CRLissuer != cert issuer + */ + if (ssh_x509store_lookup( + x509revoked, X509_LU_CRL, + X509_get_subject_name(cert), + &xobj) > 0) { +/* + * In callback we cannot check CRL signature at this point when we use + * X509_get_issuer_name(), because we don't know issuer public key! + * Of course we can get the public key from X509_STORE defined by + * static variable "x509store". + * Of course we can check revocation outside callback, but we should + * try to find public key in X509_STORE[s]. + * + * At this point we can get easy public key of "current certificate"! + * + * Method: "look forward" + * At this call we check CLR (signature and other) issued with "current + * certificate" ("CertA"). If all is OK with "CertA" by next call of + * callback method "current certificate" is signed from "CertA" and the + * CRL issued from "CertA", if any is already verified - cool ;-). + * + * Note that when a certificate is revoked all signed form that + * certificate are revoked automatically too. With method "look forward" + * we already know that all issuers of "current certificate" aren't + * revoked. + */ + ok = ssh_check_crl(ctx, cert, xobj.data.crl); + } else { + if (ssh_x509flags.mandatory_crl == 1) { + int loc; + loc = X509_get_ext_by_NID(cert, NID_crl_distribution_points, -1); + ok = (loc < 0); + if (!ok) { + error("ssh_x509revoked_cb: unable to get issued CRL"); + X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNABLE_TO_GET_CRL); + } + } + } + X509_OBJECT_free_contents(&xobj); + if (!ok) return(0); + + memset(&xobj, 0, sizeof(xobj)); + if (ssh_x509store_lookup( + x509revoked, X509_LU_CRL, + X509_get_issuer_name(cert), + &xobj) > 0) { + ok = !ssh_is_cert_revoked(ctx, xobj.data.crl, cert); + } + X509_OBJECT_free_contents(&xobj); + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + + if (!ok) return(0); + + /**/ + return(ok); +} +#endif + +#endif /*ndef SSH_X509STORE_DISABLED*/ diff -ruN openssh-5.6p1/x509store.h openssh-5.6p1+x509-6.2.3/x509store.h --- openssh-5.6p1/x509store.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-5.6p1+x509-6.2.3/x509store.h 2007-10-04 22:54:04.000000000 +0300 @@ -0,0 +1,123 @@ +#ifndef X509STORE_H +#define X509STORE_H +/* + * Copyright (c) 2002-2007 Roumen Petrov. 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" +#include + + +int ssh_X509_NAME_print(BIO* bio, X509_NAME *xn); +char* ssh_X509_NAME_oneline(X509_NAME *xn); + + +int ssh_x509cert_check(X509 *_cert); + + +typedef struct { + int is_server; + /* allowed client/server certificate purpose */ + int allowedcertpurpose; /* note field contain purpose index */ +#ifndef SSH_X509STORE_DISABLED + int key_allow_selfissued; /* make sense only when x509store is enabled */ + int mandatory_crl; +#endif /*ndef SSH_X509STORE_DISABLED*/ +} SSH_X509Flags; + +extern SSH_X509Flags ssh_x509flags; + +void ssh_x509flags_initialize(SSH_X509Flags *flags, int is_server); +void ssh_x509flags_defaults(SSH_X509Flags *flags); + +/* return purpose index, not purpose id (!) */ +int ssh_get_x509purpose_s(int _is_server, const char* _purpose_synonym); + + +#ifndef SSH_X509STORE_DISABLED +int ssh_X509_NAME_cmp(X509_NAME *_a, X509_NAME *_b); +int/*bool*/ ssh_is_selfsigned(X509 *_cert); + +int ssh_x509store_lookup(X509_STORE *store, int type, X509_NAME *name, X509_OBJECT *xobj); + +typedef struct { + /* ssh PKI(X509) store */ + const char *certificate_file; + const char *certificate_path; + const char *revocation_file; + const char *revocation_path; +#ifdef LDAP_ENABLED + const char *ldap_ver; + const char *ldap_url; +#endif +} X509StoreOptions; + +void ssh_x509store_initialize(X509StoreOptions *options); +void ssh_x509store_system_defaults(X509StoreOptions *options); +void ssh_x509store_user_defaults(X509StoreOptions *options, uid_t uid); + +int/*bool*/ ssh_x509store_addlocations(const X509StoreOptions *_locations); + +#endif /*ndef SSH_X509STORE_DISABLED*/ + + +#ifdef SSH_X509STORE_DISABLED +#ifdef LDAP_ENABLED +# include "cannot enable LDAP when x509store is disabled" +#endif /*def LDAP_ENABLED*/ +#ifdef SSH_OCSP_ENABLED +# include "cannot enable OCSP when x509store is disabled" +#endif /*def SSH_OCSP_ENABLED*/ +#endif /*def SSH_X509STORE_DISABLED*/ + + +#ifdef SSH_OCSP_ENABLED + +enum va_type { + SSHVA_NONE, + SSHVA_OCSP_CERT, + SSHVA_OCSP_SPEC +}; + + +typedef struct { + int type; /*allowed values from enum va_type*/ + + /* file with additional trusted certificates */ + const char *certificate_file; + + /* ssh OCSP Provider(Respoder) URL */ + const char *responder_url; +} VAOptions; + +int ssh_get_default_vatype(void); +int ssh_get_vatype_s(const char* type); + +void ssh_set_validator(const VAOptions *_va); /*fatal on error*/ + +int ssh_ocsp_validate(X509 *cert, X509_STORE *x509store); + +#endif /*def SSH_OCSP_ENABLED*/ + + +#endif /* X509STORE_H */