John Hansen
2011-08-23 20:58:17 UTC
Signed-off-by: John Hansen <***@geeknet.com.au>
Index: 300-x509.patch
===================================================================
--- 300-x509.patch (revision 0)
+++ 300-x509.patch (revision 0)
@@ -0,0 +1,22533 @@
+diff -ruN openssh-5.8p1/auth2-hostbased.c openssh-5.8p1+x509-6.2.4/auth2-hostbased.c
+--- openssh-5.8p1/auth2-hostbased.c 2010-08-05 06:04:50.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/auth2-hostbased.c 2011-02-04 21:06:01.000000000 +0200
+@@ -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, const char* pkalg);
++
+ static int
+ userauth_hostbased(Authctxt *authctxt)
+ {
+@@ -90,6 +92,11 @@
+ "public key algorithm: %s", pkalg);
+ goto done;
+ }
++ if (!hostbased_algorithm_allowed(pktype, pkalg)) {
++ 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,39 @@
+ return authenticated;
+ }
+
++/* return 1 if given hostbased algorithm is allowed */
++static int
++hostbased_algorithm_allowed(int pktype, const char* pkalg)
++{
++ char *s, *cp, *p;
++#ifdef OPENSSL_HAS_ECC
++ int curve_nid = -1;
++#endif
++
++ 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)) {
++#ifdef OPENSSL_HAS_ECC
++ if (key_type_plain(pktype) == KEY_ECDSA) {
++ if (curve_nid == -1)
++ curve_nid = key_ecdsa_nid_from_name(pkalg);
++ if (curve_nid != key_ecdsa_nid_from_name(p))
++ continue;
++ }
++#endif
++ 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.8p1/auth2-pubkey.c openssh-5.8p1+x509-6.2.4/auth2-pubkey.c
+--- openssh-5.8p1/auth2-pubkey.c 2010-12-01 02:50:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/auth2-pubkey.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: auth2-pubkey.c,v 1.27 2010/11/20 05:12:38 deraadt 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, const char* pkalg);
++
+ static int
+ userauth_pubkey(Authctxt *authctxt)
+ {
+@@ -100,6 +103,11 @@
+ pkalg);
+ goto done;
+ }
++ if (!pubkey_algorithm_allowed(pktype, pkalg)) {
++ 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,132 @@
+ return 0;
+ }
+
++/* return 1 if given publickey algorithm is allowed */
++static int
++pubkey_algorithm_allowed(int pktype, const char* pkalg)
++{
++ char *s, *cp, *p;
++#ifdef OPENSSL_HAS_ECC
++ int curve_nid = -1;
++#endif
++
++ 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)) {
++#ifdef OPENSSL_HAS_ECC
++ if (key_type_plain(pktype) == KEY_ECDSA) {
++ if (curve_nid == -1)
++ curve_nid = key_ecdsa_nid_from_name(pkalg);
++ if (curve_nid != key_ecdsa_nid_from_name(p))
++ continue;
++ }
++#endif
++ 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 +425,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 +440,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 +489,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 +498,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.8p1/authfd.c openssh-5.8p1+x509-6.2.4/authfd.c
+--- openssh-5.8p1/authfd.c 2010-09-10 04:39:27.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/authfd.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: authfd.c,v 1.84 2010/08/31 11:54:45 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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);
+@@ -525,6 +529,21 @@
+ break;
+ #endif
+ }
++ 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);
+ }
+
+@@ -558,6 +577,8 @@
+ case KEY_DSA_CERT_V00:
+ case KEY_ECDSA:
+ case KEY_ECDSA_CERT:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ type = constrained ?
+ SSH2_AGENTC_ADD_ID_CONSTRAINED :
+ SSH2_AGENTC_ADD_IDENTITY;
+@@ -606,6 +627,8 @@
+ 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 == KEY_X509_RSA ||
++ key->type == KEY_X509_DSA ||
+ key_type_plain(key->type) == KEY_RSA ||
+ key_type_plain(key->type) == KEY_ECDSA) {
+ key_to_blob(key, &blob, &blen);
+diff -ruN openssh-5.8p1/authfile.c openssh-5.8p1+x509-6.2.4/authfile.c
+--- openssh-5.8p1/authfile.c 2010-12-01 03:03:39.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/authfile.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: authfile.c,v 1.87 2010/11/29 18:57:04 markus Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+
+@@ -201,6 +204,10 @@
+ success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
+ cipher, passphrase, len, NULL, NULL);
+ break;
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
++ success = x509key_write_bio_pem(bio, key, cipher, passphrase, len);
++ break;
+ }
+ if (success) {
+ if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
+@@ -245,6 +252,8 @@
+ case KEY_DSA:
+ case KEY_ECDSA:
+ case KEY_RSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ return key_private_pem_to_blob(key, blob, passphrase, comment);
+ default:
+ error("%s: cannot save key type %d", __func__, key->type);
+@@ -500,6 +509,7 @@
+ char *name = "<no key>";
+ BIO *bio;
+
++ debug("read PEM private key begin");
+ if ((bio = BIO_new_mem_buf(buffer_ptr(blob),
+ buffer_len(blob))) == NULL) {
+ error("%s: BIO_new_mem_buf failed", __func__);
+@@ -507,7 +517,6 @@
+ }
+
+ pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase);
+- BIO_free(bio);
+ if (pk == NULL) {
+ debug("%s: PEM_read_PrivateKey failed", __func__);
+ (void)ERR_get_error();
+@@ -559,6 +568,17 @@
+ error("%s: PEM_read_PrivateKey: mismatch or "
+ "unknown EVP_PKEY save_type %d", __func__, pk->save_type);
+ }
++ if (prv) {
++ debug("read X.509 certificate begin");
++ BIO_seek(bio, 0); /* rewind */
++ x509key_parse_cert(prv, bio);
++ if (prv->x509 != NULL) {
++ if (!X509_check_private_key(prv->x509, pk)) {
++ fatal("X509 certificate don't match private key");
++ }
++ }
++ }
++ BIO_free(bio);
+ if (pk != NULL)
+ EVP_PKEY_free(pk);
+ if (prv != NULL && commentp)
+@@ -762,6 +782,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.8p1/config.h.in openssh-5.8p1+x509-6.2.4/config.h.in
+--- openssh-5.8p1/config.h.in 2011-02-04 02:59:51.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/config.h.in 2011-02-04 21:06:01.000000000 +0200
+@@ -335,6 +335,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
+
+@@ -551,6 +563,24 @@
+ /* Define to 1 if you have the <lastlog.h> header file. */
+ #undef HAVE_LASTLOG_H
+
++/* Define to 1 if you have the <lber.h> header file. */
++#undef HAVE_LBER_H
++
++/* Define to 1 if you have the <ldap.h> 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 <libaudit.h> header file. */
+ #undef HAVE_LIBAUDIT_H
+
+@@ -668,6 +698,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
+
+@@ -1170,6 +1203,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
+
+@@ -1221,6 +1257,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
+
+@@ -1283,6 +1322,9 @@
+ /* Define if X11 doesn't support AF_UNIX sockets on that system */
+ #undef NO_X11_UNIX_SOCKETS
+
++/* Define if OpenSSH use memory BIO buffer to read/write keys */
++#undef OPENSSH_KEYS_USE_BIO
++
+ /* Define if EVP_DigestUpdate returns void */
+ #undef OPENSSL_EVP_DIGESTUPDATE_VOID
+
+@@ -1360,6 +1402,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
+
+@@ -1372,6 +1417,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
+
+@@ -1393,6 +1445,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.8p1/configure openssh-5.8p1+x509-6.2.4/configure
+--- openssh-5.8p1/configure 2011-02-04 03:00:01.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/configure 2011-02-04 21:06:02.000000000 +0200
+@@ -730,6 +730,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
+@@ -1321,6 +1332,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
+@@ -1370,6 +1384,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
+
+@@ -1816,6 +1839,19 @@
+
+
+
++# Options to build with LDAP
++#
++# Author: Roumen Petrov
++# Revision: 22 Oct 2007
++#
++
++
++
++
++# AC_LDAP_FUNCS(FUNCTION...)
++# --------------------------------
++
++
+
+ # local macros
+
+@@ -30115,203 +30151,159 @@
+ 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
+-
++# X.509 support
++ssh_x509="yes"
+
++# Starting from version 5.7 OpenSSH use memory BIO buffer
++# to read/write keys instead file streams.
+
+ 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
++#define OPENSSH_KEYS_USE_BIO 1
+ _ACEOF
+
+- fi
+-
++# Reserved for future use
++#AC_DEFINE_UNQUOTED(
++# X509_DISABLED, 1,
++# [Define if you want to disable X.509 certificates])
+
+-fi
+-
+-# Check whether --enable-utmpx was given.
+-if test "${enable_utmpx+set}" = set; then
+- enableval=$enable_utmpx;
+- if test "x$enableval" = "xno" ; then
++# 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
+
+-cat >>confdefs.h <<\_ACEOF
+-#define DISABLE_UTMPX 1
+-_ACEOF
+
++# 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
+
+
+ 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
++cat >>confdefs.h <<_ACEOF
++#define SSHCADIR "$sshcadir"
+ _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 <limits.h> declares $ac_func.
++ For example, HP-UX 11i <limits.h> declares gettimeofday. */
++#define $ac_func innocuous_$ac_func
+
+-#include <sys/types.h>
+-#include <utmp.h>
+-#ifdef HAVE_LASTLOG_H
+-# include <lastlog.h>
++/* System header to define __stub macros and hopefully few prototypes,
++ which can conflict with char $ac_func (); below.
++ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++ <limits.h> exists even on freestanding compilers. */
++
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
+ #endif
+-#ifdef HAVE_PATHS_H
+-# include <paths.h>
++
++#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 <login.h>
++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
+@@ -30320,41 +30312,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 <sys/types.h>
+-#include <utmp.h>
+-#ifdef HAVE_LASTLOG_H
+-# include <lastlog.h>
+-#endif
+-#ifdef HAVE_PATHS_H
+-# include <paths.h>
+-#endif
+-
+-int
+-main ()
+-{
+- char *lastlog = _PATH_LASTLOG;
+- ;
+- return 0;
+-}
++$ac_includes_default
++#include <openssl/ocsp.h>
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (ac_try="$ac_compile"
+@@ -30373,24 +30371,1571 @@
+ 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 <openssl/ocsp.h>
++_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-***@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-***@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 <limits.h> declares $ac_func.
++ For example, HP-UX 11i <limits.h> 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 <limits.h> to <assert.h> if __STDC__ is defined, since
++ <limits.h> exists even on freestanding compilers. */
++
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#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 <openssl/evp.h>
++
++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 <openssl/x509_vfy.h>
++
++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 <openssl/x509_vfy.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <sys/types.h>
++#include <utmp.h>
++#ifdef HAVE_LASTLOG_H
++# include <lastlog.h>
++#endif
++#ifdef HAVE_PATHS_H
++# include <paths.h>
++#endif
++#ifdef HAVE_LOGIN_H
++# include <login.h>
++#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 <sys/types.h>
++#include <utmp.h>
++#ifdef HAVE_LASTLOG_H
++# include <lastlog.h>
++#endif
++#ifdef HAVE_PATHS_H
++# include <paths.h>
++#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
+
+-
+-fi
+-
+ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ if test -z "$conf_lastlog_location"; then
+@@ -30713,7 +32258,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
+@@ -31275,6 +32820,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" ;;
+
+@@ -31493,13 +33040,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` = 21; then
++ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 32; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+@@ -31948,6 +33506,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"
+@@ -31974,6 +33533,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 " Solaris project support: $SP_MSG"
+@@ -32007,6 +33569,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.8p1/configure.ac openssh-5.8p1+x509-6.2.4/configure.ac
+--- openssh-5.8p1/configure.ac 2011-02-04 02:42:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/configure.ac 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-# $Id: configure.ac,v 1.469.4.1 2011/02/04 00:42:14 djm Exp $
++# $Id$
+ #
+ # Copyright (c) 1999-2004 Damien Miller
+ #
+@@ -17,6 +17,7 @@
+ AC_INIT(OpenSSH, Portable, openssh-unix-***@mindrot.org)
+ AC_REVISION($Revision: 1.469.4.1 $)
+ AC_CONFIG_SRCDIR([ssh.c])
++m4_include([m4/ldap.m4])
+
+ # local macros
+ AC_DEFUN([OPENSSH_CHECK_CFLAG_COMPILE], [{
+@@ -3990,6 +3991,167 @@
+ ]
+ )
+
++# X.509 support
++ssh_x509="yes"
++
++# Starting from version 5.7 OpenSSH use memory BIO buffer
++# to read/write keys instead file streams.
++AC_DEFINE_UNQUOTED(
++ OPENSSH_KEYS_USE_BIO, 1,
++ [Define if OpenSSH use memory BIO buffer to read/write keys])
++# 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 <openssl/evp.h>
++
++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 <openssl/x509_vfy.h>])
++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 <openssl/evp.h>])
++AC_CHECK_MEMBERS([EVP_MD.copy],,,[#include <openssl/evp.h>])
++AC_CHECK_MEMBERS([EVP_MD.cleanup],,,[#include <openssl/evp.h>])
++AC_CHECK_MEMBERS([EVP_MD_CTX.md_data],,,[#include <openssl/evp.h>])
++
+ # Where to place sshd.pid
+ piddir=/var/run
+ # make sure the directory exists
+@@ -4272,6 +4434,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
+
+@@ -4294,6 +4457,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"
+@@ -4320,6 +4484,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 " Solaris project support: $SP_MSG"
+@@ -4353,6 +4520,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.8p1/dns.c openssh-5.8p1+x509-6.2.4/dns.c
+--- openssh-5.8p1/dns.c 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/dns.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,9 +1,12 @@
+-/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 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 */
+@@ -107,6 +126,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("<UNSUPPORTED>");
++}
++
++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("<UNSUPPORTED>");
++}
++
++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.
+ */
+@@ -168,6 +339,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
+ */
+@@ -200,6 +492,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) {
+@@ -278,10 +578,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)) {
+
+@@ -302,5 +649,6 @@
+ error("export_dns_rr: unsupported algorithm");
+ }
+
++ cert_param_clean(&cert_param);
+ return success;
+ }
+diff -ruN openssh-5.8p1/dns.h openssh-5.8p1+x509-6.2.4/dns.h
+--- openssh-5.8p1/dns.h 2010-02-26 22:55:05.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/dns.h 2011-02-04 21:06:00.000000000 +0200
+@@ -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.8p1/hostfile.c openssh-5.8p1+x509-6.2.4/hostfile.c
+--- openssh-5.8p1/hostfile.c 2010-12-05 00:03:31.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/hostfile.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: hostfile.c,v 1.50 2010/12/04 13:31:37 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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
+@@ -57,6 +59,7 @@
+ #include "hostfile.h"
+ #include "log.h"
+ #include "misc.h"
++#include "ssh-x509.h"
+
+ struct hostkeys {
+ struct hostkey_entry *entries;
+@@ -477,7 +480,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.8p1/INSTALL openssh-5.8p1+x509-6.2.4/INSTALL
+--- openssh-5.8p1/INSTALL 2010-02-12 00:34:22.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/INSTALL 2011-02-04 21:06:00.000000000 +0200
+@@ -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.8p1/key.c openssh-5.8p1+x509-6.2.4/key.c
+--- openssh-5.8p1/key.c 2011-02-04 02:48:34.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/key.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: key.c,v 1.96 2011/02/04 00:44:21 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * read_bignum():
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -82,10 +85,12 @@
+ k->ecdsa_nid = -1;
+ 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)
+@@ -95,8 +100,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)
+@@ -110,6 +120,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;
+ #ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA:
+@@ -136,6 +150,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)
+@@ -150,12 +165,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_ECDSA:
+ case KEY_ECDSA_CERT:
+@@ -224,6 +254,21 @@
+ k->ecdsa = NULL;
+ break;
+ #endif
++ 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:
+@@ -274,12 +319,18 @@
+ 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 &&
+@@ -305,6 +356,12 @@
+ BN_CTX_free(bnctx);
+ return 1;
+ #endif /* OPENSSL_HAS_ECC */
++#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);
+ }
+@@ -358,6 +415,8 @@
+ case KEY_DSA:
+ case KEY_ECDSA:
+ case KEY_RSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ key_to_blob(k, &blob, &len);
+ break;
+ case KEY_DSA_CERT_V00:
+@@ -537,7 +596,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 */
+@@ -694,6 +753,8 @@
+ case KEY_RSA:
+ case KEY_DSA:
+ case KEY_ECDSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ case KEY_DSA_CERT_V00:
+ case KEY_RSA_CERT_V00:
+ case KEY_DSA_CERT:
+@@ -730,6 +791,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);
+@@ -757,7 +823,30 @@
+ return -1;
+ }
+ #endif
++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");
+@@ -800,6 +889,7 @@
+ #endif
+ }
+ #endif
++x509blob:
+ success = 1;
+ /*XXXX*/
+ key_free(k);
+@@ -869,6 +959,9 @@
+ if (key->rsa == NULL)
+ return 0;
+ break;
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
++ return x509key_write(key, f);
+ default:
+ return 0;
+ }
+@@ -900,6 +993,12 @@
+ case KEY_ECDSA:
+ return "ECDSA";
+ #endif
++ 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:
+@@ -978,6 +1077,11 @@
+ const char *
+ key_ssh_name(const Key *k)
+ {
++ const char* p;
++
++ p = ssh_x509key_name(k);
++ if (p) return(p);
++
+ return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
+ }
+
+@@ -1006,6 +1110,9 @@
+ case KEY_ECDSA_CERT:
+ return key_curve_nid_to_bits(k->ecdsa_nid);
+ #endif
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
++ return ssh_x509_key_size(k);
+ }
+ return 0;
+ }
+@@ -1245,6 +1352,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) {
+@@ -1470,10 +1582,14 @@
+ EC_POINT *q = NULL;
+ int nid = -1;
+ #endif
++ 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_cstring_ret(&b, NULL)) == NULL) {
+@@ -1482,6 +1598,8 @@
+ }
+
+ type = key_type_from_name(ktype);
++ debug3("key_from_blob(..., ...) ktype=%.30s", ktype);
++
+ #ifdef OPENSSL_HAS_ECC
+ if (key_type_plain(type) == KEY_ECDSA)
+ nid = key_ecdsa_nid_from_name(ktype);
+@@ -1628,6 +1746,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);
+@@ -1665,6 +1788,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;
+@@ -1698,6 +1825,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;
+@@ -1725,6 +1856,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)
+@@ -1737,6 +1869,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)
+@@ -1761,10 +1894,20 @@
+ break;
+ #endif
+ 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.8p1/key.h openssh-5.8p1+x509-6.2.4/key.h
+--- openssh-5.8p1/key.h 2010-11-05 01:19:49.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/key.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,7 +1,9 @@
+-/* $OpenBSD: key.h,v 1.33 2010/10/28 11:22:09 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
+@@ -32,6 +34,7 @@
+ #ifdef OPENSSL_HAS_ECC
+ #include <openssl/ec.h>
+ #endif
++#include <openssl/x509.h>
+
+ typedef struct Key Key;
+ enum types {
+@@ -44,6 +47,8 @@
+ KEY_ECDSA_CERT,
+ KEY_RSA_CERT_V00,
+ KEY_DSA_CERT_V00,
++ KEY_X509_RSA,
++ KEY_X509_DSA,
+ KEY_UNSPEC
+ };
+ enum fp_type {
+@@ -84,6 +89,7 @@
+ #else
+ void *ecdsa;
+ #endif
++ X509 *x509;
+ struct KeyCert *cert;
+ };
+
+diff -ruN openssh-5.8p1/LICENCE openssh-5.8p1+x509-6.2.4/LICENCE
+--- openssh-5.8p1/LICENCE 2011-01-17 12:15:29.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/LICENCE 2011-02-04 21:06:00.000000000 +0200
+@@ -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:
+@@ -336,4 +337,4 @@
+
+
+ ------
+-$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $
++$OpenBSD$
+diff -ruN openssh-5.8p1/log.c openssh-5.8p1+x509-6.2.4/log.c
+--- openssh-5.8p1/log.c 2008-06-10 16:01:51.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/log.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: log.c,v 1.41 2008/06/10 04:50:25 dtucker Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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.8p1/log.h openssh-5.8p1+x509-6.2.4/log.h
+--- openssh-5.8p1/log.h 2008-06-13 03:22:54.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/log.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: log.h,v 1.17 2008/06/13 00:12:02 dtucker Exp $ */
++/* $OpenBSD$ */
+
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+@@ -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.8p1/m4/ldap.m4 openssh-5.8p1+x509-6.2.4/m4/ldap.m4
+--- openssh-5.8p1/m4/ldap.m4 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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.8p1/Makefile.in openssh-5.8p1+x509-6.2.4/Makefile.in
+--- openssh-5.8p1/Makefile.in 2011-02-04 02:42:13.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/Makefile.in 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-# $Id: Makefile.in,v 1.320.4.1 2011/02/04 00:42:13 djm 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,11 +46,12 @@
+ CC=@CC@
+ LD=@LD@
+ CFLAGS=@CFLAGS@
+-CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
++CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ @LDAP_CPPFLAGS@ $(PATHS) @DEFS@
+ LIBS=@LIBS@
+ SSHLIBS=@SSHLIBS@
+ SSHDLIBS=@SSHDLIBS@
+ LIBEDIT=@LIBEDIT@
++LIBLDAP=@LDAP_LDFLAGS@ @LDAP_LIBS@
+ AR=@AR@
+ AWK=@AWK@
+ RANLIB=@RANLIB@
+@@ -64,6 +67,15 @@
+ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
+ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
+
++@***@LDAP_OBJS=x509_by_ldap.o
++@***@LDAP_OBJS=
++
++@***@OCSP_OBJS=ssh-ocsp.o
++@***@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 \
+@@ -73,13 +85,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-ecdsa.o ssh-rsa.o dh.o \
++ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o $(SSHX509_OBJS) dh.o \
+ kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.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 \
+@@ -94,7 +106,7 @@
+ auth2-gss.o gss-serv.o gss-serv-krb5.o \
+ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.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
+@@ -114,6 +126,10 @@
+ -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_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' \
+@@ -143,10 +159,10 @@
+ $(RANLIB) $@
+
+ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
+- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
++ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBLDAP) $(SSHLIBS) $(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)
+@@ -160,8 +176,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)
+@@ -219,6 +235,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
+@@ -238,9 +255,10 @@
+ >$$base.0 ; \
+ done
+
+-distprep: catman-do
++distprep:
+ $(AUTORECONF)
+ -rm -rf autom4te.cache
++ @test -n "$(MANFMT)" && echo "run 'make -f Makefile.in catman-do MANFMT=....' with appropriate for you host MANFMT macro"
+
+ install: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
+ install-nokeys: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf
+@@ -257,6 +275,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)
+@@ -398,6 +418,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; \
+@@ -443,7 +467,22 @@
+ TEST_SSH_ECC="$${TEST_SSH_ECC}" \
+ TEST_SSH_SHA256="$${TEST_SSH_SHA256}" \
+ 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))
+@@ -452,6 +491,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
+@@ -467,3 +507,6 @@
+ sh buildpkg.sh; \
+ fi
+
++depend:
++ (cd openbsd-compat && $(MAKE) $@)
++ makedepend -- $(CPPFLAGS) $(CFLAGS) -- $(srcdir)/*.c
+diff -ruN openssh-5.8p1/moduli.0 openssh-5.8p1+x509-6.2.4/moduli.0
+--- openssh-5.8p1/moduli.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/moduli.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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,11 +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:
+@@ -69,4 +69,4 @@
+ Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
+ Protocol, RFC 4419, 2006.
+
+-OpenBSD 4.9 June 26, 2008 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/monitor.c openssh-5.8p1+x509-6.2.4/monitor.c
+--- openssh-5.8p1/monitor.c 2010-09-10 04:23:34.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/monitor.c 2011-02-04 21:06:01.000000000 +0200
+@@ -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.8p1/monitor_wrap.c openssh-5.8p1+x509-6.2.4/monitor_wrap.c
+--- openssh-5.8p1/monitor_wrap.c 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/monitor_wrap.c 2011-02-04 21:06:01.000000000 +0200
+@@ -245,6 +245,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.8p1/openbsd-compat/Makefile.in openssh-5.8p1+x509-6.2.4/openbsd-compat/Makefile.in
+--- openssh-5.8p1/openbsd-compat/Makefile.in 2010-10-07 14:19:24.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/openbsd-compat/Makefile.in 2011-02-04 21:06:01.000000000 +0200
+@@ -40,3 +40,6 @@
+
+ distclean: clean
+ rm -f Makefile *~
++
++depend:
++ makedepend -- $(CPPFLAGS) $(CFLAGS) -- $(srcdir)/*.c
+diff -ruN openssh-5.8p1/pathnames.h openssh-5.8p1+x509-6.2.4/pathnames.h
+--- openssh-5.8p1/pathnames.h 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/pathnames.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: pathnames.h,v 1.20 2010/08/31 11:54:45 djm Exp $ */
++/* $OpenBSD$ */
+
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+@@ -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"
+@@ -179,3 +202,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.8p1/readconf.c openssh-5.8p1+x509-6.2.4/readconf.c
+--- openssh-5.8p1/readconf.c 2010-11-20 06:19:38.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/readconf.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: readconf.c,v 1.190 2010/11/13 23:27:50 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -43,6 +66,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:
+@@ -132,6 +157,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,
+ oKexAlgorithms, oIPQoS,
+@@ -231,6 +268,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 },
+@@ -720,9 +777,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 : "<NONE>");
++ */
+ if (*activep && options->hostkeyalgorithms == NULL)
+ options->hostkeyalgorithms = xstrdup(arg);
+ break;
+@@ -997,11 +1056,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 : "<NONE>");
++ */
++ 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);
+@@ -1147,6 +1375,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;
+@@ -1159,6 +1401,22 @@
+ options->ip_qos_bulk = -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.
+@@ -1230,6 +1488,7 @@
+ /* options->macs, default set in myproposals.h */
+ /* options->kex_algorithms, 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) {
+@@ -1321,6 +1580,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 : "<null>"));
++#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.8p1/readconf.h openssh-5.8p1+x509-6.2.4/readconf.h
+--- openssh-5.8p1/readconf.h 2010-11-20 06:19:38.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/readconf.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: readconf.h,v 1.88 2010/11/13 23:27:50 djm Exp $ */
++/* $OpenBSD$ */
+
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+@@ -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 {
+@@ -122,6 +147,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.8p1/README.x509v3 openssh-5.8p1+x509-6.2.4/README.x509v3
+--- openssh-5.8p1/README.x509v3 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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:
++<KEY_TYPE><SPACE><WORDDN><SPACE>{<Distinguished_Name>|CertBlob}
++where:
++KEY_TYPE:=x509v3-sign-rsa|x509v3-sign-dss (case sensitive !)
++WORDDN:={Distinguished Name|
++ Distinguished-Name|
++ Distinguished_Name|
++ DistinguishedName|
++ DN|
++ Subject}<WORDDNSUFF>
++WORDDNSUFF:='='|':'|''
++NOTES:
++- WORDDN is case insensitive !
++
++- <Distinguished Name> is like output from command:
++$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE -nameopt oneline
++
++- <Distinguished Name> 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 <Distinguished Name> 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-<LISTITEM>.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-<SIGNATURE_ALGORITHM>[.<EXTENTION>]"
++ , where <SIGNATURE_ALGORITHM> is in format "rsa_<DIGEST>" 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.8p1/scp.0 openssh-5.8p1+x509-6.2.4/scp.0
+--- openssh-5.8p1/scp.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/scp.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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 [-12346BCpqrv] [-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:
+@@ -38,8 +38,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
+@@ -61,63 +61,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
+- IPQoS
+- KbdInteractiveDevices
+- KexAlgorithms
+- 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).
+
+@@ -127,8 +75,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
+@@ -153,4 +101,4 @@
+ Timo Rinne <***@iki.fi>
+ Tatu Ylonen <***@cs.hut.fi>
+
+-OpenBSD 4.9 December 9, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/scp.1 openssh-5.8p1+x509-6.2.4/scp.1
+--- openssh-5.8p1/scp.1 2011-01-06 13:41:21.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/scp.1 2011-02-04 21:06:00.000000000 +0200
+@@ -8,7 +8,7 @@
+ .\"
+ .\" Created: Sun May 7 00:14:37 1995 ylo
+ .\"
+-.\" $OpenBSD: scp.1,v 1.56 2010/12/09 14:13:32 jmc Exp $
++.\" $OpenBSD$
+ .\"
+ .Dd $Mdocdate: December 9 2010 $
+ .Dt SCP 1
+@@ -123,61 +123,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 IPQoS
+-.It KbdInteractiveDevices
+-.It KexAlgorithms
+-.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.8p1/servconf.c openssh-5.8p1+x509-6.2.4/servconf.c
+--- openssh-5.8p1/servconf.c 2010-11-20 06:19:38.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/servconf.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: servconf.c,v 1.213 2010/11/13 23:27:50 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -35,6 +58,7 @@
+ #include "log.h"
+ #include "buffer.h"
+ #include "servconf.h"
++#include "ssh-xkalg.h"
+ #include "compat.h"
+ #include "pathnames.h"
+ #include "misc.h"
+@@ -139,6 +163,18 @@
+ options->authorized_principals_file = NULL;
+ options->ip_qos_interactive = -1;
+ options->ip_qos_bulk = -1;
++
++ 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
+@@ -282,6 +318,21 @@
+ if (options->ip_qos_bulk == -1)
+ options->ip_qos_bulk = IPTOS_THROUGHPUT;
+
++ /* 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;
+@@ -294,7 +345,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. */
+@@ -328,6 +386,16 @@
+ sZeroKnowledgePasswordAuthentication, sHostCertificate,
+ sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
+ sKexAlgorithms, sIPQoS,
++ sHostbasedAlgorithms,
++ sPubkeyAlgorithms,
++ sX509KeyAlgorithm,
++ sAllowedClientCertPurpose,
++ sKeyAllowSelfIssued, sMandatoryCRL,
++ sCACertificateFile, sCACertificatePath,
++ sCARevocationFile, sCARevocationPath,
++ sCAldapVersion, sCAldapURL,
++ sVAType, sVACertificateFile,
++ sVAOCSPResponderURL,
+ sDeprecated, sUnsupported
+ } ServerOpCodes;
+
+@@ -441,6 +509,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 },
+@@ -1398,6 +1482,142 @@
+ }
+ break;
+
++ 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 : "<NONE>");
++ */
++ 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 : "<NONE>");
++ */
++ 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);
+@@ -1405,6 +1625,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);
+@@ -1511,6 +1748,9 @@
+ M_CP_INTOPT(ip_qos_interactive);
+ M_CP_INTOPT(ip_qos_bulk);
+
++ M_CP_STROPT(hostbased_algorithms);
++ M_CP_STROPT(pubkey_algorithms);
++
+ M_CP_STROPT(banner);
+ if (preauth)
+ return;
+@@ -1590,6 +1830,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";
+@@ -1735,6 +1993,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);
+@@ -1760,6 +2020,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.8p1/servconf.h openssh-5.8p1+x509-6.2.4/servconf.h
+--- openssh-5.8p1/servconf.h 2010-11-20 06:19:38.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/servconf.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: servconf.h,v 1.95 2010/11/13 23:27:50 djm Exp $ */
++/* $OpenBSD$ */
+
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+@@ -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. */
+@@ -152,6 +177,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.8p1/sftp.0 openssh-5.8p1+x509-6.2.4/sftp.0
+--- openssh-5.8p1/sftp.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sftp.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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,12 +47,12 @@
+ 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, symlink, and lmkdir. Termination on error can be
+- suppressed on a command by command basis by prefixing the command
+- with a `-' character (for example, -rm /tmp/blah*).
++ lpwd, df, symlink, and lmkdir. Termination on error can be sup-
++ pressed on 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).
+
+@@ -81,59 +81,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
+- IPQoS
+- KbdInteractiveDevices
+- KexAlgorithms
+- 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.
+@@ -149,9 +97,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
+@@ -160,8 +108,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.
+
+@@ -170,7 +118,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.
+
+@@ -178,18 +126,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
+@@ -206,11 +152,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
+@@ -222,18 +168,18 @@
+ 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.
+
+ ln [-s] oldpath newpath
+- Create a link from oldpath to newpath. If the -s flag is
+- specified the created link is a symbolic link, otherwise it is a
+- hard link.
++ Create a link from oldpath to newpath. If the -s flag is speci-
++ fied the created link is a symbolic link, otherwise it is a hard
++ link.
+
+ lpwd Print local working directory.
+
+@@ -247,10 +193,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,
+@@ -258,8 +204,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.
+@@ -282,13 +228,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
+@@ -324,8 +269,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 and 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.9 December 4, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/sftp.1 openssh-5.8p1+x509-6.2.4/sftp.1
+--- openssh-5.8p1/sftp.1 2010-12-05 00:02:48.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sftp.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: sftp.1,v 1.88 2010/12/04 00:18:01 djm Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Copyright (c) 2001 Damien Miller. All rights reserved.
+ .\"
+@@ -173,61 +173,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 IPQoS
+-.It KbdInteractiveDevices
+-.It KexAlgorithms
+-.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.8p1/sftp-server.0 openssh-5.8p1+x509-6.2.4/sftp-server.0
+--- openssh-5.8p1/sftp-server.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sftp-server.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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 and 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.org>
+
+-OpenBSD 4.9 January 9, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh.0 openssh-5.8p1+x509-6.2.4/ssh.0
+--- openssh-5.8p1/ssh.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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.
+
+@@ -138,12 +138,14 @@
+ Selects a file from which the identity (private key) for public
+ key authentication is read. The default is ~/.ssh/identity for
+ protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa and
+- ~/.ssh/id_rsa 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.
++ ~/.ssh/id_rsa 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 -i options (and multiple identities specified in config-
++ uration files). ssh will also try to load certificate informa-
++ tion from the filename obtained by appending -cert.pub to iden-
++ tity filenames.
+
+ -K Enables GSSAPI-based authentication and forwarding (delegation)
+ of GSSAPI credentials to the server.
+@@ -155,27 +157,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 +186,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,78 +208,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
+- IPQoS
+- KbdInteractiveDevices
+- KexAlgorithms
+- 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
+@@ -290,9 +224,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
+@@ -300,49 +234,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)
+@@ -378,9 +311,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).
+
+ AUTHENTICATION
+ The OpenSSH SSH client supports SSH protocols 1 and 2. The default is to
+@@ -392,11 +325,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
+@@ -405,74 +338,80 @@
+ ~/.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
+- one of the DSA, ECDSA or RSA algorithms. Protocol 1 is restricted to
+- using only RSA keys, but protocol 2 may use any. The HISTORY section of
+- ssl(8) contains a brief discussion of the DSA and RSA 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 one of the DSA, ECDSA or RSA algorithms. Protocol 1
++ is restricted to using only RSA keys, but protocol 2 may use any or X.509
++ certificates. The HISTORY section of ssl(8) contains a brief discussion
++ of the DSA and RSA 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), ~/.ssh/id_ecdsa (protocol 2 ECDSA), 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), ~/.ssh/id_ecdsa.pub (protocol 2
+- ECDSA), 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.
++ ECDSA), or ~/.ssh/id_rsa.pub (protocol 2 RSA) in the user's home direc-
++ tory. 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 ~/.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 certificate ``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 +432,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 +476,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 +488,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 +502,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 +553,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 +569,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 +580,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 +617,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 +628,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 +637,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 +651,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 +701,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 (DSA/ECDSA/RSA) 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 (DSA/ECDSA/RSA) 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
+@@ -783,26 +737,29 @@
+ ~/.ssh/id_dsa
+ ~/.ssh/id_ecdsa
+ ~/.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_ecdsa.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,
+@@ -818,6 +775,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).
+@@ -827,18 +802,24 @@
+ /etc/ssh/ssh_host_ecdsa_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. If 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 pur-
++ pose. 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,
+@@ -891,8 +872,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.9 November 18, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh.1 openssh-5.8p1+x509-6.2.4/ssh.1
+--- openssh-5.8p1/ssh.1 2010-11-20 06:21:03.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh.1 2011-02-04 21:06:00.000000000 +0200
+@@ -12,6 +12,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
+@@ -33,7 +34,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.316 2010/11/18 15:01:00 jmc Exp $
++.\" $OpenBSD$
+ .Dd $Mdocdate: November 18 2010 $
+ .Dt SSH 1
+ .Os
+@@ -277,6 +278,8 @@
+ and
+ .Pa ~/.ssh/id_rsa
+ 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,77 +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 IPQoS
+-.It KbdInteractiveDevices
+-.It KexAlgorithms
+-.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
+@@ -695,7 +629,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 ,
+@@ -710,18 +644,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 one of the DSA, ECDSA or RSA algorithms.
+ Protocol 1 is restricted to using only RSA keys,
+-but protocol 2 may use any.
++but protocol 2 may use any or X.509 certificates.
+ The
+ .Sx HISTORY
+ section of
+@@ -730,13 +664,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
+@@ -762,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
+@@ -1058,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.
+@@ -1078,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
+@@ -1086,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
+@@ -1279,7 +1233,7 @@
+ and not accessible by others.
+ .Pp
+ .It Pa ~/.ssh/authorized_keys
+-Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as
++Lists the public keys (DSA/ECDSA/RSA) or certificates that can be used for logging in as
+ this user.
+ The format of this file is described in the
+ .Xr sshd 8
+@@ -1287,6 +1241,18 @@
+ This file is not highly sensitive, but the recommended
+ permissions are read/write for the user, and not accessible by others.
+ .Pp
++.It Pa ~/.ssh/ca/ca-bundle.crt
++.It Pa ~/.ssh/ca/ca-bundle.crl
++Part of user
++.Dq "X.509 store" .
++Same as systemwide files below.
++.Pp
++.It Pa ~/.ssh/ca/crt
++.It Pa ~/.ssh/ca/crl
++Part of user
++.Dq "X.509 store" .
++Same as systemwide directories below.
++.Pp
+ .It Pa ~/.ssh/config
+ This is the per-user configuration file.
+ The file format and configuration options are described in
+@@ -1304,6 +1270,8 @@
+ .It Pa ~/.ssh/id_ecdsa
+ .It Pa ~/.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).
+@@ -1318,11 +1286,13 @@
+ .It Pa ~/.ssh/id_ecdsa.pub
+ .It Pa ~/.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 Pa ~/.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
+@@ -1347,6 +1317,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
+@@ -1358,6 +1350,9 @@
+ .It Pa /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.
+@@ -1372,12 +1367,17 @@
+ By default
+ .Nm
+ is not setuid root.
++If 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 Pa /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
+@@ -1488,3 +1488,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.8p1/ssh-add.0 openssh-5.8p1+x509-6.2.4/ssh-add.0
+--- openssh-5.8p1/ssh-add.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-add.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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 private key identities to the authentication agent
++ ssh-add -- adds private key identities to the authentication agent
+
+ SYNOPSIS
+ ssh-add [-cDdLlXx] [-t life] [file ...]
+@@ -10,28 +10,28 @@
+
+ DESCRIPTION
+ ssh-add adds private key identities to the authentication agent,
+- ssh-agent(1). When run without arguments, it adds the files
++ 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, ~/.ssh/id_ecdsa 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.
++ of the private key file. Alternative file names can be given on the com-
++ mand 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 +45,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 +56,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,7 +85,8 @@
+
+ ~/.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_ecdsa
+ Contains the protocol version 2 ECDSA authentication identity of
+@@ -93,7 +94,8 @@
+
+ ~/.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.
+@@ -108,8 +110,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.9 October 28, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-add.1 openssh-5.8p1+x509-6.2.4/ssh-add.1
+--- openssh-5.8p1/ssh-add.1 2010-11-05 01:20:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-add.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-add.1,v 1.55 2010/10/28 18:33:28 jmc Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Author: Tatu Ylonen <***@cs.hut.fi>
+ .\" Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, Espoo, Finland
+@@ -14,6 +14,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,8 @@
+ .Nm
+ adds private key 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 ,
+@@ -111,8 +114,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
+@@ -164,10 +167,14 @@
+ 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_ecdsa
+ Contains the protocol version 2 ECDSA authentication identity of the user.
+ .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.
+@@ -193,3 +200,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.8p1/ssh-add.c openssh-5.8p1+x509-6.2.4/ssh-add.c
+--- openssh-5.8p1/ssh-add.c 2010-11-11 05:17:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-add.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh-add.c,v 1.100 2010/08/31 12:33:38 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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;
+@@ -286,9 +290,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);
+@@ -376,6 +391,7 @@
+ seed_rng();
+
+ OpenSSL_add_all_algorithms();
++ fill_default_xkalg();
+
+ /* At first, get a connection to the authentication agent. */
+ ac = ssh_get_authentication_connection();
+diff -ruN openssh-5.8p1/ssh-agent.0 openssh-5.8p1+x509-6.2.4/ssh-agent.0
+--- openssh-5.8p1/ssh-agent.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-agent.0 2011-02-04 21:06:00.000000000 +0200
+@@ -1,20 +1,20 @@
+-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, ECDSA). 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 environment variables the agent can be located and
+- automatically used for authentication when logging in to other machines
+- using ssh(1).
++ ssh-agent is a program to hold private keys used for public key authenti-
++ cation (RSA, DSA, ECDSA). It is possible to contain in addition corre-
++ sponding X.509 certificate. 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
++ environment variables the agent can be located and automatically used for
++ authentication when logging in to other machines using ssh(1).
+
+ The options are as follows:
+
+@@ -50,16 +50,17 @@
+ the identity has a 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.
++ 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. ssh-add -l dis-
++ plays the identities 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
+@@ -69,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
+@@ -94,7 +95,8 @@
+
+ ~/.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_ecdsa
+ Contains the protocol version 2 ECDSA authentication identity of
+@@ -102,12 +104,13 @@
+
+ ~/.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.
+
+ $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>
+- 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
+@@ -116,8 +119,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.9 November 21, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-agent.1 openssh-5.8p1+x509-6.2.4/ssh-agent.1
+--- openssh-5.8p1/ssh-agent.1 2010-12-01 02:50:35.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-agent.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-agent.1,v 1.53 2010/11/21 01:01:13 djm Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Author: Tatu Ylonen <***@cs.hut.fi>
+ .\" Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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, ECDSA).
++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
+@@ -124,6 +126,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
+@@ -188,10 +191,14 @@
+ 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_ecdsa
+ Contains the protocol version 2 ECDSA authentication identity of the user.
+ .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 $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
+ .Ux Ns -domain
+ sockets used to contain the connection to the authentication agent.
+@@ -212,3 +219,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.8p1/ssh-agent.c openssh-5.8p1+x509-6.2.4/ssh-agent.c
+--- openssh-5.8p1/ssh-agent.c 2010-12-01 02:50:35.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-agent.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh-agent.c,v 1.171 2010/11/21 01:01:13 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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);
+@@ -497,6 +524,7 @@
+ type = key_type_from_name(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);
+@@ -567,6 +595,7 @@
+ break;
+ #endif /* OPENSSL_HAS_ECC */
+ 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);
+@@ -596,10 +625,29 @@
+ goto send;
+ }
+ xfree(type_name);
++ 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:
+@@ -1152,6 +1200,7 @@
+ #endif
+
+ OpenSSL_add_all_algorithms();
++ fill_default_xkalg();
+
+ __progname = ssh_get_progname(av[0]);
+ init_rng();
+diff -ruN openssh-5.8p1/ssh.c openssh-5.8p1+x509-6.2.4/ssh.c
+--- openssh-5.8p1/ssh.c 2011-02-04 02:42:15.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh.c,v 1.356 2011/01/06 22:23:53 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, Espoo, Finland
+@@ -19,6 +19,9 @@
+ * Modified to work with SSL by Niels Provos <***@citi.umich.edu>
+ * 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:
+@@ -75,6 +78,10 @@
+ #include <openssl/err.h>
+ #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"
+@@ -111,6 +118,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;
+
+@@ -235,6 +245,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
+@@ -600,6 +611,9 @@
+
+ OpenSSL_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.8p1/ssh_config openssh-5.8p1+x509-6.2.4/ssh_config
+--- openssh-5.8p1/ssh_config 2010-01-12 10:40:27.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh_config 2011-02-04 21:06:00.000000000 +0200
+@@ -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-***@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.8p1/ssh_config.0 openssh-5.8p1+x509-6.2.4/ssh_config.0
+--- openssh-5.8p1/ssh_config.0 2011-02-04 03:00:03.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh_config.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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,7 +357,9 @@
+ 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:
++ option depend from X509KeyAlgorithm. It contain first specified
++ X509KeyAlgorithm for RSA key, followed by first specified
++ X509KeyAlgorithm for DSA key, followed by
+
+ ecdsa-sha2-nistp256-cert-***@openssh.com,
+ ecdsa-sha2-nistp384-cert-***@openssh.com,
+@@ -328,19 +374,18 @@
+
+ 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
+@@ -351,23 +396,24 @@
+ ``no''.
+
+ IdentityFile
+- Specifies a file from which the user's DSA, ECDSA or DSA
+- authentication identity is read. The default is ~/.ssh/identity
+- for protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa and
+- ~/.ssh/id_rsa 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.
++ Specifies a file from which the user's DSA, ECDSA or DSA authen-
++ tication identity is read. The default is ~/.ssh/identity for
++ protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa and
++ ~/.ssh/id_rsa 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. 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.
+
+ IPQoS Specifies the IPv4 type-of-service or DSCP class for connections.
+ Accepted values are ``af11'', ``af12'', ``af13'', ``af14'',
+@@ -375,9 +421,9 @@
+ ``af42'', ``af43'', ``cs0'', ``cs1'', ``cs2'', ``cs3'', ``cs4'',
+ ``cs5'', ``cs6'', ``cs7'', ``ef'', ``lowdelay'', ``throughput'',
+ ``reliability'', or a numeric value. This option may take one or
+- two arguments, separated by whitespace. If one argument is
+- specified, it is used as the packet class unconditionally. If
+- two values are specified, the first is automatically selected for
++ two arguments, separated by whitespace. If one argument is spec-
++ ified, it is used as the packet class unconditionally. If two
++ values are specified, the first is automatically selected for
+ interactive sessions and the second for non-interactive sessions.
+ The default is ``lowdelay'' for interactive sessions and
+ ``throughput'' for non-interactive sessions.
+@@ -406,14 +452,14 @@
+ diffie-hellman-group1-sha1
+
+ 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
+@@ -429,38 +475,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-***@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
+@@ -478,9 +528,8 @@
+
+ PKCS11Provider
+ Specifies which PKCS#11 provider to use. The argument to this
+- keyword is the PKCS#11 shared library ssh(1) should use to
+- communicate with a PKCS#11 token providing the user's private RSA
+- key.
++ keyword is the PKCS#11 shared library 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.
+@@ -496,25 +545,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
+@@ -522,6 +571,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
+@@ -529,10 +588,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
+@@ -545,15 +604,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
+@@ -564,9 +622,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
+@@ -574,8 +632,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.
+
+@@ -588,11 +646,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
+@@ -609,27 +667,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
+@@ -654,32 +712,77 @@
+ 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).
+
+@@ -691,16 +794,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
+
+@@ -711,7 +832,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:
+
+@@ -722,8 +843,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
+@@ -737,8 +858,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.9 December 8, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh_config.5 openssh-5.8p1+x509-6.2.4/ssh_config.5
+--- openssh-5.8p1/ssh_config.5 2010-12-26 05:26:48.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh_config.5 2011-02-04 21:06:00.000000000 +0200
+@@ -12,6 +12,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
+@@ -33,7 +34,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.146 2010/12/08 04:02:47 djm Exp $
++.\" $OpenBSD$
+ .Dd $Mdocdate: December 8 2010 $
+ .Dt SSH_CONFIG 5
+ .Os
+@@ -123,6 +124,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 ,
+@@ -143,6 +158,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
+@@ -545,7 +614,11 @@
+ .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:
++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
+ .Bd -literal -offset 3n
+ ecdsa-sha2-nistp256-cert-***@openssh.com,
+ ecdsa-sha2-nistp384-cert-***@openssh.com,
+@@ -603,6 +676,8 @@
+ and
+ .Pa ~/.ssh/id_rsa
+ 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
+@@ -772,6 +847,15 @@
+ hmac-md5,hmac-sha1,umac-***@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
+@@ -882,6 +966,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
+@@ -1136,12 +1239,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 ,
+@@ -1180,6 +1370,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
+@@ -1248,3 +1480,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.8p1/sshconnect2.c openssh-5.8p1+x509-6.2.4/sshconnect2.c
+--- openssh-5.8p1/sshconnect2.c 2010-12-01 03:21:51.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshconnect2.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,6 +1,7 @@
+-/* $OpenBSD: sshconnect2.c,v 1.186 2010/11/29 23:45:51 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
+@@ -1187,6 +1188,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);
+@@ -1365,6 +1367,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;
+@@ -1444,11 +1447,81 @@
+ }
+ }
+
++/* TODO: to improve for ECC keys
++ * Now method is used only to failback from KEY_X509_RSA/KEY_DSA_CERT to
++ * KEY_RSA/KEY_DSA if loaded identity is a certificate and its corresponding
++ * name is not listed in PubkeyAlgorithms.
++ */
++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_ECDSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
++ case KEY_RSA_CERT:
++ case KEY_DSA_CERT:
++ case KEY_ECDSA_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++)
+@@ -1462,14 +1535,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.8p1/sshconnect.c openssh-5.8p1+x509-6.2.4/sshconnect.c
+--- openssh-5.8p1/sshconnect.c 2011-01-16 14:17:59.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshconnect.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: sshconnect.c,v 1.232 2011/01/16 11:50:36 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -57,6 +80,7 @@
+ #include "readconf.h"
+ #include "atomicio.h"
+ #include "misc.h"
++#include "ssh-x509.h"
+ #include "dns.h"
+ #include "roaming.h"
+ #include "ssh2.h"
+@@ -705,6 +729,7 @@
+ int len, cancelled_forwarding = 0;
+ struct hostkeys *host_hostkeys, *ip_hostkeys;
+ const struct hostkey_entry *host_found, *ip_found;
++ char extramsg[1024], *subject = NULL;
+
+ /*
+ * Force accepting of the host key for loopback/localhost. The
+@@ -852,16 +877,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))
+@@ -933,7 +972,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)
+@@ -1122,9 +1161,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);
+ }
+ }
+ }
+@@ -1204,7 +1249,7 @@
+ static int
+ show_other_keys(struct hostkeys *hostkeys, Key *key)
+ {
+- int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, -1};
++ int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_X509_RSA, KEY_X509_DSA, -1};
+ int i, ret = 0;
+ char *fp, *ra;
+ const struct hostkey_entry *found;
+@@ -1246,6 +1291,11 @@
+ error("It is also possible that a host key has just been changed.");
+ error("The fingerprint for the %s key sent by the remote host is\n%s.",
+ key_type(host_key), 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.8p1/sshd.0 openssh-5.8p1+x509-6.2.4/sshd.0
+--- openssh-5.8p1/sshd.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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
+@@ -80,8 +80,10 @@
+ /etc/ssh/ssh_host_key for protocol version 1, and
+ /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_ecdsa_key and
+ /etc/ssh/ssh_host_rsa_key for protocol version 2. It is possible
+- to have multiple host key files for the different protocol
+- versions and host key algorithms.
++ to have multiple host key files for the different protocol ver-
++ sions and host key algorithms. It is possible host key for pro-
++ tocol version 2 to contain private key followed by X.509 certifi-
++ cate 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 +94,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 +120,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 +130,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 ***@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 ***@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 DSA, ECDSA and RSA 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 DSA, ECDSA, RSA 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 certifi-
++ cate 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 +199,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 +234,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,22 +264,33 @@
+ 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 ``ecdsa-sha2-nistp256'', ``ecdsa-sha2-nistp384'',
+- ``ecdsa-sha2-nistp521'', ``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 ``ecdsa-sha2-nistp256'',
++ ``ecdsa-sha2-nistp384'', ``ecdsa-sha2-nistp521'', ``ssh-dss'' or
++ ``ssh-rsa''. In addition for protocol version 2 user can use X.509 cer-
++ tificates. 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 Sub-
++ ject 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, id_ecdsa.pub, or the id_rsa.pub file and edit
+ it.
+@@ -286,15 +298,15 @@
+ 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
+@@ -304,19 +316,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
+@@ -332,9 +344,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
+@@ -363,25 +375,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:
+
+@@ -393,15 +405,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...==
+ ***@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
+@@ -413,26 +427,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
+@@ -444,30 +458,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.....=
+@@ -486,12 +500,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
+@@ -499,14 +512,15 @@
+ 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 (DSA/ECDSA/RSA) that can be used for
++ Lists the public keys (DSA/ECDSA/RSA), certificates or certifi-
++ cates ``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
+@@ -521,17 +535,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
+@@ -565,14 +579,32 @@
+ 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_ecdsa_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 four 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
+@@ -580,21 +612,23 @@
+ /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
+@@ -611,8 +645,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),
+@@ -622,13 +656,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.9 October 28, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/sshd.8 openssh-5.8p1+x509-6.2.4/sshd.8
+--- openssh-5.8p1/sshd.8 2010-11-05 01:20:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd.8 2011-02-04 21:06:00.000000000 +0200
+@@ -12,6 +12,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
+@@ -33,7 +34,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.260 2010/10/28 18:33:28 jmc Exp $
++.\" $OpenBSD$
+ .Dd $Mdocdate: October 28 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 DSA, ECDSA and RSA keys;
++Protocol 2 supports DSA, ECDSA, RSA 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 #
+@@ -489,6 +496,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
+@@ -634,6 +672,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...==
+ ***@example.net
+ .Ed
+@@ -642,7 +681,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,
+@@ -745,6 +786,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.....=
+@@ -796,7 +838,10 @@
+ and not accessible by others.
+ .Pp
+ .It Pa ~/.ssh/authorized_keys
+-Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in
++Lists the public keys (DSA/ECDSA/RSA), 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
+@@ -827,7 +872,7 @@
+ option.
+ .Pp
+ .It Pa ~/.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
+@@ -874,11 +919,32 @@
+ but allows host-based authentication without permitting login with
+ rlogin/rsh.
+ .Pp
++.It Pa /etc/ssh/ca/ca-bundle.crt
++.It Pa /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 Pa /etc/ssh/ca/crt
++.It Pa /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 Pa /etc/ssh/ssh_host_key
+ .It Pa /etc/ssh/ssh_host_dsa_key
+ .It Pa /etc/ssh/ssh_host_ecdsa_key
+ .It Pa /etc/ssh/ssh_host_rsa_key
+-These three files contain the private parts of the host keys.
++These four 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
+@@ -893,6 +959,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.
+@@ -902,7 +970,7 @@
+ .It Pa /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
+@@ -963,6 +1031,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.8p1/sshd.c openssh-5.8p1+x509-6.2.4/sshd.c
+--- openssh-5.8p1/sshd.c 2011-01-11 08:20:31.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: sshd.c,v 1.381 2011/01/11 06:13:10 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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 <tcpd.h>
+@@ -139,6 +143,9 @@
+
+ extern char *__progname;
+
++/* ssh-x509.c needs this */
++extern int (*pssh_x509cert_check)(X509 *cert);
++
+ /* Server configuration options. */
+ ServerOptions options;
+
+@@ -739,6 +746,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];
+@@ -1307,6 +1318,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;
+@@ -1580,6 +1592,8 @@
+ case KEY_RSA:
+ case KEY_DSA:
+ case KEY_ECDSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ sensitive_data.have_ssh2_key = 1;
+ break;
+ }
+diff -ruN openssh-5.8p1/sshd_config openssh-5.8p1+x509-6.2.4/sshd_config
+--- openssh-5.8p1/sshd_config 2010-09-10 04:20:12.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/sshd_config 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-# $OpenBSD: sshd_config,v 1.82 2010/09/06 17:10:19 naddy Exp $
++# $OpenBSD$
+
+ # This is the sshd server system-wide configuration file. See
+ # sshd_config(5) for more information.
+@@ -25,6 +25,72 @@
+ #HostKey /etc/ssh/ssh_host_dsa_key
+ #HostKey /etc/ssh/ssh_host_ecdsa_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.8p1/sshd_config.0 openssh-5.8p1+x509-6.2.4/sshd_config.0
+--- openssh-5.8p1/sshd_config.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd_config.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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 ***@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 ***@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,9 +320,9 @@
+ ``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
+@@ -274,10 +330,12 @@
+ default is /etc/ssh/ssh_host_key for protocol version 1, and
+ /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_ecdsa_key and
+ /etc/ssh/ssh_host_rsa_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 host key files.
+- ``rsa1'' keys are used for version 1 and ``dsa'', ``ecdsa'' or
+- ``rsa'' are used for version 2 of the SSH protocol.
++ sshd(8) will refuse to use a file if it is group/world-accessi-
++ ble. It is possible to have multiple host key files. ``rsa1''
++ keys are used for version 1 and ``dsa'', ``ecdsa'' or ``rsa'' are
++ used for version 2 of the SSH protocol. For version 2 is possi-
++ ble 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
+@@ -291,19 +349,18 @@
+ ~/.ssh/known_hosts during RhostsRSAAuthentication or
+ HostbasedAuthentication. The default is ``no''.
+
+- IPQoS Specifies the IPv4 type-of-service or DSCP class for the
+- connection. Accepted values are ``af11'', ``af12'', ``af13'',
++ IPQoS Specifies the IPv4 type-of-service or DSCP class for the connec-
++ tion. Accepted values are ``af11'', ``af12'', ``af13'',
+ ``af14'', ``af22'', ``af23'', ``af31'', ``af32'', ``af33'',
+ ``af41'', ``af42'', ``af43'', ``cs0'', ``cs1'', ``cs2'', ``cs3'',
+ ``cs4'', ``cs5'', ``cs6'', ``cs7'', ``ef'', ``lowdelay'',
+ ``throughput'', ``reliability'', or a numeric value. This option
+ may take one or two arguments, separated by whitespace. If one
+- argument is specified, it is used as the packet class
+- unconditionally. If two values are specified, the first is
+- automatically selected for interactive sessions and the second
+- for non-interactive sessions. The default is ``lowdelay'' for
+- interactive sessions and ``throughput'' for non-interactive
+- sessions.
++ argument is specified, it is used as the packet class uncondi-
++ tionally. If two values are specified, the first is automati-
++ cally selected for interactive sessions and the second for non-
++ interactive sessions. The default is ``lowdelay'' for interac-
++ tive sessions and ``throughput'' for non-interactive sessions.
+
+ KerberosAuthentication
+ Specifies whether the password provided by the user for
+@@ -318,9 +375,9 @@
+ 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
+@@ -334,17 +391,32 @@
+ ``diffie-hellman-group-exchange-sha1'',
+ ``diffie-hellman-group14-sha1'', ``diffie-hellman-group1-sha1''.
+
++ 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
+@@ -357,9 +429,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
+@@ -369,14 +441,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-***@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,
+@@ -400,13 +477,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
+@@ -414,12 +492,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.
+
+@@ -441,26 +519,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
+
+- 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
+@@ -471,21 +549,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
+@@ -503,11 +581,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
+@@ -568,11 +654,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
+@@ -582,25 +668,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.
+@@ -623,10 +709,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
+@@ -639,16 +747,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
+@@ -663,19 +771,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:
+
+ <none> seconds
+ s | S seconds
+@@ -693,11 +819,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)
+@@ -705,9 +844,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.9 December 8, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/sshd_config.5 openssh-5.8p1+x509-6.2.4/sshd_config.5
+--- openssh-5.8p1/sshd_config.5 2010-12-26 05:26:48.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd_config.5 2011-02-04 21:06:00.000000000 +0200
+@@ -12,6 +12,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
+@@ -33,7 +34,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.131 2010/12/08 04:02:47 djm Exp $
++.\" $OpenBSD$
+ .Dd $Mdocdate: December 8 2010 $
+ .Dt SSHD_CONFIG 5
+ .Os
+@@ -103,6 +104,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.
+@@ -219,6 +234,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
+@@ -429,6 +498,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
+@@ -485,6 +564,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
+@@ -585,6 +666,28 @@
+ .Dq diffie-hellman-group-exchange-sha1 ,
+ .Dq diffie-hellman-group14-sha1 ,
+ .Dq diffie-hellman-group1-sha1 .
++.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).
+@@ -656,6 +759,15 @@
+ hmac-md5,hmac-sha1,umac-***@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
+@@ -709,6 +821,7 @@
+ .Cm ForceCommand ,
+ .Cm GatewayPorts ,
+ .Cm GSSAPIAuthentication ,
++.Cm HostbasedAlgorithms ,
+ .Cm HostbasedAuthentication ,
+ .Cm HostbasedUsesNameFromPacketOnly ,
+ .Cm KbdInteractiveAuthentication ,
+@@ -720,6 +833,7 @@
+ .Cm PermitOpen ,
+ .Cm PermitRootLogin ,
+ .Cm PermitTunnel ,
++.Cm PubkeyAlgorithms ,
+ .Cm PubkeyAuthentication ,
+ .Cm RhostsRSAAuthentication ,
+ .Cm RSAAuthentication ,
+@@ -907,6 +1021,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
+@@ -1070,6 +1194,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
+@@ -1135,6 +1304,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
+@@ -1183,6 +1394,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
+@@ -1204,3 +1452,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.8p1/ssh-keygen.0 openssh-5.8p1+x509-6.2.4/ssh-keygen.0
+--- openssh-5.8p1/ssh-keygen.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keygen.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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]
+@@ -29,8 +29,8 @@
+ ssh-keygen generates, manages and converts authentication keys for
+ ssh(1). ssh-keygen can create RSA keys for use by SSH protocol version 1
+ and DSA, ECDSA or RSA keys for use by SSH protocol version 2. The type
+- of key to be generated is specified with the -t option. If invoked
+- without any arguments, ssh-keygen will generate an RSA key for use in SSH
++ of key to be generated is specified with the -t option. If invoked with-
++ out any arguments, ssh-keygen will generate an RSA key for use in SSH
+ protocol 2 connections.
+
+ ssh-keygen is also used to generate groups for use in Diffie-Hellman
+@@ -38,9 +38,8 @@
+
+ Normally each user wishing to use SSH with public key authentication runs
+ this once to create the authentication key in ~/.ssh/identity,
+- ~/.ssh/id_ecdsa, ~/.ssh/id_dsa or ~/.ssh/id_rsa. Additionally, the
+- system administrator may use this to generate host keys, as seen in
+- /etc/rc.
++ ~/.ssh/id_ecdsa, ~/.ssh/id_dsa or ~/.ssh/id_rsa. Additionally, the sys-
++ tem administrator may use this to generate host keys, as seen in /etc/rc.
+
+ Normally this program generates the key and asks for a file in which to
+ store the private key. The public key is stored in a file with the same
+@@ -48,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.
+
+@@ -62,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 ``***@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 ``***@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.
+@@ -80,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
+@@ -101,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
+@@ -146,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
+@@ -176,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
+@@ -217,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.
+
+@@ -240,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
+@@ -260,10 +261,10 @@
+ for protocol 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
+@@ -280,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-
+@@ -300,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:
+@@ -309,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
+@@ -339,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
+@@ -352,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
+
+@@ -363,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,8 +398,8 @@
+ key. ssh(1) will read this file when a login attempt 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.
+@@ -407,13 +408,15 @@
+ ~/.ssh/id_ecdsa
+ ~/.ssh/id_rsa
+ Contains the protocol version 2 DSA, ECDSA or 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.
++ identity of the user. In case of DSA or RSA identity it is pos-
++ sible 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 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
+ ~/.ssh/id_ecdsa.pub
+@@ -422,7 +425,14 @@
+ authentication. 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. If file ~/.ssh/id_dsa contain
++ DSA private key followed by X.509 certificate or ~/.ssh/id_rsa
++ contain 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
+@@ -436,8 +446,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.9 October 28, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-keygen.1 openssh-5.8p1+x509-6.2.4/ssh-keygen.1
+--- openssh-5.8p1/ssh-keygen.1 2010-11-05 01:20:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keygen.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-keygen.1,v 1.101 2010/10/28 18:33:28 jmc Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Author: Tatu Ylonen <***@cs.hut.fi>
+ .\" Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, Espoo, Finland
+@@ -14,6 +14,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
+@@ -294,6 +295,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.
+@@ -409,6 +411,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
+@@ -630,6 +633,8 @@
+ .It Pa ~/.ssh/id_ecdsa
+ .It Pa ~/.ssh/id_rsa
+ Contains the protocol version 2 DSA, ECDSA or RSA authentication identity of the user.
++In case of DSA or RSA identity 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
+@@ -649,6 +654,25 @@
+ 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.
++If file
++.Pa ~/.ssh/id_dsa
++contain DSA private key followed by X.509 certificate or
++.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 .
+ .Pp
+ .It Pa /etc/moduli
+ Contains Diffie-Hellman groups used for DH-GEX.
+@@ -675,3 +699,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.8p1/ssh-keygen.c openssh-5.8p1+x509-6.2.4/ssh-keygen.c
+--- openssh-5.8p1/ssh-keygen.c 2011-01-11 08:20:31.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keygen.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh-keygen.c,v 1.205 2011/01/11 06:13:10 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1994 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -1815,6 +1839,7 @@
+ __progname = ssh_get_progname(argv[0]);
+
+ OpenSSL_add_all_algorithms();
++ fill_default_xkalg();
+ log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
+
+ init_rng();
+diff -ruN openssh-5.8p1/ssh-keyscan.0 openssh-5.8p1+x509-6.2.4/ssh-keyscan.0
+--- openssh-5.8p1/ssh-keyscan.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keyscan.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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
+- ``dsa'', ``ecdsa'' or ``rsa'' for protocol version 2. Multiple
+- values may be specified by separating them with commas. The
+- default is ``rsa''.
++ ``x509v3-sign-rsa'', ``x509v3-sign-dss'', ``dsa'', ``ecdsa'' or
++ ``rsa'' for protocol version 2. Multiple values may be specified
++ by separating them with commas. The default are keys for proto-
++ col version 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:
+@@ -79,6 +79,12 @@
+ Where keytype is either ``ecdsa-sha2-nistp256'', ``ecdsa-sha2-nistp384'',
+ ``ecdsa-sha2-nistp521'', ``ssh-dss'' or ``ssh-rsa''.
+
++ 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
+@@ -89,7 +95,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,ecdsa -f ssh_hosts | \
++ $ ssh-keyscan -t x509v3-sign-rsa,x509v3-sign-dss,rsa,dsa,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521 -f ssh_hosts | \
+ sort -u - ssh_known_hosts | diff ssh_known_hosts -
+
+ SEE ALSO
+@@ -98,7 +104,7 @@
+ AUTHORS
+ David Mazieres <***@lcs.mit.edu> wrote the initial version, and Wayne
+ Davison <***@users.sourceforge.net> 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
+@@ -106,4 +112,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.9 August 31, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-keyscan.1 openssh-5.8p1+x509-6.2.4/ssh-keyscan.1
+--- openssh-5.8p1/ssh-keyscan.1 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/ssh-keyscan.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-keyscan.1,v 1.29 2010/08/31 11:54:45 djm Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Copyright 1995, 1996 by David Mazieres <***@lcs.mit.edu>.
+ .\"
+@@ -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: August 31 2010 $
+ .Dt SSH-KEYSCAN 1
+ .Os
+@@ -88,14 +111,15 @@
+ The possible values are
+ .Dq rsa1
+ for protocol version 1 and
++.Dq x509v3-sign-rsa ,
++.Dq x509v3-sign-dss ,
+ .Dq dsa ,
+ .Dq ecdsa
+ or
+ .Dq rsa
+ 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
+@@ -138,6 +162,18 @@
+ or
+ .Dq ssh-rsa .
+ .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
+@@ -153,7 +189,7 @@
+ which have new or different keys from those in the sorted file
+ .Pa ssh_known_hosts :
+ .Bd -literal
+-$ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \e
++$ ssh-keyscan -t x509v3-sign-rsa,x509v3-sign-dss,rsa,dsa,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521 -f ssh_hosts | \e
+ sort -u - ssh_known_hosts | diff ssh_known_hosts -
+ .Ed
+ .Sh SEE ALSO
+@@ -165,6 +201,7 @@
+ wrote the initial version, and
+ .An Wayne Davison Aq ***@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.8p1/ssh-keyscan.c openssh-5.8p1+x509-6.2.4/ssh-keyscan.c
+--- openssh-5.8p1/ssh-keyscan.c 2011-01-06 13:44:45.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keyscan.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,10 +1,33 @@
+-/* $OpenBSD: ssh-keyscan.c,v 1.84 2011/01/04 20:44:13 otto Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Copyright 1995, 1996 by David Mazieres <***@lcs.mit.edu>.
+ *
+ * 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,12 +77,7 @@
+
+ int ssh_port = SSH_DEFAULT_PORT;
+
+-#define KT_RSA1 1
+-#define KT_DSA 2
+-#define KT_RSA 4
+-#define KT_ECDSA 8
+-
+-int get_keytypes = KT_RSA; /* Get only RSA keys by default */
++char* get_keynames = NULL;
+
+ int hash_hosts = 0; /* Hash hostname on output */
+
+@@ -91,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 */
+@@ -171,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;
+
+@@ -245,9 +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" : (c->c_keytype == KT_RSA ? "ssh-rsa" :
+- "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521");
++ 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;
+@@ -266,7 +284,6 @@
+ xfree(c->c_kex);
+ c->c_kex = NULL;
+ packet_close();
+-
+ return j < 0? NULL : kexjmp_key;
+ }
+
+@@ -281,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);
+ }
+
+@@ -319,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;
+@@ -348,7 +374,12 @@
+ 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));
++ k->ecdsa_nid = key_ecdsa_nid_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);
+@@ -368,7 +399,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--;
+@@ -389,7 +420,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);
+ }
+@@ -402,6 +433,7 @@
+ char remote_version[sizeof buf];
+ size_t bufsiz;
+ con *c = &fdcon[s];
++ int rsa1key;
+
+ for (;;) {
+ memset(buf, '\0', sizeof(buf));
+@@ -441,7 +473,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);
+@@ -452,10 +485,10 @@
+ confree(s);
+ return;
+ }
+- fprintf(stderr, "# %s %s\n", c->c_name, chop(buf));
++ fprintf(stderr, "# %s (%s) %s\n", c->c_name, fdcon[s].c_keyname, 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);
+@@ -466,7 +499,7 @@
+ confree(s);
+ return;
+ }
+- if (c->c_keytype != KT_RSA1) {
++ if (!rsa1key) {
+ keyprint(c, keygrab_ssh2(c));
+ confree(s);
+ return;
+@@ -570,16 +603,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_ECDSA; 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);
+ }
+ }
+
+@@ -630,6 +665,12 @@
+ if (argc <= 1)
+ usage();
+
++ fill_default_xkalg();
++ get_keynames = xstrdup("x509v3-sign-dss,x509v3-sign-rsa,ssh-rsa,ssh-dss"
++#ifdef OPENSSL_HAS_ECC
++/*",ecdsa"*/",ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"
++#endif
++); /* Get all protocol v2 keys by default */
+ while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) {
+ switch (opt) {
+ case 'H':
+@@ -665,26 +706,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_ECDSA:
+- get_keytypes |= KT_ECDSA;
+- 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.8p1/ssh-keysign.0 openssh-5.8p1+x509-6.2.4/ssh-keysign.0
+--- openssh-5.8p1/ssh-keysign.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keysign.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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
+@@ -30,14 +30,15 @@
+ 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_ecdsa_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)
+@@ -48,4 +49,4 @@
+ AUTHORS
+ Markus Friedl <***@openbsd.org>
+
+-OpenBSD 4.9 August 31, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-keysign.8 openssh-5.8p1+x509-6.2.4/ssh-keysign.8
+--- openssh-5.8p1/ssh-keysign.8 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/ssh-keysign.8 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-keysign.8,v 1.12 2010/08/31 11:54:45 djm Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Copyright (c) 2002 Markus Friedl. All rights reserved.
+ .\"
+@@ -71,6 +71,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.
+ .Pp
+ .It Pa /etc/ssh/ssh_host_dsa_key-cert.pub
+ .It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub
+diff -ruN openssh-5.8p1/ssh-ocsp.c openssh-5.8p1+x509-6.2.4/ssh-ocsp.c
+--- openssh-5.8p1/ssh-ocsp.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <string.h>
++
++#include "xmalloc.h"
++#include "log.h"
++#include <openssl/err.h>
++#include <openssl/pem.h>
++#include <openssl/ocsp.h>
++#ifdef SSH_WITH_SSLOCSP
++# include <openssl/ssl.h>
++#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 <NULL> 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.8p1/ssh-pkcs11-helper.0 openssh-5.8p1+x509-6.2.4/ssh-pkcs11-helper.0
+--- openssh-5.8p1/ssh-pkcs11-helper.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-pkcs11-helper.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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.org>
+
+-OpenBSD 4.9 February 10, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-rand-helper.0 openssh-5.8p1+x509-6.2.4/ssh-rand-helper.0
+--- openssh-5.8p1/ssh-rand-helper.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-rand-helper.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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.9 April 14, 2002 OpenBSD 4.9
++BSD April 14, 2002 BSD
+diff -ruN openssh-5.8p1/ssh-x509.c openssh-5.8p1+x509-6.2.4/ssh-x509.c
+--- openssh-5.8p1/ssh-x509.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-x509.c 2011-01-08 22:23:21.000000000 +0200
+@@ -0,0 +1,1213 @@
++/*
++ * 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 <ctype.h>
++#include <string.h>
++
++#include "ssh-xkalg.h"
++#include "log.h"
++#include <openssl/err.h>
++#include "xmalloc.h"
++#include "uuencode.h"
++#include <openssl/pem.h>
++#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[,<more_name_options>]
++ v0.9.6
++$ openssl x509 -in cert_file -subject -noout -nameopt oneline [-nameopt <other_name_option>]
++*/
++ 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*
++#ifdef OPENSSH_KEYS_USE_BIO
++x509key_parse_cert(Key *key, BIO *bio) {
++#else
++x509key_load_cert(Key *key, FILE *fp) {
++#endif
++ if (key == NULL) return(NULL);
++
++ if ( (key->type == KEY_RSA) ||
++ (key->type == KEY_DSA) ) {
++#ifdef OPENSSH_KEYS_USE_BIO
++ key->x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
++#else
++ key->x509 = PEM_read_X509(fp, NULL, NULL, NULL);
++#endif
++ if (key->x509 == NULL) {
++ char ebuf[256];
++ debug3("%s: PEM_read_X509 fail %.*s",
++ __func__, 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
++#ifdef OPENSSH_KEYS_USE_BIO
++x509key_write_bio_cert(BIO *out, X509 *x509) {
++#else
++x509key_save_cert(FILE *fp, X509 *x509) {
++#endif
++ int ret = 0;
++#ifndef OPENSSH_KEYS_USE_BIO
++ 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
++#endif /*ndef OPENSSH_KEYS_USE_BIO*/
++
++ 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 = "<No Alias>";
++ BIO_puts(out, alstr);
++ BIO_puts(out, "\n");
++ }
++
++ ret = PEM_write_bio_X509(out, x509);
++ if (!ret) {
++ char ebuf[256];
++ error("%s: PEM_write_bio_X509 fail %.*s",
++ __func__, sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf)));
++ }
++
++#ifndef OPENSSH_KEYS_USE_BIO
++ BIO_free_all(out);
++#endif /*ndef OPENSSH_KEYS_USE_BIO*/
++ return(ret);
++}
++
++
++int
++#ifdef OPENSSH_KEYS_USE_BIO
++x509key_write_bio_pem(
++ BIO *bio,
++#else
++x509key_save_pem(
++ FILE *fp,
++#endif
++ 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:
++#ifdef OPENSSH_KEYS_USE_BIO
++ if (PEM_write_bio_DSAPrivateKey(bio, key->dsa, cipher, passphrase, len, NULL, NULL))
++ return(x509key_write_bio_cert(bio, key->x509));
++#else
++ if (PEM_write_DSAPrivateKey(fp, key->dsa, cipher, passphrase, len, NULL, NULL))
++ return(x509key_save_cert(fp, key->x509));
++#endif
++ break;
++ case KEY_X509_RSA:
++#ifdef OPENSSH_KEYS_USE_BIO
++ if (PEM_write_bio_RSAPrivateKey(bio, key->rsa, cipher, passphrase, len, NULL, NULL))
++ return(x509key_write_bio_cert(bio, key->x509));
++#else
++ if (PEM_write_RSAPrivateKey(fp, key->rsa, cipher, passphrase, len, NULL, NULL))
++ return(x509key_save_cert(fp, key->x509));
++#endif
++ 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.8p1/ssh-x509.h openssh-5.8p1+x509-6.2.4/ssh-x509.h
+--- openssh-5.8p1/ssh-x509.h 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-x509.h 2011-01-08 22:23:21.000000000 +0200
+@@ -0,0 +1,86 @@
++#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*/
++
++/*
++ * The patched configure script define OPENSSH_KEYS_USE_BIO
++ * depending from OpenSSH version
++ */
++
++#ifdef OPENSSH_KEYS_USE_BIO
++Key* x509key_parse_cert(Key *key, BIO *bio);
++#else
++Key* x509key_load_cert(Key *key, FILE *fp);
++#endif
++
++#ifdef OPENSSH_KEYS_USE_BIO
++int x509key_write_bio_pem(BIO *bio, const Key *key, const EVP_CIPHER *cipher, u_char *passphrase, int len);
++#else
++int x509key_save_pem(FILE *fp, const Key *key, const EVP_CIPHER *cipher, u_char *passphrase, int len);
++#endif
++
++#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.8p1/ssh-xkalg.c openssh-5.8p1+x509-6.2.4/ssh-xkalg.c
+--- openssh-5.8p1/ssh-xkalg.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <string.h>
++
++#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.8p1/ssh-xkalg.h openssh-5.8p1+x509-6.2.4/ssh-xkalg.h
+--- openssh-5.8p1/ssh-xkalg.h 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <openssl/evp.h>
++#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.8p1/tests/CA/1-cre_cadb.sh openssh-5.8p1+x509-6.2.4/tests/CA/1-cre_cadb.sh
+--- openssh-5.8p1/tests/CA/1-cre_cadb.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <<EOF
++# Where everything is kept:
++dir = ${SSH_CAROOT}
++
++certs = \$dir/crt # Where the issued certs are kept
++crl_dir = \$dir/crl # Where the issued crl are kept
++database = \$dir/index-$1.txt # database index file.
++new_certs_dir = \$dir/newcerts # default place for new certs.
++serial = \$dir/serial # The current serial number
++
++#x509_extensions = usr_cert # The default extentions to add to the cert
++default_days = ${SSH_CACERTDAYS} # how long to certify for
++default_crl_days= 30 # how long before next CRL
++policy = policy_match
++
++# print options (internal use)
++name_opt = oneline,-space_eq,-esc_msb # print fine UTF-8
++cert_opt = compatible
++
++EOF
++}
++
++
++# ===
++# args:
++# none
++echo_CA_ocsp_options () {
++if test "x$SSH_OCSP" = "xyes"; then
++cat << EOF
++
++# OCSP Validator(Responder) URI
++# Since OpenSSL OCSP responder support only one issuer certificate
++# we should setup for the test cases many responders - each certificate
++# type with responder on different port.
++EOF
++ printf "authorityInfoAccess = "
++(
++ port=${SSH_VA_BASEPORT}
++ for DIGEST in ${RSA_DIGEST_LIST}; do
++ printf "OCSP;URI:http://${SSHD_LISTENADDRESS}:${port},"
++ port=`expr ${port} + 1`
++ done
++ printf "OCSP;URI:http://${SSHD_LISTENADDRESS}:${port}"
++)
++fi
++}
++
++
++# ===
++cre_config () {
++cat << EOF > "$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.8p1/tests/CA/2-cre_cakeys.sh openssh-5.8p1+x509-6.2.4/tests/CA/2-cre_cakeys.sh
+--- openssh-5.8p1/tests/CA/2-cre_cakeys.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <<EOF
++$SSH_DN_C
++$SSH_DN_ST
++$SSH_DN_L
++$SSH_DN_O
++$SSH_DN_OU
++$SSH_DN_OU $1 keys
++.
++OpenSSH Test $1 CA key
++.
++EOF
++}
++
++
++# ===
++gen_rsa () {
++RSA_OPT="-des3"
++if [ -f /etc/random-seed ]; then
++ RSA_OPT="${RSA_OPT} -rand /etc/random-seed"
++fi
++
++rm -f "${TMPDIR}/${CAKEY_PREFIX}-rsa.key" 2>/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.8p1/tests/CA/3-cre_certs.sh openssh-5.8p1+x509-6.2.4/tests/CA/3-cre_certs.sh
+--- openssh-5.8p1/tests/CA/3-cre_certs.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <<EOF
++usage: $0 <options>
++ -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 <<EOF
++$SSH_DN_C
++$SSH_DN_ST
++$SSH_DN_L
++$SSH_DN_O
++${SSH_DN_OU}-2
++${SSH_DN_OU}-1
++${SSH_DN_OU}-3
++$SSH_BASE_DN_CN(${type}${subtype})
++$SSH_DN_EM
++.
++EOF
++ ) |
++ $OPENSSL req \
++ -new \
++ -config "${SSH_CACFGFILE}" \
++ $SSH_DN_UTF8_FLAG \
++ -key "${SSH_BASE_KEY}" \
++ -passin pass:"" \
++ -out "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.csr" \
++ 2>> "$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.8p1/tests/CA/4-cre_crls.sh openssh-5.8p1+x509-6.2.4/tests/CA/4-cre_crls.sh
+--- openssh-5.8p1/tests/CA/4-cre_crls.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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.8p1/tests/CA/5-cre_ldap.sh openssh-5.8p1+x509-6.2.4/tests/CA/5-cre_ldap.sh
+--- openssh-5.8p1/tests/CA/5-cre_ldap.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <<EOF
++dn: ${SSH_LDAP_DC}
++objectClass: dcObject
++objectClass: organization
++dc: example
++o: Example Corporation
++description: The Example Corporation
++
++dn: cn=Manager,${SSH_LDAP_DC}
++objectClass: inetOrgPerson
++cn: Manager
++sn: Manager
++title: the world's most famous manager
++mail: ***@example.com
++uid: manager
++
++
++#The organization 'OpenSSH Test Team':
++# "O=${SSH_DN_O},${SSH_LDAP_DC}"
++dn:`utf8base64 "O=${SSH_DN_O},${SSH_LDAP_DC}"`
++objectclass: organization
++o:`utf8base64 "${SSH_DN_O}"`
++st: ${SSH_DN_ST}
++
++
++#The 'OpenSSH Test Team' "CA" organizational units:
++# "OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"
++dn:`utf8base64 "OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"`
++objectclass: organizationalUnit
++ou:`utf8base64 "${SSH_DN_OU}"`
++l:`utf8base64 "${SSH_DN_L}"`
++st: ${SSH_DN_ST}
++EOF
++
++
++ for type in ${SSH_SIGN_TYPES}; do
++ N="${CAKEY_PREFIX}-${type}.crt.pem"
++
++ cat <<EOF
++
++# "OU=${SSH_DN_OU} $type keys,OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"
++dn:`utf8base64 "OU=${SSH_DN_OU} $type keys,OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"`
++objectclass: organizationalUnit
++ou:`utf8base64 "$SSH_DN_OU $type keys"`
++l:`utf8base64 "${SSH_DN_L}"`
++st: ${SSH_DN_ST}
++EOF
++ done
++) > ldap/base.ldif
++}
++
++
++# ===
++cre_slapdconf () {
++(
++ cat <<EOF
++#required schemas
++include $LDAP_SYSCONFDIR/schema/core.schema
++include $LDAP_SYSCONFDIR/schema/cosine.schema
++include $LDAP_SYSCONFDIR/schema/inetorgperson.schema
++
++#features
++allow bind_v2
++#disallow bind_simple ;-)
++
++# dbms backend settings should be same file !
++# this is required for openldap version 2.3.32(but not for <= 2.3.20,2.2.x,2.1.x)
++##dbms
++#database $SSH_LDAP_DB
++#suffix "$SSH_LDAP_DC"
++#rootdn "cn=Manager,$SSH_LDAP_DC"
++#rootpw secret
++#
++#index objectClass eq
++EOF
++) > 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.8p1/tests/CA/config openssh-5.8p1+x509-6.2.4/tests/CA/config
+--- openssh-5.8p1/tests/CA/config 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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="***@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.8p1/tests/CA/env.in openssh-5.8p1+x509-6.2.4/tests/CA/env.in
+--- openssh-5.8p1/tests/CA/env.in 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/env.in 2004-10-29 22:52:46.000000000 +0300
+@@ -0,0 +1,4 @@
++# LDAP environment:
++@***@LDAP_SYSCONFDIR="@LDAP_SYSCONFDIR@"
++@***@LDAP_LIBEXECDIR="@LDAP_LIBEXECDIR@"
++@***@LDAP_BINDIR="@LDAP_BINDIR@"
+diff -ruN openssh-5.8p1/tests/CA/functions openssh-5.8p1+x509-6.2.4/tests/CA/functions
+--- openssh-5.8p1/tests/CA/functions 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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[<NUM>G move to column <NUM> (linux console, xterm, not vt100)
++# \033[<NUM>C move <NUM> columns forward but only upto last column
++# \033[<NUM>D move <NUM> columns backward but only upto first column
++# \033[<NUM>A move <NUM> rows up
++# \033[<NUM>B move <NUM> 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.8p1/tests/CA/Makefile.in openssh-5.8p1+x509-6.2.4/tests/CA/Makefile.in
+--- openssh-5.8p1/tests/CA/Makefile.in 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/Makefile.in 2007-01-27 16:59:16.000000000 +0200
+@@ -0,0 +1,134 @@
++srcdir=@srcdir@
++@***@SSH_OCSP=yes
++@***@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_certs:
++@***@ocsp_certs: testocsp_rsa-rsa_md5.crt testocsp_dsa-rsa_md5.crt
++
++@***@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"
++
++@***@testocsp_rsa:
++@OCSP_ON@ @echo; echo "generating RSA 'ocspkey'"
++@OCSP_ON@ $(TEST_SSH_SSHKEYGEN) -t rsa -b $(RSAKEYBITS) -f $@ -N ""
++
++@***@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"
++
++@***@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_files:
++@***@ldap_files: ldap/slapd.conf.tmpl
++
++@***@ldap/slapd.conf.tmpl: env
++@LDAP_ON@ @echo
++@LDAP_ON@ $(SHELL) $(srcdir)/5-cre_ldap.sh
++
++@***@ldap_clean:
++@***@ldap_clean:
++@LDAP_ON@ rm -f ldap_setup.log
++@LDAP_ON@ rm -fr ldap
+diff -ruN openssh-5.8p1/tests/CA/openssh_tests.sh openssh-5.8p1+x509-6.2.4/tests/CA/openssh_tests.sh
+--- openssh-5.8p1/tests/CA/openssh_tests.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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" <<EOF
++CACertificateFile /file/not/found
++CAldapURL ${LDAPD_URL}
++VAType none
++EOF
++
++"$TEST_SSH_SSHD" -t -f "${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}" <<EOF
++Port ${SSHD_PORT}
++Protocol 2
++ListenAddress ${SSHD_LISTENADDRESS}
++AuthorizedKeysFile ${AUTHORIZEDKEYSFILE}
++ChallengeResponseAuthentication no
++HostbasedAuthentication no
++#!NO(linux):KerberosAuthentication no
++#!NO(linux):KerberosOrLocalPasswd no
++#!NO(OpenBSD):PAMAuthenticationViaKbdInt no
++StrictModes no
++PasswordAuthentication no
++PubkeyAuthentication yes
++#deprecated#RhostsAuthentication no
++RhostsRSAAuthentication no
++RSAAuthentication no
++
++UsePrivilegeSeparation ${SSHSERVER_USEPRIVILEGESEPARATION}
++
++HostKey ${TEST_SSHD_HOSTKEY}
++
++#deprecated#X509rsaSigType=md5
++#AllowedCertPurpose sslclient
++EOF
++}
++
++creTestSSHcfgFile() {
++ cat > "${SSH_CFG}" <<EOF
++Host *
++Port ${SSHD_PORT}
++PreferredAuthentications publickey
++Protocol 2
++StrictHostKeyChecking yes
++UserKnownHostsFile ${USERKNOWNHOSTSFILE}
++
++#deprecated#X509rsaSigType=md5
++#AllowedCertPurpose sslserver
++EOF
++if test "x${SSH_X509STORE_DISABLED}" != "xyes"; then
++ cat >> "${SSH_CFG}" <<EOF
++CACertificatePath /path/not/found/global
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++UserCACertificatePath /path/not/found/user
++UserCACertificateFile /file/not/found/user
++EOF
++fi
++}
++
++
++# ===
++#args:
++# $1 - type
++# $2 - identity_file or empty
++# $3 - info
++# $4 - request to fail flag
++runTest () {
++(
++ printf '%s' " * ${extd}${1}${norm} ${3}"
++
++ msg="OpenSSH Certificate TeSt-${1}"
++
++ sshopts=""
++ #sshopts="${sshopts} -v -v -v"
++ test -n "$2" && sshopts="${sshopts} -i $2"
++ #assignment to variable "identity_file" crash ksh :-(
++ #identity_file="value_without_significance"
++
++ case $4 in
++ Y|y|Yes|yes|YES|1)
++ must_fail=1;;
++ *)
++ must_fail=0;;
++ esac
++
++ creTestSSHcfgFile || exit $?
++
++ "$TEST_SSH_SSH" -F "${SSH_CFG}" ${sshopts} \
++ ${SSH_EXTRA_OPTIONS} \
++ ${SSHD_LISTENADDRESS} "echo \"${msg}\"" \
++ 2> "${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.8p1/tests/CA/shell.rc openssh-5.8p1+x509-6.2.4/tests/CA/shell.rc
+--- openssh-5.8p1/tests/CA/shell.rc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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.8p1/tests/CA/test-agent.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-agent.sh.inc
+--- openssh-5.8p1/tests/CA/test-agent.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++ fi
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ printSeparator
++ echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm} ..."
++
++ for type in ${SSH_SIGN_TYPES}; do
++ testAgent || exit $?
++ done
++ done
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
+diff -ruN openssh-5.8p1/tests/CA/test-alg.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-alg.sh.inc
+--- openssh-5.8p1/tests/CA/test-alg.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-alg.sh.inc 2006-03-13 21:51:43.000000000 +0200
+@@ -0,0 +1,140 @@
++#
++# Copyright (c) 2004-2005 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 optional x509 certificate;
++# - "AuthorizedKeysFile" contain certificate BLOB.
++# - server accept different publickey algorithms.
++# Note that "Host-Based Authentication" we cannot test without to install.
++#
++
++
++# ===
++#env. vars:
++# alg
++testAlg () {
++ printSeparator
++ echo " - only ${attn}${alg}${norm} algorithm"
++
++ creTestSSHDcfgFile
++ if test "x${SSH_X509STORE_DISABLED}" != "xyes"; then
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++ fi
++ cat >> "$SSHD_CFG" <<EOF
++PubkeyAlgorithms $alg
++EOF
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ case $SSH_CLIENTKEY in
++ *rsa) keytype="rsa";;
++ *dsa) keytype="dsa";;
++ *) echo "${warn}unknown client key type${norm}"
++ exit 1;;
++ esac
++ case $alg in
++ x509v3-sign-*) withcert="yes";;
++ *) withcert="";;
++ esac
++
++ if test -z "$withcert"; then
++ must_fail=""
++ if test "X$alg" = "Xssh-rsa"; then
++ test "$keytype" = "rsa" || must_fail="yes"
++ else
++ test "$keytype" = "dsa" || must_fail="yes"
++ fi
++ else
++ must_fail="yes"
++ fi
++
++ identity_file="${SSH_CLIENTKEY}"
++ "$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 $?
++
++ 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.8p1/tests/CA/test-blob_auth.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-blob_auth.sh.inc
+--- openssh-5.8p1/tests/CA/test-blob_auth.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++ fi
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ printSeparator
++ echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm} ..."
++
++ for type in ${SSH_SIGN_TYPES}; do
++ testBLOBautorization || exit $?
++ done
++ done
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
+diff -ruN openssh-5.8p1/tests/CA/test-by_ldap.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-by_ldap.sh.inc
+--- openssh-5.8p1/tests/CA/test-by_ldap.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-by_ldap.sh.inc 2008-02-25 22:07:50.000000000 +0200
+@@ -0,0 +1,270 @@
++#
++# 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: Test OpenSSH client authentication:
++# - "IdentityFile" contain private key and x509 certificate;
++# - "AuthorizedKeysFile" contain certificate Subject;
++# - authorization against:
++# - LDAP, without CRL file and hash-dir
++#
++
++
++LDAP_SETUP_LOG="${CWD}/ldap_setup.log"
++LDAPD_PID="${CWD}/slapd.pid"
++LDAPD_ARGS="${CWD}/slapd.args"
++LDAPD_CFG="${CWD}/slapd.conf"
++
++if test -z "${LDAP_BINDIR}"; then
++ LDAPADD=ldapadd
++else
++ LDAPADD="${LDAP_BINDIR}/ldapadd"
++fi
++
++
++# ===
++#args:
++# $1 - info. message for valid cert.
++# $2 - request valid cert. to fail flag
++# $3 - info. message for revoked cert.
++# $4 - request revoked cert. to fail flag
++test_all_keys () {
++ for type in ${SSH_SIGN_TYPES}; do
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ identity_file="${SSH_CLIENTKEY}-${type}"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "$1" "$2" || return $?
++
++ identity_file="${SSH_CLIENTKEY}-${type}-revoked"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "$3" "$4" || return $?
++ done
++ done
++ return 0
++}
++
++
++# ===
++creTestLDAPDcfgFile() {
++(
++ cat <<EOF
++include $CWD/ldap/slapd.conf.tmpl
++
++# dbms backend settings must be in same file !
++# this is required for openldap version 2.3.32(but not for <= 2.3.20,2.2.x,2.1.x)
++database $SSH_LDAP_DB
++suffix "$SSH_LDAP_DC"
++rootdn "cn=Manager,$SSH_LDAP_DC"
++rootpw secret
++
++directory $CWD/ldap/data
++index objectClass eq
++
++pidfile $LDAPD_PID
++argsfile $LDAPD_ARGS
++EOF
++) > ${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 <<EOF
++# "CN=OpenSSH Test ${type} CA key,OU=${SSH_DN_OU} $type keys,OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"
++dn:`utf8base64 "CN=OpenSSH Test ${type} CA key,OU=${SSH_DN_OU} $type keys,OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"`
++objectClass: inetOrgPerson
++objectClass: pkiCA
++cACertificate;binary:< file://${CWD}/ldap/catest-${type}.crt.der
++certificateRevocationList;binary:< file://${CWD}/ldap/catest-${type}.crl.der
++cn: OpenSSH Test ${type} CA key
++sn: OpenSSH Test ${type} CA key
++ou:`utf8base64 "${SSH_DN_OU} ${type} keys"`
++ou:`utf8base64 "${SSH_DN_OU}"`
++o:`utf8base64 "${SSH_DN_O}"`
++l:`utf8base64 "${SSH_DN_L}"`
++st: ${SSH_DN_ST}
++
++EOF
++ done
++) > 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" <<EOF
++CACertificateFile /file/not/found
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++CAldapVersion $1
++CAldapURL ${LDAPD_URL}/${SSH_CONF_LDAP_DC}
++#TODO:MandatoryCRL yes
++EOF
++
++ runSSHdaemon || return $?
++ (
++ rm -f "${CWD}/ldap/data"/*
++ runLDAPdaemon
++ (
++ initLDAPdb || exit $?
++
++ test_all_keys "" "" "${warn}!${norm}" "Yes"
++ ); retval=$?
++ killLDAPdaemon
++ exit ${retval}
++ ); retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++LDAPtestBREAK() {
++ echo
++ killLDAPdaemon
++ testBREAK
++}
++
++trap LDAPtestBREAK INT QUIT ABRT KILL TERM || exit 1
++
++
++# ===
++
++do_test () {
++ if test "x${SSH_LDAP_ENABLED}" = "xno"; then
++ echo "* ${extd}LDAP${norm} is ${attn}disabled${norm}"
++ return 1
++ fi
++ echo "* ${extd}against ${attn}CALdapUrl${norm}:"
++
++ testLDAP 2 &&
++ testLDAP 3
++}
+diff -ruN openssh-5.8p1/tests/CA/test-crl.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-crl.sh.inc
+--- openssh-5.8p1/tests/CA/test-crl.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-crl.sh.inc 2005-02-23 22:33:15.000000000 +0200
+@@ -0,0 +1,266 @@
++#
++# 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 Subject;
++# - authorization against:
++# - without CRL file and hash-dir
++# - only with CRL file(CARevocationFile)
++# - only with CRL hash-dir(CARevocationPath)
++# - only one CRL file in a hash-dir
++#
++
++
++# ===
++#args:
++# $1 - info. message for valid cert.
++# $2 - request valid cert. to fail flag
++# $3 - info. message for revoked cert.
++# $4 - request revoked cert. to fail flag
++test_all_keys () {
++ for type in ${SSH_SIGN_TYPES}; do
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ identity_file="${SSH_CLIENTKEY}-${type}"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "$1" "$2" || return $?
++
++ identity_file="${SSH_CLIENTKEY}-${type}-revoked"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "$3" "$4" || return $?
++ done
++ done
++ return 0
++}
++
++
++# ===
++test_nocrl () {
++ printSeparator
++ echo "Begin test ${extd}without${norm} CRL ${attn}file${norm} and ${attn}hash-dir${norm} ..."
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "" "" "" ""; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++test_crlfile () {
++ printSeparator
++ echo "Begin test with CRL ${extd}file(${attn}CARevocationFile${norm}) ..."
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile ${SSH_CAROOT}/${CACRLFILE}
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "" "" "${warn}!${norm}" "Yes"; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++test_crldir () {
++ printSeparator
++ echo "Begin test with CRL ${extd}hash-dir(${attn}CARevocationPath${norm}) ..."
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath ${SSH_CACRLDIR}
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "" "" "${warn}!${norm}" "Yes"; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++#env. vars:
++# crltype - crl for signature type
++test_crlbytype () {
++ retval=0
++
++ echo " - ${extd}with ${attn}${crltype}${norm} only in ${attn}CARevocationPath${norm} ..."
++
++ printf " creating ${attn}${crltype}${norm} crlfile in hash dir"
++ #printf "${warn}"
++ rm -f "${CRL_TEST_DIR}"/* 2> /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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath ${CRL_TEST_DIR}
++EOF
++
++
++ runSSHdaemon &&
++ (
++ for crltype in ${SSH_SIGN_TYPES}; do
++ test_crlbytype || exit $?
++ done
++ ); retval=$?
++ killSSHdaemon
++
++ rm -f "${CRL_TEST_DIR}"/* 2> /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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile ${SSH_CAROOT}/${CACRLFILE}
++CARevocationPath /crlpath/not/found
++MandatoryCRL yes
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "" "" "${warn}!${norm}" "Yes"; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++test_crlpresence_no () {
++ printSeparator
++ echo "Begin test with mandatory ${extd}CRL presence ${attn}without${norm} CRL ..."
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++MandatoryCRL yes
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "${warn}!${norm}" "Yes" "${warn}!${norm}" "Yes"; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++
++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}CA CRL${norm} file and/or hash-dir:"
++
++ test_nocrl &&
++ test_crlfile &&
++ test_crldir &&
++ test_onlyonecrl &&
++ test_crlpresence_yes &&
++ test_crlpresence_no
++}
+diff -ruN openssh-5.8p1/tests/CA/test-dn_auth_file.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-dn_auth_file.sh.inc
+--- openssh-5.8p1/tests/CA/test-dn_auth_file.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-dn_auth_file.sh.inc 2007-08-06 23:21:19.000000000 +0300
+@@ -0,0 +1,119 @@
++#
++# 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 "Distinguished Name"/
++# "Subject" in varios formats.
++#
++
++
++# ===
++#env. vars:
++# SSH_CLIENTKEY
++# type
++testDNautorizations1 () {
++ identity_file="${SSH_CLIENTKEY}-${type}"
++ if test ! -r "$identity_file"; then
++ error_file_not_readable "${identity_file}"; return $?
++ fi
++
++ sshkeytype=`getSSHkeyType "${identity_file}"` || return $?
++ subject=`getSubject "${identity_file}"` || return $?
++
++ for subtype in \
++ "Subject:" \
++ "SuBjecT=" \
++ "sUbjecT" \
++ "diStinguished name:" \
++ "distiNguished-nAme:" \
++ "distinguiShed_naMe:" \
++ "disTinguishednamE:" \
++ "dN:" \
++ ; do
++ echo "${sshkeytype} ${subtype} ${subject}" > "${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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ printSeparator
++ echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm} ..."
++
++ for type in ${SSH_SIGN_TYPES}; do
++ testDNautorizations1 || exit $?
++ done
++ done
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
+diff -ruN openssh-5.8p1/tests/CA/test-dn_auth_path.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-dn_auth_path.sh.inc
+--- openssh-5.8p1/tests/CA/test-dn_auth_path.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-dn_auth_path.sh.inc 2004-03-09 21:37:04.000000000 +0200
+@@ -0,0 +1,119 @@
++#
++# 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 Subject;
++# - authorization against only one CA certificate in server x509 store.
++#
++
++
++# ===
++#env. vars:
++# SSH_CLIENTKEY
++# catype
++# type
++testDNautorizations2 () {
++ identity_file="${SSH_CLIENTKEY}-${type}"
++
++ creX509AuthorizedKeysFile "${identity_file}" || return $?
++
++ if test "${catype}" = "${type}"; then
++ runTest "${extd}${type}${norm}" \
++ "${identity_file}"\
++ "" ""
++ else
++ runTest "${type}" \
++ "${identity_file}" \
++ "${warn}!${norm}" "Yes"
++ fi
++}
++
++
++# ===
++#env. vars:
++# catype
++do_test_catype () {
++ echo " - autorization by x509 ${attn}Subject${norm} against CA key ${attn}${catype}${norm}"
++
++ for type in ${SSH_SIGN_TYPES}; do
++ testDNautorizations2 "${catype}" "${type}" || return $?
++ done
++}
++
++
++# ===
++
++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}CACertificatePath${norm}:"
++
++ CRT_TEST_DIR="${SSH_CAROOT}/crt-test"
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile /file/not/found
++CACertificatePath ${CRT_TEST_DIR}
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ printSeparator
++ echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm} ..."
++
++ if test ! -d "${CRT_TEST_DIR}"; then
++ mkdir "${CRT_TEST_DIR}" || return $?
++ fi
++ rm -rf "${CRT_TEST_DIR}/"* 2>/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.8p1/tests/CA/test-ocsp.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-ocsp.sh.inc
+--- openssh-5.8p1/tests/CA/test-ocsp.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++VAType ocspcert
++EOF
++
++ port=${SSH_VA_BASEPORT}
++ for type in ${SSH_SIGN_TYPES}; do
++ runResponder ${port}; retval=$?
++ if test ${retval} -ne 0; then
++ break
++ fi
++ port=`expr ${port} + 1`
++ done
++ if test ${retval} -eq 0; then
++ runSSHdaemon &&
++ (
++ for type in ${SSH_SIGN_TYPES}; do
++ test_by_keytype || exit $?
++ done
++ ); retval=$?
++ killSSHdaemon
++ fi
++ killResponders
++ if test ${retval} -ne 0; then
++ exit ${retval}
++ fi
++ done
++
++ exit ${retval}
++)
++}
++
++
++# ===
++#env. vars:
++# type
++test_by_keytype() {
++(
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ identity_file="${SSH_CLIENTKEY}-${type}"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "" "" || exit $?
++
++ identity_file="${SSH_CLIENTKEY}-${type}-revoked"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${SSH_CLIENTKEY}-${type}${warn}-revoked${norm}" \
++ "${identity_file}" "" "Yes" || exit $?
++ done
++)
++}
++
++
++# ===
++test_ocsp_spec () {
++(
++ printSeparator
++ echo "Begin test ${extd}against${norm} ${attn}specified${norm} OCSP provider ..."
++
++ #OpenSSL OCSP responder support only one CA!
++ #For each signature type we have different CA, i.e. we must start
++ #corresponding OCSP responder.
++ #Note: OpenSSL OCSP responder doesn't support dsa keys!!!
++ retval=1
++ for OCSP_RESPKEY in ${TEST_OCSP_RESPKEYS}; do
++ printSeparator
++ echo " respoder key base ${attn}${OCSP_RESPKEY}${norm} ..."
++
++ for type in ${SSH_SIGN_TYPES}; do
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++VAType ocspspec
++VAOCSPResponderURL http://${SSHD_LISTENADDRESS}:${SSH_VA_BASEPORT}
++#VACertificateFile `pwd`/${OCSP_RESPKEY}-${type}.crt
++EOF
++
++ runResponder ${SSH_VA_BASEPORT} &&
++ runSSHdaemon &&
++ test_by_keytype; retval=$?
++ killSSHdaemon
++ killResponders
++ if test ${retval} -ne 0; then
++ exit ${retval}
++ fi
++ done
++ done
++
++ exit ${retval}
++)
++}
++
++
++# ===
++
++do_test () {
++ if test "x${SSH_OCSP_ENABLED}" = "xno"; then
++ echo "* ${extd}OCSP${norm} is ${attn}disabled${norm}"
++ return 1
++ fi
++ echo "* ${extd}against ${attn}CACertificateFile${norm} and ${attn}OCSP provider${norm}:"
++
++ test_ocsp_cert &&
++ test_ocsp_spec
++}
+diff -ruN openssh-5.8p1/tests/CA/test-self.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-self.sh.inc
+--- openssh-5.8p1/tests/CA/test-self.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-self.sh.inc 2006-04-26 00:48:26.000000000 +0300
+@@ -0,0 +1,227 @@
++#
++# Copyright (c) 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 authentication:
++# - "IdentityFile" contain private key and self-issued x509 certificate;
++# - "AuthorizedKeysFile" contain certificate BLOB or DN.
++#
++
++
++# ===
++cre_keys() {
++ echo " creating keys and files for ${extd}self-issued${norm}"
++
++ for keytype in rsa dsa; do
++ SSH_CLIENTKEY="selfid_${keytype}"
++
++ cat "${SSH_CAKEYDIR}/${CAKEY_PREFIX}-${keytype}.key" \
++ > "${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" <<EOF
++AllowedCertPurpose skip
++KeyAllowSelfIssued no
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ (
++ test_self "no" "no"
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
++
++# ===
++
++test_pkey_no () {
++ retval=0
++ echo " - ${attn}without${norm} self-issued allowed by ${extd}pubkey${norm}:"
++ printSeparator
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++AllowedCertPurpose skip
++KeyAllowSelfIssued no
++CACertificateFile /file/not/found
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ (
++ test_self "yes" "yes"
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
++
++# ===
++
++test_pkey_yes () {
++ retval=0
++ echo " - ${attn}with${norm} self-issued allowed by ${extd}pubkey${norm}:"
++ printSeparator
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++AllowedCertPurpose skip
++KeyAllowSelfIssued yes
++CACertificateFile /file/not/found
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ (
++ test_self "no" "yes"
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
++
++# ===
++SELFtestBREAK() {
++ echo
++ rm -f "selfid_rsa"*
++ rm -f "selfid_dsa"*
++ testBREAK
++}
++
++trap SELFtestBREAK INT QUIT ABRT KILL TERM || exit 1
++
++
++# ===
++
++do_test () {
++ echo "* ${extd}self-issued${norm}:"
++ if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then
++ echo " ${extd}X.509 store${norm} is ${attn}disabled${norm}"
++ echo " the test is not suitable in this context"
++ return 0
++ fi
++
++ cre_keys &&
++ test_store &&
++ test_pkey_no &&
++ test_pkey_yes
++ retval=$?
++
++ rm -f "selfid_rsa"*
++ rm -f "selfid_dsa"*
++
++ return $retval
++}
+diff -ruN openssh-5.8p1/tests/CA/verify.sh openssh-5.8p1+x509-6.2.4/tests/CA/verify.sh
+--- openssh-5.8p1/tests/CA/verify.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/verify.sh 2006-02-16 22:07:03.000000000 +0200
+@@ -0,0 +1,44 @@
++#! /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: Verify all testid_*.crt testhostkey_*.crt files in current
++# directory agains openssh "Test CA".
++#
++
++CWD=`pwd`
++SCRIPTDIR=`echo $0 | sed 's/verify.sh//'`
++. "${SCRIPTDIR}functions"
++. "${SCRIPTDIR}config"
++
++
++for VERIFY in \
++ "${OPENSSL} verify -CAfile ${SSH_CAROOT}/${CACERTFILE}" \
++ "${OPENSSL} verify -CApath ${SSH_CACERTDIR}" \
++; do
++ echo ${attn}${VERIFY} ....${norm}
++ for F in \
++ testid_*.crt \
++ testhostkey_*.crt \
++ testocsp_*.crt \
++ ; do
++ ${VERIFY} "$F" || exit 1
++ done
++done
+diff -ruN openssh-5.8p1/umac.c openssh-5.8p1+x509-6.2.4/umac.c
+--- openssh-5.8p1/umac.c 2008-07-14 05:04:43.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/umac.c 2011-02-04 21:06:01.000000000 +0200
+@@ -123,7 +123,7 @@
+ /* --- Endian Conversion --- Forcing assembly on some platforms */
+ /* ---------------------------------------------------------------------- */
+
+-#if HAVE_SWAP32
++#ifdef HAVE_SWAP32
+ #define LOAD_UINT32_REVERSED(p) (swap32(*(UINT32 *)(p)))
+ #define STORE_UINT32_REVERSED(p,v) (*(UINT32 *)(p) = swap32(v))
+ #else /* HAVE_SWAP32 */
+diff -ruN openssh-5.8p1/x509_by_ldap.c openssh-5.8p1+x509-6.2.4/x509_by_ldap.c
+--- openssh-5.8p1/x509_by_ldap.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/x509_by_ldap.c 2007-10-24 00:30:08.000000000 +0300
+@@ -0,0 +1,874 @@
++/*
++ * 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 "x509_by_ldap.h"
++/* Prefered X509_NAME_cmp method from ssh-x509.c */
++extern int ssh_X509_NAME_cmp(X509_NAME *a, X509_NAME *b);
++#include <string.h>
++#ifndef LDAP_DEPRECATED
++ /* to suppress warnings in some 2.3x versions */
++# define LDAP_DEPRECATED 0
++#endif
++#include <ldap.h>
++
++
++/* ================================================================== */
++/* 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.8p1/x509_by_ldap.h openssh-5.8p1+x509-6.2.4/x509_by_ldap.h
+--- openssh-5.8p1/x509_by_ldap.h 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <openssl/x509_vfy.h>
++#include <openssl/err.h>
++
++
++#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.8p1/x509_nm_cmp.c openssh-5.8p1+x509-6.2.4/x509_nm_cmp.c
+--- openssh-5.8p1/x509_nm_cmp.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <ctype.h>
++#include <string.h>
++
++#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.8p1/x509store.c openssh-5.8p1+x509-6.2.4/x509store.c
+--- openssh-5.8p1/x509store.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <openssl/x509v3.h>
++#include "log.h"
++
++#ifndef SSH_X509STORE_DISABLED
++#include <string.h>
++
++#include "xmalloc.h"
++#include "pathnames.h"
++#include "misc.h"
++#include <openssl/err.h>
++#include <openssl/x509_vfy.h>
++/* 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.8p1/x509store.h openssh-5.8p1+x509-6.2.4/x509store.h
+--- openssh-5.8p1/x509store.h 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <openssl/x509.h>
++
++
++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 */
Index: Makefile
===================================================================
--- Makefile (revision 28065)
+++ Makefile (working copy)
@@ -25,22 +25,34 @@
define Package/openssh/Default
SECTION:=net
CATEGORY:=Network
- DEPENDS:=+libopenssl +zlib +libgcc
+ SUBMENU:=SSH
+ DEPENDS:=openssh
TITLE:=OpenSSH
+ URL:=http://www.openssh.com/
MAINTAINER:=Peter Wagner <***@gmx.at>
- URL:=http://www.openssh.com/
- SUBMENU:=SSH
endef
+define Package/openssh
+ $(call Package/openssh/Default)
+ DEPENDS:=+libopenssl +zlib +libgcc
+endef
+
+define Package/openssh/config
+ config PACKAGE_openssh_x509
+ depends on (PACKAGE_openssh-client || PACKAGE_openssh-server || PACKAGE_openssh-keygen || PACKAGE_openssh-sftp-client || PACKAGE_openssh-sftp-server)
+ bool "Enable x509 certificate support"
+ default y
+endef
+
+define Package/openssh/description
+ OpenSSH client and server suite.
+endef
+
define Package/openssh-client
$(call Package/openssh/Default)
TITLE+= client
endef
-define Package/openssh-client/description
-OpenSSH client.
-endef
-
define Package/openssh-client/conffiles
/etc/ssh/ssh_config
endef
@@ -51,29 +63,17 @@
TITLE+= client utilities
endef
-define Package/openssh-client-utils/description
-OpenSSH client utilities.
-endef
-
define Package/openssh-keygen
$(call Package/openssh/Default)
TITLE+= keygen
endef
-define Package/openssh-keygen/description
-OpenSSH keygen.
-endef
-
define Package/openssh-server
$(call Package/openssh/Default)
DEPENDS+= +openssh-keygen
TITLE+= server
endef
-define Package/openssh-server/description
-OpenSSH server.
-endef
-
define Package/openssh-server/conffiles
/etc/ssh/sshd_config
endef
@@ -83,20 +83,11 @@
TITLE+= SFTP client
endef
-define Package/openssh-sftp-client/description
-OpenSSH SFTP client.
-endef
-
define Package/openssh-sftp-server
$(call Package/openssh/Default)
- DEPENDS:=+libgcc
TITLE+= SFTP server
endef
-define Package/openssh-sftp-server/description
-OpenSSH SFTP server.
-endef
-
CONFIGURE_ARGS+= \
$(DISABLE_NLS) \
--sysconfdir=/etc/ssh \
@@ -122,6 +113,18 @@
CONFIGURE_VARS += LD="$(TARGET_CC)"
+define Build/Prepare
+ $(call Build/Prepare/Default,)
+# tar xf "$(DL_DIR)/$(PKG_SOURCE)" -C "$(BUILD_DIR)"
+# patch -p1 -d "$(PKG_BUILD_DIR)" < "$(PATCH_DIR)/100-no_cast_fix.patch"
+# patch -p1 -d "$(PKG_BUILD_DIR)" < "$(PATCH_DIR)/110-no_ripemd_fix.patch"
+# patch -p1 -d "$(PKG_BUILD_DIR)" < "$(PATCH_DIR)/130-implicit_memset_decl_fix.patch"
+# patch -p1 -d "$(PKG_BUILD_DIR)" < "$(PATCH_DIR)/200-dscp-qos.patch"
+ifdef config_PACKAGE_openssh_x509
+ patch -p1 -d "$(PKG_BUILD_DIR)" < "./300-x509.patch"
+endif
+endef
+
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
DESTDIR="$(PKG_INSTALL_DIR)" \
@@ -192,6 +205,7 @@
ln -sf ../lib/sftp-server $(1)/usr/libexec/sftp-server
endef
+$(eval $(call BuildPackage,openssh))
$(eval $(call BuildPackage,openssh-client))
$(eval $(call BuildPackage,openssh-client-utils))
$(eval $(call BuildPackage,openssh-keygen))
Index: 300-x509.patch
===================================================================
--- 300-x509.patch (revision 0)
+++ 300-x509.patch (revision 0)
@@ -0,0 +1,22533 @@
+diff -ruN openssh-5.8p1/auth2-hostbased.c openssh-5.8p1+x509-6.2.4/auth2-hostbased.c
+--- openssh-5.8p1/auth2-hostbased.c 2010-08-05 06:04:50.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/auth2-hostbased.c 2011-02-04 21:06:01.000000000 +0200
+@@ -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, const char* pkalg);
++
+ static int
+ userauth_hostbased(Authctxt *authctxt)
+ {
+@@ -90,6 +92,11 @@
+ "public key algorithm: %s", pkalg);
+ goto done;
+ }
++ if (!hostbased_algorithm_allowed(pktype, pkalg)) {
++ 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,39 @@
+ return authenticated;
+ }
+
++/* return 1 if given hostbased algorithm is allowed */
++static int
++hostbased_algorithm_allowed(int pktype, const char* pkalg)
++{
++ char *s, *cp, *p;
++#ifdef OPENSSL_HAS_ECC
++ int curve_nid = -1;
++#endif
++
++ 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)) {
++#ifdef OPENSSL_HAS_ECC
++ if (key_type_plain(pktype) == KEY_ECDSA) {
++ if (curve_nid == -1)
++ curve_nid = key_ecdsa_nid_from_name(pkalg);
++ if (curve_nid != key_ecdsa_nid_from_name(p))
++ continue;
++ }
++#endif
++ 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.8p1/auth2-pubkey.c openssh-5.8p1+x509-6.2.4/auth2-pubkey.c
+--- openssh-5.8p1/auth2-pubkey.c 2010-12-01 02:50:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/auth2-pubkey.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: auth2-pubkey.c,v 1.27 2010/11/20 05:12:38 deraadt 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, const char* pkalg);
++
+ static int
+ userauth_pubkey(Authctxt *authctxt)
+ {
+@@ -100,6 +103,11 @@
+ pkalg);
+ goto done;
+ }
++ if (!pubkey_algorithm_allowed(pktype, pkalg)) {
++ 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,132 @@
+ return 0;
+ }
+
++/* return 1 if given publickey algorithm is allowed */
++static int
++pubkey_algorithm_allowed(int pktype, const char* pkalg)
++{
++ char *s, *cp, *p;
++#ifdef OPENSSL_HAS_ECC
++ int curve_nid = -1;
++#endif
++
++ 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)) {
++#ifdef OPENSSL_HAS_ECC
++ if (key_type_plain(pktype) == KEY_ECDSA) {
++ if (curve_nid == -1)
++ curve_nid = key_ecdsa_nid_from_name(pkalg);
++ if (curve_nid != key_ecdsa_nid_from_name(p))
++ continue;
++ }
++#endif
++ 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 +425,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 +440,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 +489,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 +498,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.8p1/authfd.c openssh-5.8p1+x509-6.2.4/authfd.c
+--- openssh-5.8p1/authfd.c 2010-09-10 04:39:27.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/authfd.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: authfd.c,v 1.84 2010/08/31 11:54:45 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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);
+@@ -525,6 +529,21 @@
+ break;
+ #endif
+ }
++ 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);
+ }
+
+@@ -558,6 +577,8 @@
+ case KEY_DSA_CERT_V00:
+ case KEY_ECDSA:
+ case KEY_ECDSA_CERT:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ type = constrained ?
+ SSH2_AGENTC_ADD_ID_CONSTRAINED :
+ SSH2_AGENTC_ADD_IDENTITY;
+@@ -606,6 +627,8 @@
+ 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 == KEY_X509_RSA ||
++ key->type == KEY_X509_DSA ||
+ key_type_plain(key->type) == KEY_RSA ||
+ key_type_plain(key->type) == KEY_ECDSA) {
+ key_to_blob(key, &blob, &blen);
+diff -ruN openssh-5.8p1/authfile.c openssh-5.8p1+x509-6.2.4/authfile.c
+--- openssh-5.8p1/authfile.c 2010-12-01 03:03:39.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/authfile.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: authfile.c,v 1.87 2010/11/29 18:57:04 markus Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+
+@@ -201,6 +204,10 @@
+ success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
+ cipher, passphrase, len, NULL, NULL);
+ break;
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
++ success = x509key_write_bio_pem(bio, key, cipher, passphrase, len);
++ break;
+ }
+ if (success) {
+ if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
+@@ -245,6 +252,8 @@
+ case KEY_DSA:
+ case KEY_ECDSA:
+ case KEY_RSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ return key_private_pem_to_blob(key, blob, passphrase, comment);
+ default:
+ error("%s: cannot save key type %d", __func__, key->type);
+@@ -500,6 +509,7 @@
+ char *name = "<no key>";
+ BIO *bio;
+
++ debug("read PEM private key begin");
+ if ((bio = BIO_new_mem_buf(buffer_ptr(blob),
+ buffer_len(blob))) == NULL) {
+ error("%s: BIO_new_mem_buf failed", __func__);
+@@ -507,7 +517,6 @@
+ }
+
+ pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase);
+- BIO_free(bio);
+ if (pk == NULL) {
+ debug("%s: PEM_read_PrivateKey failed", __func__);
+ (void)ERR_get_error();
+@@ -559,6 +568,17 @@
+ error("%s: PEM_read_PrivateKey: mismatch or "
+ "unknown EVP_PKEY save_type %d", __func__, pk->save_type);
+ }
++ if (prv) {
++ debug("read X.509 certificate begin");
++ BIO_seek(bio, 0); /* rewind */
++ x509key_parse_cert(prv, bio);
++ if (prv->x509 != NULL) {
++ if (!X509_check_private_key(prv->x509, pk)) {
++ fatal("X509 certificate don't match private key");
++ }
++ }
++ }
++ BIO_free(bio);
+ if (pk != NULL)
+ EVP_PKEY_free(pk);
+ if (prv != NULL && commentp)
+@@ -762,6 +782,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.8p1/config.h.in openssh-5.8p1+x509-6.2.4/config.h.in
+--- openssh-5.8p1/config.h.in 2011-02-04 02:59:51.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/config.h.in 2011-02-04 21:06:01.000000000 +0200
+@@ -335,6 +335,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
+
+@@ -551,6 +563,24 @@
+ /* Define to 1 if you have the <lastlog.h> header file. */
+ #undef HAVE_LASTLOG_H
+
++/* Define to 1 if you have the <lber.h> header file. */
++#undef HAVE_LBER_H
++
++/* Define to 1 if you have the <ldap.h> 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 <libaudit.h> header file. */
+ #undef HAVE_LIBAUDIT_H
+
+@@ -668,6 +698,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
+
+@@ -1170,6 +1203,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
+
+@@ -1221,6 +1257,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
+
+@@ -1283,6 +1322,9 @@
+ /* Define if X11 doesn't support AF_UNIX sockets on that system */
+ #undef NO_X11_UNIX_SOCKETS
+
++/* Define if OpenSSH use memory BIO buffer to read/write keys */
++#undef OPENSSH_KEYS_USE_BIO
++
+ /* Define if EVP_DigestUpdate returns void */
+ #undef OPENSSL_EVP_DIGESTUPDATE_VOID
+
+@@ -1360,6 +1402,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
+
+@@ -1372,6 +1417,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
+
+@@ -1393,6 +1445,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.8p1/configure openssh-5.8p1+x509-6.2.4/configure
+--- openssh-5.8p1/configure 2011-02-04 03:00:01.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/configure 2011-02-04 21:06:02.000000000 +0200
+@@ -730,6 +730,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
+@@ -1321,6 +1332,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
+@@ -1370,6 +1384,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
+
+@@ -1816,6 +1839,19 @@
+
+
+
++# Options to build with LDAP
++#
++# Author: Roumen Petrov
++# Revision: 22 Oct 2007
++#
++
++
++
++
++# AC_LDAP_FUNCS(FUNCTION...)
++# --------------------------------
++
++
+
+ # local macros
+
+@@ -30115,203 +30151,159 @@
+ 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
+-
++# X.509 support
++ssh_x509="yes"
+
++# Starting from version 5.7 OpenSSH use memory BIO buffer
++# to read/write keys instead file streams.
+
+ 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
++#define OPENSSH_KEYS_USE_BIO 1
+ _ACEOF
+
+- fi
+-
++# Reserved for future use
++#AC_DEFINE_UNQUOTED(
++# X509_DISABLED, 1,
++# [Define if you want to disable X.509 certificates])
+
+-fi
+-
+-# Check whether --enable-utmpx was given.
+-if test "${enable_utmpx+set}" = set; then
+- enableval=$enable_utmpx;
+- if test "x$enableval" = "xno" ; then
++# 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
+
+-cat >>confdefs.h <<\_ACEOF
+-#define DISABLE_UTMPX 1
+-_ACEOF
+
++# 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
+
+
+ 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
++cat >>confdefs.h <<_ACEOF
++#define SSHCADIR "$sshcadir"
+ _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 <limits.h> declares $ac_func.
++ For example, HP-UX 11i <limits.h> declares gettimeofday. */
++#define $ac_func innocuous_$ac_func
+
+-#include <sys/types.h>
+-#include <utmp.h>
+-#ifdef HAVE_LASTLOG_H
+-# include <lastlog.h>
++/* System header to define __stub macros and hopefully few prototypes,
++ which can conflict with char $ac_func (); below.
++ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++ <limits.h> exists even on freestanding compilers. */
++
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
+ #endif
+-#ifdef HAVE_PATHS_H
+-# include <paths.h>
++
++#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 <login.h>
++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
+@@ -30320,41 +30312,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 <sys/types.h>
+-#include <utmp.h>
+-#ifdef HAVE_LASTLOG_H
+-# include <lastlog.h>
+-#endif
+-#ifdef HAVE_PATHS_H
+-# include <paths.h>
+-#endif
+-
+-int
+-main ()
+-{
+- char *lastlog = _PATH_LASTLOG;
+- ;
+- return 0;
+-}
++$ac_includes_default
++#include <openssl/ocsp.h>
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (ac_try="$ac_compile"
+@@ -30373,24 +30371,1571 @@
+ 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 <openssl/ocsp.h>
++_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-***@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-***@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 <limits.h> declares $ac_func.
++ For example, HP-UX 11i <limits.h> 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 <limits.h> to <assert.h> if __STDC__ is defined, since
++ <limits.h> exists even on freestanding compilers. */
++
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#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 <openssl/evp.h>
++
++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 <openssl/x509_vfy.h>
++
++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 <openssl/x509_vfy.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <openssl/evp.h>
++
++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 <sys/types.h>
++#include <utmp.h>
++#ifdef HAVE_LASTLOG_H
++# include <lastlog.h>
++#endif
++#ifdef HAVE_PATHS_H
++# include <paths.h>
++#endif
++#ifdef HAVE_LOGIN_H
++# include <login.h>
++#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 <sys/types.h>
++#include <utmp.h>
++#ifdef HAVE_LASTLOG_H
++# include <lastlog.h>
++#endif
++#ifdef HAVE_PATHS_H
++# include <paths.h>
++#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
+
+-
+-fi
+-
+ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ if test -z "$conf_lastlog_location"; then
+@@ -30713,7 +32258,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
+@@ -31275,6 +32820,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" ;;
+
+@@ -31493,13 +33040,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` = 21; then
++ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 32; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+@@ -31948,6 +33506,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"
+@@ -31974,6 +33533,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 " Solaris project support: $SP_MSG"
+@@ -32007,6 +33569,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.8p1/configure.ac openssh-5.8p1+x509-6.2.4/configure.ac
+--- openssh-5.8p1/configure.ac 2011-02-04 02:42:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/configure.ac 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-# $Id: configure.ac,v 1.469.4.1 2011/02/04 00:42:14 djm Exp $
++# $Id$
+ #
+ # Copyright (c) 1999-2004 Damien Miller
+ #
+@@ -17,6 +17,7 @@
+ AC_INIT(OpenSSH, Portable, openssh-unix-***@mindrot.org)
+ AC_REVISION($Revision: 1.469.4.1 $)
+ AC_CONFIG_SRCDIR([ssh.c])
++m4_include([m4/ldap.m4])
+
+ # local macros
+ AC_DEFUN([OPENSSH_CHECK_CFLAG_COMPILE], [{
+@@ -3990,6 +3991,167 @@
+ ]
+ )
+
++# X.509 support
++ssh_x509="yes"
++
++# Starting from version 5.7 OpenSSH use memory BIO buffer
++# to read/write keys instead file streams.
++AC_DEFINE_UNQUOTED(
++ OPENSSH_KEYS_USE_BIO, 1,
++ [Define if OpenSSH use memory BIO buffer to read/write keys])
++# 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 <openssl/evp.h>
++
++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 <openssl/x509_vfy.h>])
++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 <openssl/evp.h>])
++AC_CHECK_MEMBERS([EVP_MD.copy],,,[#include <openssl/evp.h>])
++AC_CHECK_MEMBERS([EVP_MD.cleanup],,,[#include <openssl/evp.h>])
++AC_CHECK_MEMBERS([EVP_MD_CTX.md_data],,,[#include <openssl/evp.h>])
++
+ # Where to place sshd.pid
+ piddir=/var/run
+ # make sure the directory exists
+@@ -4272,6 +4434,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
+
+@@ -4294,6 +4457,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"
+@@ -4320,6 +4484,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 " Solaris project support: $SP_MSG"
+@@ -4353,6 +4520,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.8p1/dns.c openssh-5.8p1+x509-6.2.4/dns.c
+--- openssh-5.8p1/dns.c 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/dns.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,9 +1,12 @@
+-/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 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 */
+@@ -107,6 +126,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("<UNSUPPORTED>");
++}
++
++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("<UNSUPPORTED>");
++}
++
++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.
+ */
+@@ -168,6 +339,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
+ */
+@@ -200,6 +492,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) {
+@@ -278,10 +578,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)) {
+
+@@ -302,5 +649,6 @@
+ error("export_dns_rr: unsupported algorithm");
+ }
+
++ cert_param_clean(&cert_param);
+ return success;
+ }
+diff -ruN openssh-5.8p1/dns.h openssh-5.8p1+x509-6.2.4/dns.h
+--- openssh-5.8p1/dns.h 2010-02-26 22:55:05.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/dns.h 2011-02-04 21:06:00.000000000 +0200
+@@ -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.8p1/hostfile.c openssh-5.8p1+x509-6.2.4/hostfile.c
+--- openssh-5.8p1/hostfile.c 2010-12-05 00:03:31.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/hostfile.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: hostfile.c,v 1.50 2010/12/04 13:31:37 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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
+@@ -57,6 +59,7 @@
+ #include "hostfile.h"
+ #include "log.h"
+ #include "misc.h"
++#include "ssh-x509.h"
+
+ struct hostkeys {
+ struct hostkey_entry *entries;
+@@ -477,7 +480,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.8p1/INSTALL openssh-5.8p1+x509-6.2.4/INSTALL
+--- openssh-5.8p1/INSTALL 2010-02-12 00:34:22.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/INSTALL 2011-02-04 21:06:00.000000000 +0200
+@@ -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.8p1/key.c openssh-5.8p1+x509-6.2.4/key.c
+--- openssh-5.8p1/key.c 2011-02-04 02:48:34.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/key.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: key.c,v 1.96 2011/02/04 00:44:21 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * read_bignum():
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -82,10 +85,12 @@
+ k->ecdsa_nid = -1;
+ 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)
+@@ -95,8 +100,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)
+@@ -110,6 +120,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;
+ #ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA:
+@@ -136,6 +150,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)
+@@ -150,12 +165,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_ECDSA:
+ case KEY_ECDSA_CERT:
+@@ -224,6 +254,21 @@
+ k->ecdsa = NULL;
+ break;
+ #endif
++ 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:
+@@ -274,12 +319,18 @@
+ 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 &&
+@@ -305,6 +356,12 @@
+ BN_CTX_free(bnctx);
+ return 1;
+ #endif /* OPENSSL_HAS_ECC */
++#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);
+ }
+@@ -358,6 +415,8 @@
+ case KEY_DSA:
+ case KEY_ECDSA:
+ case KEY_RSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ key_to_blob(k, &blob, &len);
+ break;
+ case KEY_DSA_CERT_V00:
+@@ -537,7 +596,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 */
+@@ -694,6 +753,8 @@
+ case KEY_RSA:
+ case KEY_DSA:
+ case KEY_ECDSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ case KEY_DSA_CERT_V00:
+ case KEY_RSA_CERT_V00:
+ case KEY_DSA_CERT:
+@@ -730,6 +791,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);
+@@ -757,7 +823,30 @@
+ return -1;
+ }
+ #endif
++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");
+@@ -800,6 +889,7 @@
+ #endif
+ }
+ #endif
++x509blob:
+ success = 1;
+ /*XXXX*/
+ key_free(k);
+@@ -869,6 +959,9 @@
+ if (key->rsa == NULL)
+ return 0;
+ break;
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
++ return x509key_write(key, f);
+ default:
+ return 0;
+ }
+@@ -900,6 +993,12 @@
+ case KEY_ECDSA:
+ return "ECDSA";
+ #endif
++ 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:
+@@ -978,6 +1077,11 @@
+ const char *
+ key_ssh_name(const Key *k)
+ {
++ const char* p;
++
++ p = ssh_x509key_name(k);
++ if (p) return(p);
++
+ return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
+ }
+
+@@ -1006,6 +1110,9 @@
+ case KEY_ECDSA_CERT:
+ return key_curve_nid_to_bits(k->ecdsa_nid);
+ #endif
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
++ return ssh_x509_key_size(k);
+ }
+ return 0;
+ }
+@@ -1245,6 +1352,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) {
+@@ -1470,10 +1582,14 @@
+ EC_POINT *q = NULL;
+ int nid = -1;
+ #endif
++ 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_cstring_ret(&b, NULL)) == NULL) {
+@@ -1482,6 +1598,8 @@
+ }
+
+ type = key_type_from_name(ktype);
++ debug3("key_from_blob(..., ...) ktype=%.30s", ktype);
++
+ #ifdef OPENSSL_HAS_ECC
+ if (key_type_plain(type) == KEY_ECDSA)
+ nid = key_ecdsa_nid_from_name(ktype);
+@@ -1628,6 +1746,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);
+@@ -1665,6 +1788,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;
+@@ -1698,6 +1825,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;
+@@ -1725,6 +1856,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)
+@@ -1737,6 +1869,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)
+@@ -1761,10 +1894,20 @@
+ break;
+ #endif
+ 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.8p1/key.h openssh-5.8p1+x509-6.2.4/key.h
+--- openssh-5.8p1/key.h 2010-11-05 01:19:49.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/key.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,7 +1,9 @@
+-/* $OpenBSD: key.h,v 1.33 2010/10/28 11:22:09 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
+@@ -32,6 +34,7 @@
+ #ifdef OPENSSL_HAS_ECC
+ #include <openssl/ec.h>
+ #endif
++#include <openssl/x509.h>
+
+ typedef struct Key Key;
+ enum types {
+@@ -44,6 +47,8 @@
+ KEY_ECDSA_CERT,
+ KEY_RSA_CERT_V00,
+ KEY_DSA_CERT_V00,
++ KEY_X509_RSA,
++ KEY_X509_DSA,
+ KEY_UNSPEC
+ };
+ enum fp_type {
+@@ -84,6 +89,7 @@
+ #else
+ void *ecdsa;
+ #endif
++ X509 *x509;
+ struct KeyCert *cert;
+ };
+
+diff -ruN openssh-5.8p1/LICENCE openssh-5.8p1+x509-6.2.4/LICENCE
+--- openssh-5.8p1/LICENCE 2011-01-17 12:15:29.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/LICENCE 2011-02-04 21:06:00.000000000 +0200
+@@ -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:
+@@ -336,4 +337,4 @@
+
+
+ ------
+-$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $
++$OpenBSD$
+diff -ruN openssh-5.8p1/log.c openssh-5.8p1+x509-6.2.4/log.c
+--- openssh-5.8p1/log.c 2008-06-10 16:01:51.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/log.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: log.c,v 1.41 2008/06/10 04:50:25 dtucker Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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.8p1/log.h openssh-5.8p1+x509-6.2.4/log.h
+--- openssh-5.8p1/log.h 2008-06-13 03:22:54.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/log.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: log.h,v 1.17 2008/06/13 00:12:02 dtucker Exp $ */
++/* $OpenBSD$ */
+
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+@@ -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.8p1/m4/ldap.m4 openssh-5.8p1+x509-6.2.4/m4/ldap.m4
+--- openssh-5.8p1/m4/ldap.m4 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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.8p1/Makefile.in openssh-5.8p1+x509-6.2.4/Makefile.in
+--- openssh-5.8p1/Makefile.in 2011-02-04 02:42:13.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/Makefile.in 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-# $Id: Makefile.in,v 1.320.4.1 2011/02/04 00:42:13 djm 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,11 +46,12 @@
+ CC=@CC@
+ LD=@LD@
+ CFLAGS=@CFLAGS@
+-CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
++CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ @LDAP_CPPFLAGS@ $(PATHS) @DEFS@
+ LIBS=@LIBS@
+ SSHLIBS=@SSHLIBS@
+ SSHDLIBS=@SSHDLIBS@
+ LIBEDIT=@LIBEDIT@
++LIBLDAP=@LDAP_LDFLAGS@ @LDAP_LIBS@
+ AR=@AR@
+ AWK=@AWK@
+ RANLIB=@RANLIB@
+@@ -64,6 +67,15 @@
+ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
+ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
+
++@***@LDAP_OBJS=x509_by_ldap.o
++@***@LDAP_OBJS=
++
++@***@OCSP_OBJS=ssh-ocsp.o
++@***@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 \
+@@ -73,13 +85,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-ecdsa.o ssh-rsa.o dh.o \
++ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o $(SSHX509_OBJS) dh.o \
+ kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.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 \
+@@ -94,7 +106,7 @@
+ auth2-gss.o gss-serv.o gss-serv-krb5.o \
+ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.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
+@@ -114,6 +126,10 @@
+ -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_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' \
+@@ -143,10 +159,10 @@
+ $(RANLIB) $@
+
+ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
+- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
++ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBLDAP) $(SSHLIBS) $(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)
+@@ -160,8 +176,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)
+@@ -219,6 +235,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
+@@ -238,9 +255,10 @@
+ >$$base.0 ; \
+ done
+
+-distprep: catman-do
++distprep:
+ $(AUTORECONF)
+ -rm -rf autom4te.cache
++ @test -n "$(MANFMT)" && echo "run 'make -f Makefile.in catman-do MANFMT=....' with appropriate for you host MANFMT macro"
+
+ install: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
+ install-nokeys: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf
+@@ -257,6 +275,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)
+@@ -398,6 +418,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; \
+@@ -443,7 +467,22 @@
+ TEST_SSH_ECC="$${TEST_SSH_ECC}" \
+ TEST_SSH_SHA256="$${TEST_SSH_SHA256}" \
+ 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))
+@@ -452,6 +491,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
+@@ -467,3 +507,6 @@
+ sh buildpkg.sh; \
+ fi
+
++depend:
++ (cd openbsd-compat && $(MAKE) $@)
++ makedepend -- $(CPPFLAGS) $(CFLAGS) -- $(srcdir)/*.c
+diff -ruN openssh-5.8p1/moduli.0 openssh-5.8p1+x509-6.2.4/moduli.0
+--- openssh-5.8p1/moduli.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/moduli.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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,11 +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:
+@@ -69,4 +69,4 @@
+ Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
+ Protocol, RFC 4419, 2006.
+
+-OpenBSD 4.9 June 26, 2008 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/monitor.c openssh-5.8p1+x509-6.2.4/monitor.c
+--- openssh-5.8p1/monitor.c 2010-09-10 04:23:34.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/monitor.c 2011-02-04 21:06:01.000000000 +0200
+@@ -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.8p1/monitor_wrap.c openssh-5.8p1+x509-6.2.4/monitor_wrap.c
+--- openssh-5.8p1/monitor_wrap.c 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/monitor_wrap.c 2011-02-04 21:06:01.000000000 +0200
+@@ -245,6 +245,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.8p1/openbsd-compat/Makefile.in openssh-5.8p1+x509-6.2.4/openbsd-compat/Makefile.in
+--- openssh-5.8p1/openbsd-compat/Makefile.in 2010-10-07 14:19:24.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/openbsd-compat/Makefile.in 2011-02-04 21:06:01.000000000 +0200
+@@ -40,3 +40,6 @@
+
+ distclean: clean
+ rm -f Makefile *~
++
++depend:
++ makedepend -- $(CPPFLAGS) $(CFLAGS) -- $(srcdir)/*.c
+diff -ruN openssh-5.8p1/pathnames.h openssh-5.8p1+x509-6.2.4/pathnames.h
+--- openssh-5.8p1/pathnames.h 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/pathnames.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: pathnames.h,v 1.20 2010/08/31 11:54:45 djm Exp $ */
++/* $OpenBSD$ */
+
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+@@ -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"
+@@ -179,3 +202,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.8p1/readconf.c openssh-5.8p1+x509-6.2.4/readconf.c
+--- openssh-5.8p1/readconf.c 2010-11-20 06:19:38.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/readconf.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: readconf.c,v 1.190 2010/11/13 23:27:50 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -43,6 +66,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:
+@@ -132,6 +157,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,
+ oKexAlgorithms, oIPQoS,
+@@ -231,6 +268,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 },
+@@ -720,9 +777,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 : "<NONE>");
++ */
+ if (*activep && options->hostkeyalgorithms == NULL)
+ options->hostkeyalgorithms = xstrdup(arg);
+ break;
+@@ -997,11 +1056,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 : "<NONE>");
++ */
++ 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);
+@@ -1147,6 +1375,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;
+@@ -1159,6 +1401,22 @@
+ options->ip_qos_bulk = -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.
+@@ -1230,6 +1488,7 @@
+ /* options->macs, default set in myproposals.h */
+ /* options->kex_algorithms, 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) {
+@@ -1321,6 +1580,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 : "<null>"));
++#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.8p1/readconf.h openssh-5.8p1+x509-6.2.4/readconf.h
+--- openssh-5.8p1/readconf.h 2010-11-20 06:19:38.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/readconf.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: readconf.h,v 1.88 2010/11/13 23:27:50 djm Exp $ */
++/* $OpenBSD$ */
+
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+@@ -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 {
+@@ -122,6 +147,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.8p1/README.x509v3 openssh-5.8p1+x509-6.2.4/README.x509v3
+--- openssh-5.8p1/README.x509v3 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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:
++<KEY_TYPE><SPACE><WORDDN><SPACE>{<Distinguished_Name>|CertBlob}
++where:
++KEY_TYPE:=x509v3-sign-rsa|x509v3-sign-dss (case sensitive !)
++WORDDN:={Distinguished Name|
++ Distinguished-Name|
++ Distinguished_Name|
++ DistinguishedName|
++ DN|
++ Subject}<WORDDNSUFF>
++WORDDNSUFF:='='|':'|''
++NOTES:
++- WORDDN is case insensitive !
++
++- <Distinguished Name> is like output from command:
++$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE -nameopt oneline
++
++- <Distinguished Name> 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 <Distinguished Name> 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-<LISTITEM>.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-<SIGNATURE_ALGORITHM>[.<EXTENTION>]"
++ , where <SIGNATURE_ALGORITHM> is in format "rsa_<DIGEST>" 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.8p1/scp.0 openssh-5.8p1+x509-6.2.4/scp.0
+--- openssh-5.8p1/scp.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/scp.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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 [-12346BCpqrv] [-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:
+@@ -38,8 +38,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
+@@ -61,63 +61,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
+- IPQoS
+- KbdInteractiveDevices
+- KexAlgorithms
+- 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).
+
+@@ -127,8 +75,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
+@@ -153,4 +101,4 @@
+ Timo Rinne <***@iki.fi>
+ Tatu Ylonen <***@cs.hut.fi>
+
+-OpenBSD 4.9 December 9, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/scp.1 openssh-5.8p1+x509-6.2.4/scp.1
+--- openssh-5.8p1/scp.1 2011-01-06 13:41:21.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/scp.1 2011-02-04 21:06:00.000000000 +0200
+@@ -8,7 +8,7 @@
+ .\"
+ .\" Created: Sun May 7 00:14:37 1995 ylo
+ .\"
+-.\" $OpenBSD: scp.1,v 1.56 2010/12/09 14:13:32 jmc Exp $
++.\" $OpenBSD$
+ .\"
+ .Dd $Mdocdate: December 9 2010 $
+ .Dt SCP 1
+@@ -123,61 +123,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 IPQoS
+-.It KbdInteractiveDevices
+-.It KexAlgorithms
+-.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.8p1/servconf.c openssh-5.8p1+x509-6.2.4/servconf.c
+--- openssh-5.8p1/servconf.c 2010-11-20 06:19:38.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/servconf.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: servconf.c,v 1.213 2010/11/13 23:27:50 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -35,6 +58,7 @@
+ #include "log.h"
+ #include "buffer.h"
+ #include "servconf.h"
++#include "ssh-xkalg.h"
+ #include "compat.h"
+ #include "pathnames.h"
+ #include "misc.h"
+@@ -139,6 +163,18 @@
+ options->authorized_principals_file = NULL;
+ options->ip_qos_interactive = -1;
+ options->ip_qos_bulk = -1;
++
++ 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
+@@ -282,6 +318,21 @@
+ if (options->ip_qos_bulk == -1)
+ options->ip_qos_bulk = IPTOS_THROUGHPUT;
+
++ /* 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;
+@@ -294,7 +345,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. */
+@@ -328,6 +386,16 @@
+ sZeroKnowledgePasswordAuthentication, sHostCertificate,
+ sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
+ sKexAlgorithms, sIPQoS,
++ sHostbasedAlgorithms,
++ sPubkeyAlgorithms,
++ sX509KeyAlgorithm,
++ sAllowedClientCertPurpose,
++ sKeyAllowSelfIssued, sMandatoryCRL,
++ sCACertificateFile, sCACertificatePath,
++ sCARevocationFile, sCARevocationPath,
++ sCAldapVersion, sCAldapURL,
++ sVAType, sVACertificateFile,
++ sVAOCSPResponderURL,
+ sDeprecated, sUnsupported
+ } ServerOpCodes;
+
+@@ -441,6 +509,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 },
+@@ -1398,6 +1482,142 @@
+ }
+ break;
+
++ 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 : "<NONE>");
++ */
++ 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 : "<NONE>");
++ */
++ 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);
+@@ -1405,6 +1625,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);
+@@ -1511,6 +1748,9 @@
+ M_CP_INTOPT(ip_qos_interactive);
+ M_CP_INTOPT(ip_qos_bulk);
+
++ M_CP_STROPT(hostbased_algorithms);
++ M_CP_STROPT(pubkey_algorithms);
++
+ M_CP_STROPT(banner);
+ if (preauth)
+ return;
+@@ -1590,6 +1830,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";
+@@ -1735,6 +1993,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);
+@@ -1760,6 +2020,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.8p1/servconf.h openssh-5.8p1+x509-6.2.4/servconf.h
+--- openssh-5.8p1/servconf.h 2010-11-20 06:19:38.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/servconf.h 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: servconf.h,v 1.95 2010/11/13 23:27:50 djm Exp $ */
++/* $OpenBSD$ */
+
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+@@ -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. */
+@@ -152,6 +177,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.8p1/sftp.0 openssh-5.8p1+x509-6.2.4/sftp.0
+--- openssh-5.8p1/sftp.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sftp.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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,12 +47,12 @@
+ 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, symlink, and lmkdir. Termination on error can be
+- suppressed on a command by command basis by prefixing the command
+- with a `-' character (for example, -rm /tmp/blah*).
++ lpwd, df, symlink, and lmkdir. Termination on error can be sup-
++ pressed on 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).
+
+@@ -81,59 +81,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
+- IPQoS
+- KbdInteractiveDevices
+- KexAlgorithms
+- 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.
+@@ -149,9 +97,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
+@@ -160,8 +108,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.
+
+@@ -170,7 +118,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.
+
+@@ -178,18 +126,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
+@@ -206,11 +152,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
+@@ -222,18 +168,18 @@
+ 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.
+
+ ln [-s] oldpath newpath
+- Create a link from oldpath to newpath. If the -s flag is
+- specified the created link is a symbolic link, otherwise it is a
+- hard link.
++ Create a link from oldpath to newpath. If the -s flag is speci-
++ fied the created link is a symbolic link, otherwise it is a hard
++ link.
+
+ lpwd Print local working directory.
+
+@@ -247,10 +193,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,
+@@ -258,8 +204,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.
+@@ -282,13 +228,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
+@@ -324,8 +269,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 and 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.9 December 4, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/sftp.1 openssh-5.8p1+x509-6.2.4/sftp.1
+--- openssh-5.8p1/sftp.1 2010-12-05 00:02:48.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sftp.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: sftp.1,v 1.88 2010/12/04 00:18:01 djm Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Copyright (c) 2001 Damien Miller. All rights reserved.
+ .\"
+@@ -173,61 +173,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 IPQoS
+-.It KbdInteractiveDevices
+-.It KexAlgorithms
+-.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.8p1/sftp-server.0 openssh-5.8p1+x509-6.2.4/sftp-server.0
+--- openssh-5.8p1/sftp-server.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sftp-server.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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 and 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.org>
+
+-OpenBSD 4.9 January 9, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh.0 openssh-5.8p1+x509-6.2.4/ssh.0
+--- openssh-5.8p1/ssh.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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.
+
+@@ -138,12 +138,14 @@
+ Selects a file from which the identity (private key) for public
+ key authentication is read. The default is ~/.ssh/identity for
+ protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa and
+- ~/.ssh/id_rsa 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.
++ ~/.ssh/id_rsa 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 -i options (and multiple identities specified in config-
++ uration files). ssh will also try to load certificate informa-
++ tion from the filename obtained by appending -cert.pub to iden-
++ tity filenames.
+
+ -K Enables GSSAPI-based authentication and forwarding (delegation)
+ of GSSAPI credentials to the server.
+@@ -155,27 +157,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 +186,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,78 +208,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
+- IPQoS
+- KbdInteractiveDevices
+- KexAlgorithms
+- 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
+@@ -290,9 +224,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
+@@ -300,49 +234,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)
+@@ -378,9 +311,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).
+
+ AUTHENTICATION
+ The OpenSSH SSH client supports SSH protocols 1 and 2. The default is to
+@@ -392,11 +325,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
+@@ -405,74 +338,80 @@
+ ~/.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
+- one of the DSA, ECDSA or RSA algorithms. Protocol 1 is restricted to
+- using only RSA keys, but protocol 2 may use any. The HISTORY section of
+- ssl(8) contains a brief discussion of the DSA and RSA 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 one of the DSA, ECDSA or RSA algorithms. Protocol 1
++ is restricted to using only RSA keys, but protocol 2 may use any or X.509
++ certificates. The HISTORY section of ssl(8) contains a brief discussion
++ of the DSA and RSA 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), ~/.ssh/id_ecdsa (protocol 2 ECDSA), 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), ~/.ssh/id_ecdsa.pub (protocol 2
+- ECDSA), 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.
++ ECDSA), or ~/.ssh/id_rsa.pub (protocol 2 RSA) in the user's home direc-
++ tory. 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 ~/.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 certificate ``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 +432,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 +476,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 +488,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 +502,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 +553,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 +569,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 +580,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 +617,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 +628,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 +637,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 +651,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 +701,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 (DSA/ECDSA/RSA) 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 (DSA/ECDSA/RSA) 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
+@@ -783,26 +737,29 @@
+ ~/.ssh/id_dsa
+ ~/.ssh/id_ecdsa
+ ~/.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_ecdsa.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,
+@@ -818,6 +775,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).
+@@ -827,18 +802,24 @@
+ /etc/ssh/ssh_host_ecdsa_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. If 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 pur-
++ pose. 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,
+@@ -891,8 +872,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.9 November 18, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh.1 openssh-5.8p1+x509-6.2.4/ssh.1
+--- openssh-5.8p1/ssh.1 2010-11-20 06:21:03.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh.1 2011-02-04 21:06:00.000000000 +0200
+@@ -12,6 +12,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
+@@ -33,7 +34,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.316 2010/11/18 15:01:00 jmc Exp $
++.\" $OpenBSD$
+ .Dd $Mdocdate: November 18 2010 $
+ .Dt SSH 1
+ .Os
+@@ -277,6 +278,8 @@
+ and
+ .Pa ~/.ssh/id_rsa
+ 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,77 +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 IPQoS
+-.It KbdInteractiveDevices
+-.It KexAlgorithms
+-.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
+@@ -695,7 +629,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 ,
+@@ -710,18 +644,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 one of the DSA, ECDSA or RSA algorithms.
+ Protocol 1 is restricted to using only RSA keys,
+-but protocol 2 may use any.
++but protocol 2 may use any or X.509 certificates.
+ The
+ .Sx HISTORY
+ section of
+@@ -730,13 +664,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
+@@ -762,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
+@@ -1058,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.
+@@ -1078,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
+@@ -1086,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
+@@ -1279,7 +1233,7 @@
+ and not accessible by others.
+ .Pp
+ .It Pa ~/.ssh/authorized_keys
+-Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as
++Lists the public keys (DSA/ECDSA/RSA) or certificates that can be used for logging in as
+ this user.
+ The format of this file is described in the
+ .Xr sshd 8
+@@ -1287,6 +1241,18 @@
+ This file is not highly sensitive, but the recommended
+ permissions are read/write for the user, and not accessible by others.
+ .Pp
++.It Pa ~/.ssh/ca/ca-bundle.crt
++.It Pa ~/.ssh/ca/ca-bundle.crl
++Part of user
++.Dq "X.509 store" .
++Same as systemwide files below.
++.Pp
++.It Pa ~/.ssh/ca/crt
++.It Pa ~/.ssh/ca/crl
++Part of user
++.Dq "X.509 store" .
++Same as systemwide directories below.
++.Pp
+ .It Pa ~/.ssh/config
+ This is the per-user configuration file.
+ The file format and configuration options are described in
+@@ -1304,6 +1270,8 @@
+ .It Pa ~/.ssh/id_ecdsa
+ .It Pa ~/.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).
+@@ -1318,11 +1286,13 @@
+ .It Pa ~/.ssh/id_ecdsa.pub
+ .It Pa ~/.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 Pa ~/.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
+@@ -1347,6 +1317,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
+@@ -1358,6 +1350,9 @@
+ .It Pa /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.
+@@ -1372,12 +1367,17 @@
+ By default
+ .Nm
+ is not setuid root.
++If 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 Pa /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
+@@ -1488,3 +1488,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.8p1/ssh-add.0 openssh-5.8p1+x509-6.2.4/ssh-add.0
+--- openssh-5.8p1/ssh-add.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-add.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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 private key identities to the authentication agent
++ ssh-add -- adds private key identities to the authentication agent
+
+ SYNOPSIS
+ ssh-add [-cDdLlXx] [-t life] [file ...]
+@@ -10,28 +10,28 @@
+
+ DESCRIPTION
+ ssh-add adds private key identities to the authentication agent,
+- ssh-agent(1). When run without arguments, it adds the files
++ 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, ~/.ssh/id_ecdsa 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.
++ of the private key file. Alternative file names can be given on the com-
++ mand 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 +45,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 +56,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,7 +85,8 @@
+
+ ~/.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_ecdsa
+ Contains the protocol version 2 ECDSA authentication identity of
+@@ -93,7 +94,8 @@
+
+ ~/.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.
+@@ -108,8 +110,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.9 October 28, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-add.1 openssh-5.8p1+x509-6.2.4/ssh-add.1
+--- openssh-5.8p1/ssh-add.1 2010-11-05 01:20:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-add.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-add.1,v 1.55 2010/10/28 18:33:28 jmc Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Author: Tatu Ylonen <***@cs.hut.fi>
+ .\" Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, Espoo, Finland
+@@ -14,6 +14,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,8 @@
+ .Nm
+ adds private key 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 ,
+@@ -111,8 +114,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
+@@ -164,10 +167,14 @@
+ 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_ecdsa
+ Contains the protocol version 2 ECDSA authentication identity of the user.
+ .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.
+@@ -193,3 +200,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.8p1/ssh-add.c openssh-5.8p1+x509-6.2.4/ssh-add.c
+--- openssh-5.8p1/ssh-add.c 2010-11-11 05:17:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-add.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh-add.c,v 1.100 2010/08/31 12:33:38 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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;
+@@ -286,9 +290,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);
+@@ -376,6 +391,7 @@
+ seed_rng();
+
+ OpenSSL_add_all_algorithms();
++ fill_default_xkalg();
+
+ /* At first, get a connection to the authentication agent. */
+ ac = ssh_get_authentication_connection();
+diff -ruN openssh-5.8p1/ssh-agent.0 openssh-5.8p1+x509-6.2.4/ssh-agent.0
+--- openssh-5.8p1/ssh-agent.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-agent.0 2011-02-04 21:06:00.000000000 +0200
+@@ -1,20 +1,20 @@
+-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, ECDSA). 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 environment variables the agent can be located and
+- automatically used for authentication when logging in to other machines
+- using ssh(1).
++ ssh-agent is a program to hold private keys used for public key authenti-
++ cation (RSA, DSA, ECDSA). It is possible to contain in addition corre-
++ sponding X.509 certificate. 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
++ environment variables the agent can be located and automatically used for
++ authentication when logging in to other machines using ssh(1).
+
+ The options are as follows:
+
+@@ -50,16 +50,17 @@
+ the identity has a 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.
++ 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. ssh-add -l dis-
++ plays the identities 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
+@@ -69,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
+@@ -94,7 +95,8 @@
+
+ ~/.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_ecdsa
+ Contains the protocol version 2 ECDSA authentication identity of
+@@ -102,12 +104,13 @@
+
+ ~/.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.
+
+ $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>
+- 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
+@@ -116,8 +119,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.9 November 21, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-agent.1 openssh-5.8p1+x509-6.2.4/ssh-agent.1
+--- openssh-5.8p1/ssh-agent.1 2010-12-01 02:50:35.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-agent.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-agent.1,v 1.53 2010/11/21 01:01:13 djm Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Author: Tatu Ylonen <***@cs.hut.fi>
+ .\" Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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, ECDSA).
++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
+@@ -124,6 +126,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
+@@ -188,10 +191,14 @@
+ 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_ecdsa
+ Contains the protocol version 2 ECDSA authentication identity of the user.
+ .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 $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
+ .Ux Ns -domain
+ sockets used to contain the connection to the authentication agent.
+@@ -212,3 +219,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.8p1/ssh-agent.c openssh-5.8p1+x509-6.2.4/ssh-agent.c
+--- openssh-5.8p1/ssh-agent.c 2010-12-01 02:50:35.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-agent.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh-agent.c,v 1.171 2010/11/21 01:01:13 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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);
+@@ -497,6 +524,7 @@
+ type = key_type_from_name(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);
+@@ -567,6 +595,7 @@
+ break;
+ #endif /* OPENSSL_HAS_ECC */
+ 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);
+@@ -596,10 +625,29 @@
+ goto send;
+ }
+ xfree(type_name);
++ 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:
+@@ -1152,6 +1200,7 @@
+ #endif
+
+ OpenSSL_add_all_algorithms();
++ fill_default_xkalg();
+
+ __progname = ssh_get_progname(av[0]);
+ init_rng();
+diff -ruN openssh-5.8p1/ssh.c openssh-5.8p1+x509-6.2.4/ssh.c
+--- openssh-5.8p1/ssh.c 2011-02-04 02:42:15.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh.c,v 1.356 2011/01/06 22:23:53 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, Espoo, Finland
+@@ -19,6 +19,9 @@
+ * Modified to work with SSL by Niels Provos <***@citi.umich.edu>
+ * 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:
+@@ -75,6 +78,10 @@
+ #include <openssl/err.h>
+ #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"
+@@ -111,6 +118,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;
+
+@@ -235,6 +245,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
+@@ -600,6 +611,9 @@
+
+ OpenSSL_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.8p1/ssh_config openssh-5.8p1+x509-6.2.4/ssh_config
+--- openssh-5.8p1/ssh_config 2010-01-12 10:40:27.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh_config 2011-02-04 21:06:00.000000000 +0200
+@@ -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-***@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.8p1/ssh_config.0 openssh-5.8p1+x509-6.2.4/ssh_config.0
+--- openssh-5.8p1/ssh_config.0 2011-02-04 03:00:03.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh_config.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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,7 +357,9 @@
+ 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:
++ option depend from X509KeyAlgorithm. It contain first specified
++ X509KeyAlgorithm for RSA key, followed by first specified
++ X509KeyAlgorithm for DSA key, followed by
+
+ ecdsa-sha2-nistp256-cert-***@openssh.com,
+ ecdsa-sha2-nistp384-cert-***@openssh.com,
+@@ -328,19 +374,18 @@
+
+ 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
+@@ -351,23 +396,24 @@
+ ``no''.
+
+ IdentityFile
+- Specifies a file from which the user's DSA, ECDSA or DSA
+- authentication identity is read. The default is ~/.ssh/identity
+- for protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa and
+- ~/.ssh/id_rsa 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.
++ Specifies a file from which the user's DSA, ECDSA or DSA authen-
++ tication identity is read. The default is ~/.ssh/identity for
++ protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa and
++ ~/.ssh/id_rsa 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. 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.
+
+ IPQoS Specifies the IPv4 type-of-service or DSCP class for connections.
+ Accepted values are ``af11'', ``af12'', ``af13'', ``af14'',
+@@ -375,9 +421,9 @@
+ ``af42'', ``af43'', ``cs0'', ``cs1'', ``cs2'', ``cs3'', ``cs4'',
+ ``cs5'', ``cs6'', ``cs7'', ``ef'', ``lowdelay'', ``throughput'',
+ ``reliability'', or a numeric value. This option may take one or
+- two arguments, separated by whitespace. If one argument is
+- specified, it is used as the packet class unconditionally. If
+- two values are specified, the first is automatically selected for
++ two arguments, separated by whitespace. If one argument is spec-
++ ified, it is used as the packet class unconditionally. If two
++ values are specified, the first is automatically selected for
+ interactive sessions and the second for non-interactive sessions.
+ The default is ``lowdelay'' for interactive sessions and
+ ``throughput'' for non-interactive sessions.
+@@ -406,14 +452,14 @@
+ diffie-hellman-group1-sha1
+
+ 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
+@@ -429,38 +475,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-***@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
+@@ -478,9 +528,8 @@
+
+ PKCS11Provider
+ Specifies which PKCS#11 provider to use. The argument to this
+- keyword is the PKCS#11 shared library ssh(1) should use to
+- communicate with a PKCS#11 token providing the user's private RSA
+- key.
++ keyword is the PKCS#11 shared library 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.
+@@ -496,25 +545,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
+@@ -522,6 +571,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
+@@ -529,10 +588,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
+@@ -545,15 +604,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
+@@ -564,9 +622,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
+@@ -574,8 +632,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.
+
+@@ -588,11 +646,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
+@@ -609,27 +667,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
+@@ -654,32 +712,77 @@
+ 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).
+
+@@ -691,16 +794,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
+
+@@ -711,7 +832,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:
+
+@@ -722,8 +843,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
+@@ -737,8 +858,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.9 December 8, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh_config.5 openssh-5.8p1+x509-6.2.4/ssh_config.5
+--- openssh-5.8p1/ssh_config.5 2010-12-26 05:26:48.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh_config.5 2011-02-04 21:06:00.000000000 +0200
+@@ -12,6 +12,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
+@@ -33,7 +34,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.146 2010/12/08 04:02:47 djm Exp $
++.\" $OpenBSD$
+ .Dd $Mdocdate: December 8 2010 $
+ .Dt SSH_CONFIG 5
+ .Os
+@@ -123,6 +124,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 ,
+@@ -143,6 +158,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
+@@ -545,7 +614,11 @@
+ .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:
++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
+ .Bd -literal -offset 3n
+ ecdsa-sha2-nistp256-cert-***@openssh.com,
+ ecdsa-sha2-nistp384-cert-***@openssh.com,
+@@ -603,6 +676,8 @@
+ and
+ .Pa ~/.ssh/id_rsa
+ 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
+@@ -772,6 +847,15 @@
+ hmac-md5,hmac-sha1,umac-***@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
+@@ -882,6 +966,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
+@@ -1136,12 +1239,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 ,
+@@ -1180,6 +1370,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
+@@ -1248,3 +1480,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.8p1/sshconnect2.c openssh-5.8p1+x509-6.2.4/sshconnect2.c
+--- openssh-5.8p1/sshconnect2.c 2010-12-01 03:21:51.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshconnect2.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,6 +1,7 @@
+-/* $OpenBSD: sshconnect2.c,v 1.186 2010/11/29 23:45:51 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
+@@ -1187,6 +1188,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);
+@@ -1365,6 +1367,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;
+@@ -1444,11 +1447,81 @@
+ }
+ }
+
++/* TODO: to improve for ECC keys
++ * Now method is used only to failback from KEY_X509_RSA/KEY_DSA_CERT to
++ * KEY_RSA/KEY_DSA if loaded identity is a certificate and its corresponding
++ * name is not listed in PubkeyAlgorithms.
++ */
++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_ECDSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
++ case KEY_RSA_CERT:
++ case KEY_DSA_CERT:
++ case KEY_ECDSA_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++)
+@@ -1462,14 +1535,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.8p1/sshconnect.c openssh-5.8p1+x509-6.2.4/sshconnect.c
+--- openssh-5.8p1/sshconnect.c 2011-01-16 14:17:59.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshconnect.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: sshconnect.c,v 1.232 2011/01/16 11:50:36 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -57,6 +80,7 @@
+ #include "readconf.h"
+ #include "atomicio.h"
+ #include "misc.h"
++#include "ssh-x509.h"
+ #include "dns.h"
+ #include "roaming.h"
+ #include "ssh2.h"
+@@ -705,6 +729,7 @@
+ int len, cancelled_forwarding = 0;
+ struct hostkeys *host_hostkeys, *ip_hostkeys;
+ const struct hostkey_entry *host_found, *ip_found;
++ char extramsg[1024], *subject = NULL;
+
+ /*
+ * Force accepting of the host key for loopback/localhost. The
+@@ -852,16 +877,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))
+@@ -933,7 +972,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)
+@@ -1122,9 +1161,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);
+ }
+ }
+ }
+@@ -1204,7 +1249,7 @@
+ static int
+ show_other_keys(struct hostkeys *hostkeys, Key *key)
+ {
+- int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, -1};
++ int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_X509_RSA, KEY_X509_DSA, -1};
+ int i, ret = 0;
+ char *fp, *ra;
+ const struct hostkey_entry *found;
+@@ -1246,6 +1291,11 @@
+ error("It is also possible that a host key has just been changed.");
+ error("The fingerprint for the %s key sent by the remote host is\n%s.",
+ key_type(host_key), 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.8p1/sshd.0 openssh-5.8p1+x509-6.2.4/sshd.0
+--- openssh-5.8p1/sshd.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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
+@@ -80,8 +80,10 @@
+ /etc/ssh/ssh_host_key for protocol version 1, and
+ /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_ecdsa_key and
+ /etc/ssh/ssh_host_rsa_key for protocol version 2. It is possible
+- to have multiple host key files for the different protocol
+- versions and host key algorithms.
++ to have multiple host key files for the different protocol ver-
++ sions and host key algorithms. It is possible host key for pro-
++ tocol version 2 to contain private key followed by X.509 certifi-
++ cate 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 +94,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 +120,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 +130,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 ***@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 ***@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 DSA, ECDSA and RSA 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 DSA, ECDSA, RSA 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 certifi-
++ cate 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 +199,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 +234,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,22 +264,33 @@
+ 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 ``ecdsa-sha2-nistp256'', ``ecdsa-sha2-nistp384'',
+- ``ecdsa-sha2-nistp521'', ``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 ``ecdsa-sha2-nistp256'',
++ ``ecdsa-sha2-nistp384'', ``ecdsa-sha2-nistp521'', ``ssh-dss'' or
++ ``ssh-rsa''. In addition for protocol version 2 user can use X.509 cer-
++ tificates. 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 Sub-
++ ject 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, id_ecdsa.pub, or the id_rsa.pub file and edit
+ it.
+@@ -286,15 +298,15 @@
+ 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
+@@ -304,19 +316,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
+@@ -332,9 +344,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
+@@ -363,25 +375,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:
+
+@@ -393,15 +405,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...==
+ ***@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
+@@ -413,26 +427,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
+@@ -444,30 +458,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.....=
+@@ -486,12 +500,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
+@@ -499,14 +512,15 @@
+ 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 (DSA/ECDSA/RSA) that can be used for
++ Lists the public keys (DSA/ECDSA/RSA), certificates or certifi-
++ cates ``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
+@@ -521,17 +535,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
+@@ -565,14 +579,32 @@
+ 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_ecdsa_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 four 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
+@@ -580,21 +612,23 @@
+ /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
+@@ -611,8 +645,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),
+@@ -622,13 +656,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.9 October 28, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/sshd.8 openssh-5.8p1+x509-6.2.4/sshd.8
+--- openssh-5.8p1/sshd.8 2010-11-05 01:20:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd.8 2011-02-04 21:06:00.000000000 +0200
+@@ -12,6 +12,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
+@@ -33,7 +34,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.260 2010/10/28 18:33:28 jmc Exp $
++.\" $OpenBSD$
+ .Dd $Mdocdate: October 28 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 DSA, ECDSA and RSA keys;
++Protocol 2 supports DSA, ECDSA, RSA 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 #
+@@ -489,6 +496,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
+@@ -634,6 +672,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...==
+ ***@example.net
+ .Ed
+@@ -642,7 +681,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,
+@@ -745,6 +786,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.....=
+@@ -796,7 +838,10 @@
+ and not accessible by others.
+ .Pp
+ .It Pa ~/.ssh/authorized_keys
+-Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in
++Lists the public keys (DSA/ECDSA/RSA), 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
+@@ -827,7 +872,7 @@
+ option.
+ .Pp
+ .It Pa ~/.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
+@@ -874,11 +919,32 @@
+ but allows host-based authentication without permitting login with
+ rlogin/rsh.
+ .Pp
++.It Pa /etc/ssh/ca/ca-bundle.crt
++.It Pa /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 Pa /etc/ssh/ca/crt
++.It Pa /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 Pa /etc/ssh/ssh_host_key
+ .It Pa /etc/ssh/ssh_host_dsa_key
+ .It Pa /etc/ssh/ssh_host_ecdsa_key
+ .It Pa /etc/ssh/ssh_host_rsa_key
+-These three files contain the private parts of the host keys.
++These four 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
+@@ -893,6 +959,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.
+@@ -902,7 +970,7 @@
+ .It Pa /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
+@@ -963,6 +1031,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.8p1/sshd.c openssh-5.8p1+x509-6.2.4/sshd.c
+--- openssh-5.8p1/sshd.c 2011-01-11 08:20:31.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: sshd.c,v 1.381 2011/01/11 06:13:10 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, 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 <tcpd.h>
+@@ -139,6 +143,9 @@
+
+ extern char *__progname;
+
++/* ssh-x509.c needs this */
++extern int (*pssh_x509cert_check)(X509 *cert);
++
+ /* Server configuration options. */
+ ServerOptions options;
+
+@@ -739,6 +746,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];
+@@ -1307,6 +1318,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;
+@@ -1580,6 +1592,8 @@
+ case KEY_RSA:
+ case KEY_DSA:
+ case KEY_ECDSA:
++ case KEY_X509_RSA:
++ case KEY_X509_DSA:
+ sensitive_data.have_ssh2_key = 1;
+ break;
+ }
+diff -ruN openssh-5.8p1/sshd_config openssh-5.8p1+x509-6.2.4/sshd_config
+--- openssh-5.8p1/sshd_config 2010-09-10 04:20:12.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/sshd_config 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-# $OpenBSD: sshd_config,v 1.82 2010/09/06 17:10:19 naddy Exp $
++# $OpenBSD$
+
+ # This is the sshd server system-wide configuration file. See
+ # sshd_config(5) for more information.
+@@ -25,6 +25,72 @@
+ #HostKey /etc/ssh/ssh_host_dsa_key
+ #HostKey /etc/ssh/ssh_host_ecdsa_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.8p1/sshd_config.0 openssh-5.8p1+x509-6.2.4/sshd_config.0
+--- openssh-5.8p1/sshd_config.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd_config.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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 ***@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 ***@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,9 +320,9 @@
+ ``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
+@@ -274,10 +330,12 @@
+ default is /etc/ssh/ssh_host_key for protocol version 1, and
+ /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_ecdsa_key and
+ /etc/ssh/ssh_host_rsa_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 host key files.
+- ``rsa1'' keys are used for version 1 and ``dsa'', ``ecdsa'' or
+- ``rsa'' are used for version 2 of the SSH protocol.
++ sshd(8) will refuse to use a file if it is group/world-accessi-
++ ble. It is possible to have multiple host key files. ``rsa1''
++ keys are used for version 1 and ``dsa'', ``ecdsa'' or ``rsa'' are
++ used for version 2 of the SSH protocol. For version 2 is possi-
++ ble 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
+@@ -291,19 +349,18 @@
+ ~/.ssh/known_hosts during RhostsRSAAuthentication or
+ HostbasedAuthentication. The default is ``no''.
+
+- IPQoS Specifies the IPv4 type-of-service or DSCP class for the
+- connection. Accepted values are ``af11'', ``af12'', ``af13'',
++ IPQoS Specifies the IPv4 type-of-service or DSCP class for the connec-
++ tion. Accepted values are ``af11'', ``af12'', ``af13'',
+ ``af14'', ``af22'', ``af23'', ``af31'', ``af32'', ``af33'',
+ ``af41'', ``af42'', ``af43'', ``cs0'', ``cs1'', ``cs2'', ``cs3'',
+ ``cs4'', ``cs5'', ``cs6'', ``cs7'', ``ef'', ``lowdelay'',
+ ``throughput'', ``reliability'', or a numeric value. This option
+ may take one or two arguments, separated by whitespace. If one
+- argument is specified, it is used as the packet class
+- unconditionally. If two values are specified, the first is
+- automatically selected for interactive sessions and the second
+- for non-interactive sessions. The default is ``lowdelay'' for
+- interactive sessions and ``throughput'' for non-interactive
+- sessions.
++ argument is specified, it is used as the packet class uncondi-
++ tionally. If two values are specified, the first is automati-
++ cally selected for interactive sessions and the second for non-
++ interactive sessions. The default is ``lowdelay'' for interac-
++ tive sessions and ``throughput'' for non-interactive sessions.
+
+ KerberosAuthentication
+ Specifies whether the password provided by the user for
+@@ -318,9 +375,9 @@
+ 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
+@@ -334,17 +391,32 @@
+ ``diffie-hellman-group-exchange-sha1'',
+ ``diffie-hellman-group14-sha1'', ``diffie-hellman-group1-sha1''.
+
++ 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
+@@ -357,9 +429,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
+@@ -369,14 +441,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-***@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,
+@@ -400,13 +477,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
+@@ -414,12 +492,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.
+
+@@ -441,26 +519,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
+
+- 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
+@@ -471,21 +549,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
+@@ -503,11 +581,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
+@@ -568,11 +654,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
+@@ -582,25 +668,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.
+@@ -623,10 +709,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
+@@ -639,16 +747,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
+@@ -663,19 +771,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:
+
+ <none> seconds
+ s | S seconds
+@@ -693,11 +819,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)
+@@ -705,9 +844,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.9 December 8, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/sshd_config.5 openssh-5.8p1+x509-6.2.4/sshd_config.5
+--- openssh-5.8p1/sshd_config.5 2010-12-26 05:26:48.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/sshd_config.5 2011-02-04 21:06:00.000000000 +0200
+@@ -12,6 +12,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
+@@ -33,7 +34,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.131 2010/12/08 04:02:47 djm Exp $
++.\" $OpenBSD$
+ .Dd $Mdocdate: December 8 2010 $
+ .Dt SSHD_CONFIG 5
+ .Os
+@@ -103,6 +104,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.
+@@ -219,6 +234,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
+@@ -429,6 +498,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
+@@ -485,6 +564,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
+@@ -585,6 +666,28 @@
+ .Dq diffie-hellman-group-exchange-sha1 ,
+ .Dq diffie-hellman-group14-sha1 ,
+ .Dq diffie-hellman-group1-sha1 .
++.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).
+@@ -656,6 +759,15 @@
+ hmac-md5,hmac-sha1,umac-***@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
+@@ -709,6 +821,7 @@
+ .Cm ForceCommand ,
+ .Cm GatewayPorts ,
+ .Cm GSSAPIAuthentication ,
++.Cm HostbasedAlgorithms ,
+ .Cm HostbasedAuthentication ,
+ .Cm HostbasedUsesNameFromPacketOnly ,
+ .Cm KbdInteractiveAuthentication ,
+@@ -720,6 +833,7 @@
+ .Cm PermitOpen ,
+ .Cm PermitRootLogin ,
+ .Cm PermitTunnel ,
++.Cm PubkeyAlgorithms ,
+ .Cm PubkeyAuthentication ,
+ .Cm RhostsRSAAuthentication ,
+ .Cm RSAAuthentication ,
+@@ -907,6 +1021,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
+@@ -1070,6 +1194,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
+@@ -1135,6 +1304,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
+@@ -1183,6 +1394,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
+@@ -1204,3 +1452,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.8p1/ssh-keygen.0 openssh-5.8p1+x509-6.2.4/ssh-keygen.0
+--- openssh-5.8p1/ssh-keygen.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keygen.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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]
+@@ -29,8 +29,8 @@
+ ssh-keygen generates, manages and converts authentication keys for
+ ssh(1). ssh-keygen can create RSA keys for use by SSH protocol version 1
+ and DSA, ECDSA or RSA keys for use by SSH protocol version 2. The type
+- of key to be generated is specified with the -t option. If invoked
+- without any arguments, ssh-keygen will generate an RSA key for use in SSH
++ of key to be generated is specified with the -t option. If invoked with-
++ out any arguments, ssh-keygen will generate an RSA key for use in SSH
+ protocol 2 connections.
+
+ ssh-keygen is also used to generate groups for use in Diffie-Hellman
+@@ -38,9 +38,8 @@
+
+ Normally each user wishing to use SSH with public key authentication runs
+ this once to create the authentication key in ~/.ssh/identity,
+- ~/.ssh/id_ecdsa, ~/.ssh/id_dsa or ~/.ssh/id_rsa. Additionally, the
+- system administrator may use this to generate host keys, as seen in
+- /etc/rc.
++ ~/.ssh/id_ecdsa, ~/.ssh/id_dsa or ~/.ssh/id_rsa. Additionally, the sys-
++ tem administrator may use this to generate host keys, as seen in /etc/rc.
+
+ Normally this program generates the key and asks for a file in which to
+ store the private key. The public key is stored in a file with the same
+@@ -48,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.
+
+@@ -62,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 ``***@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 ``***@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.
+@@ -80,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
+@@ -101,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
+@@ -146,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
+@@ -176,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
+@@ -217,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.
+
+@@ -240,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
+@@ -260,10 +261,10 @@
+ for protocol 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
+@@ -280,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-
+@@ -300,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:
+@@ -309,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
+@@ -339,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
+@@ -352,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
+
+@@ -363,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,8 +398,8 @@
+ key. ssh(1) will read this file when a login attempt 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.
+@@ -407,13 +408,15 @@
+ ~/.ssh/id_ecdsa
+ ~/.ssh/id_rsa
+ Contains the protocol version 2 DSA, ECDSA or 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.
++ identity of the user. In case of DSA or RSA identity it is pos-
++ sible 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 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
+ ~/.ssh/id_ecdsa.pub
+@@ -422,7 +425,14 @@
+ authentication. 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. If file ~/.ssh/id_dsa contain
++ DSA private key followed by X.509 certificate or ~/.ssh/id_rsa
++ contain 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
+@@ -436,8 +446,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.9 October 28, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-keygen.1 openssh-5.8p1+x509-6.2.4/ssh-keygen.1
+--- openssh-5.8p1/ssh-keygen.1 2010-11-05 01:20:14.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keygen.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-keygen.1,v 1.101 2010/10/28 18:33:28 jmc Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Author: Tatu Ylonen <***@cs.hut.fi>
+ .\" Copyright (c) 1995 Tatu Ylonen <***@cs.hut.fi>, Espoo, Finland
+@@ -14,6 +14,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
+@@ -294,6 +295,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.
+@@ -409,6 +411,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
+@@ -630,6 +633,8 @@
+ .It Pa ~/.ssh/id_ecdsa
+ .It Pa ~/.ssh/id_rsa
+ Contains the protocol version 2 DSA, ECDSA or RSA authentication identity of the user.
++In case of DSA or RSA identity 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
+@@ -649,6 +654,25 @@
+ 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.
++If file
++.Pa ~/.ssh/id_dsa
++contain DSA private key followed by X.509 certificate or
++.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 .
+ .Pp
+ .It Pa /etc/moduli
+ Contains Diffie-Hellman groups used for DH-GEX.
+@@ -675,3 +699,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.8p1/ssh-keygen.c openssh-5.8p1+x509-6.2.4/ssh-keygen.c
+--- openssh-5.8p1/ssh-keygen.c 2011-01-11 08:20:31.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keygen.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh-keygen.c,v 1.205 2011/01/11 06:13:10 djm Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Author: Tatu Ylonen <***@cs.hut.fi>
+ * Copyright (c) 1994 Tatu Ylonen <***@cs.hut.fi>, 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"
+@@ -1815,6 +1839,7 @@
+ __progname = ssh_get_progname(argv[0]);
+
+ OpenSSL_add_all_algorithms();
++ fill_default_xkalg();
+ log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
+
+ init_rng();
+diff -ruN openssh-5.8p1/ssh-keyscan.0 openssh-5.8p1+x509-6.2.4/ssh-keyscan.0
+--- openssh-5.8p1/ssh-keyscan.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keyscan.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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
+- ``dsa'', ``ecdsa'' or ``rsa'' for protocol version 2. Multiple
+- values may be specified by separating them with commas. The
+- default is ``rsa''.
++ ``x509v3-sign-rsa'', ``x509v3-sign-dss'', ``dsa'', ``ecdsa'' or
++ ``rsa'' for protocol version 2. Multiple values may be specified
++ by separating them with commas. The default are keys for proto-
++ col version 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:
+@@ -79,6 +79,12 @@
+ Where keytype is either ``ecdsa-sha2-nistp256'', ``ecdsa-sha2-nistp384'',
+ ``ecdsa-sha2-nistp521'', ``ssh-dss'' or ``ssh-rsa''.
+
++ 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
+@@ -89,7 +95,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,ecdsa -f ssh_hosts | \
++ $ ssh-keyscan -t x509v3-sign-rsa,x509v3-sign-dss,rsa,dsa,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521 -f ssh_hosts | \
+ sort -u - ssh_known_hosts | diff ssh_known_hosts -
+
+ SEE ALSO
+@@ -98,7 +104,7 @@
+ AUTHORS
+ David Mazieres <***@lcs.mit.edu> wrote the initial version, and Wayne
+ Davison <***@users.sourceforge.net> 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
+@@ -106,4 +112,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.9 August 31, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-keyscan.1 openssh-5.8p1+x509-6.2.4/ssh-keyscan.1
+--- openssh-5.8p1/ssh-keyscan.1 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/ssh-keyscan.1 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-keyscan.1,v 1.29 2010/08/31 11:54:45 djm Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Copyright 1995, 1996 by David Mazieres <***@lcs.mit.edu>.
+ .\"
+@@ -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: August 31 2010 $
+ .Dt SSH-KEYSCAN 1
+ .Os
+@@ -88,14 +111,15 @@
+ The possible values are
+ .Dq rsa1
+ for protocol version 1 and
++.Dq x509v3-sign-rsa ,
++.Dq x509v3-sign-dss ,
+ .Dq dsa ,
+ .Dq ecdsa
+ or
+ .Dq rsa
+ 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
+@@ -138,6 +162,18 @@
+ or
+ .Dq ssh-rsa .
+ .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
+@@ -153,7 +189,7 @@
+ which have new or different keys from those in the sorted file
+ .Pa ssh_known_hosts :
+ .Bd -literal
+-$ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \e
++$ ssh-keyscan -t x509v3-sign-rsa,x509v3-sign-dss,rsa,dsa,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521 -f ssh_hosts | \e
+ sort -u - ssh_known_hosts | diff ssh_known_hosts -
+ .Ed
+ .Sh SEE ALSO
+@@ -165,6 +201,7 @@
+ wrote the initial version, and
+ .An Wayne Davison Aq ***@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.8p1/ssh-keyscan.c openssh-5.8p1+x509-6.2.4/ssh-keyscan.c
+--- openssh-5.8p1/ssh-keyscan.c 2011-01-06 13:44:45.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keyscan.c 2011-02-04 21:06:01.000000000 +0200
+@@ -1,10 +1,33 @@
+-/* $OpenBSD: ssh-keyscan.c,v 1.84 2011/01/04 20:44:13 otto Exp $ */
++/* $OpenBSD$ */
+ /*
+ * Copyright 1995, 1996 by David Mazieres <***@lcs.mit.edu>.
+ *
+ * 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,12 +77,7 @@
+
+ int ssh_port = SSH_DEFAULT_PORT;
+
+-#define KT_RSA1 1
+-#define KT_DSA 2
+-#define KT_RSA 4
+-#define KT_ECDSA 8
+-
+-int get_keytypes = KT_RSA; /* Get only RSA keys by default */
++char* get_keynames = NULL;
+
+ int hash_hosts = 0; /* Hash hostname on output */
+
+@@ -91,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 */
+@@ -171,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;
+
+@@ -245,9 +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" : (c->c_keytype == KT_RSA ? "ssh-rsa" :
+- "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521");
++ 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;
+@@ -266,7 +284,6 @@
+ xfree(c->c_kex);
+ c->c_kex = NULL;
+ packet_close();
+-
+ return j < 0? NULL : kexjmp_key;
+ }
+
+@@ -281,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);
+ }
+
+@@ -319,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;
+@@ -348,7 +374,12 @@
+ 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));
++ k->ecdsa_nid = key_ecdsa_nid_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);
+@@ -368,7 +399,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--;
+@@ -389,7 +420,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);
+ }
+@@ -402,6 +433,7 @@
+ char remote_version[sizeof buf];
+ size_t bufsiz;
+ con *c = &fdcon[s];
++ int rsa1key;
+
+ for (;;) {
+ memset(buf, '\0', sizeof(buf));
+@@ -441,7 +473,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);
+@@ -452,10 +485,10 @@
+ confree(s);
+ return;
+ }
+- fprintf(stderr, "# %s %s\n", c->c_name, chop(buf));
++ fprintf(stderr, "# %s (%s) %s\n", c->c_name, fdcon[s].c_keyname, 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);
+@@ -466,7 +499,7 @@
+ confree(s);
+ return;
+ }
+- if (c->c_keytype != KT_RSA1) {
++ if (!rsa1key) {
+ keyprint(c, keygrab_ssh2(c));
+ confree(s);
+ return;
+@@ -570,16 +603,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_ECDSA; 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);
+ }
+ }
+
+@@ -630,6 +665,12 @@
+ if (argc <= 1)
+ usage();
+
++ fill_default_xkalg();
++ get_keynames = xstrdup("x509v3-sign-dss,x509v3-sign-rsa,ssh-rsa,ssh-dss"
++#ifdef OPENSSL_HAS_ECC
++/*",ecdsa"*/",ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"
++#endif
++); /* Get all protocol v2 keys by default */
+ while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) {
+ switch (opt) {
+ case 'H':
+@@ -665,26 +706,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_ECDSA:
+- get_keytypes |= KT_ECDSA;
+- 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.8p1/ssh-keysign.0 openssh-5.8p1+x509-6.2.4/ssh-keysign.0
+--- openssh-5.8p1/ssh-keysign.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-keysign.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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
+@@ -30,14 +30,15 @@
+ 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_ecdsa_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)
+@@ -48,4 +49,4 @@
+ AUTHORS
+ Markus Friedl <***@openbsd.org>
+
+-OpenBSD 4.9 August 31, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-keysign.8 openssh-5.8p1+x509-6.2.4/ssh-keysign.8
+--- openssh-5.8p1/ssh-keysign.8 2010-08-31 15:41:14.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/ssh-keysign.8 2011-02-04 21:06:00.000000000 +0200
+@@ -1,4 +1,4 @@
+-.\" $OpenBSD: ssh-keysign.8,v 1.12 2010/08/31 11:54:45 djm Exp $
++.\" $OpenBSD$
+ .\"
+ .\" Copyright (c) 2002 Markus Friedl. All rights reserved.
+ .\"
+@@ -71,6 +71,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.
+ .Pp
+ .It Pa /etc/ssh/ssh_host_dsa_key-cert.pub
+ .It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub
+diff -ruN openssh-5.8p1/ssh-ocsp.c openssh-5.8p1+x509-6.2.4/ssh-ocsp.c
+--- openssh-5.8p1/ssh-ocsp.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <string.h>
++
++#include "xmalloc.h"
++#include "log.h"
++#include <openssl/err.h>
++#include <openssl/pem.h>
++#include <openssl/ocsp.h>
++#ifdef SSH_WITH_SSLOCSP
++# include <openssl/ssl.h>
++#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 <NULL> 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.8p1/ssh-pkcs11-helper.0 openssh-5.8p1+x509-6.2.4/ssh-pkcs11-helper.0
+--- openssh-5.8p1/ssh-pkcs11-helper.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-pkcs11-helper.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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.org>
+
+-OpenBSD 4.9 February 10, 2010 OpenBSD 4.9
++BSD February 4, 2011 BSD
+diff -ruN openssh-5.8p1/ssh-rand-helper.0 openssh-5.8p1+x509-6.2.4/ssh-rand-helper.0
+--- openssh-5.8p1/ssh-rand-helper.0 2011-02-04 03:00:02.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-rand-helper.0 2011-02-04 21:06:00.000000000 +0200
+@@ -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.9 April 14, 2002 OpenBSD 4.9
++BSD April 14, 2002 BSD
+diff -ruN openssh-5.8p1/ssh-x509.c openssh-5.8p1+x509-6.2.4/ssh-x509.c
+--- openssh-5.8p1/ssh-x509.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-x509.c 2011-01-08 22:23:21.000000000 +0200
+@@ -0,0 +1,1213 @@
++/*
++ * 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 <ctype.h>
++#include <string.h>
++
++#include "ssh-xkalg.h"
++#include "log.h"
++#include <openssl/err.h>
++#include "xmalloc.h"
++#include "uuencode.h"
++#include <openssl/pem.h>
++#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[,<more_name_options>]
++ v0.9.6
++$ openssl x509 -in cert_file -subject -noout -nameopt oneline [-nameopt <other_name_option>]
++*/
++ 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*
++#ifdef OPENSSH_KEYS_USE_BIO
++x509key_parse_cert(Key *key, BIO *bio) {
++#else
++x509key_load_cert(Key *key, FILE *fp) {
++#endif
++ if (key == NULL) return(NULL);
++
++ if ( (key->type == KEY_RSA) ||
++ (key->type == KEY_DSA) ) {
++#ifdef OPENSSH_KEYS_USE_BIO
++ key->x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
++#else
++ key->x509 = PEM_read_X509(fp, NULL, NULL, NULL);
++#endif
++ if (key->x509 == NULL) {
++ char ebuf[256];
++ debug3("%s: PEM_read_X509 fail %.*s",
++ __func__, 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
++#ifdef OPENSSH_KEYS_USE_BIO
++x509key_write_bio_cert(BIO *out, X509 *x509) {
++#else
++x509key_save_cert(FILE *fp, X509 *x509) {
++#endif
++ int ret = 0;
++#ifndef OPENSSH_KEYS_USE_BIO
++ 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
++#endif /*ndef OPENSSH_KEYS_USE_BIO*/
++
++ 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 = "<No Alias>";
++ BIO_puts(out, alstr);
++ BIO_puts(out, "\n");
++ }
++
++ ret = PEM_write_bio_X509(out, x509);
++ if (!ret) {
++ char ebuf[256];
++ error("%s: PEM_write_bio_X509 fail %.*s",
++ __func__, sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf)));
++ }
++
++#ifndef OPENSSH_KEYS_USE_BIO
++ BIO_free_all(out);
++#endif /*ndef OPENSSH_KEYS_USE_BIO*/
++ return(ret);
++}
++
++
++int
++#ifdef OPENSSH_KEYS_USE_BIO
++x509key_write_bio_pem(
++ BIO *bio,
++#else
++x509key_save_pem(
++ FILE *fp,
++#endif
++ 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:
++#ifdef OPENSSH_KEYS_USE_BIO
++ if (PEM_write_bio_DSAPrivateKey(bio, key->dsa, cipher, passphrase, len, NULL, NULL))
++ return(x509key_write_bio_cert(bio, key->x509));
++#else
++ if (PEM_write_DSAPrivateKey(fp, key->dsa, cipher, passphrase, len, NULL, NULL))
++ return(x509key_save_cert(fp, key->x509));
++#endif
++ break;
++ case KEY_X509_RSA:
++#ifdef OPENSSH_KEYS_USE_BIO
++ if (PEM_write_bio_RSAPrivateKey(bio, key->rsa, cipher, passphrase, len, NULL, NULL))
++ return(x509key_write_bio_cert(bio, key->x509));
++#else
++ if (PEM_write_RSAPrivateKey(fp, key->rsa, cipher, passphrase, len, NULL, NULL))
++ return(x509key_save_cert(fp, key->x509));
++#endif
++ 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.8p1/ssh-x509.h openssh-5.8p1+x509-6.2.4/ssh-x509.h
+--- openssh-5.8p1/ssh-x509.h 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/ssh-x509.h 2011-01-08 22:23:21.000000000 +0200
+@@ -0,0 +1,86 @@
++#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*/
++
++/*
++ * The patched configure script define OPENSSH_KEYS_USE_BIO
++ * depending from OpenSSH version
++ */
++
++#ifdef OPENSSH_KEYS_USE_BIO
++Key* x509key_parse_cert(Key *key, BIO *bio);
++#else
++Key* x509key_load_cert(Key *key, FILE *fp);
++#endif
++
++#ifdef OPENSSH_KEYS_USE_BIO
++int x509key_write_bio_pem(BIO *bio, const Key *key, const EVP_CIPHER *cipher, u_char *passphrase, int len);
++#else
++int x509key_save_pem(FILE *fp, const Key *key, const EVP_CIPHER *cipher, u_char *passphrase, int len);
++#endif
++
++#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.8p1/ssh-xkalg.c openssh-5.8p1+x509-6.2.4/ssh-xkalg.c
+--- openssh-5.8p1/ssh-xkalg.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <string.h>
++
++#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.8p1/ssh-xkalg.h openssh-5.8p1+x509-6.2.4/ssh-xkalg.h
+--- openssh-5.8p1/ssh-xkalg.h 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <openssl/evp.h>
++#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.8p1/tests/CA/1-cre_cadb.sh openssh-5.8p1+x509-6.2.4/tests/CA/1-cre_cadb.sh
+--- openssh-5.8p1/tests/CA/1-cre_cadb.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <<EOF
++# Where everything is kept:
++dir = ${SSH_CAROOT}
++
++certs = \$dir/crt # Where the issued certs are kept
++crl_dir = \$dir/crl # Where the issued crl are kept
++database = \$dir/index-$1.txt # database index file.
++new_certs_dir = \$dir/newcerts # default place for new certs.
++serial = \$dir/serial # The current serial number
++
++#x509_extensions = usr_cert # The default extentions to add to the cert
++default_days = ${SSH_CACERTDAYS} # how long to certify for
++default_crl_days= 30 # how long before next CRL
++policy = policy_match
++
++# print options (internal use)
++name_opt = oneline,-space_eq,-esc_msb # print fine UTF-8
++cert_opt = compatible
++
++EOF
++}
++
++
++# ===
++# args:
++# none
++echo_CA_ocsp_options () {
++if test "x$SSH_OCSP" = "xyes"; then
++cat << EOF
++
++# OCSP Validator(Responder) URI
++# Since OpenSSL OCSP responder support only one issuer certificate
++# we should setup for the test cases many responders - each certificate
++# type with responder on different port.
++EOF
++ printf "authorityInfoAccess = "
++(
++ port=${SSH_VA_BASEPORT}
++ for DIGEST in ${RSA_DIGEST_LIST}; do
++ printf "OCSP;URI:http://${SSHD_LISTENADDRESS}:${port},"
++ port=`expr ${port} + 1`
++ done
++ printf "OCSP;URI:http://${SSHD_LISTENADDRESS}:${port}"
++)
++fi
++}
++
++
++# ===
++cre_config () {
++cat << EOF > "$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.8p1/tests/CA/2-cre_cakeys.sh openssh-5.8p1+x509-6.2.4/tests/CA/2-cre_cakeys.sh
+--- openssh-5.8p1/tests/CA/2-cre_cakeys.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <<EOF
++$SSH_DN_C
++$SSH_DN_ST
++$SSH_DN_L
++$SSH_DN_O
++$SSH_DN_OU
++$SSH_DN_OU $1 keys
++.
++OpenSSH Test $1 CA key
++.
++EOF
++}
++
++
++# ===
++gen_rsa () {
++RSA_OPT="-des3"
++if [ -f /etc/random-seed ]; then
++ RSA_OPT="${RSA_OPT} -rand /etc/random-seed"
++fi
++
++rm -f "${TMPDIR}/${CAKEY_PREFIX}-rsa.key" 2>/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.8p1/tests/CA/3-cre_certs.sh openssh-5.8p1+x509-6.2.4/tests/CA/3-cre_certs.sh
+--- openssh-5.8p1/tests/CA/3-cre_certs.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <<EOF
++usage: $0 <options>
++ -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 <<EOF
++$SSH_DN_C
++$SSH_DN_ST
++$SSH_DN_L
++$SSH_DN_O
++${SSH_DN_OU}-2
++${SSH_DN_OU}-1
++${SSH_DN_OU}-3
++$SSH_BASE_DN_CN(${type}${subtype})
++$SSH_DN_EM
++.
++EOF
++ ) |
++ $OPENSSL req \
++ -new \
++ -config "${SSH_CACFGFILE}" \
++ $SSH_DN_UTF8_FLAG \
++ -key "${SSH_BASE_KEY}" \
++ -passin pass:"" \
++ -out "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.csr" \
++ 2>> "$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.8p1/tests/CA/4-cre_crls.sh openssh-5.8p1+x509-6.2.4/tests/CA/4-cre_crls.sh
+--- openssh-5.8p1/tests/CA/4-cre_crls.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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.8p1/tests/CA/5-cre_ldap.sh openssh-5.8p1+x509-6.2.4/tests/CA/5-cre_ldap.sh
+--- openssh-5.8p1/tests/CA/5-cre_ldap.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <<EOF
++dn: ${SSH_LDAP_DC}
++objectClass: dcObject
++objectClass: organization
++dc: example
++o: Example Corporation
++description: The Example Corporation
++
++dn: cn=Manager,${SSH_LDAP_DC}
++objectClass: inetOrgPerson
++cn: Manager
++sn: Manager
++title: the world's most famous manager
++mail: ***@example.com
++uid: manager
++
++
++#The organization 'OpenSSH Test Team':
++# "O=${SSH_DN_O},${SSH_LDAP_DC}"
++dn:`utf8base64 "O=${SSH_DN_O},${SSH_LDAP_DC}"`
++objectclass: organization
++o:`utf8base64 "${SSH_DN_O}"`
++st: ${SSH_DN_ST}
++
++
++#The 'OpenSSH Test Team' "CA" organizational units:
++# "OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"
++dn:`utf8base64 "OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"`
++objectclass: organizationalUnit
++ou:`utf8base64 "${SSH_DN_OU}"`
++l:`utf8base64 "${SSH_DN_L}"`
++st: ${SSH_DN_ST}
++EOF
++
++
++ for type in ${SSH_SIGN_TYPES}; do
++ N="${CAKEY_PREFIX}-${type}.crt.pem"
++
++ cat <<EOF
++
++# "OU=${SSH_DN_OU} $type keys,OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"
++dn:`utf8base64 "OU=${SSH_DN_OU} $type keys,OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"`
++objectclass: organizationalUnit
++ou:`utf8base64 "$SSH_DN_OU $type keys"`
++l:`utf8base64 "${SSH_DN_L}"`
++st: ${SSH_DN_ST}
++EOF
++ done
++) > ldap/base.ldif
++}
++
++
++# ===
++cre_slapdconf () {
++(
++ cat <<EOF
++#required schemas
++include $LDAP_SYSCONFDIR/schema/core.schema
++include $LDAP_SYSCONFDIR/schema/cosine.schema
++include $LDAP_SYSCONFDIR/schema/inetorgperson.schema
++
++#features
++allow bind_v2
++#disallow bind_simple ;-)
++
++# dbms backend settings should be same file !
++# this is required for openldap version 2.3.32(but not for <= 2.3.20,2.2.x,2.1.x)
++##dbms
++#database $SSH_LDAP_DB
++#suffix "$SSH_LDAP_DC"
++#rootdn "cn=Manager,$SSH_LDAP_DC"
++#rootpw secret
++#
++#index objectClass eq
++EOF
++) > 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.8p1/tests/CA/config openssh-5.8p1+x509-6.2.4/tests/CA/config
+--- openssh-5.8p1/tests/CA/config 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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="***@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.8p1/tests/CA/env.in openssh-5.8p1+x509-6.2.4/tests/CA/env.in
+--- openssh-5.8p1/tests/CA/env.in 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/env.in 2004-10-29 22:52:46.000000000 +0300
+@@ -0,0 +1,4 @@
++# LDAP environment:
++@***@LDAP_SYSCONFDIR="@LDAP_SYSCONFDIR@"
++@***@LDAP_LIBEXECDIR="@LDAP_LIBEXECDIR@"
++@***@LDAP_BINDIR="@LDAP_BINDIR@"
+diff -ruN openssh-5.8p1/tests/CA/functions openssh-5.8p1+x509-6.2.4/tests/CA/functions
+--- openssh-5.8p1/tests/CA/functions 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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[<NUM>G move to column <NUM> (linux console, xterm, not vt100)
++# \033[<NUM>C move <NUM> columns forward but only upto last column
++# \033[<NUM>D move <NUM> columns backward but only upto first column
++# \033[<NUM>A move <NUM> rows up
++# \033[<NUM>B move <NUM> 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.8p1/tests/CA/Makefile.in openssh-5.8p1+x509-6.2.4/tests/CA/Makefile.in
+--- openssh-5.8p1/tests/CA/Makefile.in 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/Makefile.in 2007-01-27 16:59:16.000000000 +0200
+@@ -0,0 +1,134 @@
++srcdir=@srcdir@
++@***@SSH_OCSP=yes
++@***@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_certs:
++@***@ocsp_certs: testocsp_rsa-rsa_md5.crt testocsp_dsa-rsa_md5.crt
++
++@***@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"
++
++@***@testocsp_rsa:
++@OCSP_ON@ @echo; echo "generating RSA 'ocspkey'"
++@OCSP_ON@ $(TEST_SSH_SSHKEYGEN) -t rsa -b $(RSAKEYBITS) -f $@ -N ""
++
++@***@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"
++
++@***@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_files:
++@***@ldap_files: ldap/slapd.conf.tmpl
++
++@***@ldap/slapd.conf.tmpl: env
++@LDAP_ON@ @echo
++@LDAP_ON@ $(SHELL) $(srcdir)/5-cre_ldap.sh
++
++@***@ldap_clean:
++@***@ldap_clean:
++@LDAP_ON@ rm -f ldap_setup.log
++@LDAP_ON@ rm -fr ldap
+diff -ruN openssh-5.8p1/tests/CA/openssh_tests.sh openssh-5.8p1+x509-6.2.4/tests/CA/openssh_tests.sh
+--- openssh-5.8p1/tests/CA/openssh_tests.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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" <<EOF
++CACertificateFile /file/not/found
++CAldapURL ${LDAPD_URL}
++VAType none
++EOF
++
++"$TEST_SSH_SSHD" -t -f "${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}" <<EOF
++Port ${SSHD_PORT}
++Protocol 2
++ListenAddress ${SSHD_LISTENADDRESS}
++AuthorizedKeysFile ${AUTHORIZEDKEYSFILE}
++ChallengeResponseAuthentication no
++HostbasedAuthentication no
++#!NO(linux):KerberosAuthentication no
++#!NO(linux):KerberosOrLocalPasswd no
++#!NO(OpenBSD):PAMAuthenticationViaKbdInt no
++StrictModes no
++PasswordAuthentication no
++PubkeyAuthentication yes
++#deprecated#RhostsAuthentication no
++RhostsRSAAuthentication no
++RSAAuthentication no
++
++UsePrivilegeSeparation ${SSHSERVER_USEPRIVILEGESEPARATION}
++
++HostKey ${TEST_SSHD_HOSTKEY}
++
++#deprecated#X509rsaSigType=md5
++#AllowedCertPurpose sslclient
++EOF
++}
++
++creTestSSHcfgFile() {
++ cat > "${SSH_CFG}" <<EOF
++Host *
++Port ${SSHD_PORT}
++PreferredAuthentications publickey
++Protocol 2
++StrictHostKeyChecking yes
++UserKnownHostsFile ${USERKNOWNHOSTSFILE}
++
++#deprecated#X509rsaSigType=md5
++#AllowedCertPurpose sslserver
++EOF
++if test "x${SSH_X509STORE_DISABLED}" != "xyes"; then
++ cat >> "${SSH_CFG}" <<EOF
++CACertificatePath /path/not/found/global
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++UserCACertificatePath /path/not/found/user
++UserCACertificateFile /file/not/found/user
++EOF
++fi
++}
++
++
++# ===
++#args:
++# $1 - type
++# $2 - identity_file or empty
++# $3 - info
++# $4 - request to fail flag
++runTest () {
++(
++ printf '%s' " * ${extd}${1}${norm} ${3}"
++
++ msg="OpenSSH Certificate TeSt-${1}"
++
++ sshopts=""
++ #sshopts="${sshopts} -v -v -v"
++ test -n "$2" && sshopts="${sshopts} -i $2"
++ #assignment to variable "identity_file" crash ksh :-(
++ #identity_file="value_without_significance"
++
++ case $4 in
++ Y|y|Yes|yes|YES|1)
++ must_fail=1;;
++ *)
++ must_fail=0;;
++ esac
++
++ creTestSSHcfgFile || exit $?
++
++ "$TEST_SSH_SSH" -F "${SSH_CFG}" ${sshopts} \
++ ${SSH_EXTRA_OPTIONS} \
++ ${SSHD_LISTENADDRESS} "echo \"${msg}\"" \
++ 2> "${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.8p1/tests/CA/shell.rc openssh-5.8p1+x509-6.2.4/tests/CA/shell.rc
+--- openssh-5.8p1/tests/CA/shell.rc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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.8p1/tests/CA/test-agent.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-agent.sh.inc
+--- openssh-5.8p1/tests/CA/test-agent.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++ fi
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ printSeparator
++ echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm} ..."
++
++ for type in ${SSH_SIGN_TYPES}; do
++ testAgent || exit $?
++ done
++ done
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
+diff -ruN openssh-5.8p1/tests/CA/test-alg.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-alg.sh.inc
+--- openssh-5.8p1/tests/CA/test-alg.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-alg.sh.inc 2006-03-13 21:51:43.000000000 +0200
+@@ -0,0 +1,140 @@
++#
++# Copyright (c) 2004-2005 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 optional x509 certificate;
++# - "AuthorizedKeysFile" contain certificate BLOB.
++# - server accept different publickey algorithms.
++# Note that "Host-Based Authentication" we cannot test without to install.
++#
++
++
++# ===
++#env. vars:
++# alg
++testAlg () {
++ printSeparator
++ echo " - only ${attn}${alg}${norm} algorithm"
++
++ creTestSSHDcfgFile
++ if test "x${SSH_X509STORE_DISABLED}" != "xyes"; then
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++ fi
++ cat >> "$SSHD_CFG" <<EOF
++PubkeyAlgorithms $alg
++EOF
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ case $SSH_CLIENTKEY in
++ *rsa) keytype="rsa";;
++ *dsa) keytype="dsa";;
++ *) echo "${warn}unknown client key type${norm}"
++ exit 1;;
++ esac
++ case $alg in
++ x509v3-sign-*) withcert="yes";;
++ *) withcert="";;
++ esac
++
++ if test -z "$withcert"; then
++ must_fail=""
++ if test "X$alg" = "Xssh-rsa"; then
++ test "$keytype" = "rsa" || must_fail="yes"
++ else
++ test "$keytype" = "dsa" || must_fail="yes"
++ fi
++ else
++ must_fail="yes"
++ fi
++
++ identity_file="${SSH_CLIENTKEY}"
++ "$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 $?
++
++ 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.8p1/tests/CA/test-blob_auth.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-blob_auth.sh.inc
+--- openssh-5.8p1/tests/CA/test-blob_auth.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++ fi
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ printSeparator
++ echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm} ..."
++
++ for type in ${SSH_SIGN_TYPES}; do
++ testBLOBautorization || exit $?
++ done
++ done
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
+diff -ruN openssh-5.8p1/tests/CA/test-by_ldap.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-by_ldap.sh.inc
+--- openssh-5.8p1/tests/CA/test-by_ldap.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-by_ldap.sh.inc 2008-02-25 22:07:50.000000000 +0200
+@@ -0,0 +1,270 @@
++#
++# 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: Test OpenSSH client authentication:
++# - "IdentityFile" contain private key and x509 certificate;
++# - "AuthorizedKeysFile" contain certificate Subject;
++# - authorization against:
++# - LDAP, without CRL file and hash-dir
++#
++
++
++LDAP_SETUP_LOG="${CWD}/ldap_setup.log"
++LDAPD_PID="${CWD}/slapd.pid"
++LDAPD_ARGS="${CWD}/slapd.args"
++LDAPD_CFG="${CWD}/slapd.conf"
++
++if test -z "${LDAP_BINDIR}"; then
++ LDAPADD=ldapadd
++else
++ LDAPADD="${LDAP_BINDIR}/ldapadd"
++fi
++
++
++# ===
++#args:
++# $1 - info. message for valid cert.
++# $2 - request valid cert. to fail flag
++# $3 - info. message for revoked cert.
++# $4 - request revoked cert. to fail flag
++test_all_keys () {
++ for type in ${SSH_SIGN_TYPES}; do
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ identity_file="${SSH_CLIENTKEY}-${type}"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "$1" "$2" || return $?
++
++ identity_file="${SSH_CLIENTKEY}-${type}-revoked"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "$3" "$4" || return $?
++ done
++ done
++ return 0
++}
++
++
++# ===
++creTestLDAPDcfgFile() {
++(
++ cat <<EOF
++include $CWD/ldap/slapd.conf.tmpl
++
++# dbms backend settings must be in same file !
++# this is required for openldap version 2.3.32(but not for <= 2.3.20,2.2.x,2.1.x)
++database $SSH_LDAP_DB
++suffix "$SSH_LDAP_DC"
++rootdn "cn=Manager,$SSH_LDAP_DC"
++rootpw secret
++
++directory $CWD/ldap/data
++index objectClass eq
++
++pidfile $LDAPD_PID
++argsfile $LDAPD_ARGS
++EOF
++) > ${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 <<EOF
++# "CN=OpenSSH Test ${type} CA key,OU=${SSH_DN_OU} $type keys,OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"
++dn:`utf8base64 "CN=OpenSSH Test ${type} CA key,OU=${SSH_DN_OU} $type keys,OU=${SSH_DN_OU},O=${SSH_DN_O},${SSH_LDAP_DC}"`
++objectClass: inetOrgPerson
++objectClass: pkiCA
++cACertificate;binary:< file://${CWD}/ldap/catest-${type}.crt.der
++certificateRevocationList;binary:< file://${CWD}/ldap/catest-${type}.crl.der
++cn: OpenSSH Test ${type} CA key
++sn: OpenSSH Test ${type} CA key
++ou:`utf8base64 "${SSH_DN_OU} ${type} keys"`
++ou:`utf8base64 "${SSH_DN_OU}"`
++o:`utf8base64 "${SSH_DN_O}"`
++l:`utf8base64 "${SSH_DN_L}"`
++st: ${SSH_DN_ST}
++
++EOF
++ done
++) > 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" <<EOF
++CACertificateFile /file/not/found
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++CAldapVersion $1
++CAldapURL ${LDAPD_URL}/${SSH_CONF_LDAP_DC}
++#TODO:MandatoryCRL yes
++EOF
++
++ runSSHdaemon || return $?
++ (
++ rm -f "${CWD}/ldap/data"/*
++ runLDAPdaemon
++ (
++ initLDAPdb || exit $?
++
++ test_all_keys "" "" "${warn}!${norm}" "Yes"
++ ); retval=$?
++ killLDAPdaemon
++ exit ${retval}
++ ); retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++LDAPtestBREAK() {
++ echo
++ killLDAPdaemon
++ testBREAK
++}
++
++trap LDAPtestBREAK INT QUIT ABRT KILL TERM || exit 1
++
++
++# ===
++
++do_test () {
++ if test "x${SSH_LDAP_ENABLED}" = "xno"; then
++ echo "* ${extd}LDAP${norm} is ${attn}disabled${norm}"
++ return 1
++ fi
++ echo "* ${extd}against ${attn}CALdapUrl${norm}:"
++
++ testLDAP 2 &&
++ testLDAP 3
++}
+diff -ruN openssh-5.8p1/tests/CA/test-crl.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-crl.sh.inc
+--- openssh-5.8p1/tests/CA/test-crl.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-crl.sh.inc 2005-02-23 22:33:15.000000000 +0200
+@@ -0,0 +1,266 @@
++#
++# 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 Subject;
++# - authorization against:
++# - without CRL file and hash-dir
++# - only with CRL file(CARevocationFile)
++# - only with CRL hash-dir(CARevocationPath)
++# - only one CRL file in a hash-dir
++#
++
++
++# ===
++#args:
++# $1 - info. message for valid cert.
++# $2 - request valid cert. to fail flag
++# $3 - info. message for revoked cert.
++# $4 - request revoked cert. to fail flag
++test_all_keys () {
++ for type in ${SSH_SIGN_TYPES}; do
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ identity_file="${SSH_CLIENTKEY}-${type}"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "$1" "$2" || return $?
++
++ identity_file="${SSH_CLIENTKEY}-${type}-revoked"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "$3" "$4" || return $?
++ done
++ done
++ return 0
++}
++
++
++# ===
++test_nocrl () {
++ printSeparator
++ echo "Begin test ${extd}without${norm} CRL ${attn}file${norm} and ${attn}hash-dir${norm} ..."
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "" "" "" ""; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++test_crlfile () {
++ printSeparator
++ echo "Begin test with CRL ${extd}file(${attn}CARevocationFile${norm}) ..."
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile ${SSH_CAROOT}/${CACRLFILE}
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "" "" "${warn}!${norm}" "Yes"; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++test_crldir () {
++ printSeparator
++ echo "Begin test with CRL ${extd}hash-dir(${attn}CARevocationPath${norm}) ..."
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath ${SSH_CACRLDIR}
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "" "" "${warn}!${norm}" "Yes"; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++#env. vars:
++# crltype - crl for signature type
++test_crlbytype () {
++ retval=0
++
++ echo " - ${extd}with ${attn}${crltype}${norm} only in ${attn}CARevocationPath${norm} ..."
++
++ printf " creating ${attn}${crltype}${norm} crlfile in hash dir"
++ #printf "${warn}"
++ rm -f "${CRL_TEST_DIR}"/* 2> /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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath ${CRL_TEST_DIR}
++EOF
++
++
++ runSSHdaemon &&
++ (
++ for crltype in ${SSH_SIGN_TYPES}; do
++ test_crlbytype || exit $?
++ done
++ ); retval=$?
++ killSSHdaemon
++
++ rm -f "${CRL_TEST_DIR}"/* 2> /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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile ${SSH_CAROOT}/${CACRLFILE}
++CARevocationPath /crlpath/not/found
++MandatoryCRL yes
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "" "" "${warn}!${norm}" "Yes"; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++test_crlpresence_no () {
++ printSeparator
++ echo "Begin test with mandatory ${extd}CRL presence ${attn}without${norm} CRL ..."
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++MandatoryCRL yes
++EOF
++
++ runSSHdaemon || return $?
++ test_all_keys "${warn}!${norm}" "Yes" "${warn}!${norm}" "Yes"; retval=$?
++ killSSHdaemon
++
++ return ${retval}
++}
++
++
++# ===
++
++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}CA CRL${norm} file and/or hash-dir:"
++
++ test_nocrl &&
++ test_crlfile &&
++ test_crldir &&
++ test_onlyonecrl &&
++ test_crlpresence_yes &&
++ test_crlpresence_no
++}
+diff -ruN openssh-5.8p1/tests/CA/test-dn_auth_file.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-dn_auth_file.sh.inc
+--- openssh-5.8p1/tests/CA/test-dn_auth_file.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-dn_auth_file.sh.inc 2007-08-06 23:21:19.000000000 +0300
+@@ -0,0 +1,119 @@
++#
++# 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 "Distinguished Name"/
++# "Subject" in varios formats.
++#
++
++
++# ===
++#env. vars:
++# SSH_CLIENTKEY
++# type
++testDNautorizations1 () {
++ identity_file="${SSH_CLIENTKEY}-${type}"
++ if test ! -r "$identity_file"; then
++ error_file_not_readable "${identity_file}"; return $?
++ fi
++
++ sshkeytype=`getSSHkeyType "${identity_file}"` || return $?
++ subject=`getSubject "${identity_file}"` || return $?
++
++ for subtype in \
++ "Subject:" \
++ "SuBjecT=" \
++ "sUbjecT" \
++ "diStinguished name:" \
++ "distiNguished-nAme:" \
++ "distinguiShed_naMe:" \
++ "disTinguishednamE:" \
++ "dN:" \
++ ; do
++ echo "${sshkeytype} ${subtype} ${subject}" > "${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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ printSeparator
++ echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm} ..."
++
++ for type in ${SSH_SIGN_TYPES}; do
++ testDNautorizations1 || exit $?
++ done
++ done
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
+diff -ruN openssh-5.8p1/tests/CA/test-dn_auth_path.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-dn_auth_path.sh.inc
+--- openssh-5.8p1/tests/CA/test-dn_auth_path.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-dn_auth_path.sh.inc 2004-03-09 21:37:04.000000000 +0200
+@@ -0,0 +1,119 @@
++#
++# 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 Subject;
++# - authorization against only one CA certificate in server x509 store.
++#
++
++
++# ===
++#env. vars:
++# SSH_CLIENTKEY
++# catype
++# type
++testDNautorizations2 () {
++ identity_file="${SSH_CLIENTKEY}-${type}"
++
++ creX509AuthorizedKeysFile "${identity_file}" || return $?
++
++ if test "${catype}" = "${type}"; then
++ runTest "${extd}${type}${norm}" \
++ "${identity_file}"\
++ "" ""
++ else
++ runTest "${type}" \
++ "${identity_file}" \
++ "${warn}!${norm}" "Yes"
++ fi
++}
++
++
++# ===
++#env. vars:
++# catype
++do_test_catype () {
++ echo " - autorization by x509 ${attn}Subject${norm} against CA key ${attn}${catype}${norm}"
++
++ for type in ${SSH_SIGN_TYPES}; do
++ testDNautorizations2 "${catype}" "${type}" || return $?
++ done
++}
++
++
++# ===
++
++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}CACertificatePath${norm}:"
++
++ CRT_TEST_DIR="${SSH_CAROOT}/crt-test"
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile /file/not/found
++CACertificatePath ${CRT_TEST_DIR}
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++
++ runSSHdaemon || return $?
++ (
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ printSeparator
++ echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm} ..."
++
++ if test ! -d "${CRT_TEST_DIR}"; then
++ mkdir "${CRT_TEST_DIR}" || return $?
++ fi
++ rm -rf "${CRT_TEST_DIR}/"* 2>/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.8p1/tests/CA/test-ocsp.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-ocsp.sh.inc
+--- openssh-5.8p1/tests/CA/test-ocsp.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++VAType ocspcert
++EOF
++
++ port=${SSH_VA_BASEPORT}
++ for type in ${SSH_SIGN_TYPES}; do
++ runResponder ${port}; retval=$?
++ if test ${retval} -ne 0; then
++ break
++ fi
++ port=`expr ${port} + 1`
++ done
++ if test ${retval} -eq 0; then
++ runSSHdaemon &&
++ (
++ for type in ${SSH_SIGN_TYPES}; do
++ test_by_keytype || exit $?
++ done
++ ); retval=$?
++ killSSHdaemon
++ fi
++ killResponders
++ if test ${retval} -ne 0; then
++ exit ${retval}
++ fi
++ done
++
++ exit ${retval}
++)
++}
++
++
++# ===
++#env. vars:
++# type
++test_by_keytype() {
++(
++ for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do
++ identity_file="${SSH_CLIENTKEY}-${type}"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${identity_file}" \
++ "${identity_file}" "" "" || exit $?
++
++ identity_file="${SSH_CLIENTKEY}-${type}-revoked"
++ creX509AuthorizedKeysFile "${identity_file}" &&
++ runTest "${SSH_CLIENTKEY}-${type}${warn}-revoked${norm}" \
++ "${identity_file}" "" "Yes" || exit $?
++ done
++)
++}
++
++
++# ===
++test_ocsp_spec () {
++(
++ printSeparator
++ echo "Begin test ${extd}against${norm} ${attn}specified${norm} OCSP provider ..."
++
++ #OpenSSL OCSP responder support only one CA!
++ #For each signature type we have different CA, i.e. we must start
++ #corresponding OCSP responder.
++ #Note: OpenSSL OCSP responder doesn't support dsa keys!!!
++ retval=1
++ for OCSP_RESPKEY in ${TEST_OCSP_RESPKEYS}; do
++ printSeparator
++ echo " respoder key base ${attn}${OCSP_RESPKEY}${norm} ..."
++
++ for type in ${SSH_SIGN_TYPES}; do
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++VAType ocspspec
++VAOCSPResponderURL http://${SSHD_LISTENADDRESS}:${SSH_VA_BASEPORT}
++#VACertificateFile `pwd`/${OCSP_RESPKEY}-${type}.crt
++EOF
++
++ runResponder ${SSH_VA_BASEPORT} &&
++ runSSHdaemon &&
++ test_by_keytype; retval=$?
++ killSSHdaemon
++ killResponders
++ if test ${retval} -ne 0; then
++ exit ${retval}
++ fi
++ done
++ done
++
++ exit ${retval}
++)
++}
++
++
++# ===
++
++do_test () {
++ if test "x${SSH_OCSP_ENABLED}" = "xno"; then
++ echo "* ${extd}OCSP${norm} is ${attn}disabled${norm}"
++ return 1
++ fi
++ echo "* ${extd}against ${attn}CACertificateFile${norm} and ${attn}OCSP provider${norm}:"
++
++ test_ocsp_cert &&
++ test_ocsp_spec
++}
+diff -ruN openssh-5.8p1/tests/CA/test-self.sh.inc openssh-5.8p1+x509-6.2.4/tests/CA/test-self.sh.inc
+--- openssh-5.8p1/tests/CA/test-self.sh.inc 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/test-self.sh.inc 2006-04-26 00:48:26.000000000 +0300
+@@ -0,0 +1,227 @@
++#
++# Copyright (c) 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 authentication:
++# - "IdentityFile" contain private key and self-issued x509 certificate;
++# - "AuthorizedKeysFile" contain certificate BLOB or DN.
++#
++
++
++# ===
++cre_keys() {
++ echo " creating keys and files for ${extd}self-issued${norm}"
++
++ for keytype in rsa dsa; do
++ SSH_CLIENTKEY="selfid_${keytype}"
++
++ cat "${SSH_CAKEYDIR}/${CAKEY_PREFIX}-${keytype}.key" \
++ > "${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" <<EOF
++AllowedCertPurpose skip
++KeyAllowSelfIssued no
++CACertificateFile ${SSH_CAROOT}/${CACERTFILE}
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ (
++ test_self "no" "no"
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
++
++# ===
++
++test_pkey_no () {
++ retval=0
++ echo " - ${attn}without${norm} self-issued allowed by ${extd}pubkey${norm}:"
++ printSeparator
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++AllowedCertPurpose skip
++KeyAllowSelfIssued no
++CACertificateFile /file/not/found
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ (
++ test_self "yes" "yes"
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
++
++# ===
++
++test_pkey_yes () {
++ retval=0
++ echo " - ${attn}with${norm} self-issued allowed by ${extd}pubkey${norm}:"
++ printSeparator
++
++ creTestSSHDcfgFile
++ cat >> "$SSHD_CFG" <<EOF
++AllowedCertPurpose skip
++KeyAllowSelfIssued yes
++CACertificateFile /file/not/found
++CACertificatePath /path/not/found
++CARevocationFile /crlfile/not/found
++CARevocationPath /crlpath/not/found
++EOF
++
++ runSSHdaemon || return $?
++ (
++ test_self "no" "yes"
++ ); retval=$?
++ killSSHdaemon
++ return $retval
++}
++
++# ===
++SELFtestBREAK() {
++ echo
++ rm -f "selfid_rsa"*
++ rm -f "selfid_dsa"*
++ testBREAK
++}
++
++trap SELFtestBREAK INT QUIT ABRT KILL TERM || exit 1
++
++
++# ===
++
++do_test () {
++ echo "* ${extd}self-issued${norm}:"
++ if test "x${SSH_X509STORE_DISABLED}" = "xyes"; then
++ echo " ${extd}X.509 store${norm} is ${attn}disabled${norm}"
++ echo " the test is not suitable in this context"
++ return 0
++ fi
++
++ cre_keys &&
++ test_store &&
++ test_pkey_no &&
++ test_pkey_yes
++ retval=$?
++
++ rm -f "selfid_rsa"*
++ rm -f "selfid_dsa"*
++
++ return $retval
++}
+diff -ruN openssh-5.8p1/tests/CA/verify.sh openssh-5.8p1+x509-6.2.4/tests/CA/verify.sh
+--- openssh-5.8p1/tests/CA/verify.sh 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/tests/CA/verify.sh 2006-02-16 22:07:03.000000000 +0200
+@@ -0,0 +1,44 @@
++#! /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: Verify all testid_*.crt testhostkey_*.crt files in current
++# directory agains openssh "Test CA".
++#
++
++CWD=`pwd`
++SCRIPTDIR=`echo $0 | sed 's/verify.sh//'`
++. "${SCRIPTDIR}functions"
++. "${SCRIPTDIR}config"
++
++
++for VERIFY in \
++ "${OPENSSL} verify -CAfile ${SSH_CAROOT}/${CACERTFILE}" \
++ "${OPENSSL} verify -CApath ${SSH_CACERTDIR}" \
++; do
++ echo ${attn}${VERIFY} ....${norm}
++ for F in \
++ testid_*.crt \
++ testhostkey_*.crt \
++ testocsp_*.crt \
++ ; do
++ ${VERIFY} "$F" || exit 1
++ done
++done
+diff -ruN openssh-5.8p1/umac.c openssh-5.8p1+x509-6.2.4/umac.c
+--- openssh-5.8p1/umac.c 2008-07-14 05:04:43.000000000 +0300
++++ openssh-5.8p1+x509-6.2.4/umac.c 2011-02-04 21:06:01.000000000 +0200
+@@ -123,7 +123,7 @@
+ /* --- Endian Conversion --- Forcing assembly on some platforms */
+ /* ---------------------------------------------------------------------- */
+
+-#if HAVE_SWAP32
++#ifdef HAVE_SWAP32
+ #define LOAD_UINT32_REVERSED(p) (swap32(*(UINT32 *)(p)))
+ #define STORE_UINT32_REVERSED(p,v) (*(UINT32 *)(p) = swap32(v))
+ #else /* HAVE_SWAP32 */
+diff -ruN openssh-5.8p1/x509_by_ldap.c openssh-5.8p1+x509-6.2.4/x509_by_ldap.c
+--- openssh-5.8p1/x509_by_ldap.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/x509_by_ldap.c 2007-10-24 00:30:08.000000000 +0300
+@@ -0,0 +1,874 @@
++/*
++ * 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 "x509_by_ldap.h"
++/* Prefered X509_NAME_cmp method from ssh-x509.c */
++extern int ssh_X509_NAME_cmp(X509_NAME *a, X509_NAME *b);
++#include <string.h>
++#ifndef LDAP_DEPRECATED
++ /* to suppress warnings in some 2.3x versions */
++# define LDAP_DEPRECATED 0
++#endif
++#include <ldap.h>
++
++
++/* ================================================================== */
++/* 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.8p1/x509_by_ldap.h openssh-5.8p1+x509-6.2.4/x509_by_ldap.h
+--- openssh-5.8p1/x509_by_ldap.h 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <openssl/x509_vfy.h>
++#include <openssl/err.h>
++
++
++#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.8p1/x509_nm_cmp.c openssh-5.8p1+x509-6.2.4/x509_nm_cmp.c
+--- openssh-5.8p1/x509_nm_cmp.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <ctype.h>
++#include <string.h>
++
++#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.8p1/x509store.c openssh-5.8p1+x509-6.2.4/x509store.c
+--- openssh-5.8p1/x509store.c 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <openssl/x509v3.h>
++#include "log.h"
++
++#ifndef SSH_X509STORE_DISABLED
++#include <string.h>
++
++#include "xmalloc.h"
++#include "pathnames.h"
++#include "misc.h"
++#include <openssl/err.h>
++#include <openssl/x509_vfy.h>
++/* 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.8p1/x509store.h openssh-5.8p1+x509-6.2.4/x509store.h
+--- openssh-5.8p1/x509store.h 1970-01-01 02:00:00.000000000 +0200
++++ openssh-5.8p1+x509-6.2.4/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 <openssl/x509.h>
++
++
++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 */
Index: Makefile
===================================================================
--- Makefile (revision 28065)
+++ Makefile (working copy)
@@ -25,22 +25,34 @@
define Package/openssh/Default
SECTION:=net
CATEGORY:=Network
- DEPENDS:=+libopenssl +zlib +libgcc
+ SUBMENU:=SSH
+ DEPENDS:=openssh
TITLE:=OpenSSH
+ URL:=http://www.openssh.com/
MAINTAINER:=Peter Wagner <***@gmx.at>
- URL:=http://www.openssh.com/
- SUBMENU:=SSH
endef
+define Package/openssh
+ $(call Package/openssh/Default)
+ DEPENDS:=+libopenssl +zlib +libgcc
+endef
+
+define Package/openssh/config
+ config PACKAGE_openssh_x509
+ depends on (PACKAGE_openssh-client || PACKAGE_openssh-server || PACKAGE_openssh-keygen || PACKAGE_openssh-sftp-client || PACKAGE_openssh-sftp-server)
+ bool "Enable x509 certificate support"
+ default y
+endef
+
+define Package/openssh/description
+ OpenSSH client and server suite.
+endef
+
define Package/openssh-client
$(call Package/openssh/Default)
TITLE+= client
endef
-define Package/openssh-client/description
-OpenSSH client.
-endef
-
define Package/openssh-client/conffiles
/etc/ssh/ssh_config
endef
@@ -51,29 +63,17 @@
TITLE+= client utilities
endef
-define Package/openssh-client-utils/description
-OpenSSH client utilities.
-endef
-
define Package/openssh-keygen
$(call Package/openssh/Default)
TITLE+= keygen
endef
-define Package/openssh-keygen/description
-OpenSSH keygen.
-endef
-
define Package/openssh-server
$(call Package/openssh/Default)
DEPENDS+= +openssh-keygen
TITLE+= server
endef
-define Package/openssh-server/description
-OpenSSH server.
-endef
-
define Package/openssh-server/conffiles
/etc/ssh/sshd_config
endef
@@ -83,20 +83,11 @@
TITLE+= SFTP client
endef
-define Package/openssh-sftp-client/description
-OpenSSH SFTP client.
-endef
-
define Package/openssh-sftp-server
$(call Package/openssh/Default)
- DEPENDS:=+libgcc
TITLE+= SFTP server
endef
-define Package/openssh-sftp-server/description
-OpenSSH SFTP server.
-endef
-
CONFIGURE_ARGS+= \
$(DISABLE_NLS) \
--sysconfdir=/etc/ssh \
@@ -122,6 +113,18 @@
CONFIGURE_VARS += LD="$(TARGET_CC)"
+define Build/Prepare
+ $(call Build/Prepare/Default,)
+# tar xf "$(DL_DIR)/$(PKG_SOURCE)" -C "$(BUILD_DIR)"
+# patch -p1 -d "$(PKG_BUILD_DIR)" < "$(PATCH_DIR)/100-no_cast_fix.patch"
+# patch -p1 -d "$(PKG_BUILD_DIR)" < "$(PATCH_DIR)/110-no_ripemd_fix.patch"
+# patch -p1 -d "$(PKG_BUILD_DIR)" < "$(PATCH_DIR)/130-implicit_memset_decl_fix.patch"
+# patch -p1 -d "$(PKG_BUILD_DIR)" < "$(PATCH_DIR)/200-dscp-qos.patch"
+ifdef config_PACKAGE_openssh_x509
+ patch -p1 -d "$(PKG_BUILD_DIR)" < "./300-x509.patch"
+endif
+endef
+
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
DESTDIR="$(PKG_INSTALL_DIR)" \
@@ -192,6 +205,7 @@
ln -sf ../lib/sftp-server $(1)/usr/libexec/sftp-server
endef
+$(eval $(call BuildPackage,openssh))
$(eval $(call BuildPackage,openssh-client))
$(eval $(call BuildPackage,openssh-client-utils))
$(eval $(call BuildPackage,openssh-keygen))