diff -ruN openssh-3.4p1/acconfig.h openssh-3.4p1+x509e/acconfig.h --- openssh-3.4p1/acconfig.h 2002-06-26 01:35:16.000000000 +0300 +++ openssh-3.4p1+x509e/acconfig.h 2002-10-01 16:20:40.000000000 +0300 @@ -1,4 +1,4 @@ -/* $Id: acconfig.h,v 1.141 2002/06/25 22:35:16 tim Exp $ */ +/* $Id$ */ #ifndef _CONFIG_H #define _CONFIG_H @@ -289,6 +289,9 @@ /* Specify default $PATH */ #undef USER_PATH +/* Specify location of ssh CA root */ +#undef SSHCADIR + /* Specify location of ssh.pid */ #undef _PATH_SSH_PIDDIR diff -ruN openssh-3.4p1/authfd.c openssh-3.4p1+x509e/authfd.c --- openssh-3.4p1/authfd.c 2002-06-26 02:22:55.000000000 +0300 +++ openssh-3.4p1+x509e/authfd.c 2002-11-14 11:03:17.000000000 +0200 @@ -12,6 +12,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 @@ -35,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: authfd.c,v 1.56 2002/06/25 16:22:42 markus Exp $"); +RCSID("$OpenBSD$"); #include @@ -456,6 +458,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); @@ -464,6 +467,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); @@ -471,6 +475,21 @@ buffer_put_bignum2(b, key->dsa->priv_key); break; } + if ((key->type == KEY_X509_RSA) || (key->type == KEY_X509_DSA)) { + int len; + void* str; + unsigned char *p; + + len = i2d_X509(key->x509, NULL); + str = xmalloc(len); + if (str == NULL) + { error("ssh_encode_identity_ssh2: out of memory"); return; } + + p = str; + i2d_X509(key->x509, &p); + buffer_put_string(b, str, len); + xfree(str); + } buffer_put_cstring(b, comment); } @@ -498,6 +517,8 @@ break; case KEY_RSA: case KEY_DSA: + case KEY_X509_RSA: + case KEY_X509_DSA: type = constrained ? SSH2_AGENTC_ADD_ID_CONSTRAINED : SSH2_AGENTC_ADD_IDENTITY; @@ -550,7 +571,7 @@ buffer_put_int(&msg, BN_num_bits(key->rsa->n)); buffer_put_bignum(&msg, key->rsa->e); buffer_put_bignum(&msg, key->rsa->n); - } else if (key->type == KEY_DSA || key->type == KEY_RSA) { + } else if (key->type == KEY_DSA || key->type == KEY_RSA || key->type == KEY_X509_DSA || key->type == KEY_X509_RSA ) { key_to_blob(key, &blob, &blen); buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); buffer_put_string(&msg, blob, blen); diff -ruN openssh-3.4p1/authfile.c openssh-3.4p1+x509e/authfile.c --- openssh-3.4p1/authfile.c 2002-06-26 02:19:13.000000000 +0300 +++ openssh-3.4p1+x509e/authfile.c 2002-11-14 11:04:09.000000000 +0200 @@ -13,6 +13,8 @@ * * * 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 @@ -36,7 +38,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: authfile.c,v 1.50 2002/06/24 14:55:38 markus Exp $"); +RCSID("$OpenBSD$"); #include #include @@ -51,6 +53,7 @@ #include "log.h" #include "authfile.h" #include "rsa.h" +#include "ssh-x509.h" /* Version identification string for SSH v1 identity files. */ static const char authfile_id_string[] = @@ -195,6 +198,10 @@ success = PEM_write_RSAPrivateKey(fp, key->rsa, cipher, passphrase, len, NULL, NULL); break; + case KEY_X509_RSA: + case KEY_X509_DSA: + success = x509key_save_pem(fp, key, cipher, passphrase, len); + break; } fclose(fp); return success; @@ -211,6 +218,8 @@ break; case KEY_DSA: case KEY_RSA: + case KEY_X509_RSA: + case KEY_X509_DSA: return key_save_private_pem(key, filename, passphrase, comment); break; @@ -430,6 +439,7 @@ Key *prv = NULL; char *name = ""; + debug("read PEM private key begin"); fp = fdopen(fd, "r"); if (fp == NULL) { error("fdopen failed: %s", strerror(errno)); @@ -462,6 +472,8 @@ error("PEM_read_PrivateKey: mismatch or " "unknown EVP_PKEY save_type %d", pk->save_type); } + if (prv) + x509key_load_cert(prv, fp); fclose(fp); if (pk != NULL) EVP_PKEY_free(pk); @@ -607,6 +619,7 @@ Key *pub; char file[MAXPATHLEN]; + debug3("key_load_public(%.200s,...)", filename); pub = key_load_public_type(KEY_RSA1, filename, commentp); if (pub != NULL) return pub; diff -ruN openssh-3.4p1/config.h.in openssh-3.4p1+x509e/config.h.in --- openssh-3.4p1/config.h.in 2002-06-26 17:08:19.000000000 +0300 +++ openssh-3.4p1+x509e/config.h.in 2002-10-01 16:24:24.000000000 +0300 @@ -1,5 +1,5 @@ /* config.h.in. Generated from configure.ac by autoheader. */ -/* $Id: acconfig.h,v 1.141 2002/06/25 22:35:16 tim Exp $ */ +/* $Id$ */ #ifndef _CONFIG_H #define _CONFIG_H @@ -289,6 +289,9 @@ /* Specify default $PATH */ #undef USER_PATH +/* Specify location of ssh CA root */ +#undef SSHCADIR + /* Specify location of ssh.pid */ #undef _PATH_SSH_PIDDIR diff -ruN openssh-3.4p1/configure openssh-3.4p1+x509e/configure --- openssh-3.4p1/configure 2002-06-26 17:08:18.000000000 +0300 +++ openssh-3.4p1+x509e/configure 2002-11-18 17:38:54.000000000 +0200 @@ -873,6 +873,7 @@ --with-ipv4-default Use IPv4 by connections unless '-6' specified --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-pid-dir=PATH Specify location of ssh.pid file --with-lastlog=FILE|DIR specify lastlog location common locations @@ -8280,6 +8281,66 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi +# Check vulnerable for ASN.1 encoding errors OpenSSL version. +# see http://www.openssl.org/news/secadv_20020730.txt +echo "$as_me:$LINENO: checking for ASN.1 encoding errors vulnerable OpenSSL version" >&5 +echo $ECHO_N "checking for ASN.1 encoding errors vulnerable OpenSSL version... $ECHO_C" >&6 +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling" >&5 +echo "$as_me: error: cannot run test program while cross compiling" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#include +#include + +int main(void) { + unsigned long ssl_ver = SSLeay(); + /* 0.9.6X where X > e */ + if ((0x0090606fL <= ssl_ver) && (ssl_ver <= 0x00906fffL)) + exit (0); + /* 0.9.7X where X > beta2 */ + if ((0x00907003L <= ssl_ver)) + exit (0); + exit (1); + return (1); +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + { echo "$as_me:$LINENO: WARNING: Your OpenSSL library might is vulnerable for ASN.1 encoding errors" >&5 +echo "$as_me: WARNING: Your OpenSSL library might is vulnerable for ASN.1 encoding errors" >&2;} + + +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + # Some Linux systems (Slackware) need crypt() from libcrypt, *not* the # version in OpenSSL. Skip this for PAM if test "x$PAM_MSG" = "xno" -a "x$check_for_libcrypt_later" = "x1"; then @@ -15871,6 +15932,33 @@ fi; +# Where to place ssh CA root +sshcadir='${sysconfdir}/ca' +sshcadir=`eval echo ${sshcadir}` +sshcadir=`eval echo ${sshcadir}` +case $sshcadir in + NONE/*) sshcadir=`echo $sshcadir | sed "s~NONE~$ac_default_prefix~"` ;; +esac + + +# Check whether --with-sshca-dir or --without-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; + +cat >>confdefs.h <<_ACEOF +#define SSHCADIR "$sshcadir" +_ACEOF + + + + # Where to place sshd.pid piddir=/var/run # make sure the directory exists @@ -16414,7 +16502,7 @@ fi -ac_config_files="$ac_config_files Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds" +ac_config_files="$ac_config_files Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds tests/CA/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -16891,6 +16979,7 @@ "openbsd-compat/Makefile" ) CONFIG_FILES="$CONFIG_FILES openbsd-compat/Makefile" ;; "scard/Makefile" ) CONFIG_FILES="$CONFIG_FILES scard/Makefile" ;; "ssh_prng_cmds" ) CONFIG_FILES="$CONFIG_FILES ssh_prng_cmds" ;; + "tests/CA/Makefile" ) CONFIG_FILES="$CONFIG_FILES tests/CA/Makefile" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -17032,6 +17121,7 @@ s,@MANTYPE@,$MANTYPE,;t t s,@mansubdir@,$mansubdir,;t t s,@user_path@,$user_path,;t t +s,@sshcadir@,$sshcadir,;t t s,@piddir@,$piddir,;t t CEOF @@ -17497,6 +17587,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" diff -ruN openssh-3.4p1/configure.ac openssh-3.4p1+x509e/configure.ac --- openssh-3.4p1/configure.ac 2002-06-26 01:35:16.000000000 +0300 +++ openssh-3.4p1+x509e/configure.ac 2002-11-14 11:14:24.000000000 +0200 @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.72 2002/06/25 22:35:16 tim Exp $ +# $Id$ AC_INIT AC_CONFIG_SRCDIR([ssh.c]) @@ -787,6 +787,35 @@ ] ) +# Check vulnerable for ASN.1 encoding errors OpenSSL version. +# see http://www.openssl.org/news/secadv_20020730.txt +AC_MSG_CHECKING([for ASN.1 encoding errors vulnerable OpenSSL version]) +AC_TRY_RUN( + [ +#include +#include + +int main(void) { + unsigned long ssl_ver = SSLeay(); + /* 0.9.6X where X > e */ + if ((0x0090606fL <= ssl_ver) && (ssl_ver <= 0x00906fffL)) + exit (0); + /* 0.9.7X where X > beta2 */ + if ((0x00907003L <= ssl_ver)) + exit (0); + exit (1); + return (1); +} + ], + [ + AC_MSG_RESULT(no) + ], + [ + AC_MSG_RESULT(yes) + AC_MSG_WARN(Your OpenSSL library might is vulnerable for ASN.1 encoding errors) + ] +) + # Some Linux systems (Slackware) need crypt() from libcrypt, *not* the # version in OpenSSL. Skip this for PAM if test "x$PAM_MSG" = "xno" -a "x$check_for_libcrypt_later" = "x1"; then @@ -2103,6 +2132,27 @@ ] ) +# 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") +AC_SUBST(sshcadir) + + # Where to place sshd.pid piddir=/var/run # make sure the directory exists @@ -2363,7 +2413,7 @@ fi AC_EXEEXT -AC_CONFIG_FILES([Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds]) +AC_CONFIG_FILES([Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds tests/CA/Makefile]) AC_OUTPUT # Print summary of options @@ -2385,6 +2435,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" diff -ruN openssh-3.4p1/hostfile.c openssh-3.4p1+x509e/hostfile.c --- openssh-3.4p1/hostfile.c 2001-12-21 03:47:09.000000000 +0200 +++ openssh-3.4p1+x509e/hostfile.c 2002-11-18 11:01:40.000000000 +0200 @@ -13,6 +13,8 @@ * * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. * Copyright (c) 1999 Niels Provos. All rights reserved. + * X509 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 @@ -36,13 +38,14 @@ */ #include "includes.h" -RCSID("$OpenBSD: hostfile.c,v 1.29 2001/12/18 10:04:21 jakob Exp $"); +RCSID("$OpenBSD$"); #include "packet.h" #include "match.h" #include "key.h" #include "hostfile.h" #include "log.h" +#include "ssh-x509.h" /* * Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the @@ -193,7 +196,13 @@ if (!f) return 0; fprintf(f, "%s ", host); - if (key_write(key, f)) { + 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 { + success = key_write(key, f); + } + if (success) { success = 1; } else { error("add_host_to_hostfile: saving key in %s failed", filename); diff -ruN openssh-3.4p1/key.c openssh-3.4p1+x509e/key.c --- openssh-3.4p1/key.c 2002-06-24 00:21:31.000000000 +0300 +++ openssh-3.4p1+x509e/key.c 2002-11-14 11:05:52.000000000 +0200 @@ -10,6 +10,8 @@ * * * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * X509 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,7 +34,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: key.c,v 1.45 2002/06/23 03:26:19 deraadt Exp $"); +RCSID("$OpenBSD$"); #include @@ -41,6 +43,7 @@ #include "rsa.h" #include "ssh-dss.h" #include "ssh-rsa.h" +#include "ssh-x509.h" #include "uuencode.h" #include "buffer.h" #include "bufaux.h" @@ -57,9 +60,11 @@ k->flags = 0; k->dsa = NULL; k->rsa = NULL; + k->x509 = NULL; switch (k->type) { case KEY_RSA1: case KEY_RSA: + case KEY_X509_RSA: if ((rsa = RSA_new()) == NULL) fatal("key_new: RSA_new failed"); if ((rsa->n = BN_new()) == NULL) @@ -67,8 +72,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: if ((dsa = DSA_new()) == NULL) fatal("key_new: DSA_new failed"); if ((dsa->p = BN_new()) == NULL) @@ -80,6 +90,10 @@ if ((dsa->pub_key = BN_new()) == NULL) fatal("key_new: BN_new failed"); k->dsa = dsa; + if (k->type == KEY_X509_DSA) { + if ((k->x509 = X509_new()) == NULL) + fatal("key_new: X509_new failed"); + } break; case KEY_UNSPEC: break; @@ -97,6 +111,7 @@ switch (k->type) { case KEY_RSA1: case KEY_RSA: + case KEY_X509_RSA: if ((k->rsa->d = BN_new()) == NULL) fatal("key_new_private: BN_new failed"); if ((k->rsa->iqmp = BN_new()) == NULL) @@ -109,10 +124,25 @@ 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: if ((k->dsa->priv_key = BN_new()) == NULL) fatal("key_new_private: BN_new failed"); + if (k->type == KEY_X509_DSA) { + debug3("key_new_private: X509(dsa) MORE ...?"); + /* + if ((k->x509 = X509_new()) == NULL) + fatal("key_new: X509_new failed"); + */ + } break; case KEY_UNSPEC: break; @@ -137,6 +167,21 @@ DSA_free(k->dsa); k->dsa = NULL; break; + case KEY_X509_RSA: + case KEY_X509_DSA: + if (k->dsa != NULL) { + DSA_free(k->dsa); + k->dsa = NULL; + } + if (k->rsa != NULL) { + RSA_free(k->rsa); + k->rsa = NULL; + } + if (k->x509 != NULL) { + X509_free(k->x509); + k->x509 = NULL; + } + break; case KEY_UNSPEC: break; default: @@ -145,6 +190,7 @@ } xfree(k); } + int key_equal(Key *a, Key *b) { @@ -164,6 +210,15 @@ BN_cmp(a->dsa->g, b->dsa->g) == 0 && BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; break; + case KEY_X509_RSA: + case KEY_X509_DSA: + /* 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 + */ + return X509_subject_name_cmp(a->x509, b->x509) == 0; + break; default: fatal("key_equal: bad key type %d", a->type); break; @@ -205,6 +260,8 @@ break; case KEY_DSA: case KEY_RSA: + case KEY_X509_RSA: /*XXX*/ + case KEY_X509_DSA: /*XXX*/ key_to_blob(k, &blob, &len); break; case KEY_UNSPEC: @@ -408,6 +465,8 @@ case KEY_UNSPEC: case KEY_RSA: case KEY_DSA: + case KEY_X509_RSA: + case KEY_X509_DSA: space = strchr(cp, ' '); if (space == NULL) { debug3("key_read: no space"); @@ -432,6 +491,9 @@ debug3("key_read: type mismatch"); return -1; } + k = x509key_from_subject(type, cp); + if(k != NULL) + goto noblob; len = 2*strlen(cp); blob = xmalloc(len); n = uudecode(cp, blob, len); @@ -451,7 +513,30 @@ key_free(k); return -1; } +noblob: /*XXXX*/ + if (ret->type == KEY_X509_RSA || + ret->type == KEY_X509_DSA ) { + if (ret->rsa != NULL) + RSA_free(ret->rsa); + ret->rsa = k->rsa; + k->rsa = NULL; + if (ret->dsa != NULL) + DSA_free(ret->dsa); + ret->dsa = k->dsa; + k->dsa = NULL; + if (ret->x509 != NULL) + X509_free(ret->x509); + ret->x509 = k->x509; + k->x509 = NULL; +#ifdef DEBUG_PK + if (ret->type == KEY_X509_RSA) + RSA_print_fp(stderr, ret->rsa, 8); + else + DSA_print_fp(stderr, ret->dsa, 8); +#endif + success = 1; + } else if (ret->type == KEY_RSA) { if (ret->rsa != NULL) RSA_free(ret->rsa); @@ -517,6 +602,8 @@ } xfree(blob); xfree(uu); + } else if ( (key->type == KEY_X509_RSA) || (key->type == KEY_X509_DSA) ) { + success = x509key_write(key, f); } return success; } @@ -534,6 +621,14 @@ case KEY_DSA: return "DSA"; break; + case KEY_X509_RSA: + if(k->rsa) return "RSA+cert"; + return "X509(rsa)"; + break; + case KEY_X509_DSA: + if(k->dsa) return "DSA+cert"; + return "X509(dsa)"; + break; } return "unknown"; } @@ -548,6 +643,12 @@ case KEY_DSA: return "ssh-dss"; break; + case KEY_X509_RSA: + return "x509v3-sign-rsa"; + break; + case KEY_X509_DSA: + return "x509v3-sign-dss"; + break; } return "ssh-unknown"; } @@ -637,6 +738,7 @@ int key_type_from_name(char *name) { + debug3("call key_type_from_name(%.200s) ...", name); if (strcmp(name, "rsa1") == 0) { return KEY_RSA1; } else if (strcmp(name, "rsa") == 0) { @@ -647,6 +749,10 @@ return KEY_RSA; } else if (strcmp(name, "ssh-dss") == 0) { return KEY_DSA; + } else if (strcmp(name, "x509v3-sign-rsa") == 0) { + return KEY_X509_RSA; + } else if (strcmp(name, "x509v3-sign-dss") == 0) { + return KEY_X509_DSA; } debug2("key_type_from_name: unknown key type '%s'", name); return KEY_UNSPEC; @@ -681,14 +787,19 @@ char *ktype; int rlen, type; Key *key = NULL; + debug3("key_from_blob(..., %d)", blen); #ifdef DEBUG_PK dump_base64(stderr, blob, blen); #endif + if ((key = x509key_from_blob(blob, blen)) != NULL) { + return key; + } buffer_init(&b); buffer_append(&b, blob, blen); ktype = buffer_get_string(&b, NULL); type = key_type_from_name(ktype); + debug3("key_from_blob(..., ...) ktype=%.30s", ktype); switch (type) { case KEY_RSA: @@ -749,6 +860,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); @@ -779,6 +895,10 @@ case KEY_RSA: return ssh_rsa_sign(key, sigp, lenp, data, datalen); break; + case KEY_X509_RSA: + case KEY_X509_DSA: + return ssh_x509_sign(key, sigp, lenp, data, datalen); + break; default: error("key_sign: illegal key type %d", key->type); return -1; @@ -806,6 +926,10 @@ case KEY_RSA: return ssh_rsa_verify(key, signature, signaturelen, data, datalen); break; + case KEY_X509_RSA: + case KEY_X509_DSA: + return ssh_x509_verify(key, signature, signaturelen, data, datalen); + break; default: error("key_verify: illegal key type %d", key->type); return -1; @@ -828,6 +952,7 @@ switch (k->type) { 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) @@ -836,6 +961,7 @@ fatal("key_demote: BN_dup failed"); break; 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) @@ -848,9 +974,19 @@ fatal("key_demote: BN_dup failed"); break; default: - fatal("key_free: bad key type %d", k->type); + fatal("key_demote: bad key type %d", k->type); break; } + switch (k->type) { + case KEY_X509_RSA: + case KEY_X509_DSA: + if(k->x509) { + if ((pk->x509 = X509_dup(k->x509)) == NULL) + fatal("key_demote: X509_dup failed"); + } else + fatal("key_demote: no X509 data"); + break; + } return (pk); } diff -ruN openssh-3.4p1/key.h openssh-3.4p1+x509e/key.h --- openssh-3.4p1/key.h 2002-03-22 03:45:55.000000000 +0200 +++ openssh-3.4p1+x509e/key.h 2002-11-14 11:18:17.000000000 +0200 @@ -1,7 +1,9 @@ -/* $OpenBSD: key.h,v 1.19 2002/03/18 17:23:31 markus Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * X509 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 @@ -28,12 +30,15 @@ #include #include +#include typedef struct Key Key; enum types { KEY_RSA1, KEY_RSA, KEY_DSA, + KEY_X509_RSA, + KEY_X509_DSA, KEY_UNSPEC }; enum fp_type { @@ -53,6 +58,7 @@ int flags; RSA *rsa; DSA *dsa; + X509 *x509; }; Key *key_new(int); diff -ruN openssh-3.4p1/Makefile.in openssh-3.4p1+x509e/Makefile.in --- openssh-3.4p1/Makefile.in 2002-06-26 02:45:42.000000000 +0300 +++ openssh-3.4p1+x509e/Makefile.in 2002-11-18 17:17:25.000000000 +0200 @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.217 2002/06/25 23:45:42 tim Exp $ +# $Id$ # uncomment if you run a non bourne compatable shell. Ie. csh #SHELL = @SH@ @@ -14,6 +14,7 @@ mandir=@mandir@ mansubdir=@mansubdir@ sysconfdir=@sysconfdir@ +sshcadir=@sshcadir@ piddir=@piddir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ @@ -29,6 +30,7 @@ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ + -DSSHCADIR=\"$(sshcadir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ @@ -58,9 +60,11 @@ @NO_SFTP@SFTP_PROGS=sftp-server$(EXEEXT) sftp$(EXEEXT) +X509_OBJS=ssh-x509.o x509store.o + TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} $(SFTP_PROGS) -LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o msg.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o scard-opensc.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o monitor_wrap.o monitor_fdpass.o +LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o msg.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o scard-opensc.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o monitor_wrap.o monitor_fdpass.o $(X509_OBJS) SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o @@ -83,6 +87,10 @@ -D/etc/ssh/ssh_host_key=$(sysconfdir)/ssh_host_key \ -D/etc/ssh/ssh_host_dsa_key=$(sysconfdir)/ssh_host_dsa_key \ -D/etc/ssh/ssh_host_rsa_key=$(sysconfdir)/ssh_host_rsa_key \ + -D/etc/ssh/ca/ca-bundle.crt=$(sshcadir)/ca-bundle.crt \ + -D/etc/ssh/ca/crt=$(sshcadir)/crt \ + -D/etc/ssh/ca/ca-bundle.crl=$(sshcadir)/ca-bundle.crl \ + -D/etc/ssh/ca/crl=$(sshcadir)/crl \ -D/var/run/sshd.pid=$(piddir)/sshd.pid \ -D/etc/ssh/moduli=$(sysconfdir)/moduli \ -D/etc/ssh/sshrc=$(sysconfdir)/sshrc \ @@ -167,6 +175,7 @@ rm -f *.o *.a $(TARGETS) logintest config.cache config.log rm -f *.out core (cd openbsd-compat && $(MAKE) clean) + (cd tests/CA && $(MAKE) clean) distclean: rm -f *.o *.a $(TARGETS) logintest config.cache config.log @@ -175,6 +184,7 @@ rm -rf autom4te.cache (cd openbsd-compat && $(MAKE) distclean) (cd scard && $(MAKE) distclean) + (cd tests/CA && $(MAKE) distclean) veryclean: rm -f configure config.h.in *.0 @@ -183,6 +193,7 @@ rm -f Makefile config.h config.status ssh_prng_cmds *~ (cd openbsd-compat && $(MAKE) distclean) (cd scard && $(MAKE) distclean) + (cd tests/CA && $(MAKE) distclean) mrproper: distclean @@ -202,7 +213,7 @@ install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files check-user: - id $(SSH_PRIVSEP_USER) || \ + @id $(SSH_PRIVSEP_USER) > /dev/null || \ echo "WARNING: Privilege separation user \"$(SSH_PRIVSEP_USER)\" does not exist" scard-install: @@ -217,6 +228,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) $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH) chmod 0700 $(DESTDIR)$(PRIVSEP_PATH) $(INSTALL) -m 0755 -s ssh $(DESTDIR)$(bindir)/ssh @@ -344,3 +357,23 @@ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 + + +check: $(TARGETS) check-certs + +check-certs: + @if test ! -d "tests/CA"; then \ + mkdir -p "tests/CA" || exit 1; \ + fi + @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" \ + $@ ) diff -ruN openssh-3.4p1/myproposal.h openssh-3.4p1+x509e/myproposal.h --- openssh-3.4p1/myproposal.h 2002-04-05 01:10:39.000000000 +0300 +++ openssh-3.4p1+x509e/myproposal.h 2002-11-14 11:05:00.000000000 +0200 @@ -1,7 +1,9 @@ -/* $OpenBSD: myproposal.h,v 1.14 2002/04/03 09:26:11 markus Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. + * X509 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 @@ -24,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define KEX_DEFAULT_KEX "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1" -#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss" +#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss,x509v3-sign-rsa,x509v3-sign-dss" #define KEX_DEFAULT_ENCRYPT \ "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" diff -ruN openssh-3.4p1/pathnames.h openssh-3.4p1+x509e/pathnames.h --- openssh-3.4p1/pathnames.h 2002-06-06 22:57:34.000000000 +0300 +++ openssh-3.4p1+x509e/pathnames.h 2002-11-14 11:06:54.000000000 +0200 @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.13 2002/05/23 19:24:30 markus Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen @@ -10,6 +10,29 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X509 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" @@ -167,3 +190,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 global 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-3.4p1/readconf.c openssh-3.4p1+x509e/readconf.c --- openssh-3.4p1/readconf.c 2002-06-21 03:41:52.000000000 +0300 +++ openssh-3.4p1+x509e/readconf.c 2002-11-14 11:06:21.000000000 +0200 @@ -9,10 +9,33 @@ * 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 store 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. */ #include "includes.h" -RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $"); +RCSID("$OpenBSD$"); #include "ssh.h" #include "xmalloc.h" @@ -114,6 +137,11 @@ oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, oClearAllForwardings, oNoHostAuthenticationForLocalhost, + sAllowedServerCertPurpose, + sCACertificateFile, sCACertificatePath, + sCARevocationFile, sCARevocationPath, + sUserCACertificateFile, sUserCACertificatePath, + sUserCARevocationFile, sUserCARevocationPath, oDeprecated } OpCodes; @@ -186,6 +214,15 @@ { "smartcarddevice", oSmartcardDevice }, { "clearallforwardings", oClearAllForwardings }, { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, + { "allowedcertpurpose", sAllowedServerCertPurpose }, + { "cacertificatefile", sCACertificateFile }, + { "cacertificatepath", sCACertificatePath }, + { "carevocationfile", sCARevocationFile }, + { "carevocationpath", sCARevocationPath }, + { "usercacertificatefile", sUserCACertificateFile }, + { "usercacertificatepath", sUserCACertificatePath }, + { "usercarevocationfile", sUserCARevocationFile }, + { "usercarevocationpath", sUserCARevocationPath }, { NULL, oBadOption } }; @@ -669,6 +706,58 @@ *intptr = value; break; + case sAllowedServerCertPurpose: + arg = strdelim(&s); + if (arg && *arg) { + if (strcasecmp(arg, "skip") == 0) goto skip_purpose; + + { /* convert string to OpenSSL index */ + int purpose_index; + purpose_index = sshserver_cert_purpose (arg); + if (purpose_index < 0) + fatal("config error: unsupported purpose '%.30s' in file %s line %d.", arg, filename, linenum); + + options->allowedcertpurpose = purpose_index; + } + } else { +skip_purpose: + options->allowedcertpurpose = -2; + verbose("config warning: option is set to don`t check certificate purpose in file %s line %d.", filename, linenum); + } + break; + + case sCACertificateFile: + case sCACertificatePath: + case sCARevocationFile: + case sCARevocationPath: + case sUserCACertificateFile: + case sUserCACertificatePath: + case sUserCARevocationFile: + case sUserCARevocationPath: + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + switch (opcode) { + case sCACertificateFile: + options->ca.certificate_file = xstrdup(arg); break; + case sCACertificatePath: + options->ca.certificate_path = xstrdup(arg); break; + case sCARevocationFile: + options->ca.revocation_file = xstrdup(arg); break; + case sCARevocationPath: + options->ca.revocation_path = xstrdup(arg); break; + case sUserCACertificateFile: + options->userca.certificate_file = xstrdup(arg); break; + case sUserCACertificatePath: + options->userca.certificate_path = xstrdup(arg); break; + case sUserCARevocationFile: + options->userca.revocation_file = xstrdup(arg); break; + case sUserCARevocationPath: + options->userca.revocation_path = xstrdup(arg); break; + default: + } + break; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); @@ -793,6 +882,56 @@ options->bind_address = NULL; options->smartcard_device = NULL; options->no_host_authentication_for_localhost = - 1; + options->allowedcertpurpose = -1; + options->ca.certificate_file = NULL; + options->ca.certificate_path = NULL; + options->ca.revocation_file = NULL; + options->ca.revocation_path = NULL; + options->userca.certificate_file = NULL; + options->userca.certificate_path = NULL; + options->userca.revocation_file = NULL; + options->userca.revocation_path = NULL; +} + +static int +ssh_x509store_init (Options *options) { + int x509_store_loaded = 0; + X509_STORE *x509store_ctx = X509_STORE_new(); + + debug3("ssh_x509store_init() begin"); + if (x509store_ctx == NULL) return x509_store_loaded; + ssh_x509store_setcontext(x509store_ctx, options->allowedcertpurpose); + + if (options->userca.certificate_path) { + if (ssh_x509store_addlookup(X509_L_ADD_DIR , options->userca.certificate_path)) { + x509_store_loaded = 1; + } + } + + if (options->userca.certificate_file) { + if (ssh_x509store_addlookup(X509_L_FILE_LOAD, options->userca.certificate_file)) { + x509_store_loaded = 1; + } + } + + if (options->ca.certificate_path) { + if (ssh_x509store_addlookup(X509_L_ADD_DIR , options->ca.certificate_path)) { + x509_store_loaded = 1; + } + } + + if (options->ca.certificate_file) { + if (ssh_x509store_addlookup(X509_L_FILE_LOAD, options->ca.certificate_file)) { + x509_store_loaded = 1; + } + } + + if (!x509_store_loaded) { + ssh_x509store_setcontext(NULL, -1); + debug("bad x509store configuration"); + } + debug3("ssh_x509store_init() end"); + return x509_store_loaded; } /* @@ -912,4 +1051,26 @@ /* 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 */ + + if (options->allowedcertpurpose == -1) + options->allowedcertpurpose = sshserver_cert_purpose("sslserver"); + if (options->ca.certificate_file == NULL) + options->ca.certificate_file = _PATH_CA_CERTIFICATE_FILE; + if (options->ca.certificate_path == NULL) + options->ca.certificate_path = _PATH_CA_CERTIFICATE_PATH; + if (options->ca.revocation_file == NULL) + options->ca.revocation_file = _PATH_CA_REVOCATION_FILE; + if (options->ca.revocation_path == NULL) + options->ca.revocation_path = _PATH_CA_REVOCATION_PATH; + + if (options->userca.certificate_file == NULL) + options->userca.certificate_file = _PATH_USERCA_CERTIFICATE_FILE; + if (options->userca.certificate_path == NULL) + options->userca.certificate_path = _PATH_USERCA_CERTIFICATE_PATH; + if (options->userca.revocation_file == NULL) + options->userca.revocation_file = _PATH_USERCA_REVOCATION_FILE; + if (options->userca.revocation_path == NULL) + options->userca.revocation_path = _PATH_USERCA_REVOCATION_PATH; + + ssh_x509store_init(options); } diff -ruN openssh-3.4p1/readconf.h openssh-3.4p1+x509e/readconf.h --- openssh-3.4p1/readconf.h 2002-06-09 23:04:03.000000000 +0300 +++ openssh-3.4p1+x509e/readconf.h 2002-11-14 11:06:17.000000000 +0200 @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.43 2002/06/08 05:17:01 markus Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen @@ -11,12 +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 store 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. */ #ifndef READCONF_H #define READCONF_H #include "key.h" +#include "x509store.h" /* Data structure for representing a forwarding request. */ @@ -100,6 +124,13 @@ Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; int clear_forwardings; int no_host_authentication_for_localhost; + + /* allowed server certificate purpose */ + int allowedcertpurpose; + /* sshd PKI(X509) global store */ + X509StoreOptions ca; + /* sshd PKI(X509) user store */ + X509StoreOptions userca; } Options; diff -ruN openssh-3.4p1/README.x509v3 openssh-3.4p1+x509e/README.x509v3 --- openssh-3.4p1/README.x509v3 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/README.x509v3 2002-11-21 17:56:39.000000000 +0200 @@ -0,0 +1,169 @@ + Roumen Petrov + Sofia, Bulgaria + Thu Nov 21 2002 + +How to use x509certificates with OpenSSH? + +1.) server configuration: +1.1.) .../sshd_config +CACertificateFile /etc/ssh/ca/ca-bundle.crt + +The CACertificateFile should contain multiple certificates 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 + + +CACertificatePath /etc/ssh/ca/crt + +CACertificatePath is a directory of trusted certificates. +The certificates(files) should have name of the form: hash. or +have symbolic links to them of this form. Hash is result from command +like this: +$ openssl x509 -in path_to_file_with_cert -noout -hash + +HostKey ... +Now hostkey can contain private key and x509 certificate. + +1.2.) append in USER_HOME/.ssh/authorized_keys a record with following +format: + +where: +KEY_TYPE:=x509v3-sign-rsa|x509v3-sign-dss (case sensitive !) +WORDDN:={Distinguished Name| + Distinguished-Name| + Distinguished_Name| + DistinguishedName| + DN| + Subject} +WORDDNSUFF:='='|':'|'' +Notes: +- WORDDN is case insensitive ! +- "Distinguished Name"/Subject is equal to output from command: +$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE + +Shell sample: +$ printf '%s' "x509v3-sign-rsa "; + openssl x509 -noout -subject \ + -in A_CERTIFICATE_FILE \ + >> PATH_TO_USER_HOME/.ssh/authorized_keys + +NOTES: +- adjust user authorized_keys file ownership - user must have at least +read access. +- SecSH x509v3 key type is "x509v3-sign-rsa" or "x509v3-sign-dss". +- currently distinguished name in RFC2253 format is not supported ! + Command is: +$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE -nameopt RFC2253 + + +2.) client settings: +2.1.) IdentityFile +Depends from client. To use x509 certificate "OpenSSH id-file" must +contain both sections - private key and certificate: +-----BEGIN RSA PRIVATE KEY----- +..... +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +..... +-----END CERTIFICATE----- +NOTE: Don`t forget to update public key file with command: +$ ssh-keygen -y -f KEY_FILE_NAME > KEY_FILE_NAME.pub +Command ssh-add use public key file! + +2.2.) global ssh_config or $HOME/.ssh/config +Check options [User]CACertificatePath and [User]CACertificateFile. Same +as p. 1.1. All four option are for "x509 store". "x509 store" is used +to verify server hostkey. + +Note: When we use own CA we must import CA certificate[s] to +"x509 store". More info on: + http://satva.skalasoft.com/~rumen/domino_CA/#dca2bundle + + + +3.) test x509 certificates. + +3.1.) In openssh build dir run "make check". If x509 test scripts fail +edit OPENSSH_SOURCE_PATH/tests/CA/config file. Variables is config file: + +3.1.1) main variables: + - SUDO: + on some system sshd must be started as root. + if necessary set variable to sudo and configure sudo'ers. + - OPENSSL: + path to openssl. if necessary set variable. + - TMPDIR: + directory for temporary files. defailt is "/tmp". + +3.1.2) server section: + Read sshd_config.5 manual page for valid values. + - SSHSERVER_USEPRIVILEGESEPARATION: + sshd "UsePrivilegeSeparation" option. + if necessary set to "no", to disable privilege separation. + - SSHSERVER_SYSLOGFACILITY=LOCAL1 + sshd "SyslogFacility" option. + - SSHSERVER_LOGLEVEL=INFO + sshd 'LogLevel' option. + +3.1.3) section related to certificates: + - RSA_DIGEST_LIST: + List with RSA digests in support of openssl. + Check list and select. + +3.2.) Current test scripts use only rsa as server hostkey. +To test sshd with x509 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 OSes". +This is not part of document. +Tip: use testid_*.p12 files created after make check from directory +OPENSSH_BUILD_PATH/tests/CA. and read related 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 + +1-cre_cadb.sh: + create "Test CA" directories and files. + +2-cre_cakeys.sh: + create "Test CA" private keys and certificates. + +3-cre_certs.sh: + create client/server certificates. + this command create files with mask + "PATH_TO_KEYFILEn-[.]" + , where is in format "rsa_" or "dsa". + DIGEST are form variable "RSA_DIGEST_LIST" specified in "config" + file. Files without extention are openssh identity or hostkey files. + File with .pub extention contain openssh public key (BLOB format). + File with .crt extention contain openssl "text output" for identity + files. File with .p12 extention are for "Microsoft Windows keystore". + + +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: + see DESCRIPTION in each file. + + +Enjoy ;-) diff -ruN openssh-3.4p1/scp.0 openssh-3.4p1+x509e/scp.0 --- openssh-3.4p1/scp.0 2002-06-26 17:08:06.000000000 +0300 +++ openssh-3.4p1+x509e/scp.0 2002-11-18 17:38:39.000000000 +0200 @@ -43,7 +43,7 @@ -q Disables the progress meter. - -C Compression enable. Passes the -C flag to ssh(1) to enable comM-- + -C Compression enable. Passes the -C flag to ssh(1) to enable com- pression. -F ssh_config diff -ruN openssh-3.4p1/servconf.c openssh-3.4p1+x509e/servconf.c --- openssh-3.4p1/servconf.c 2002-06-25 06:22:04.000000000 +0300 +++ openssh-3.4p1+x509e/servconf.c 2002-11-14 11:06:12.000000000 +0200 @@ -7,10 +7,33 @@ * 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 store 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. */ #include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.112 2002/06/23 09:46:51 deraadt Exp $"); +RCSID("$OpenBSD$"); #if defined(KRB4) #include @@ -122,11 +145,45 @@ options->client_alive_count_max = -1; options->authorized_keys_file = NULL; options->authorized_keys_file2 = NULL; + options->allowedcertpurpose = -1; + options->ca.certificate_file = NULL; + options->ca.certificate_path = NULL; + options->ca.revocation_file = NULL; + options->ca.revocation_path = NULL; /* Needs to be accessable in many places */ use_privsep = -1; } +static int +sshd_x509store_init (ServerOptions *options) { + int x509_store_loaded = 0; + X509_STORE *x509store_ctx = X509_STORE_new(); + + debug3("sshd_x509store_init() begin"); + if (x509store_ctx == NULL) return x509_store_loaded; + ssh_x509store_setcontext(x509store_ctx, options->allowedcertpurpose); + + if (options->ca.certificate_path) { + if (ssh_x509store_addlookup(X509_L_ADD_DIR , options->ca.certificate_path)) { + x509_store_loaded = 1; + } + } + + if (options->ca.certificate_file) { + if (ssh_x509store_addlookup(X509_L_FILE_LOAD, options->ca.certificate_file)) { + x509_store_loaded = 1; + } + } + + if (!x509_store_loaded) { + ssh_x509store_setcontext(NULL, -1); + debug("bad x509store configuration"); + } + debug3("sshd_x509store_init() end"); + return x509_store_loaded; +} + void fill_default_server_options(ServerOptions *options) { @@ -253,6 +310,17 @@ if (options->authorized_keys_file == NULL) options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; + if (options->allowedcertpurpose == -1) + options->allowedcertpurpose = sshclient_cert_purpose("sslclient"); + if (options->ca.certificate_file == NULL) + options->ca.certificate_file = _PATH_CA_CERTIFICATE_FILE; + if (options->ca.certificate_path == NULL) + options->ca.certificate_path = _PATH_CA_CERTIFICATE_PATH; + if (options->ca.revocation_file == NULL) + options->ca.revocation_file = _PATH_CA_REVOCATION_FILE; + if (options->ca.revocation_path == NULL) + options->ca.revocation_path = _PATH_CA_REVOCATION_PATH; + /* Turn privilege separation on by default */ if (use_privsep == -1) use_privsep = 1; @@ -266,6 +334,7 @@ } #endif + sshd_x509store_init(options); } /* Keyword tokens. */ @@ -299,6 +368,9 @@ sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, sUsePrivilegeSeparation, + sAllowedClientCertPurpose, + sCACertificateFile, sCACertificatePath, + sCARevocationFile, sCARevocationPath, sDeprecated } ServerOpCodes; @@ -376,6 +448,11 @@ { "authorizedkeysfile", sAuthorizedKeysFile }, { "authorizedkeysfile2", sAuthorizedKeysFile2 }, { "useprivilegeseparation", sUsePrivilegeSeparation}, + { "allowedcertpurpose", sAllowedClientCertPurpose }, + { "cacertificatefile", sCACertificateFile }, + { "cacertificatepath", sCACertificatePath }, + { "carevocationfile", sCARevocationFile }, + { "carevocationpath", sCARevocationPath }, { NULL, sBadOption } }; @@ -901,6 +978,47 @@ intptr = &options->client_alive_count_max; goto parse_int; + case sAllowedClientCertPurpose: + arg = strdelim(&cp); + if (arg && *arg) { + if (strcasecmp(arg, "skip") == 0) goto skip_purpose; + + { /* convert string to OpenSSL index */ + int purpose_index; + purpose_index = sshclient_cert_purpose (arg); + if (purpose_index < 0) + fatal("config error: unsupported purpose '%.30s' in file %s line %d.", arg, filename, linenum); + + options->allowedcertpurpose = purpose_index; + } + } else { +skip_purpose: + options->allowedcertpurpose = -2; + verbose("config warning: option is set to don`t check certificate purpose in file %s line %d.", filename, linenum); + } + break; + + + case sCACertificateFile: + case sCACertificatePath: + case sCARevocationFile: + case sCARevocationPath: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + switch (opcode) { + case sCACertificateFile: + options->ca.certificate_file = xstrdup(arg); break; + case sCACertificatePath: + options->ca.certificate_path = xstrdup(arg); break; + case sCARevocationFile: + options->ca.revocation_file = xstrdup(arg); break; + case sCARevocationPath: + options->ca.revocation_path = xstrdup(arg); break; + default: + } + break; + case sDeprecated: log("%s line %d: Deprecated option %s", filename, linenum, arg); diff -ruN openssh-3.4p1/servconf.h openssh-3.4p1+x509e/servconf.h --- openssh-3.4p1/servconf.h 2002-06-21 04:09:47.000000000 +0300 +++ openssh-3.4p1+x509e/servconf.h 2002-11-14 11:06:09.000000000 +0200 @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.58 2002/06/20 23:05:55 markus Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen @@ -11,11 +11,36 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * X509 certificate store 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. */ #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. */ @@ -131,6 +156,11 @@ char *authorized_keys_file; /* File containing public keys */ char *authorized_keys_file2; int pam_authentication_via_kbd_int; + + /* allowed client certificate purpose */ + int allowedcertpurpose; + /* sshd PKI(X509) global store */ + X509StoreOptions ca; } ServerOptions; void initialize_server_options(ServerOptions *); diff -ruN openssh-3.4p1/sftp.0 openssh-3.4p1+x509e/sftp.0 --- openssh-3.4p1/sftp.0 2002-06-26 17:08:08.000000000 +0300 +++ openssh-3.4p1+x509e/sftp.0 2002-11-18 17:38:41.000000000 +0200 @@ -13,15 +13,15 @@ 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 compresM-- + 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-interM-- - active authentication method is used; otherwise it will do so after sucM-- + 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 last usage format allows the sftp client to start in a remote direcM-- + The last usage format allows the sftp client to start in a remote direc- tory. The options are as follows: @@ -42,7 +42,7 @@ -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 does not have an sftp subsysM-- + version 1, or when the remote sshd does not have an sftp subsys- tem configured. -v Raise logging level. This option is also passed to ssh. @@ -106,7 +106,7 @@ help Display help text. lls [ls-options [path]] - Display local directory listing of either path or current direcM-- + Display local directory listing of either path or current direc- tory if path is not specified. lmkdir path @@ -118,7 +118,7 @@ lpwd Print local working directory. ls [path] - Display remote directory listing of either path or current direcM-- + Display remote directory listing of either path or current direc- tory if path is not specified. lumask umask diff -ruN openssh-3.4p1/ssh.0 openssh-3.4p1+x509e/ssh.0 --- openssh-3.4p1/ssh.0 2002-06-26 17:08:07.000000000 +0300 +++ openssh-3.4p1+x509e/ssh.0 2002-11-18 17:38:40.000000000 +0200 @@ -33,13 +33,13 @@ This form of authentication alone is normally not allowed by the server because it is not secure. - The second authentication method is the rhosts or hosts.equiv method comM-- + The second authentication method is the rhosts or hosts.equiv method com- bined with RSA-based host authentication. It means that if the login would be permitted by $HOME/.rhosts, $HOME/.shosts, /etc/hosts.equiv, or /etc/shosts.equiv, and if additionally the server can verify the client's host key (see /etc/ssh/ssh_known_hosts and $HOME/.ssh/known_hosts in the FILES section), only then login is permitted. This authentication method - closes security holes due to IP spoofing, DNS spoofing and routing spoofM-- + closes security holes due to IP spoofing, DNS spoofing and routing spoof- ing. [Note to the administrator: /etc/hosts.equiv, $HOME/.rhosts, and the rlogin/rsh protocol in general, are inherently insecure and should be disabled if security is desired.] @@ -57,7 +57,7 @@ checks if this key is permitted, and if so, sends the user (actually the ssh program running on behalf of the user) a challenge, a random number, encrypted by the user's public key. The challenge can only be decrypted - using the proper private key. The user's client then decrypts the chalM-- + using the proper private key. The user's client then decrypts the chal- lenge using the private key, proving that he/she knows the private key but without disclosing it to the server. @@ -69,13 +69,13 @@ directory on the remote machine (the authorized_keys file corresponds to the conventional $HOME/.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. RSA authentication is much more secure than rhosts authenM-- + the password. RSA authentication is much more secure than rhosts authen- tication. - The most convenient way to use RSA authentication may be with an authenM-- + The most convenient way to use RSA authentication may be with an authen- tication agent. See ssh-agent(1) for more information. - If other authentication methods fail, ssh prompts the user for a passM-- + If other authentication methods fail, ssh prompts the user for a pass- word. 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. @@ -102,10 +102,10 @@ If public key authentication fails or is not available a password can be sent encrypted to the remote host for proving the user's identity. - Additionally, ssh supports hostbased or challenge response authenticaM-- + Additionally, ssh supports hostbased or challenge response authentica- tion. - Protocol 2 provides additional mechanisms for confidentiality (the trafM-- + Protocol 2 provides additional mechanisms for confidentiality (the traf- fic is encrypted using 3DES, Blowfish, CAST128 or Arcfour) and integrity (hmac-md5, hmac-sha1). Note that protocol 1 lacks a strong mechanism for ensuring the integrity of the connection. @@ -126,18 +126,18 @@ if a tty is used. The session terminates when the command or shell on the remote machine - exits and all X11 and TCP/IP connections have been closed. The exit staM-- + exits and all X11 and TCP/IP connections have been closed. The exit sta- tus of the remote program is returned as the exit status of ssh. Escape Characters - When a pseudo terminal has been requested, ssh supports a number of funcM-- + 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 characM-- - ter can be changed in configuration files using the EscapeChar configuraM-- + 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: @@ -167,7 +167,7 @@ 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. ForM-- + from the local machine. The user should not manually set DISPLAY. For- warding of X11 connections can be configured on the command line or in configuration files. @@ -184,7 +184,7 @@ machine (and no cookies are sent in the plain). If the user is using an authentication agent, the connection to the agent - is automatically forwarded to the remote side unless disabled on the comM-- + is automatically forwarded to the remote side unless disabled on the com- mand line or in a configuration file. Forwarding of arbitrary TCP/IP connections over the secure channel can be @@ -194,13 +194,13 @@ Server authentication - ssh automatically maintains and checks a database containing identificaM-- + ssh automatically maintains and checks a database containing identifica- tions for all hosts it has ever been used with. Host keys are stored in $HOME/.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 a trojan horse from getting the user's passM-- + authentication to prevent a trojan horse from getting the user's pass- word. Another purpose of this mechanism is to prevent man-in-the-middle attacks which could otherwise be used to circumvent the encryption. The StrictHostKeyChecking option can be used to prevent logins to machines @@ -256,7 +256,7 @@ for protocol version 1, and $HOME/.ssh/id_rsa and $HOME/.ssh/id_dsa for protocol version 2. Identity files may also be specified on a per-host basis in the configuration file. - It is possible to have multiple -i options (and multiple identiM-- + It is possible to have multiple -i options (and multiple identi- ties specified in configuration files). -I smartcard_device @@ -286,11 +286,11 @@ ssh needs to ask for a password or passphrase; see also the -f option.) - -N Do not execute a remote command. This is useful for just forM-- + -N Do not execute a remote command. This is useful for just for- warding ports (protocol version 2 only). -o option - Can be used to give options in the format used in the configuraM-- + 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. @@ -308,11 +308,11 @@ -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 appliM-- - cations (eg. sftp). The subsystem is specified as the remote comM-- + facilitate the use of SSH as a secure transport for other appli- + cations (eg. sftp). The subsystem is specified as the remote com- mand. - -t Force pseudo-tty allocation. This can be used to execute arbiM-- + -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. @@ -320,7 +320,7 @@ -T Disable pseudo-tty allocation. -v Verbose mode. Causes ssh to print debugging messages about its - progress. This is helpful in debugging connection, authenticaM-- + progress. This is helpful in debugging connection, authentica- tion, and configuration problems. Multiple -v options increases the verbosity. Maximum is 3. @@ -332,14 +332,14 @@ -C Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11 and TCP/IP connections). The compression algorithm is the same used by gzip(1), and the - ``level'' can be controlled by the CompressionLevel option. ComM-- + ``level'' can be controlled by the CompressionLevel option. Com- pression is desirable on modem lines and other slow connections, but will only slow down things on fast networks. The default value can be set on a host-by-host basis in the configuration files; see the Compression option. -F configfile - Specifies an alternative per-user configuration file. If a conM-- + 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 $HOME/.ssh/config. @@ -351,7 +351,7 @@ 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 remote machine. Port forwardings can - also be specified in the configuration file. Only root can forM-- + also be specified in the configuration file. Only root can for- ward privileged ports. IPv6 addresses can be specified with an alternative syntax: port/host/hostport @@ -359,9 +359,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 connecM-- + 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 forwardM-- + made to host port hostport from the local machine. Port forward- ings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on the remote machine. IPv6 addresses can be specified with an alternative @@ -370,11 +370,11 @@ -D port Specifies a local ``dynamic'' application-level port forwarding. This works by allocating a socket to listen to port on the local - side, and whenever a connection is made to this port, the connecM-- + side, and whenever a connection is made to this port, the connec- tion is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. Currently the SOCKS4 protocol is supported, and - ssh will act as a SOCKS4 server. Only root can forward priviM-- + ssh will act as a SOCKS4 server. Only root can forward privi- leged ports. Dynamic port forwardings can also be specified in the configuration file. @@ -387,8 +387,8 @@ -6 Forces ssh to use IPv6 addresses only. CONFIGURATION FILES - ssh may additionally obtain configuration data from a per-user configuraM-- - tion file and a system-wide configuration file. The file format and conM-- + 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). ENVIRONMENT @@ -429,17 +429,17 @@ with the agent. SSH_CLIENT - Identifies the client end of the connection. The variable conM-- + Identifies the client end of the connection. The variable con- tains three space-separated values: client ip-address, client port number, and server port number. SSH_ORIGINAL_COMMAND - The variable contains the original command line if a forced comM-- - mand is executed. It can be used to extract the original arguM-- + The variable contains the original command line if a forced com- + mand is executed. It can be used to extract the original argu- ments. SSH_TTY - This is set to the name of the tty (path to the device) associM-- + This is set to the name of the tty (path to the device) associ- ated with the current shell or command. If the current session has no tty, this variable is not set. @@ -462,7 +462,7 @@ protocol 1 RSA, protocol 2 DSA, and protocol 2 RSA, respectively. These files contain sensitive data and should be readable by the user but not accessible by others (read/write/execute). Note - that ssh ignores a private key file if it is accessible by othM-- + that ssh ignores a private key file if it is accessible by oth- ers. It is possible to specify a passphrase when generating the key; the passphrase will be used to encrypt the sensitive part of this file using 3DES. @@ -472,13 +472,13 @@ identity file in human-readable form). The contents of the $HOME/.ssh/identity.pub file should be added to $HOME/.ssh/authorized_keys on all machines where the user wishes - to log in using protocol version 1 RSA authentication. The conM-- + to log in using protocol version 1 RSA authentication. The con- tents of the $HOME/.ssh/id_dsa.pub and $HOME/.ssh/id_rsa.pub file should be added to $HOME/.ssh/authorized_keys on all machines where the user wishes to log in using protocol version 2 DSA/RSA authentication. These files are not sensitive and can (but need - not) be readable by anyone. These files are never used automatiM-- - cally and are not necessary; they are only provided for the conM-- + not) be readable by anyone. These files are never used automati- + cally and are not necessary; they are only provided for the con- venience of the user. $HOME/.ssh/config @@ -498,9 +498,9 @@ by the system administrator to contain the public host keys of all machines in the organization. This file should be world- readable. This file contains public keys, one per line, in the - following format (fields separated by spaces): system name, pubM-- + following format (fields separated by spaces): system name, pub- lic key and optional comment field. When different names are - used for the same machine, all such names should be listed, sepaM-- + used for the same machine, all such names should be listed, sepa- rated by commas. The format is described on the sshd(8) manual page. @@ -533,7 +533,7 @@ Each line of the file contains a host name (in the canonical form returned by name servers), and then a user name on that host, separated by a space. On some machines this file may need to be - world-readable if the user's home directory is on a NFS partiM-- + world-readable if the user's home directory is on a NFS parti- tion, because sshd(8) 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 @@ -543,7 +543,7 @@ requires successful RSA host authentication before permitting .rhosts authentication. If the server machine does not have the client's host key in /etc/ssh/ssh_known_hosts, it can be stored - in $HOME/.ssh/known_hosts. The easiest way to do this is to conM-- + in $HOME/.ssh/known_hosts. The easiest way to do this is to con- nect back to the client from the server machine using ssh; this will automatically add the host key to $HOME/.ssh/known_hosts. @@ -587,7 +587,7 @@ 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 creM-- + 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. diff -ruN openssh-3.4p1/ssh-add.0 openssh-3.4p1+x509e/ssh-add.0 --- openssh-3.4p1/ssh-add.0 2002-06-26 17:08:06.000000000 +0300 +++ openssh-3.4p1+x509e/ssh-add.0 2002-11-18 17:38:39.000000000 +0200 @@ -11,7 +11,7 @@ DESCRIPTION ssh-add adds RSA or DSA identities to the authentication agent, ssh-agent(1). When run without arguments, it adds the files - $HOME/.ssh/id_rsa, $HOME/.ssh/id_dsa and $HOME/.ssh/identity. AlternaM-- + $HOME/.ssh/id_rsa, $HOME/.ssh/id_dsa and $HOME/.ssh/identity. Alterna- tive file names can be given on the command line. If any file requires a passphrase, ssh-add asks for the passphrase from the user. The passphrase is read from the user's tty. ssh-add retries the last @@ -25,7 +25,7 @@ -l Lists fingerprints of all identities currently represented by the agent. - -L Lists public key parameters of all identities currently repreM-- + -L Lists public key parameters of all identities currently repre- sented by the agent. -d Instead of adding the identity, removes the identity from the @@ -39,7 +39,7 @@ -t life Set a maximum lifetime when adding identities to an agent. The - lifetime may be specified in seconds or in a time format speciM-- + lifetime may be specified in seconds or in a time format speci- fied in sshd(8). -s reader @@ -86,7 +86,7 @@ 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 creM-- + 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. diff -ruN openssh-3.4p1/ssh-add.c openssh-3.4p1+x509e/ssh-add.c --- openssh-3.4p1/ssh-add.c 2002-06-21 03:41:52.000000000 +0300 +++ openssh-3.4p1+x509e/ssh-add.c 2002-11-14 17:35:46.000000000 +0200 @@ -12,6 +12,8 @@ * * SSH2 implementation, * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * X509 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 @@ -35,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-add.c,v 1.61 2002/06/19 00:27:55 deraadt Exp $"); +RCSID("$OpenBSD$"); #include @@ -49,6 +51,7 @@ #include "pathnames.h" #include "readpass.h" #include "misc.h" +#include "ssh-x509.h" #ifdef HAVE___PROGNAME extern char *__progname; @@ -224,9 +227,16 @@ key_size(key), fp, comment, key_type(key)); xfree(fp); } else { - if (!key_write(key, stdout)) - fprintf(stderr, "key_write failed"); - fprintf(stdout, " %s\n", comment); + 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 { + if (!key_write(key, stdout)) + fprintf(stderr, "key_write failed"); + fprintf(stdout, " %s\n", comment); + } } key_free(key); xfree(comment); diff -ruN openssh-3.4p1/ssh-agent.0 openssh-3.4p1+x509e/ssh-agent.0 --- openssh-3.4p1/ssh-agent.0 2002-06-26 17:08:06.000000000 +0300 +++ openssh-3.4p1+x509e/ssh-agent.0 2002-11-18 17:38:39.000000000 +0200 @@ -8,9 +8,9 @@ ssh-agent [-c | -s] -k DESCRIPTION - ssh-agent is a program to hold private keys used for public key authentiM-- - cation (RSA, DSA). The idea is that ssh-agent is started in the beginM-- - ning of an X-session or a login session, and all other windows or proM-- + ssh-agent is a program to hold private keys used for public key authenti- + cation (RSA, DSA). The idea is that ssh-agent is started in the begin- + ning of an X-session or a login session, and all other windows or pro- grams are started as clients to the ssh-agent program. Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using ssh(1). @@ -40,17 +40,17 @@ ssh-add(1). When executed without arguments, ssh-add(1) adds the files $HOME/.ssh/id_rsa, $HOME/.ssh/id_dsa and $HOME/.ssh/identity. If the identity has a passphrase, ssh-add(1) asks for the passphrase (using a - small X11 application if running under X11, or from the terminal if runM-- - ning without X). It then sends the identity to the agent. Several idenM-- + small X11 application if running under X11, or from the terminal if run- + ning without X). It then sends the identity to the agent. Several iden- tities 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 terM-- + 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 conM-- + 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 netM-- + 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 setup: Either the agent starts a @@ -62,7 +62,7 @@ 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, priM-- + 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 @@ -89,7 +89,7 @@ the user. /tmp/ssh-XXXXXXXX/agent. - Unix-domain sockets used to contain the connection to the authenM-- + 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. @@ -97,7 +97,7 @@ 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 creM-- + 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. diff -ruN openssh-3.4p1/ssh-agent.c openssh-3.4p1+x509e/ssh-agent.c --- openssh-3.4p1/ssh-agent.c 2002-06-26 02:19:13.000000000 +0300 +++ openssh-3.4p1+x509e/ssh-agent.c 2002-11-14 11:35:01.000000000 +0200 @@ -11,6 +11,8 @@ * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * X509 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 @@ -35,7 +37,7 @@ #include "includes.h" #include "openbsd-compat/fake-queue.h" -RCSID("$OpenBSD: ssh-agent.c,v 1.97 2002/06/24 14:55:38 markus Exp $"); +RCSID("$OpenBSD$"); #include #include @@ -50,6 +52,7 @@ #include "authfd.h" #include "compat.h" #include "log.h" +#include "ssh-x509.h" #ifdef SMARTCARD #include "scard.h" @@ -417,6 +420,7 @@ xfree(type_name); switch (type) { case KEY_DSA: + case KEY_X509_DSA: k = key_new_private(type); buffer_get_bignum2(&e->request, k->dsa->p); buffer_get_bignum2(&e->request, k->dsa->q); @@ -425,6 +429,7 @@ buffer_get_bignum2(&e->request, k->dsa->priv_key); break; case KEY_RSA: + case KEY_X509_RSA: k = key_new_private(type); buffer_get_bignum2(&e->request, k->rsa->n); buffer_get_bignum2(&e->request, k->rsa->e); @@ -440,6 +445,24 @@ buffer_clear(&e->request); goto send; } + switch (type) { + case KEY_X509_RSA: + case KEY_X509_DSA: { + u_char *blob = NULL; + u_int blen = 0; + Key *key = NULL; + + blob = buffer_get_string(&e->request, &blen); + key = x509key_from_blob(blob, blen); + if(key == NULL) { + fatal("process_add_identity() x509key_from_blob fail"); + } + k->x509 = key->x509; + key->x509 = NULL; + key_free(key); + } + break; + } break; } comment = buffer_get_string(&e->request, NULL); diff -ruN openssh-3.4p1/ssh_config openssh-3.4p1+x509e/ssh_config --- openssh-3.4p1/ssh_config 2002-06-21 04:06:04.000000000 +0300 +++ openssh-3.4p1+x509e/ssh_config 2002-11-12 21:49:14.000000000 +0200 @@ -1,4 +1,4 @@ -# $OpenBSD: ssh_config,v 1.15 2002/06/20 20:03:34 stevesk Exp $ +# $OpenBSD$ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -33,3 +33,12 @@ # Cipher 3des # Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc # EscapeChar ~ +# AllowedCertPurpose sslserver +# 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 diff -ruN openssh-3.4p1/ssh_config.0 openssh-3.4p1+x509e/ssh_config.0 --- openssh-3.4p1/ssh_config.0 2002-06-26 17:08:09.000000000 +0300 +++ openssh-3.4p1+x509e/ssh_config.0 2002-11-18 17:38:42.000000000 +0200 @@ -8,18 +8,18 @@ /etc/ssh/ssh_config DESCRIPTION - ssh obtains configuration data from the following sources in the followM-- + ssh obtains configuration data from the following sources in the follow- ing order: command line options, user's configuration file ($HOME/.ssh/config), and system-wide configuration file (/etc/ssh/ssh_config). - For each parameter, the first obtained value will be used. The configuM-- + For each parameter, the first obtained value will be used. The configu- ration files contain sections bracketed 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-speM-- + 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. @@ -29,26 +29,36 @@ 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 whitesM-- + one `='; the latter format is useful to avoid the need to quote whites- pace when specifying configuration options using the ssh, scp and sftp -o option. - The possible keywords and their meanings are as follows (note that keyM-- + 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 keyM-- + 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. `*' and `'? can be used as wildcards - in the patterns. A single `*' as a pattern can be used to proM-- + in the patterns. A single `*' as a pattern can be used to pro- vide global defaults for all hosts. The host is the hostname - argument given on the command line (i.e., the name is not conM-- + argument given on the command line (i.e., the name is not con- verted to a canonicalized host name before matching). AFSTokenPassing - Specifies whether to pass AFS tokens to remote host. The arguM-- + Specifies whether to pass AFS tokens to remote host. The argu- ment to this keyword must be ``yes'' or ``no''. This option applies to protocol version 1 only. + AllowedCertPurpose + The intended use for the X509 server certificate. Without this + option no chain verification will be done. Currently accepted + uses are case insensitive: + - `sslserver' , `SSL server' , `SSL_server' or `server' + - `any' , `Any Purpose' , `Any_Purpose' or `AnyPurpose' + - `skip' or `' (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 @@ -60,6 +70,22 @@ interfaces or aliased addresses. Note that this option does not work if UsePrivilegedPort is set to ``yes''. + CACertificateFile + A file of trusted certificates. The file should contain multiple + certificates in PEM format concatenated together. The default is + /etc/ssh/ca/ca-bundle.crt + + CACertificatePath + A directory of trusted certificates. The certificates(files) + should have name of the form: hash. or have symbolic + links to them of this form. The default is /etc/ssh/ca/crt + + CARevocationFile + Reserved. The default is /etc/ssh/ca/ca-bundle.crl + + CARevocationPath + Reserved. 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 @@ -72,7 +98,7 @@ 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 protoM-- + 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 client for interoperability with legacy protocol 1 implementations that do @@ -92,7 +118,7 @@ specified in the configuration files or on the command line be cleared. This option is primarily useful when used from the ssh command line to clear port forwardings set in configuration - files, and is automatically set by scp(1) and sftp(1). The arguM-- + files, and is automatically set by scp(1) and sftp(1). The argu- ment must be ``yes'' or ``no''. The default is ``no''. Compression @@ -115,17 +141,17 @@ Specifies that a TCP/IP port on the local machine be forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. - The argument must be a port number. Currently the SOCKS4 protoM-- + The argument must be a port number. Currently the SOCKS4 proto- col is supported, and ssh will act as a SOCKS4 server. Multiple forwardings may be specified, and additional forwardings can be - given on the command line. Only the superuser can forward priviM-- + given on the command line. Only the superuser can forward privi- leged ports. EscapeChar 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 disM-- - able the escape character entirely (making the connection transM-- + single character, `^' followed by a letter, or ``none'' to dis- + able the escape character entirely (making the connection trans- parent for binary data). ForwardAgent @@ -134,14 +160,14 @@ be ``yes'' or ``no''. The default is ``no''. ForwardX11 - Specifies whether X11 connections will be automatically rediM-- + 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''. GatewayPorts Specifies whether remote hosts are allowed to connect to local forwarded ports. By default, ssh binds local port forwardings to - the loopback address. This prevents other remote hosts from conM-- + the loopback address. This prevents other remote hosts from con- necting 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 @@ -166,23 +192,23 @@ 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 connecM-- + database files. This option is useful for tunneling ssh connec- tions 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. Default is the name given on the command line. Numeric IP addresses are also - permitted (both on the command line and in HostName specificaM-- + permitted (both on the command line and in HostName specifica- tions). IdentityFile Specifies a file from which the user's RSA or DSA authentication identity is read. The default is $HOME/.ssh/identity for protocol - version 1, and $HOME/.ssh/id_rsa and $HOME/.ssh/id_dsa for protoM-- + version 1, and $HOME/.ssh/id_rsa and $HOME/.ssh/id_dsa for proto- col version 2. Additionally, any identities represented by the authentication agent will be used for authentication. The file - name may use the tilde syntax to refer to a user's home direcM-- + name may use the tilde syntax to refer to a user's home direc- tory. It is possible to have multiple identity files specified in configuration files; all these identities will be tried in sequence. @@ -191,7 +217,7 @@ 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 temM-- + this means that connections will die if the route is down tem- porarily, and some people find it annoying. The default is ``yes'' (to send keepalives), and the client will @@ -216,18 +242,18 @@ remote machine. The first argument must be a port number, and the second must be host:port. IPv6 addresses can be specified with an alternative syntax: host/port. Multiple forwardings may - be specified, and additional forwardings can be given on the comM-- + be specified, and additional forwardings can be given on the com- mand line. Only the superuser can forward privileged ports. LogLevel Gives the verbosity level that is used when logging messages from - ssh. The possible values are: QUIET, FATAL, ERROR, INFO, VERM-- + ssh. 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 verM-- + 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,hmac-ripemd160,hmac-sha1-96,hmac-md5-96''. @@ -235,7 +261,7 @@ 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 warnM-- + 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 @@ -268,13 +294,13 @@ version 2 is not available. ProxyCommand - Specifies the command to use to connect to the server. The comM-- + 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 /bin/sh. In the command string, `%h' will be substituted by the host name to connect and `%p' by the port. 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 someM-- + sshd(8) server running on some machine, or execute sshd -i some- where. Host key management will be done using the HostName of the host being connected (defaulting to the name typed by the user). Note that CheckHostIP is not available for connects with @@ -297,7 +323,7 @@ RhostsAuthentication Specifies whether to try rhosts based authentication. Note that this declaration only affects the client side and has no effect - whatsoever on security. Most servers do not permit RhostsAuthenM-- + whatsoever on security. Most servers do not permit RhostsAuthen- tication because it is not secure (see RhostsRSAAuthentication). The argument to this keyword must be ``yes'' or ``no''. The default is ``no''. This option applies to protocol version 1 @@ -312,19 +338,19 @@ 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 authenticaM-- + 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. SmartcardDevice Specifies which smartcard device to use. The argument to this - keyword is the device ssh should use to communicate with a smartM-- + keyword is the device ssh should use to communicate with a smart- card used for storing the user's private RSA key. By default, no device is specified and smartcard support is not activated. StrictHostKeyChecking If this flag is set to ``yes'', ssh will never automatically add - host keys to the $HOME/.ssh/known_hosts file, and refuses to conM-- + host keys to the $HOME/.ssh/known_hosts file, and refuses to con- nect to hosts whose host key has changed. This provides maximum protection against trojan horse attacks, however, can be annoying when the /etc/ssh/ssh_known_hosts file is poorly maintained, or @@ -340,17 +366,30 @@ ``ask''. UsePrivilegedPort - Specifies whether to use a privileged port for outgoing connecM-- + Specifies whether to use a privileged port for outgoing connec- tions. The argument must be ``yes'' or ``no''. The default is ``no''. Note that this option must be set to ``yes'' if RhostsAuthentication and RhostsRSAAuthentication authentications are needed with older servers. - User Specifies the user to log in as. This can be useful when a difM-- + 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 comM-- + trouble of having to remember to give the user name on the com- mand line. + UserCACertificateFile + User CACertificateFile , the default is $HOME/.ssh/ca-bundle.crt + + UserCACertificatePath + User CACertificatePath , the default is $HOME/.ssh/crt + + UserCARevocationFile + Reserved. User CARevocationFile , the default is + $HOME/.ssh/ca-bundle.crl + + UserCARevocationPath + Reserved. User CARevocationPath , the default is $HOME/.ssh/crl + UserKnownHostsFile Specifies a file to use for the user host key database instead of $HOME/.ssh/known_hosts. @@ -376,9 +415,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 creM-- + 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. + versions 1.5 and 2.0. Roumen Petrov contributed support for x509 cer- + tificates. SEE ALSO ssh(1) diff -ruN openssh-3.4p1/ssh_config.5 openssh-3.4p1+x509e/ssh_config.5 --- openssh-3.4p1/ssh_config.5 2002-06-21 03:59:06.000000000 +0300 +++ openssh-3.4p1+x509e/ssh_config.5 2002-11-15 13:43:19.000000000 +0200 @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -34,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.1 2002/06/20 19:56:07 stevesk Exp $ +.\" $OpenBSD$ .Dd September 25, 1999 .Dt SSH_CONFIG 5 .Os @@ -116,6 +117,35 @@ or .Dq no . This option applies to protocol version 1 only. +.It Cm AllowedCertPurpose +The intended use for the X509 server certificate. Without this option +no chain verification will be done. Currently accepted uses are case +insensitive: + - +.Sq sslserver +, +.Sq SSL server +, +.Sq SSL_server +or +.Sq server + - +.Sq any +, +.Sq Any Purpose +, +.Sq Any_Purpose +or +.Sq AnyPurpose + - +.Sq skip +or +.Sq +.. +(empty): do not check purpose. +.Pp +The default is +.Dq sslserver . .It Cm BatchMode If set to .Dq yes , @@ -135,6 +165,27 @@ .Cm UsePrivilegedPort is set to .Dq yes . +.Pp +.It Cm CACertificateFile +A file of trusted certificates. The file should contain multiple +certificates in PEM format concatenated together. +The default is +.Pa /etc/ssh/ca/ca-bundle.crt +.Pp +.It Cm CACertificatePath +A directory of trusted certificates. The certificates(files) should +have name of the form: hash. or have symbolic links to them +of this form. +The default is +.Pa /etc/ssh/ca/crt +.Pp +.It Cm CARevocationFile +Reserved. The default is +.Pa /etc/ssh/ca/ca-bundle.crl +.Pp +.It Cm CARevocationPath +Reserved. 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 @@ -579,6 +630,30 @@ 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. +.Pp +.It Cm UserCACertificateFile +User +.Cm CACertificateFile +, the default is +.Pa $HOME/.ssh/ca-bundle.crt +.Pp +.It Cm UserCACertificatePath +User +.Cm CACertificatePath +, the default is +.Pa $HOME/.ssh/crt +.Pp +.It Cm UserCARevocationFile +Reserved. User +.Cm CARevocationFile +, the default is +.Pa $HOME/.ssh/ca-bundle.crl +.Pp +.It Cm UserCARevocationPath +Reserved. User +.Cm CARevocationPath +, the default is +.Pa $HOME/.ssh/crl .It Cm UserKnownHostsFile Specifies a file to use for the user host key database instead of @@ -617,5 +692,6 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for x509 certificates. .Sh SEE ALSO .Xr ssh 1 diff -ruN openssh-3.4p1/sshconnect.c openssh-3.4p1+x509e/sshconnect.c --- openssh-3.4p1/sshconnect.c 2002-06-24 00:23:20.000000000 +0300 +++ openssh-3.4p1+x509e/sshconnect.c 2002-11-18 12:59:58.000000000 +0200 @@ -10,10 +10,13 @@ * 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 certificates support, + * Copyright (c) 2002 Roumen Petrov. All rights reserved. */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.126 2002/06/23 03:30:17 deraadt Exp $"); +RCSID("$OpenBSD$"); #include @@ -32,6 +35,7 @@ #include "atomicio.h" #include "misc.h" #include "readpass.h" +#include "ssh-x509.h" char *client_version_string = NULL; char *server_version_string = NULL; @@ -505,6 +509,7 @@ char msg[1024]; int len, host_line, ip_line; const char *host_file = NULL, *ip_file = NULL; + char extramsg[1024], *subject = NULL; /* * Force accepting of the host key for loopback/localhost. The @@ -649,12 +654,26 @@ } else if (options.strict_host_key_checking == 2) { /* The default */ fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); + 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", + X509KEY_SUBJECT_MAXLEN, subject); + } else { + subject = NULL; + *extramsg = '\0'; + } snprintf(msg, sizeof(msg), "The authenticity of host '%.200s (%s)' can't be " "established.\n" "%s key fingerprint is %s.\n" + "%s" "Are you sure you want to continue connecting " - "(yes/no)? ", host, ip, type, fp); + "(yes/no)? ", host, ip, type, fp, extramsg); + if(subject != NULL) { + xfree(subject); + subject = NULL; + } xfree(fp); if (!confirm(msg)) goto fail; @@ -706,6 +725,13 @@ error("It is also possible that the %s host key has just been changed.", type); error("The fingerprint for the %s key sent by the remote host is\n%s.", type, fp); + if ((host_key->type == KEY_X509_RSA) || (host_key->type == KEY_X509_DSA)) { + subject = x509key_subject(host_key); + error("Distinguished name sent by remote host is\n%.*s.", + X509KEY_SUBJECT_MAXLEN, subject); + xfree(subject); + subject = NULL; + } error("Please contact your system administrator."); error("Add correct host key in %.100s to get rid of this message.", user_hostfile); diff -ruN openssh-3.4p1/sshd.0 openssh-3.4p1+x509e/sshd.0 --- openssh-3.4p1/sshd.0 2002-06-26 17:08:07.000000000 +0300 +++ openssh-3.4p1+x509e/sshd.0 2002-11-18 17:38:41.000000000 +0200 @@ -8,21 +8,21 @@ [-h host_key_file] [-k key_gen_time] [-o option] [-p port] [-u len] DESCRIPTION - sshd (SSH Daemon) is the daemon program for ssh(1). Together these proM-- + sshd (SSH Daemon) is the daemon program for ssh(1). Together these pro- grams replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network. The programs are intended to be as easy to install and use as possible. - sshd is the daemon that listens for connections from clients. It is norM-- + sshd is the daemon that listens for connections from clients. It is nor- mally 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. This implementaM-- + authentication, command execution, and data exchange. This implementa- tion of sshd supports both SSH protocol version 1 and 2 simultaneously. sshd works as follows. SSH protocol version 1 - Each host has a host-specific RSA key (normally 1024 bits) used to idenM-- + Each host has a host-specific RSA key (normally 1024 bits) used to iden- tify the host. Additionally, when the daemon starts, it generates a server RSA key (normally 768 bits). This key is normally regenerated every hour if it has been used, and is never stored on disk. @@ -35,7 +35,7 @@ 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 encrypM-- + or 3DES, with 3DES being used by default. The client selects the encryp- tion algorithm to use from those offered by the server. Next, the server and the client enter an authentication dialog. The @@ -45,7 +45,7 @@ Rhosts authentication is normally disabled because it is fundamentally insecure, but can be enabled in the server configuration file if desired. - System security is not improved unless rshd, rlogind, and rexecd are disM-- + System security is not improved unless rshd, rlogind, and rexecd are dis- abled (thus completely disabling rlogin and rsh into the machine). SSH protocol version 2 @@ -63,9 +63,9 @@ through a cryptographic message authentication code (hmac-sha1 or hmac- md5). - Protocol version 2 provides a public key based user (PubkeyAuthenticaM-- + Protocol version 2 provides a public key based user (PubkeyAuthentica- tion) or client host (HostbasedAuthentication) authentication method, - conventional password authentication and challenge response based methM-- + conventional password authentication and challenge response based meth- ods. Command execution and data forwarding @@ -81,12 +81,12 @@ 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 connecM-- + 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. sshd can be configured using command-line options or a configuration - file. Command-line options override values specified in the configuraM-- + file. Command-line options override values specified in the configura- tion file. sshd rereads its configuration file when it receives a hangup signal, @@ -110,7 +110,7 @@ -f configuration_file Specifies the name of the configuration file. The default is - /etc/ssh/sshd_config. sshd refuses to start if there is no conM-- + /etc/ssh/sshd_config. sshd refuses to start if there is no con- figuration file. -g login_grace_time @@ -124,7 +124,7 @@ be given if sshd is not run as root (as the normal host key files are normally not readable by anyone but root). The default is /etc/ssh/ssh_host_key for protocol version 1, and - /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_dsa_key for proM-- + /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_dsa_key for pro- tocol version 2. It is possible to have multiple host key files for the different protocol versions and host key algorithms. @@ -137,7 +137,7 @@ -k key_gen_time Specifies how often the ephemeral protocol version 1 server key - is regenerated (default 3600 seconds, or one hour). The motivaM-- + 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 @@ -145,13 +145,13 @@ zero indicates that the key will never be regenerated. -o option - Can be used to give options in the format used in the configuraM-- + 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. -p port Specifies the port on which the server listens for connections - (default 22). Multiple port options are permitted. Ports speciM-- + (default 22). Multiple port options are permitted. Ports speci- fied in the configuration file are ignored when a command-line port is specified. @@ -166,7 +166,7 @@ -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 overM-- + 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 is also be used to prevent sshd from making @@ -186,7 +186,7 @@ CONFIGURATION FILE sshd reads configuration data from /etc/ssh/sshd_config (or the file - specified with -f on the command line). The file format and configuraM-- + specified with -f on the command line). The file format and configura- tion options are described in sshd_config(5). LOGIN PROCESS @@ -194,7 +194,7 @@ 1. If the login is on a tty, and no command has been specified, prints last login time and /etc/motd (unless prevented in the - configuration file or by $HOME/.hushlogin; see the FILES secM-- + configuration file or by $HOME/.hushlogin; see the FILES sec- tion). 2. If the login is on a tty, records login time. @@ -226,11 +226,11 @@ Each line of the file contains one key (empty lines and lines starting with a `#' are ignored as comments). Each RSA public key consists of the following fields, separated by spaces: options, bits, exponent, modulus, - comment. Each protocol version 2 public key consists of: options, keyM-- + comment. Each protocol version 2 public key consists of: options, key- type, base64 encoded key, comment. The options fields are optional; its presence is determined by whether the line starts with a number or not - (the option field never starts with a number). The bits, exponent, moduM-- - lus and comment fields give the RSA key for protocol version 1; the comM-- + (the option field never starts with a number). The bits, exponent, modu- + lus and comment fields give the RSA key for protocol version 1; the com- ment field is not used for anything (but may be convenient for the user to identify the key). For protocol version 2 the keytype is ``ssh-dss'' or ``ssh-rsa''. @@ -243,8 +243,8 @@ 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 specificaM-- - tions. No spaces are permitted, except within double quotes. The folM-- + 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): @@ -268,7 +268,7 @@ ignored. The command is run on a pty if the client requests a pty; otherwise it is run without a tty. If a 8-bit clean channel 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 backM-- + A quote may be included in the command by quoting it with a back- slash. This option might be useful to restrict certain RSA keys to perform just a specific operation. An example might be a key that permits remote backups but nothing else. Note that the @@ -284,7 +284,7 @@ if UseLogin is enabled. no-port-forwarding - Forbids TCP/IP forwarding when this key is used for authenticaM-- + Forbids TCP/IP forwarding when this key is used for authentica- tion. Any port forward requests by the client will return an error. This might be used, e.g., in connection with the command option. @@ -300,8 +300,8 @@ no-pty Prevents tty allocation (a request to allocate a pty will fail). permitopen="host:port" - Limit local ``ssh -L'' port forwarding such that it may only conM-- - nect to the specified host and port. IPv6 addresses can be specM-- + 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 with an alternative syntax: host/port. Multiple permitopen options may be applied separated by commas. No pattern matching is performed on the specified hostnames, they must be literal @@ -327,7 +327,7 @@ Each line in these files contains the following fields: hostnames, bits, exponent, modulus, comment. The fields are separated by spaces. - Hostnames is a comma-separated list of patterns ('*' and '?' act as wildM-- + 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 @@ -341,10 +341,10 @@ 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. It is thus permissible (but not recomM-- + matching line has the proper key. It is thus permissible (but not recom- mended) 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 conM-- + domains are put in the file. It is possible that the files contain con- flicting information; authentication is accepted if valid information can be found from either file. @@ -360,7 +360,7 @@ FILES /etc/ssh/sshd_config - Contains configuration data for sshd. The file format and conM-- + Contains configuration data for sshd. The file format and con- figuration options are described in sshd_config(5). /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, @@ -393,7 +393,7 @@ 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-readM-- + The content of this file is not sensitive; it can be world-read- able. $HOME/.ssh/authorized_keys @@ -407,7 +407,7 @@ as described in ssh-keygen(1). /etc/ssh/ssh_known_hosts and $HOME/.ssh/known_hosts - These files are consulted when using rhosts with RSA host authenM-- + These files are consulted when using rhosts with RSA host authen- tication or protocol version 2 hostbased authentication to check the public key of the host. The key must be listed in one of these files to be accepted. The client uses the same files to @@ -430,7 +430,7 @@ This file contains host-username pairs, separated by a space, one per line. The given user on the corresponding host is permitted to log in without password. The same file is used by rlogind and - rshd. The file must be writable only by the user; it is recomM-- + rshd. The file must be writable only by the user; it is recom- mended that it not be accessible by others. If is also possible to use netgroups in the file. Either host or @@ -482,7 +482,7 @@ $HOME/.ssh/rc If this file exists, it is run with /bin/sh after reading the - environment files but before starting the user's shell or comM-- + environment files but before starting the user's shell or com- mand. 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 @@ -491,7 +491,7 @@ The primary purpose of this file is to run any initialization routines which may be needed before the user's home directory - becomes accessible; AFS is a particular example of such an enviM-- + becomes accessible; AFS is a particular example of such an envi- ronment. This file will probably contain some initialization code followed @@ -522,7 +522,7 @@ 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 creM-- + 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. diff -ruN openssh-3.4p1/sshd.c openssh-3.4p1+x509e/sshd.c --- openssh-3.4p1/sshd.c 2002-06-26 02:24:19.000000000 +0300 +++ openssh-3.4p1+x509e/sshd.c 2002-11-14 11:05:38.000000000 +0200 @@ -20,6 +20,9 @@ * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved. * + * X509 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: @@ -42,7 +45,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.251 2002/06/25 18:51:04 markus Exp $"); +RCSID("$OpenBSD$"); #include #include @@ -684,6 +687,8 @@ switch (key->type) { case KEY_RSA: case KEY_DSA: + case KEY_X509_RSA: + case KEY_X509_DSA: if (buffer_len(&b) > 0) buffer_append(&b, ",", 1); p = key_ssh_name(key); @@ -980,6 +985,8 @@ break; case KEY_RSA: case KEY_DSA: + case KEY_X509_RSA: + case KEY_X509_DSA: sensitive_data.have_ssh2_key = 1; break; } @@ -1199,6 +1206,8 @@ if (f) { fprintf(f, "%ld\n", (long) getpid()); fclose(f); + } else { + error("Could not create pid file: %.400s", options.pid_file); } } diff -ruN openssh-3.4p1/sshd_config openssh-3.4p1+x509e/sshd_config --- openssh-3.4p1/sshd_config 2002-06-21 04:11:36.000000000 +0300 +++ openssh-3.4p1+x509e/sshd_config 2002-11-15 13:41:52.000000000 +0200 @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.56 2002/06/20 23:37:12 markus Exp $ +# $OpenBSD$ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -21,6 +21,26 @@ #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key +# 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 + +# A file of trusted certificates. The file should contain multiple +# certificates in PEM format concatenated together. +#CACertificateFile /etc/ssh/ca/ca-bundle.crt + +# A directory of trusted certificates. The certificates(files) should +# have name of the form: hash. or have symbolic links to them +# of this form. +#CACertificatePath /etc/ssh/ca/crt + +#CARevocationFile /etc/ssh/ca/ca-bundle.crl +#CARevocationPath /etc/ssh/ca/crl + # Lifetime and size of ephemeral version 1 server key #KeyRegenerationInterval 3600 #ServerKeyBits 768 diff -ruN openssh-3.4p1/sshd_config.0 openssh-3.4p1+x509e/sshd_config.0 --- openssh-3.4p1/sshd_config.0 2002-06-26 17:08:09.000000000 +0300 +++ openssh-3.4p1+x509e/sshd_config.0 2002-11-18 17:38:42.000000000 +0200 @@ -8,17 +8,27 @@ DESCRIPTION sshd reads configuration data from /etc/ssh/sshd_config (or the file - specified with -f on the command line). The file contains keyword-arguM-- + 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. - The possible keywords and their meanings are as follows (note that keyM-- + The possible keywords and their meanings are as follows (note that key- words are case-insensitive and arguments are case-sensitive): AFSTokenPassing Specifies whether an AFS token may be forwarded to the server. Default is ``no''. + AllowedCertPurpose + 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): 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 @@ -54,12 +64,28 @@ path or one relative to the user's home directory. The default is ``.ssh/authorized_keys''. - Banner In some jurisdictions, sending a warning message before authentiM-- - cation may be relevant for getting legal protection. The conM-- + Banner In some jurisdictions, sending a warning message before authenti- + cation may be relevant for getting legal protection. The con- tents of the specified file are sent to the remote user before authentication is allowed. This option is only available for protocol version 2. By default, no banner is displayed. + CACertificateFile + A file of trusted certificates. The file should contain multiple + certificates in PEM format concatenated together. The default is + /etc/ssh/ca/ca-bundle.crt + + CACertificatePath + A directory of trusted certificates. The certificates(files) + should have name of the form: hash. or have symbolic + links to them of this form. The default is /etc/ssh/ca/crt + + CARevocationFile + Reserved. The default is /etc/ssh/ca/ca-bundle.crl + + CARevocationPath + Reserved. The default is /etc/ssh/ca/crl + ChallengeResponseAuthentication Specifies whether challenge response authentication is allowed. All authentication styles from login.conf(5) are supported. The @@ -89,7 +115,7 @@ are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by KeepAlive is spoofable. The client alive mechanism is valuable when the client - or server depend on knowing when a connection has become inacM-- + or server depend on knowing when a connection has become inac- tive. The default value is 3. If ClientAliveInterval (above) is set to @@ -138,7 +164,7 @@ HostKey Specifies a file containing a private host key used by SSH. The default is /etc/ssh/ssh_host_key for protocol version 1, and - /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_dsa_key for proM-- + /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_dsa_key for pro- tocol version 2. Note that sshd will refuse to use a file if it is group/world-accessible. It is possible to have multiple host key files. ``rsa1'' keys are used for version 1 and ``dsa'' or @@ -161,7 +187,7 @@ 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 temM-- + this means that connections will die if the route is down tem- porarily, and some people find it annoying. On the other hand, if keepalives are not sent, sessions may hang indefinitely on the server, leaving ``ghost'' users and consuming server resources. @@ -177,7 +203,7 @@ be in the form of a Kerberos ticket, or if PasswordAuthentication is yes, the password provided by the user will be validated through the Kerberos KDC. To use this option, the server needs a - Kerberos servtab which allows the verification of the KDC's idenM-- + Kerberos servtab which allows the verification of the KDC's iden- tity. Default is ``no''. KerberosOrLocalPasswd @@ -197,13 +223,13 @@ 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 sesM-- + 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 should listen on. The followM-- + Specifies the local addresses sshd should listen on. The follow- ing forms may be used: ListenAddress host|IPv4_addr|IPv6_addr @@ -217,35 +243,35 @@ port qualified addresses. LoginGraceTime - The server disconnects after this time if the user has not sucM-- + 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 600 (seconds). LogLevel Gives the verbosity level that is used when logging messages from - sshd. The possible values are: QUIET, FATAL, ERROR, INFO, VERM-- + sshd. 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 debugging output. Logging with a DEBUG level violates the privacy of users and is not recommended. - MACs Specifies the available MAC (message authentication code) algoM-- + 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-sepaM-- + integrity protection. Multiple algorithms must be comma-sepa- rated. The default is ``hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96''. MaxStartups - Specifies the maximum number of concurrent unauthenticated conM-- + Specifies the maximum number of concurrent unauthenticated con- nections to the sshd daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection. The default is 10. Alternatively, random early drop can be enabled by specifying the three colon separated values ``start:rate:full'' (e.g., - "10:30:60"). sshd will refuse connection attempts with a probaM-- + "10:30:60"). sshd will refuse connection attempts with a proba- bility of ``rate/100'' (30%) if there are currently ``start'' - (10) unauthenticated connections. The probability increases linM-- + (10) unauthenticated connections. The probability increases lin- early and all connection attempts are refused if the number of unauthenticated connections reaches ``full'' (60). @@ -269,7 +295,7 @@ be ``yes'', ``without-password'', ``forced-commands-only'' or ``no''. The default is ``yes''. - If this option is set to ``without-password'' password authentiM-- + 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 @@ -281,7 +307,7 @@ If this option is set to ``no'' root is not allowed to login. PidFile - Specifies the file that contains the process ID of the sshd daeM-- + Specifies the file that contains the process ID of the sshd dae- mon. The default is /var/run/sshd.pid. Port Specifies the port number that sshd listens on. The default is @@ -298,7 +324,7 @@ /etc/profile, or equivalent.) The default is ``yes''. Protocol - Specifies the protocol versions sshd should support. The possiM-- + Specifies the protocol versions sshd should support. The possi- ble values are ``1'' and ``2''. Multiple versions must be comma- separated. The default is ``2,1''. @@ -309,7 +335,7 @@ RhostsAuthentication Specifies whether authentication using rhosts or /etc/hosts.equiv - files is sufficient. Normally, this method should not be permitM-- + files is sufficient. Normally, this method should not be permit- ted because it is insecure. RhostsRSAAuthentication should be used instead, because it performs RSA-based host authentication in addition to normal rhosts or /etc/hosts.equiv authentication. @@ -353,7 +379,7 @@ default is AUTH. UseLogin - Specifies whether login(1) is used for interactive login sesM-- + 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 @@ -365,7 +391,7 @@ 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 conM-- + privilege separation is to prevent privilege escalation by con- taining any corruption within the unprivileged processes. The default is ``yes''. @@ -375,14 +401,14 @@ maps back to the very same IP address. The default is ``no''. X11DisplayOffset - Specifies the first display number available for sshd's X11 forM-- + Specifies the first display number available for sshd's X11 for- warding. This prevents sshd from interfering with real X11 servers. The default is 10. X11Forwarding Specifies whether X11 forwarding is permitted. The default is ``no''. Note that disabling X11 forwarding does not improve - security in any way, as users can always install their own forM-- + security in any way, as users can always install their own for- warders. X11 forwarding is automatically disabled if UseLogin is enabled. @@ -394,7 +420,7 @@ ``localhost''. This prevents remote hosts from connecting to the fake 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 wildM-- + specify that the forwarding server should be bound to the wild- card address. The argument must be ``yes'' or ``no''. The default is ``yes''. @@ -406,7 +432,7 @@ sshd 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 folM-- + where time is a positive integer value and qualifier is one of the fol- lowing: seconds @@ -428,16 +454,17 @@ FILES /etc/ssh/sshd_config Contains configuration data for sshd. This file should be - writable by root only, but it is recommended (though not necesM-- + writable by root only, but it is recommended (though not neces- sary) that it be world-readable. 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 creM-- + 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 x509 + certificates. SEE ALSO sshd(8) diff -ruN openssh-3.4p1/sshd_config.5 openssh-3.4p1+x509e/sshd_config.5 --- openssh-3.4p1/sshd_config.5 2002-06-26 16:05:16.000000000 +0300 +++ openssh-3.4p1+x509e/sshd_config.5 2002-11-15 13:43:37.000000000 +0200 @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -34,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.4 2002/06/22 16:45:29 stevesk Exp $ +.\" $OpenBSD$ .Dd September 25, 1999 .Dt SSHD_CONFIG 5 .Os @@ -65,6 +66,36 @@ Specifies whether an AFS token may be forwarded to the server. Default is .Dq no . +.It Cm AllowedCertPurpose +The intended use for the X509 client certificate. Without this option +no chain verification will be done. Currently accepted uses are case +insensitive: + - +.Sq sslclient +, +.Sq SSL client +, +.Sq SSL_client +or +.Sq client + - +.Sq any +, +.Sq Any Purpose +, +.Sq Any_Purpose +or +.Sq AnyPurpose + - +.Sq skip +or +.Sq +.. +(empty): do not check purpose. +.Pp +The default is +.Dq sslclient . +.Pp .It Cm AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. @@ -124,6 +155,27 @@ This option is only available for protocol version 2. By default, no banner is displayed. .Pp +.It Cm CACertificateFile +A file of trusted certificates. The file should contain multiple +certificates in PEM format concatenated together. +The default is +.Pa /etc/ssh/ca/ca-bundle.crt +.Pp +.It Cm CACertificatePath +A directory of trusted certificates. The certificates(files) should +have name of the form: hash. or have symbolic links to them +of this form. +The default is +.Pa /etc/ssh/ca/crt +.Pp +.It Cm CARevocationFile +Reserved. The default is +.Pa /etc/ssh/ca/ca-bundle.crl +.Pp +.It Cm CARevocationPath +Reserved. The default is +.Pa /etc/ssh/ca/crl +.Pp .It Cm ChallengeResponseAuthentication Specifies whether challenge response authentication is allowed. All authentication styles from @@ -709,5 +761,6 @@ protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. +Roumen Petrov contributed support for x509 certificates. .Sh SEE ALSO .Xr sshd 8 diff -ruN openssh-3.4p1/ssh-keygen.0 openssh-3.4p1+x509e/ssh-keygen.0 --- openssh-3.4p1/ssh-keygen.0 2002-06-26 17:08:06.000000000 +0300 +++ openssh-3.4p1+x509e/ssh-keygen.0 2002-11-18 17:38:40.000000000 +0200 @@ -24,7 +24,7 @@ Normally each user wishing to use SSH with RSA or DSA authentication runs this once to create the authentication key in $HOME/.ssh/identity, - $HOME/.ssh/id_dsa or $HOME/.ssh/id_rsa. Additionally, the system adminM-- + $HOME/.ssh/id_dsa or $HOME/.ssh/id_rsa. Additionally, the system admin- istrator 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 @@ -33,7 +33,7 @@ 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 charM-- + 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), @@ -47,7 +47,7 @@ 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 initialM-- + tell what the key is for, or whatever is useful. The comment is initial- ized to ``user@host'' when the key is created, but can be changed using the -c option. @@ -63,7 +63,7 @@ slower. The default is 1024 bits. -c Requests changing the comment in the private and public key - files. This operation is only supported for RSA1 keys. The proM-- + 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. @@ -97,7 +97,7 @@ -t type Specifies the type of the key to create. The possible values are - ``rsa1'' for protocol version 1 and ``rsa'' or ``dsa'' for protoM-- + ``rsa1'' for protocol version 1 and ``rsa'' or ``dsa'' for proto- col version 2. -B Show the bubblebabble digest of specified private or public key @@ -129,7 +129,7 @@ key. ssh(1) will read this file when a login attempt is made. $HOME/.ssh/identity.pub - Contains the protocol version 1 RSA public key for authenticaM-- + Contains the protocol version 1 RSA public key for authentica- tion. The contents of this file should be added to $HOME/.ssh/authorized_keys on all machines where the user wishes to log in using RSA authentication. There is no need to keep the @@ -145,7 +145,7 @@ key. ssh(1) will read this file when a login attempt is made. $HOME/.ssh/id_dsa.pub - Contains the protocol version 2 DSA public key for authenticaM-- + Contains the protocol version 2 DSA public key for authentica- tion. The contents of this file should be added to $HOME/.ssh/authorized_keys on all machines where the user wishes to log in using public key authentication. There is no need to @@ -161,7 +161,7 @@ key. ssh(1) will read this file when a login attempt is made. $HOME/.ssh/id_rsa.pub - Contains the protocol version 2 RSA public key for authenticaM-- + Contains the protocol version 2 RSA public key for authentica- tion. The contents of this file should be added to $HOME/.ssh/authorized_keys on all machines where the user wishes to log in using public key authentication. There is no need to @@ -170,7 +170,7 @@ 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 creM-- + 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. diff -ruN openssh-3.4p1/ssh-keyscan.0 openssh-3.4p1+x509e/ssh-keyscan.0 --- openssh-3.4p1/ssh-keyscan.0 2002-06-26 17:08:07.000000000 +0300 +++ openssh-3.4p1+x509e/ssh-keyscan.0 2002-11-18 17:38:40.000000000 +0200 @@ -8,16 +8,16 @@ [host | addrlist namelist] [...] DESCRIPTION - ssh-keyscan is a utility for gathering the public ssh host keys of a numM-- + 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 posM-- + 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 proM-- + access to the machines that are being scanned, nor does the scanning pro- cess involve any encryption. The options are as follows: @@ -52,7 +52,7 @@ -6 Forces ssh-keyscan to use IPv6 addresses only. SECURITY - If a ssh_known_hosts file is constructed using ssh-keyscan without veriM-- + If a ssh_known_hosts file is constructed using ssh-keyscan without veri- fying the keys, users will be vulnerable to 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 diff -ruN openssh-3.4p1/ssh-rand-helper.0 openssh-3.4p1+x509e/ssh-rand-helper.0 --- openssh-3.4p1/ssh-rand-helper.0 2002-06-26 17:08:08.000000000 +0300 +++ openssh-3.4p1+x509e/ssh-rand-helper.0 2002-11-18 17:38:41.000000000 +0200 @@ -27,7 +27,7 @@ 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 comM-- + 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 diff -ruN openssh-3.4p1/ssh-x509.c openssh-3.4p1+x509e/ssh-x509.c --- openssh-3.4p1/ssh-x509.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/ssh-x509.c 2002-11-21 14:52:43.000000000 +0200 @@ -0,0 +1,628 @@ +/* + * 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. + */ +#include "ssh-x509.h" +#include "includes.h" +#include "log.h" +#include +#include "xmalloc.h" +#include "uuencode.h" +#include +#include "bufaux.h" +#include "x509store.h" + +static char* +x509key_find_subject(int _keytype, char* _cp) { + static char *keywords[] = { + "subject", + "distinguished name", + "distinguished-name", + "distinguished_name", + "distinguishedname", + "dn", + NULL + }; + char **q, *p; + size_t len; + + if (_keytype != KEY_X509_RSA && + _keytype != KEY_X509_DSA) { + debug3("x509key_find_subject: %d is not x509 key ", _keytype); + return 0; + } + for (q=keywords; *q; q++) { + len = strlen(*q); + if (strncasecmp(_cp, *q, len) == 0) { + for (p = _cp + len; *p && isspace(*p); p++) + {} + if (!*p) { + error("x509key_find_subject: no data"); + return NULL; + } + if (*p == ':' || *p == '=') + p++; + for (; *p && isspace(*p); p++) + {} + if (!*p) { + error("x509key_find_subject: no data"); + return NULL; + } + if (*p == '/') + p++; + return p; + } + } + return NULL; +} + + +static int +x509key_str2X509NAME(char* _str, X509_NAME *_name) { + int ret = 1; + char *p, *q, *token; + char ch; + + p = _str; + while (*p) { + int nid; + for (; *p && isspace(*p); p++) + {} + if (!*p) break; + token = strchr(p, ','); + if (token == NULL) token = strchr(p, '/'); + if (token) { + ch = *token; + *token = 0; + } else { + ch = 0; + token = p + strlen(p); + } + q = strchr(p, '='); + if (!q) { + error("x509key_str2X509NAME: cannot parse %.200s ...", p); + ret = 0; + break; + } + *q = 0; + nid = OBJ_txt2nid(p); + *q = '='; + p = q + 1; + if(!*p) { + error("x509key_str2X509NAME: no data"); + ret = 0; + } else { /* add */ + + for(q = token - 1; (q >= p) && isspace(*q); q--) + {/*skip unexpected \n,etc. from end*/} + ret = X509_NAME_add_entry_by_NID(_name, nid, V_ASN1_PRINTABLESTRING, p, q-p+1, -1, 0); + if(ret <= 0) { + int ecode = ERR_get_error(); + error("x509key_str2X509NAME: X509_NAME_add_entry_by_NID fail %.200s", ERR_error_string(ecode, NULL)); + } + } + *token = ch; + if(ret <= 0) { + break; + } + p = token; + if(*p) p++; + } + debug3("x509key_str2X509NAME: return %d", ret); + return ret; +} + + +Key* +x509key_from_subject(int _keytype, char* _cp) { + int ret = 1; + Key* key = NULL; + X509_NAME *subj; + char *subject; + + debug3("x509key_from_subject(%d, [%.200s]) called ", _keytype, _cp); + subject = x509key_find_subject(_keytype, _cp); + if(subject == NULL) + return NULL; + + debug3("x509key_from_subject: subject=[%.200s]", 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) { + key_free(key); + key = NULL; + } + } + debug3("x509key_from_subject: return %p", key); + return key; +} + + +static Key* +x509_to_key(X509 *x509) { + Key *key = NULL; + EVP_PKEY *env_pkey; + + env_pkey = X509_get_pubkey(x509); + + if (env_pkey == NULL) { + int ecode = ERR_get_error(); + error("x509_to_key: X509_get_pubkey fail %.200s", ERR_error_string(ecode, NULL)); + return key; + } + 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: + debug3("x509_to_key: unspec key" ); + } + + return key; +} + + +Key* +x509key_from_blob( + 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) { + int ecode = ERR_get_error(); + /* 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. + */ + debug3("x509key_from_blob: read X509 from BIO fail %.200s", ERR_error_string(ecode, NULL)); + } + 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(char* method, 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( + Key *key, + Buffer *b +) { + int len; + void* str; + unsigned char *p; + + if (!x509key_check("x509key_to_blob", key)) + return 0; + + len = i2d_X509(key->x509, NULL); + str = xmalloc(len); + if (str == NULL) + { error("x509key_to_blob: out of memory"); return 0; } + + p = str; + i2d_X509(key->x509, &p); + buffer_append(b, str, len); + xfree(str); + return 1; +} + + +char* +x509key_subject(Key *key) { + char *buf = NULL; + if (!x509key_check("x509key_subject", key)) + return buf; + buf = xmalloc(X509KEY_SUBJECT_MAXLEN); /* xmalloc exit if cannot allocate memory */ + X509_NAME_oneline(X509_get_subject_name(key->x509), buf, X509KEY_SUBJECT_MAXLEN); + return buf; +} + + +int +x509key_write( + Key *key, + FILE *f +) { + int ret = 0; + Buffer b; + int 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 */ + char * ktype = key_ssh_name(key); + n = strlen(ktype); + ret = ( fwrite(ktype, 1, n, f) == n ) && + ( fwrite(" " , 1, 1, f) == 1 ); + } + if (ret) { + u_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; +} + + +int +x509key_write_subject( + Key *key, + FILE *f +) { + BIO *out=NULL; + char buf[X509KEY_SUBJECT_MAXLEN]; + + if (!x509key_check("x509key_write_subject", key)) + return 0; + + out=BIO_new_fp(f, BIO_NOCLOSE); +#ifdef VMS + { + BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + out = BIO_push(tmpbio, out); + } +#endif + + BIO_puts(out, key_ssh_name(key)); + BIO_puts(out, " Subject:"); + X509_NAME_oneline(X509_get_subject_name(key->x509), buf, sizeof(buf)); + BIO_puts(out, buf); + + BIO_free_all(out); + return 1; +} + + +Key* +x509key_load_cert( + Key *key, + FILE *fp +) { + if (!key) return NULL; + + if ( (key->type == KEY_RSA) || + (key->type == KEY_DSA) ) { + key->x509 = PEM_read_X509(fp, NULL, NULL, NULL); + if (key->x509 == NULL) { + int ecode = ERR_get_error(); + debug3("x509key_load_cert: PEM_read_X509 fail %.200s", ERR_error_string(ecode, NULL)); + } + else { + key->type = (key->type == KEY_RSA) ? KEY_X509_RSA : KEY_X509_DSA; + debug("read X509 certificate done: type %.40s", + key ? key_type(key) : ""); + } + } + return key; +} + + +static int +x509key_save_cert( + FILE *fp, + X509 *x509 +) { + int ret = 0; + BIO *out=NULL; + char buf[X509KEY_SUBJECT_MAXLEN]; + + out=BIO_new_fp(fp, BIO_NOCLOSE); +#ifdef VMS + { + BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + out = BIO_push(tmpbio, out); + } +#endif + + BIO_puts(out, "issuer= "); + X509_NAME_oneline(X509_get_issuer_name(x509), buf, sizeof(buf)); + BIO_puts(out, buf); + BIO_puts(out, "\n"); + + BIO_puts(out, "subject= "); + X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf)); + BIO_puts(out, buf); + BIO_puts(out, "\n"); + { + unsigned char *alstr; + alstr = X509_alias_get0(x509, NULL); + if (!alstr) alstr = ""; + BIO_puts(out,alstr); + BIO_puts(out, "\n"); + } + ret = PEM_write_bio_X509(out, x509); + if (!ret) { + int ecode = ERR_get_error(); + error("x509key_save_cert: PEM_write_bio_X509 fail %.200s", ERR_error_string(ecode, NULL)); + } + + BIO_free_all(out); + return ret; +} + + +int +x509key_save_pem( + FILE *fp, + Key *key, + const EVP_CIPHER *cipher, + u_char *passphrase, + int len +) { + if (!x509key_check("x509key_save_pem", key)) + return 0; + + switch (key->type) { + case KEY_X509_DSA: + if(PEM_write_DSAPrivateKey(fp, key->dsa, cipher, passphrase, len, NULL, NULL)) + return x509key_save_cert(fp, key->x509); + break; + case KEY_X509_RSA: + if(PEM_write_RSAPrivateKey(fp, key->rsa, cipher, passphrase, len, NULL, NULL)) + return x509key_save_cert(fp, key->x509); + break; + } + return 0; +} + + +int +ssh_x509_sign( + Key * key, + u_char **psignature, u_int *psignaturelen, + u_char *data, u_int datalen +) { + int ret = -1; + u_char sigret[256]; + 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 = NULL; + + privkey = EVP_PKEY_new(); + if (!privkey) { + 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) { + int ecode = ERR_get_error(); + error("ssh_x509_sign: EVP_PKEY_set1_XXX: failed %.200s", ERR_error_string(ecode, NULL)); + } + } + + if (ret > 0) { + EVP_MD_CTX ctx; + const EVP_MD *evp_md = (key->rsa) ? EVP_md5() : EVP_dss1(); + debug3("ssh_x509_sign: evp_md { %d, %d, %d, ... }", evp_md->type, evp_md->pkey_type, evp_md->md_size); + + EVP_SignInit(&ctx,evp_md); + EVP_SignUpdate(&ctx,data,datalen); + + if (ret > 0) { + ret = EVP_SignFinal(&ctx,sigret,&siglen,privkey); + if (ret <= 0) { + int ecode = ERR_get_error(); + error("ssh_x509_sign: digest failed: %.200s", ERR_error_string(ecode, NULL)); + } + } + } + EVP_PKEY_free(privkey); + } + if (ret > 0) { + Buffer b; + + buffer_init(&b); + buffer_put_cstring(&b, key_ssh_name(key)); + buffer_put_string(&b, sigret, siglen); + + { + u_int len = buffer_len(&b); + if (psignaturelen != NULL) + *psignaturelen = len; + + if (psignature != NULL) { + *psignature = xmalloc(len); + memcpy(*psignature, buffer_ptr(&b), len); + } + } + buffer_free(&b); + } + ret = ret > 0 ? 0 : -1; + debug3("ssh_x509_sign: return %d", ret); + return ret; +} + + +int ssh_x509_verify( + Key *key, + u_char *signature, u_int signaturelen, + 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; + buffer_init(&b); + buffer_append(&b, signature, signaturelen); + + { /* check signature key type */ + char *ktype = buffer_get_string(&b, NULL); + debug3("ssh_x509_verify: signature key type = %.40s", ktype ); + ret = strcmp("x509v3-sign-rsa", ktype) == 0 || + strcmp("x509v3-sign-dss", ktype) == 0; + if (!ret) { + error("ssh_x509_verify: cannot handle signature key type %.40s", ktype); + } + xfree(ktype); + } + + if (ret > 0) { + sigblob = buffer_get_string(&b, &len); + } + + if (ret > 0) { + int 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; + + pubkey = X509_get_pubkey(key->x509); + if (!pubkey) { + error("ssh_x509_verify: no 'X509 Public Key'"); + ret = -1; + } + + if (ret > 0) { + EVP_MD_CTX ctx; + const EVP_MD *evp_md = (key->rsa) ? EVP_md5() : EVP_dss1(); + debug3("ssh_x509_verify: evp_md { %d, %d, %d, ... }", evp_md->type, evp_md->pkey_type, evp_md->md_size); + + EVP_VerifyInit(&ctx,evp_md); + EVP_VerifyUpdate(&ctx,data,datalen); + ret = EVP_VerifyFinal(&ctx,sigblob,len,pubkey); + if (ret <= 0) { + int ecode = ERR_get_error(); + error("ssh_x509_verify: verify failed: %.200s", ERR_error_string(ecode, NULL)); + ret = 0; + } + } + } + if (ret > 0) { + ret = ssh_x509store_check(key->x509); + } + if (sigblob) { + memset(sigblob, 's', len); + xfree(sigblob); + } + ret = ret > 0 ? 1 : (ret < 0 ? -1 : 0); + debug3("ssh_x509_verify return %d", ret); + return ret; +} diff -ruN openssh-3.4p1/ssh-x509.h openssh-3.4p1+x509e/ssh-x509.h --- openssh-3.4p1/ssh-x509.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/ssh-x509.h 2002-11-18 11:59:25.000000000 +0200 @@ -0,0 +1,57 @@ +#ifndef SSH_X509_H +#define SSH_X509_H +/* + * 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. + */ + + +#include "key.h" +#include "buffer.h" + + /* + * This method return a key(x509) only with "Subject"("Distinguished Name") ! + */ +Key* x509key_from_subject(int _keytype, char* _cp); + + +Key* x509key_from_blob(u_char *blob, int blen); +int x509key_to_blob(Key *key, Buffer *b); + +#define X509KEY_SUBJECT_MAXLEN 512 +char* x509key_subject(Key *key); + + /* write x509 certificate as blob */ +int x509key_write(Key *key, FILE *f); + /* write x509 certificate subject */ +int x509key_write_subject(Key *key, FILE *f); + +Key* x509key_load_cert(Key *key, FILE *fp); + +int x509key_save_pem(FILE *fp, Key *key, const EVP_CIPHER *cipher, u_char *passphrase, int len); + + +int ssh_x509_sign(Key *, u_char **, u_int *, u_char *, u_int); +int ssh_x509_verify(Key *key, u_char *signature, u_int signaturelen, u_char *data, u_int datalen); + + +#endif /* SSH_X509_H */ diff -ruN openssh-3.4p1/tests/CA/1-cre_cadb.sh openssh-3.4p1+x509e/tests/CA/1-cre_cadb.sh --- openssh-3.4p1/tests/CA/1-cre_cadb.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/1-cre_cadb.sh 2002-10-07 17:08:03.000000000 +0300 @@ -0,0 +1,209 @@ +#!/bin/sh +# Copyright (c) 2002 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}functions" +. "${SCRIPTDIR}config" + + +# === +echo_CA_common_options () { +cat < "$1" +[ ca ] +default_ca = CA_OpenSSH_rsa_md5 + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +default_bits = 1024 +distinguished_name = req_distinguished_name +attributes = req_attributes +#prompt = no + +# The extensions to add to a certificate request: +#???req_extensions = usr_cert + + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = $SSH_DN_C +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = $SSH_DN_ST + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = $SSH_DN_O + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = $SSH_DN_OU + +commonName = Common Name (eg, YOUR name) +commonName_min = 2 +commonName_max = 64 + +emailAddress = Email Address (optional) +emailAddress_max = 40 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +[ 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 Client Test Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always + +[ srv_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints = CA:FALSE +nsCertType = server + +# 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 Server Test Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always + +EOF + + +for DIGEST in ${RSA_DIGEST_LIST}; do +( cat << EOF + + +[ CA_OpenSSH_rsa_${DIGEST} ] +EOF + echo_CA_common_options + cat << EOF +# which md to use: +default_md = ${DIGEST} + +# The private key (!) +private_key = "${SSH_CAKEYDIR}/${RSA_BASENAME}.key" + +#The CA certificate (!) +certificate = "${SSH_CACERTDIR}/${RSA_BASENAME}_${DIGEST}.crt.pem" +EOF +) >> "$1" +done + +( cat << EOF + + +[ CA_OpenSSH_dsa ] +EOF + echo_CA_common_options + cat << EOF +# which md to use: +default_md = sha1 + +# The private key (!) +private_key = "${SSH_CAKEYDIR}/${DSA_BASENAME}.key" + +#The CA certificate (!) +certificate = "${SSH_CACERTDIR}/${DSA_BASENAME}.crt.pem" +EOF +) >> "$1" +} + + +# === +cre_db () { + var="${SSH_CAROOT}" + if test ! -d "$var"; then + mkdir -p "$var" || return $? + else + count=`getNextDirName "${var}"` || return $? + if test -d "${var}"; then + printf '%s' "saving old directoty as ${attn}${var}.${warn}${count}${norm} ... " + mv "${var}" "${var}.${count}"; show_status $? || return $? + fi + fi + mkdir -p "$var" && + mkdir "$var/crt" && + mkdir "$var/crl" && + cp /dev/null "$var/index.txt" && + mkdir "$var/newcerts" && + echo '01' > "$var/serial" +} + + +# === +cre_config "${TMPDIR}/${CACONFIG}" && +cre_db && +update_file "${TMPDIR}/${CACONFIG}" "${SSH_CACFGFILE}"; status=$? + + +show_status $status "${extd}Creating a new ${warn}TEST${norm} ${attn}Certificate Authority Database${norm} ..." +exit $status + diff -ruN openssh-3.4p1/tests/CA/2-cre_cakeys.sh openssh-3.4p1+x509e/tests/CA/2-cre_cakeys.sh --- openssh-3.4p1/tests/CA/2-cre_cakeys.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/2-cre_cakeys.sh 2002-10-07 17:08:55.000000000 +0300 @@ -0,0 +1,244 @@ +#!/bin/sh +# Copyright (c) 2002 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}functions" +. "${SCRIPTDIR}config" + + +# === +SSH_DN_OU="OpenSSH Test CA Root" +SSH_DN_CN_BASE="OpenSSH Test CA key" + + +echo_SSH_CA_DN () { +cat </dev/null + +$OPENSSL genrsa ${RSA_OPT} \ + -passout pass:${KEY_PASS} \ + -out "${TMPDIR}/${RSA_BASENAME}.key" 1024 \ + 2>/dev/null \ +; show_status $? "${extd}generating a new ${attn}rsa ${norm} private key for the ${warn}TEST${norm}${extd} ${attn}CA${norm} ..." \ +|| exit $? + + +for DIGEST in ${RSA_DIGEST_LIST}; do + +rm -f "${TMPDIR}/${RSA_BASENAME}_${DIGEST}.crt" 2>/dev/null + +echo_SSH_CA_DN "rsa_${DIGEST}" | +$OPENSSL req -new -x509 \ + -days $SSH_CACERTDAYS \ + -passin pass:${KEY_PASS} \ + -key "${TMPDIR}/${RSA_BASENAME}.key" \ + -${DIGEST} \ + -out "${TMPDIR}/${RSA_BASENAME}_${DIGEST}.crt" \ + 2> /dev/null \ +; show_status $? "${extd}generating the new ${warn}TEST${norm}${extd} ${attn}CA${norm}/(${DIGEST} with rsa) ..." \ +|| exit $? + +done +} + + +# === +gen_dsa () { +DSA_OPT="" +if [ -f /etc/random-seed ]; then + DSA_OPT="${DSA_OPT} -rand /etc/random-seed" +fi + +rm -f "${TMPDIR}/${DSA_BASENAME}.prm" 2>/dev/null +$OPENSSL dsaparam ${DSA_OPT} \ + -out "${TMPDIR}/${DSA_BASENAME}.prm" 1024\ + 2> /dev/null;\ +show_status $? "${extd}generating a new ${attn}DSA parameter file${norm} ..." \ +|| exit $? + +rm -f "${TMPDIR}/${DSA_BASENAME}.key" 2>/dev/null +DSA_OPT="${DSA_OPT} -des3" +$OPENSSL gendsa ${DSA_OPT} \ + -passout pass:${KEY_PASS} \ + -out "${TMPDIR}/${DSA_BASENAME}.key" \ + "${TMPDIR}/${DSA_BASENAME}.prm" \ + 2>/dev/null \ +; show_status $? "${extd}generating a new ${attn}dsa${norm} private key for the ${warn}TEST${norm}${extd} ${attn}CA${norm} ..." \ +|| exit $? + + +#request & ceritificate +rm -f "${TMPDIR}/${DSA_BASENAME}.crt" 2>/dev/null + +echo_SSH_CA_DN "dsa" | +$OPENSSL req -new -x509 \ + -days $SSH_CACERTDAYS \ + -passin pass:${KEY_PASS} \ + -key "${TMPDIR}/${DSA_BASENAME}.key" \ + -out "${TMPDIR}/${DSA_BASENAME}.crt" \ + 2> /dev/null \ +; show_status $? "${extd}generating the new ${warn}TEST${norm}${extd} ${attn}CA${norm}/(sha1 with dsa) ..." \ +|| exit $? + +} + + +# === +crt2bundle () { + val="$1" + test -z "${val}" && { echo ${warn}missing DN${norm} 1>&2; return 1; } + echo + echo ${val} + echo ${val} | sed -e 's/./=/g' + openssl x509 -inform PEM -in "${2}" -fingerprint -noout + echo PEM data: + openssl x509 -inform PEM -in "${2}" -trustout + echo Certificate Ingredients: + openssl x509 -inform PEM -in "${2}" -text -noout +} + + +# === +install () { + + for D in \ + "${SSH_CAROOT}" \ + "${SSH_CAKEYDIR}" \ + "${SSH_CACERTDIR}" \ + ;do + test ! -d "$D" && mkdir -p "${D}" + done + + update_file "${TMPDIR}/${DSA_BASENAME}.prm" "${SSH_CAROOT}/${DSA_BASENAME}.prm" \ +&& + chmod 700 "${SSH_CAKEYDIR}" \ +&& + update_file "${TMPDIR}/${RSA_BASENAME}.key" "${SSH_CAKEYDIR}/${RSA_BASENAME}.key" && + chmod 400 "${SSH_CAKEYDIR}/${RSA_BASENAME}.key" \ +&& + update_file "${TMPDIR}/${DSA_BASENAME}.key" "${SSH_CAKEYDIR}/${DSA_BASENAME}.key" && + chmod 400 "${SSH_CAKEYDIR}/${DSA_BASENAME}.key" \ +|| return 1 + + +for DIGEST in ${RSA_DIGEST_LIST}; do + update_file "${TMPDIR}/${RSA_BASENAME}_${DIGEST}.crt" "${SSH_CACERTDIR}/${RSA_BASENAME}_${DIGEST}.crt.pem" || return 1 +done + update_file "${TMPDIR}/${DSA_BASENAME}.crt" "${SSH_CACERTDIR}/${DSA_BASENAME}.crt.pem" || return 1 + + +printf '%s' "" > "${TMPDIR}/${CACERTFILE}" +for DIGEST in ${RSA_DIGEST_LIST}; do + crt2bundle "$SSH_DN_OU" "${SSH_CACERTDIR}/${RSA_BASENAME}_${DIGEST}.crt.pem" \ + >> "${TMPDIR}/${CACERTFILE}" \ + || return 1 +done + + crt2bundle "$SSH_DN_OU" "${SSH_CACERTDIR}/${DSA_BASENAME}.crt.pem" \ + >> "${TMPDIR}/${CACERTFILE}" \ + || return 1 + +update_file "${TMPDIR}/${CACERTFILE}" "${SSH_CAROOT}/${CACERTFILE}" +} + + +# === +rm_all_hash () { + local HASH=$1 + for F in $HASH.*; do + test -h $F && rm -f $F + done +} + + +get_next_hashname () { + name="$1" + let N=0 + while true; do + if [ ! -f "$name.$N" ]; then + break; + fi + let N=N+1 + done + echo $N; +} + + +cre_hash_link () { + local HASH=`$OPENSSL x509 -in "$1" -noout -hash` + local N=`get_next_hashname $HASH` + echo "creating link ${attn}$HASH.$N${norm} to ${attn}$1${norm}" + ln -sf "$1" $HASH.$N +} + + +cre_hashs () { +#(!) openssl script "c_rehash" is missing in some installations :-( +# c_rehash "${SSH_CACERTDIR}" +( cd "${SSH_CACERTDIR}" + for F in [0-9a-f]*.[0-9]; do + # we must use test -L, but on ?-OSes ... :-( + if test -h $F; then + rm "$F" + fi + done + + for DIGEST in ${RSA_DIGEST_LIST}; do + cre_hash_link "${RSA_BASENAME}_${DIGEST}.crt.pem" + done + cre_hash_link "${DSA_BASENAME}.crt.pem" +) + return 0; +} + + +# === + +gen_rsa && +gen_dsa && +install && +cre_hashs; status=$? + +show_status $status "${extd}Creating a new ${warn}TEST${norm} ${attn}Certificate Authority${norm} ..." +echo "${warn}password for all private keys is ${attn}${KEY_PASS}${norm}" +exit $status diff -ruN openssh-3.4p1/tests/CA/3-cre_certs.sh openssh-3.4p1+x509e/tests/CA/3-cre_certs.sh --- openssh-3.4p1/tests/CA/3-cre_certs.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/3-cre_certs.sh 2002-11-21 16:42:25.000000000 +0200 @@ -0,0 +1,229 @@ +#!/bin/sh +# Copyright (c) 2002 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}functions" +. "${SCRIPTDIR}config" + +usage () { + cat < + -f[ile] [ssh]key_file_name + -t[ype] certificate type: client or server + -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 -z "$1"; do + case $1 in + -f|\ + -file) + shift + if test -z "$1"; then + usage + fi + if ! test -z "${SSH_BASE_KEY}"; then + usage + fi + SSH_BASE_KEY="$1" + shift + ;; + + -t|\ + -type) + shift + if test -z "$1"; then + usage + fi + if ! test -z "$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" + ;; + *) + echo "${warn}wrong type${norm}" + usage + ;; + esac + ;; + + -n|\ + -name) + shift + if test -z "$1"; then + usage + fi + if ! test -z "${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.log" +cat /dev/null > .delmy +update_file .delmy "$OPENSSH_LOG" > /dev/null || exit $? + +# === + +echo_SSH_DN () { + type="$1" + cat <> "$OPENSSH_LOG" + sync + echo_SSH_DN "${type}" | + $OPENSSL req -new -config "${SSH_CACFGFILE}" \ + -key "${SSH_BASE_KEY}" \ + -passin pass:"" \ + -out "${TMPDIR}/user-${type}.csr" \ + 2>> "$OPENSSH_LOG" \ + ; show_status $? "creating new ${extd}CSR${norm} for ${attn}${SSH_BASE_DN_CN}(${type})${norm} ..." || return $? + sync +} + + +# === +cre_crt () { + local type="$1" + + echo "=== create a new CRT ===" >> "$OPENSSH_LOG" + sync + $OPENSSL ca -config "${SSH_CACFGFILE}" \ + -batch \ + -in "${TMPDIR}/user-${type}.csr" \ + -name "CA_OpenSSH_${type}" \ + -passin pass:$KEY_PASS \ + -out "${TMPDIR}/user-${type}.crt" \ + -extensions ${SSH_X509V3_EXTENSIONS} \ + 2>> "$OPENSSH_LOG" \ + ; show_status $? "creating new ${extd}CRT${norm} for ${attn}${SSH_BASE_DN_CN}(${type})${norm} ..." || + { status=$? + printf '%s' "${warn}" + grep 'ERROR:' "$OPENSSH_LOG" + printf '%s' "${norm}" + return $status + } + + sync + $OPENSSL verify -CAfile "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" "${TMPDIR}/user-${type}.crt" && + rm -f "${TMPDIR}/user-${type}.csr" + update_file "${TMPDIR}/user-${type}.crt" "${SSH_BASE_KEY}-${type}.crt" +} + + +# === + +cre_OpenSSH_Crt () { + local type="$1" + printf '%s' "creating ${extd}OpenSSH certificate${norm} with signature ${attn}${type}${norm} ..." + ( cat "${SSH_BASE_KEY}" + $OPENSSL x509 -in "${SSH_BASE_KEY}-${type}.crt" -subject -issuer -alias + ) > "${SSH_BASE_KEY}-${type}" && + chmod 600 "${SSH_BASE_KEY}-${type}" \ + ; show_status $? || return $status +} + +cre_OpenSSH_PubKey () { + local type="$1" + printf '%s' "creating ${extd}OpenSSH public key for certificate${norm} with signature ${attn}${type}${norm} ..." + "$TEST_SSH_SSHKEYGEN" -y -f "${SSH_BASE_KEY}-${type}" \ + > "${SSH_BASE_KEY}-${type}.pub" \ + ; show_status $? || return $status +} + +cre_P12_Crt () { + local type="$1" + printf '%s' "creating ${extd}p12 certificate${norm} with signature ${attn}${type}${norm} ..." + $OPENSSL pkcs12 \ + -passin pass:"" \ + -passout pass:"" \ + -in "${SSH_BASE_KEY}-${type}" \ + -out "${SSH_BASE_KEY}-${type}".p12 \ + -export \ + ; show_status $? || return $status +} + + +# === +cre_all2 () { + local type="$1" + cre_csr "${type}" && + cre_crt "${type}" && + cre_OpenSSH_Crt "${type}" && + cre_OpenSSH_PubKey "${type}" && + cre_P12_Crt "${type}" +} + + +# === +cre_all () { + for DIGEST in ${RSA_DIGEST_LIST}; do + cre_all2 "rsa_${DIGEST}" || return 1 + done + cre_all2 dsa +} + +# === +cre_all + +show_status $? "${extd}Creating ${warn}TEST certificates${norm} ${extd}wich common name:${norm}${attn}${SSH_BASE_DN_CN}${norm} ..." diff -ruN openssh-3.4p1/tests/CA/config openssh-3.4p1+x509e/tests/CA/config --- openssh-3.4p1/tests/CA/config 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/config 2002-11-20 18:56:59.000000000 +0200 @@ -0,0 +1,74 @@ +# Copyright (c) 2002 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. +# + + +# on some system (with pam?, AIX?) 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 + + +OPENSSL=`which openssl` +if test -z "$OPENSSL"; then + echo "openssl binary not found!"1>&2 + exit 1 +fi +TMPDIR="/tmp" + +# === ssh server: + +#"yes" or "no" +SSHSERVER_USEPRIVILEGESEPARATION="yes" + +SSHSERVER_SYSLOGFACILITY=LOCAL1 +SSHSERVER_LOGLEVEL=INFO +#SSHSERVER_SYSLOGFACILITY=LOCAL3 +#SSHSERVER_LOGLEVEL=DEBUG3 + +# === certificates: +KEY_PASS="change_it" +CAKEY_PREFIX="catest" +RSA_BASENAME="${CAKEY_PREFIX}-rsa" +DSA_BASENAME="${CAKEY_PREFIX}-dsa" + +# These are the known patent issues with OpenSSL: +# name # expires +# mdc2: 4,908,861 13/03/2007 +RSA_DIGEST_LIST="md5 sha1 md2 md4 rmd160" + +SSH_CAROOT="`pwd`/ca-test" +SSH_CAKEYDIR="${SSH_CAROOT}/keys" + +CACERTFILE="catest-bundle.crt" +SSH_CACERTDIR="${SSH_CAROOT}/crt" + +CACONFIG="catest.config" +SSH_CACFGFILE="${SSH_CAROOT}/${CACONFIG}" + +SSH_CACERTDAYS=60 + +SSH_DN_C="XX" +SSH_DN_ST="World" +SSH_DN_O="OpenSSH Test Team" +SSH_DN_OU="OpenSSH Testers" diff -ruN openssh-3.4p1/tests/CA/functions openssh-3.4p1+x509e/tests/CA/functions --- openssh-3.4p1/tests/CA/functions 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/functions 2002-11-12 21:54:49.000000000 +0200 @@ -0,0 +1,185 @@ +# Copyright (c) 2002 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Usefull functions. +# + + +# === +# +# define colors and more for echo commands +# +# \033 ascii ESCape +# \033[G move to column (linux console, xterm, not vt100) +# \033[C move columns forward but only upto last column +# \033[D move columns backward but only upto first column +# \033[A move rows up +# \033[B move rows down +# \033[1m switch bold on +# \033[31m switch red on +# \033[32m switch green on +# \033[33m switch yellow on +# \033[m switch color/bold off +# \017 exit alternate mode (xterm, vt100, linux console) +# \033[10m exit alternate mode (linux console) +# \015 carriage return (without newline) +# + +if test -z "${LINES}" -o -z "${COLUMNS}" ; then + eval `stty size 2>/dev/null | (read L C; \ + echo LINES=${L:-24} COLUMNS=${C:-80})` +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 +} + + +# === +show_status () { + if ! test -z "$2"; then + printf '%s' "$2" + fi + if test $1 == 0; then + echo "$msg_done" + else + echo "$msg_failed" + fi + return $1 +} + + +# === +getNextFileName() { + var="$1" + count=0 + while true; do + test ! -f "${var}.${count}" && break + let count=${count}+1 + done + if test ${count} -ge 10; then + echo "${warn}please remove ${attn}${var}${warn} backup files !${norm}" 1>&2 + return 33 + fi + echo $count + return 0 +} + + +# === +getNextDirName() { + var="$1" + count=0 + while true; do + test ! -d "${var}.${count}" && break + let count=${count}+1 + done + if test ${count} -ge 10; then + echo "${warn}please remove ${attn}${var}${warn} backup directories !${norm}" 1>&2 + return 33 + fi + echo $count + return 0 +} + + +# === +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 + + count=`getNextFileName "${var_old}"` || return $? + printf '%s' "saving old file as ${attn}${var_old}.${warn}${count}${norm} ... " + cp -p "${var_old}" "${var_old}.${count}"; show_status $? || return $? + + printf '%s' "updating file ${attn}${var_old}${norm} ... " + if test ! -w "${var_old}"; then + chmod +w "${var_old}" + not_writable="yes" + fi + cat "${var_new}" > "${var_old}"; show_status $? || return $? + if test "$not_writable" == "yes"; then + chmod -w "${var_old}" + fi + rm -f "${var_new}" + return 0 +} + + +# === +FUNCTIONS_INCLUDED="yes" diff -ruN openssh-3.4p1/tests/CA/Makefile.in openssh-3.4p1+x509e/tests/CA/Makefile.in --- openssh-3.4p1/tests/CA/Makefile.in 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/Makefile.in 2002-11-18 17:00:38.000000000 +0200 @@ -0,0 +1,66 @@ +srcdir=@srcdir@ + +all: + + +clean: + rm -f testhostkey_* testid_* + rm -fr ca-test/ + rm -f openssh_ca.log* + rm -f sshd_x509.log + +distclean: clean + rm -f Makefile + +# === + +check-certs: ca_files host_keys rsa_keys dsa_keys + @sh $(srcdir)/openssh_tests.sh -f testid_rsa + @sh $(srcdir)/openssh_tests.sh -f testid_dsa + +# === +ca_files: ca-test/catest.config ca-test/catest-bundle.crt + +ca-test/catest.config: + sh $(srcdir)/1-cre_cadb.sh + +ca-test/catest-bundle.crt: + sh $(srcdir)/2-cre_cakeys.sh + + +# === +host_keys: testhostkey_rsa testhostkey_rsa-rsa_md5 testhostkey_dsa testhostkey_dsa-rsa_md5 + +testhostkey_rsa: + $(TEST_SSH_SSHKEYGEN) -t rsa -b 1024 -f $@ -N "" + +testhostkey_rsa-rsa_md5: testhostkey_rsa + sh $(srcdir)/3-cre_certs.sh -f testhostkey_rsa -t server -n "localhost RSA" + +testhostkey_dsa: + $(TEST_SSH_SSHKEYGEN) -t dsa -b 1024 -f $@ -N "" + +testhostkey_dsa-rsa_md5: testhostkey_dsa + sh $(srcdir)/3-cre_certs.sh -f testhostkey_dsa -t server -n "localhost DSA" + + +# === +rsa_keys: testid_rsa testid_rsa-rsa_md5 + +testid_rsa: + $(TEST_SSH_SSHKEYGEN) -t rsa -b 1024 -f $@ -N "" + +testid_rsa-rsa_md5: testid_rsa + sh $(srcdir)/3-cre_certs.sh -f testid_rsa -t client -n "OpenSSH RSA test certificate" + + +# === +dsa_keys: testid_dsa testid_dsa-rsa_md5 + +testid_dsa: + $(TEST_SSH_SSHKEYGEN) -t dsa -b 1024 -f $@ -N "" + +testid_dsa-rsa_md5: testid_dsa + sh $(srcdir)/3-cre_certs.sh -f testid_dsa -t client -n "OpenSSH DSA test certificate" + + diff -ruN openssh-3.4p1/tests/CA/openssh_tests.sh openssh-3.4p1+x509e/tests/CA/openssh_tests.sh --- openssh-3.4p1/tests/CA/openssh_tests.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/openssh_tests.sh 2002-11-21 16:30:43.000000000 +0200 @@ -0,0 +1,327 @@ +#!/bin/sh +# Copyright (c) 2002 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}functions" +. "${SCRIPTDIR}config" + +test "x$TEST_SSH_SSH" == "x" && { echo "Please define TEST_SSH_SSH" ; exit 1; } +test "x$TEST_SSH_SSHD" == "x" && { echo "Please define TEST_SSH_SSHD" ; exit 1; } +test "x$TEST_SSH_SSHAGENT" == "x" && { echo "Please define TEST_SSH_SSHAGENT" ; exit 1; } +test "x$TEST_SSH_SSHADD" == "x" && { echo "Please define TEST_SSH_SSHADD" ; exit 1; } +test "x$TEST_SSH_SSHKEYGEN" == "x" && { echo "Please define TEST_SSH_SSHKEYGEN"; exit 1; } +#TEST_SSH_SSHKEYSCAN +#TEST_SSH_SFTP +#TEST_SSH_SFTPSERVER + + + +usage () { + cat < + -f[ile] base key_files_name as example /home/tester/.ssh/id_dsa + [-p[ort]] sshd test port (default 20022) +EOF + exit 1 +} + +test -z "$1" && usage + +while ! test -z "$1"; do + case $1 in + -f|\ + -file) + shift + if test -z "$1"; then + usage + fi + if ! test -z "${SSH_CLIENTKEY}"; then + usage + fi + SSH_CLIENTKEY="$1" + shift + ;; + + -p|\ + -port) + shift + if test -z "$1"; then + usage + fi + if ! test -z "${SSHD_PORT}"; then + usage + fi + SSHD_PORT="$1" + shift + ;; + + *) + usage + ;; + esac +done + +test -z "${SSH_CLIENTKEY}" && usage +SSHD_PORT="${SSHD_PORT:-20022}" + + +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" + + +#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 +fi +chmod 700 "${USERDIR}" || exit 1 + +AUTHORIZEDKEYSFILE="${USERDIR}/authorized_keys-certTests" +USERKNOWNHOSTSFILE="${USERDIR}/known_hosts-certTests" + + +# === +runSSHdaemon() { + echo "=======================================================================" >> "${SSHD_LOG}" + $SUDO "$TEST_SSH_SSHD" -f "${SSHD_CFG}" \ + -o PidFile="${SSHD_PID}" \ + -o SyslogFacility="${SSHSERVER_SYSLOGFACILITY}" \ + -o LogLevel="${SSHSERVER_LOGLEVEL}" \ + >> "${SSHD_LOG}" 2>&1 || return $? + #NOTE: bug or ?: with option -e no log to stderr in daemon mode + sleep 3 +} + + +# === +killSSHdaemon() { + $SUDO kill `cat "${SSHD_PID}" 2>/dev/null` > /dev/null 2>&1 + let K=0 + while test $K -le 9; do + if test ! -f "${SSHD_PID}"; then + break + fi + sleep 1 + let K=$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 + return 0 + fi + return 0 +} + + +# === +testEND() { + ( echo + echo "*=- The END -=*" + ) >> "${SSHD_LOG}" + + rm -f "${SSH_ERRLOG}" + rm -f "${SSH_REPLY}" + rm -f "${AUTHORIZEDKEYSFILE}" + rm -f "${USERKNOWNHOSTSFILE}" + rm -f "${SSH_CFG}" +} + +testBREAK() { + ( echo + echo "*=- BREAK -=*" + ) >> "${SSHD_LOG}" + killSSHdaemon +} + +trap testBREAK INT QUIT ABRT KILL TERM || exit 1 +trap testEND EXIT || exit 1 + + +# === +creTestSSHDcfgFile() { + cat > "${SSHD_CFG}" < "${SSH_CFG}" < "${SSH_ERRLOG}" > "${SSH_REPLY}" +} + + +runTest () { + local type="$1" + local identity_file="$2" + local info="$3" + local must_fail="$4" + local msg="OpenSSH Certificate TeSt-${type}" + local status=0 + + case $must_fail in + Y|y|Yes|yes|YES|1) + must_fail=1;; + *) + must_fail=0;; + esac + + printf '%s' " * ${extd}${type}${norm} ${info}" + run_ssh "${identity_file}" "${msg}"; status=$? + + if test "x$must_fail" = "x1"; then + if test $status -ne 0; then + status=0 + else + status=1 + fi + fi + + show_status $status + if test $status -ne 0; then + printf '%s' "${warn}" + cat "${SSH_ERRLOG}"; printf '%s' "${norm}" + else + if test "x$must_fail" = "x1"; then + if ! grep 'Permission denied (publickey)' "${SSH_ERRLOG}" > /dev/null; then + status=33 + printf '%s' "${warn}" + else + printf '%s' "${done}" + fi + cat "${SSH_ERRLOG}"; printf '%s' "${norm}" + else + if ! grep "$msg" "${SSH_REPLY}" > /dev/null; then + status=33 + printf '%s' "${warn}" + cat "${SSH_REPLY}"; printf '%s' "${norm}" + fi + fi + fi + + return $status +} + + +# === +do_all () { + echo + echo "${extd}Testing ssh client with certificates:${norm}" + echo " base key_file name is ${attn}${SSH_CLIENTKEY}${norm}" + echo "Tests begin." + + printf '%s' "" > "${AUTHORIZEDKEYSFILE}" + chmod 644 "${AUTHORIZEDKEYSFILE}" || return $? + + printf '%s' "" > "${SSHD_LOG}" + if test ! -f "${TEST_SSHD_HOSTKEY}"; then + "$TEST_SSH_SSHKEYGEN" -t rsa -f "${TEST_SSHD_HOSTKEY}" -N "" + fi + 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' "localhost " + cat "${TEST_SSHD_HOSTKEY}.pub" + ) > "${USERKNOWNHOSTSFILE}" + chmod 644 "${USERKNOWNHOSTSFILE}" || return $? + + for LTEST in \ + test-blob_auth.sh.inc\ + test-dn_auth_file.sh.inc\ + test-dn_auth_path.sh.inc\ + ; do + ( + . ${SCRIPTDIR}${LTEST} && + do_test + ) || return $? + done + + echo "=======================================================================" + return 0 +} + + +# === +do_all; status=$? + +echo "${extd}Testing ${warn}OpenSSH client certificates${norm}" +echo " with base key_file name ${attn}${SSH_CLIENTKEY}${norm}" +show_status $status " ${extd}status${norm}:" +echo + +exit $status diff -ruN openssh-3.4p1/tests/CA/test-blob_auth.sh.inc openssh-3.4p1+x509e/tests/CA/test-blob_auth.sh.inc --- openssh-3.4p1/tests/CA/test-blob_auth.sh.inc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/test-blob_auth.sh.inc 2002-11-20 17:39:48.000000000 +0200 @@ -0,0 +1,70 @@ +# +# Copyright (c) 2002 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. +# + + +testBLOBautorization () { + local type="$1" + local 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 $? + + local blob=`cat "$AUTHORIZEDKEYSFILE"` + echo $blob | cut -c 1-50 > "$AUTHORIZEDKEYSFILE" + runTest "${type}" "${identity_file}"\ + "${warn}invalid${norm} blob" "Yes" || return $? + + return 0 +} + + +# === + +do_test () { + local status=0 + echo "=======================================================================" + echo "* ${extd}against ${attn}CACertificateFile${norm} and autorization by x509 ${attn}blob${norm}:" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" </dev/null`; then + return 33 + fi + sshkeytype=`echo "${sshkeytype}" | cut -d ' ' -f 1` + + local subject=`$OPENSSL x509 -noout -subject -in "${identity_file}" | cut -d ' ' -f 2-` || 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 + + 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" + ( echo -n "${sshkeytype} ${subtype}" + echo "${subject}" | cut -c -40 + ) > "$AUTHORIZEDKEYSFILE" + runTest "${type} ${warn}invalid${norm} ${subtype}" "${identity_file}"\ + "" "Yes" || return $? + + return 0 +} + + +# === + +do_test () { + local status=0 + echo "=======================================================================" + echo "* ${extd}against ${attn}CACertificateFile${norm} and autorization by x509 ${attn}'Distinguished Name'${norm}:" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" </dev/null`; then + return 33 + fi + sshkeytype=`echo "${sshkeytype}" | cut -d ' ' -f 1` + + local subject=`$OPENSSL x509 -noout -subject -in "${identity_file}" | cut -d ' ' -f 2-` || return $? + echo "${sshkeytype} Subject: ${subject}" > "$AUTHORIZEDKEYSFILE" + runTest "${type}" "${identity_file}"\ + "${info}" "${must_fail}" || return $? +} + + +# === + +do_test_catype () { + local catype="$1" + local type="undefined" + + echo " - autorization by x509 ${attn}Subject${norm} against CA key ${attn}${catype}${norm}" + + for DIGEST in ${RSA_DIGEST_LIST}; do + type="rsa_${DIGEST}" + if test "${catype}" = "${type}"; then + testDNautorizations2 "${type}" || return $? + else + testDNautorizations2 "${type}" "yes" || return $? + fi + done + + type="dsa" + if test "${catype}" = "${type}"; then + testDNautorizations2 "${type}" || return $? + else + testDNautorizations2 "${type}" "yes" || return $? + fi + + return 0 +} + + +# === + +do_test () { + local status=0 + echo "=======================================================================" + echo "* ${extd}against ${attn}CACertificatePath${norm}:" + + creTestSSHDcfgFile + local CRT_TEST_DIR="${SSH_CAROOT}/crt-test" + cat >> "$SSHD_CFG" </dev/null + + for DIGEST in ${RSA_DIGEST_LIST}; do + if test $status -eq 0; then + type="rsa_${DIGEST}" + HASH=`$OPENSSL x509 -in "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" -noout -hash` + ( cd "${CRT_TEST_DIR}"; ln -s "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" "$HASH.0" ) + do_test_catype "${type}"; status=$? + rm -f "${CRT_TEST_DIR}/$HASH.0" + fi + done + if test $status -eq 0; then + type="dsa" + HASH=`$OPENSSL x509 -in "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" -noout -hash` + ( cd "${CRT_TEST_DIR}"; ln -s "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" "$HASH.0" ) + do_test_catype "${type}"; status=$? + rm -f "${CRT_TEST_DIR}/$HASH.0" + fi + + rmdir "${CRT_TEST_DIR}" + killSSHdaemon + return $status +} diff -ruN openssh-3.4p1/tests/CA/verify.sh openssh-3.4p1+x509e/tests/CA/verify.sh --- openssh-3.4p1/tests/CA/verify.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/tests/CA/verify.sh 2002-11-21 16:28:15.000000000 +0200 @@ -0,0 +1,40 @@ +#!/bin/sh +# Copyright (c) 2002 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; do + $VERIFY $F || exit 1 + done +done diff -ruN openssh-3.4p1/x509store.c openssh-3.4p1+x509e/x509store.c --- openssh-3.4p1/x509store.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/x509store.c 2002-11-18 11:35:54.000000000 +0200 @@ -0,0 +1,236 @@ +/* + * 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. + */ +#include "x509store.h" +#include "log.h" +#include "openssl/e_os.h" +#include "openssl/err.h" +#include "includes.h" +#include "openssl/x509v3.h" + + +/* allowed client certificate purpose */ +static int sshpurpose_index = -1; +static X509_STORE *x509store_ctx = NULL; + + +static int MS_CALLBACK +ssh_x509store_cb(int ok, X509_STORE_CTX *ctx) { + if (!ok) { + char buf[256]; + X509_NAME_oneline( X509_get_subject_name(ctx->current_cert), buf, sizeof(buf)); + error("ssh_x509store_cb: subject='%.256s', error %d at %d depth lookup:%.200s\n", + buf, + ctx->error, + ctx->error_depth, + X509_verify_cert_error_string(ctx->error)); +#if 0 + if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) ok=1; + /* since we are just checking the certificates, it is + * ok if they are self signed. But we should still warn + * the user. + */ + if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; + /* Continue after extension errors too */ + if (ctx->error == X509_V_ERR_INVALID_CA) ok=1; + if (ctx->error == X509_V_ERR_PATH_LENGTH_EXCEEDED) ok=1; + if (ctx->error == X509_V_ERR_INVALID_PURPOSE) ok=1; + if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; +#endif + } + /* + if (!v_verbose) + ERR_clear_error(); + */ + return(ok); +} + + +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[0]; 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; +} + + + +int +sshclient_cert_purpose (const char* _purpose_synonym) { + const char * sslpurpose = get_cert_purpose(_purpose_synonym, sslclient_purposes); + if (sslpurpose != NULL) { + int purpose_index = X509_PURPOSE_get_by_sname((char*)sslpurpose); + if (purpose_index < 0) + fatal("client:X509_PURPOSE_get_by_sname fail for argument '%.30s(%.40s)'", sslpurpose, _purpose_synonym); + return purpose_index; + } + return -1; +} + + +int +sshserver_cert_purpose (const char* _purpose_synonym) { + const char * sslpurpose = get_cert_purpose(_purpose_synonym, sslserver_purposes); + if (sslpurpose != NULL) { + int purpose_index = X509_PURPOSE_get_by_sname((char*)sslpurpose); + if (purpose_index < 0) + fatal("server:X509_PURPOSE_get_by_sname fail for argument '%.30s(%.40s)'", sslpurpose, _purpose_synonym); + return purpose_index; + } + return -1; +} + + +void +ssh_x509store_setcontext(X509_STORE *_x509store_ctx, int _sshpurpose_index) { + if (x509store_ctx != NULL) { + X509_STORE_free (x509store_ctx); + x509store_ctx = NULL; + } + x509store_ctx = _x509store_ctx; + if (x509store_ctx) { + X509_STORE_set_verify_cb_func(x509store_ctx, ssh_x509store_cb); + } + sshpurpose_index = _sshpurpose_index; +} + + +int +ssh_x509store_addlookup (int _cmd, const char* _path) { + X509_LOOKUP *lookup=NULL; + int ecode = 0; + + if (_path == NULL) { + error("ssh_x509store_addlookup: path is NULL"); + return 0; + } + + lookup = (_cmd == X509_L_ADD_DIR) + ? X509_STORE_add_lookup(x509store_ctx, X509_LOOKUP_hash_dir()) + : X509_STORE_add_lookup(x509store_ctx, X509_LOOKUP_file() ) + ; + if (lookup == NULL) { + fatal("cannot add %.20s lookup !", ((_cmd == X509_L_ADD_DIR) ? "hash dir" : "file")); + return 0; /* ;-) */ + } + + if(X509_LOOKUP_ctrl(lookup, _cmd, _path, X509_FILETYPE_PEM, NULL)) { + debug2( "%.20s %.400s added to x509 store", ((_cmd == X509_L_ADD_DIR) ? "directory" : "file"), _path); + return 1; + } + + + ecode = ERR_get_error(); + debug("ssh_x509store_addlookup:X509_LOOKUP_ctrl failed with '%.200s' for '%.400s'", ERR_error_string(ecode, NULL), _path); + + ERR_clear_error(); /* XXX ??? */ + return 0; +} + + +int +ssh_x509store_check(X509 *_cert) { + int ret = 1; + + if (x509store_ctx == NULL) { + error("ssh_x509store_check: context is NULL\n"); + ret = 0; + } + if (ret > 0 ) { + X509_STORE_CTX *csc; + csc = X509_STORE_CTX_new(); + if (csc == NULL) { + int ecode = ERR_get_error(); + error("ssh_x509store_check:X509_STORE_CTX_new failed with '%.200s'", ERR_error_string(ecode, NULL)); + ret = 0; + } + if (ret > 0) { + X509_STORE_CTX_init(csc, x509store_ctx, _cert, NULL); + if(sshpurpose_index >= 0) { + int purpose_id; + { + X509_PURPOSE *xptmp = X509_PURPOSE_get0(sshpurpose_index); + purpose_id = X509_PURPOSE_get_id(xptmp); + } + X509_STORE_CTX_set_purpose(csc, purpose_id); + } + /* + if(issuer_checks) + X509_STORE_CTX_set_flags(csc, X509_V_FLAG_CB_ISSUER_CHECK); + */ + ret = X509_verify_cert(csc); + } + X509_STORE_CTX_free(csc); + } + debug3("ssh_x509store_check: return %d", ret); + return (ret); +} diff -ruN openssh-3.4p1/x509store.h openssh-3.4p1+x509e/x509store.h --- openssh-3.4p1/x509store.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509e/x509store.h 2002-11-20 15:47:36.000000000 +0200 @@ -0,0 +1,59 @@ +#ifndef X509STORE_H +#define X509STORE_H +/* + * 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. + */ + + +#include +#if 0 +/* Set 0 (above) to 1 for OpenSSL 0.9.7beta2/3 :-( or comment it in openssl "des_old.h" file. + #define cript is commented in beta4 :-) + */ +#ifdef crypt +# undef crypt +#endif +#endif + + +int ssh_x509store_check(X509 *_cert); + +/* return purpose index, not purpose id (!) */ +int sshclient_cert_purpose (const char* _purpose_synonym); +int sshserver_cert_purpose (const char* _purpose_synonym); + + +void ssh_x509store_setcontext(X509_STORE *_x509store_ctx, int _sshpurpose_index); +int ssh_x509store_addlookup (int _cmd, const char* _path); + + +typedef struct { + /* ssh PKI(X509) store */ + char *certificate_file; + char *certificate_path; + char *revocation_file; + char *revocation_path; +} X509StoreOptions; + + +#endif /* X509STORE_H */