diff -ruN openssh-3.4p1+x509e/auth2-pubkey.c openssh-3.4p1+x509f/auth2-pubkey.c --- openssh-3.4p1+x509e/auth2-pubkey.c 2002-06-06 23:27:56.000000000 +0300 +++ openssh-3.4p1+x509f/auth2-pubkey.c 2003-01-30 09:06:01.000000000 +0200 @@ -1,5 +1,7 @@ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. + * X509 certificates support, + * Copyright (c) 2003 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,7 +25,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); +RCSID("$OpenBSD$"); #include "ssh2.h" #include "xmalloc.h" @@ -40,6 +42,7 @@ #include "auth-options.h" #include "canohost.h" #include "monitor_wrap.h" +#include "ssh-x509.h" /* import */ extern ServerOptions options; @@ -244,6 +247,13 @@ fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); verbose("Found matching %s key: %s", key_type(found), fp); + if ((key->type == KEY_X509_RSA) || + (key->type == KEY_X509_DSA)) { + if (ssh_x509store_check(key->x509) != 1) { + found_key = 0; + verbose("x509store reject matching key"); + } + } xfree(fp); break; } diff -ruN openssh-3.4p1+x509e/key.c openssh-3.4p1+x509f/key.c --- openssh-3.4p1+x509e/key.c 2002-11-14 11:05:52.000000000 +0200 +++ openssh-3.4p1+x509f/key.c 2003-01-30 09:06:01.000000000 +0200 @@ -212,12 +212,7 @@ 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; + return ssh_x509_equal(a, b) == 0; break; default: fatal("key_equal: bad key type %d", a->type); @@ -260,8 +255,8 @@ break; case KEY_DSA: case KEY_RSA: - case KEY_X509_RSA: /*XXX*/ - case KEY_X509_DSA: /*XXX*/ + case KEY_X509_RSA: + case KEY_X509_DSA: key_to_blob(k, &blob, &len); break; case KEY_UNSPEC: @@ -664,6 +659,10 @@ case KEY_DSA: return BN_num_bits(k->dsa->p); break; + case KEY_X509_RSA: + case KEY_X509_DSA: + return ssh_x509_key_size(k); + break; } return 0; } diff -ruN openssh-3.4p1+x509e/log.c openssh-3.4p1+x509f/log.c --- openssh-3.4p1+x509e/log.c 2002-02-26 19:52:15.000000000 +0200 +++ openssh-3.4p1+x509f/log.c 2003-01-30 09:06:01.000000000 +0200 @@ -34,7 +34,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: log.c,v 1.22 2002/02/22 12:20:34 markus Exp $"); +RCSID("$OpenBSD$"); #include "log.h" #include "xmalloc.h" @@ -313,6 +313,11 @@ } } +LogLevel +get_log_level(void) { + return log_level; +} + #define MSGBUFSIZ 1024 void diff -ruN openssh-3.4p1+x509e/log.h openssh-3.4p1+x509f/log.h --- openssh-3.4p1+x509e/log.h 2002-06-06 22:51:06.000000000 +0300 +++ openssh-3.4p1+x509f/log.h 2003-01-30 09:06:00.000000000 +0200 @@ -1,4 +1,4 @@ -/* $OpenBSD: log.h,v 1.7 2002/05/19 20:54:52 deraadt Exp $ */ +/* $OpenBSD$ */ /* * Author: Tatu Ylonen @@ -49,6 +49,7 @@ } LogLevel; void log_init(char *, LogLevel, SyslogFacility, int); +LogLevel get_log_level(void); SyslogFacility log_facility_number(char *); LogLevel log_level_number(char *); diff -ruN openssh-3.4p1+x509e/myproposal.h openssh-3.4p1+x509f/myproposal.h --- openssh-3.4p1+x509e/myproposal.h 2002-11-14 11:05:00.000000000 +0200 +++ openssh-3.4p1+x509f/myproposal.h 2003-01-30 09:06:00.000000000 +0200 @@ -26,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,x509v3-sign-rsa,x509v3-sign-dss" +#define KEX_DEFAULT_PK_ALG "x509v3-sign-rsa,x509v3-sign-dss,ssh-rsa,ssh-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+x509e/pathnames.h openssh-3.4p1+x509f/pathnames.h --- openssh-3.4p1+x509e/pathnames.h 2002-11-14 11:06:54.000000000 +0200 +++ openssh-3.4p1+x509f/pathnames.h 2003-01-30 09:06:00.000000000 +0200 @@ -197,10 +197,10 @@ #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" +#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" diff -ruN openssh-3.4p1+x509e/readconf.c openssh-3.4p1+x509f/readconf.c --- openssh-3.4p1+x509e/readconf.c 2002-11-14 11:06:21.000000000 +0200 +++ openssh-3.4p1+x509f/readconf.c 2003-01-30 09:06:01.000000000 +0200 @@ -48,6 +48,7 @@ #include "misc.h" #include "kex.h" #include "mac.h" +#include "tildexpand.h" /* Format of the configuration file: @@ -896,42 +897,30 @@ 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; - } - } + ssh_x509store_setpurpose(options->allowedcertpurpose); - if (options->userca.certificate_file) { - if (ssh_x509store_addlookup(X509_L_FILE_LOAD, options->userca.certificate_file)) { - x509_store_loaded = 1; - } + if(ssh_x509store_addlocations(&options->userca)) { + 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(ssh_x509store_addlocations(&options->ca)) { + 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; - } - } + return x509_store_loaded; +} + +static void +tilde_expand_filename2(char **_fn, char* _default) { + extern uid_t original_real_uid; - if (!x509_store_loaded) { - ssh_x509store_setcontext(NULL, -1); - debug("bad x509store configuration"); + if (*_fn == NULL) { + *_fn = tilde_expand_filename(_default, original_real_uid); + } else { + char *p = *_fn; + *_fn = tilde_expand_filename(*_fn, original_real_uid); + xfree(p); } - debug3("ssh_x509store_init() end"); - return x509_store_loaded; } /* @@ -1063,14 +1052,10 @@ 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; + tilde_expand_filename2(&options->userca.certificate_file, _PATH_USERCA_CERTIFICATE_FILE); + tilde_expand_filename2(&options->userca.certificate_path, _PATH_USERCA_CERTIFICATE_PATH); + tilde_expand_filename2(&options->userca.revocation_file , _PATH_USERCA_REVOCATION_FILE ); + tilde_expand_filename2(&options->userca.revocation_path , _PATH_USERCA_REVOCATION_PATH ); ssh_x509store_init(options); } diff -ruN openssh-3.4p1+x509e/README.x509v3 openssh-3.4p1+x509f/README.x509v3 --- openssh-3.4p1+x509e/README.x509v3 2002-11-21 17:56:39.000000000 +0200 +++ openssh-3.4p1+x509f/README.x509v3 2003-01-30 09:06:00.000000000 +0200 @@ -1,30 +1,61 @@ Roumen Petrov Sofia, Bulgaria - Thu Nov 21 2002 + Fri Jan 30 2003 + +How to use X.509 certificates with OpenSSH? + + +Identity or hostkey file for protocol version 2 can contain private key +plus x509 certificate in PEM format. Note that protocol version 2 keys +are in PEM format. To use X.509 certificate as identity or hostkey user +should convert certificate in PEM format and append to file. After this +with "ssh-keygen -y ..." user must update "pub" file. +File (identity or hostkey) with X.509 certificate (RSA key): +-----BEGIN RSA PRIVATE KEY----- +..... +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +..... +-----END CERTIFICATE----- +Note that to use X.509 certificates in OpenSSH files must contain +private key followed by certificate. -How to use x509certificates with OpenSSH? 1.) server configuration: 1.1.) .../sshd_config -CACertificateFile /etc/ssh/ca/ca-bundle.crt +1.1.1.) "X509 store". "X509 store" is used to verify client keys. +AllowedCertPurpose sslclient + The intended use off the X509 client certificate. -The CACertificateFile should contain multiple certificates in PEM +CACertificateFile /etc/ssh/ca/ca-bundle.crt + This file contain multiple certificates of certificate signers in PEM format concatenated together. You can get a copy from openssl, apache, KDE, mutt, etc. packages. Original file might is exported from Netscape certificate database and one download URL is: http://www.modssl.org/contrib/ca-bundle.crt.tar.gz - CACertificatePath /etc/ssh/ca/crt + "Hash dir" with certificates of certificate signers. Each certificate +should be stored in separate file with name [HASH].[NUMBER], where +[HASH] is certificate hash value and [NUMBER] is an integer starting +from zero. Hash is result from command like this: +$ openssl x509 -in certificate_file_name -noout -hash + +CARevocationFile /etc/ssh/ca/ca-bundle.crl + This file contain multiple "Certificate Revocation List" (CRL) of +certificate signers in PEM format concatenated together. + +CARevocationPath /etc/ssh/ca/crl + "Hash dir" with "Certificate Revocation List" (CRL) of certificate +signers. Each CRL should be stored in separate file with name +[HASH].r[NUMBER], where [HASH] is CRL hash value and [NUMBER] is an +integer starting from zero. Hash is result from command like this: +$ openssl crl -in crl_file_name -noout -hash + +1.1.2.) HostKey files... + Host key for protocol version 2 can contain private key plus x509 +certificate in PEM format. -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: @@ -38,44 +69,48 @@ DN| Subject} WORDDNSUFF:='='|':'|'' -Notes: +NOTES: - WORDDN is case insensitive ! -- "Distinguished Name"/Subject is equal to output from command: + +- is like output from command: $ openssl x509 -noout -subject -in A_CERTIFICATE_FILE +- can be in RFC2253 format like output from command: +$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE -nameopt RFC2253 + +- Order of items in is not important and separator +can be symbol "/", "," or mixed. All following subjects are equal: +a)CN=OpenSSH RSA test certificate(dsa),OU=OpenSSH Testers,O=OpenSSH Test Team,ST=World,C=XX +b)/C=XX/ST=World/O=OpenSSH Test Team/OU=OpenSSH Testers/CN=OpenSSH RSA test certificate(dsa) +c)/O=OpenSSH Test Team/OU=OpenSSH Testers/C=XX/ST=World/CN=OpenSSH RSA test certificate(dsa) +d)O=OpenSSH Test Team,OU=OpenSSH Testers/C=XX,ST=World/CN=OpenSSH RSA test certificate(dsa) + + Shell sample: $ printf '%s' "x509v3-sign-rsa "; openssl x509 -noout -subject \ - -in A_CERTIFICATE_FILE \ - >> PATH_TO_USER_HOME/.ssh/authorized_keys + -in A_OPENSSH_CERT_FILE \ + >> $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: + Depends from client. To use X.509 certificate "OpenSSH id-file" must +contain both sections - private key and certificate in PEM format: +Note: Don't forget to update public key file with command: $ ssh-keygen -y -f 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. + Check options AllowedCertPurpose, [User]CACertificatePath, +[User]CACertificateFile, [User]CARevocationFile and +[User]CARevocationPath. See p. 1.1.1. All nine options 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: @@ -85,43 +120,106 @@ 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.) In openssh build dir run "make check". +If x509 test scripts fail edit file OPENSSH_SOURCE_PATH/tests/CA/config +or set some environment variables. +Output from make check is in color and when is redirected to file later +we can see content best with command "less -r ...". +When script run a test command print star '*' followed by simple +information about command. When command succeed script print at right +"done" in GREEN(!) otherwise "failed" in RED(!). After failed command +script show on next lines in RED(!) response, skip execution of next +command/script, print message like this: +.... +Testing OpenSSH client with certificates finished. + status: failed +.... +Note that failed is in RED(!) and exit code is NONZERO(!). +Some command in a test script must fail. Part of "simple information" +about command expected fail is in RED(!). When command fail script print +"done" (THIS IS CORRECT - COMMAND MUST FAIL) and on next lines print in +GREEN(!) response. Usualy this occur when server reject logon. +WHEN ALL TESTS SUCCEED output is: +.... +Testing OpenSSH client with certificates finished. + status: done +.... +Note that "done" is in GREEN(!) and exit code is ZERO(!). + + +Description of variables is config file: 3.1.1) main variables: - - SUDO: + - SUDO + (only in config) 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". + If necessary set variable to sudo and configure sudo'ers. + - TMPDIR + (environment or config) + directory for temporary files. If not set its value is selected + from /tmp, /var/tmp or /usr/tmp. + - SSH_X509TESTS + (environment or config) + list with test scripts. A test script is in file with following + name: test-.sh.inc. + +3.1.2) openssl: + - OPENSSL + (environment or config) + path to openssl binary. The default is result from command: + `which openssl`. + - RSA_DIGEST_LIST + (environment or config) + list with RSA digests in support of openssl. The default value is + build at run time from following digest list "md5 sha1 md2 md4 + rmd160" and contain only supported from openssl. -3.1.2) server section: +3.1.3) server section: Read sshd_config.5 manual page for valid values. - - SSHSERVER_USEPRIVILEGESEPARATION: + - SSHD_PORT + (environment or config) + specifies the port number that server listens on and client connect + to on localhost. The default is 20022. + - SSHD_LISTENADDRESS + (only in config) + Same as sshd option "ListenAddress" but without(!) port number. + The default is "127.0.0.1". + - SSHSERVER_USEPRIVILEGESEPARATION="yes": + (only in config) sshd "UsePrivilegeSeparation" option. if necessary set to "no", to disable privilege separation. - - SSHSERVER_SYSLOGFACILITY=LOCAL1 + - SSHSERVER_SYSLOGFACILITY=AUTH + (only in config) sshd "SyslogFacility" option. - SSHSERVER_LOGLEVEL=INFO + (only in config) 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: +3.1.4) certificates: + - Variables related to test certificates and CA. + (only in config) + +3.1.5.) Sample commands to run tests: +$ OPENSLL=/usr/local/openssl/0.9.6h/bin/openssl make check +$ SSHD_PORT=1122 SSH_X509TESTS="agent blob_auth" make check +$ RSA_DIGEST_LIST="md5 sha1" make check + + +3.2.) Current test scripts uses 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. + This is not part of document. +Tips: use created after make check files: +- convert OPENSSH_BUILD_PATH/tests/CA/ca-test/crt/*crt.pem CA + certificates from PEM to DER format and import in + "Windows keystore" +- import OPENSSH_BUILD_PATH/tests/CA/testid_*.p12 in + "Windows keystore" +- setup your client to use certificate[s](see SecSH client manuals). DON`T FORGET TO REMOVE entries from "Windows keystore" after test! @@ -162,8 +260,14 @@ test-blob_auth.sh.inc, test-dn_auth_file.sh.inc, -test-dn_auth_path.sh.inc: +test-dn_auth_path.sh.inc, +test-agent.sh.inc, +test-crl.sh.inc: see DESCRIPTION in each file. +Note that hostbased authentication we cannot test without to install. +Generated testhostkey_* certificates are with sslserver and sslclient +purposes and you can use them to test manualy hostbased authentication. + Enjoy ;-) diff -ruN openssh-3.4p1+x509e/servconf.c openssh-3.4p1+x509f/servconf.c --- openssh-3.4p1+x509e/servconf.c 2002-11-14 11:06:12.000000000 +0200 +++ openssh-3.4p1+x509f/servconf.c 2003-01-30 09:06:01.000000000 +0200 @@ -158,29 +158,13 @@ static int sshd_x509store_init (ServerOptions *options) { int x509_store_loaded = 0; - X509_STORE *x509store_ctx = X509_STORE_new(); + + ssh_x509store_setpurpose(options->allowedcertpurpose); - 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(ssh_x509store_addlocations(&options->ca)) { + 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; } diff -ruN openssh-3.4p1+x509e/ssh.0 openssh-3.4p1+x509f/ssh.0 --- openssh-3.4p1+x509e/ssh.0 2002-11-18 17:38:40.000000000 +0200 +++ openssh-3.4p1+x509f/ssh.0 2003-01-30 09:06:00.000000000 +0200 @@ -91,13 +91,16 @@ The public key method is similar to RSA authentication described in the previous section and allows the RSA or DSA algorithm to be used: The - client uses his private key, $HOME/.ssh/id_dsa or $HOME/.ssh/id_rsa, to - sign the session identifier and sends the result to the server. The - server checks whether the matching public key is listed in + client uses his private key, $HOME/.ssh/id_dsa or $HOME/.ssh/id_rsa, + which can contain a x509 certificate in addition to key to sign the ses- + sion identifier and sends the result to the server. The server checks + whether the matching public key or certificate is listed in $HOME/.ssh/authorized_keys and grants access if both the key is found and - the signature is correct. The session identifier is derived from a - shared Diffie-Hellman value and is only known to the client and the - server. + the signature is correct. In case with x509 certificate server perform + additional verification of that certificate through database with cer- + tificates and CRLs of certificate signers. The session identifier is + derived from a shared Diffie-Hellman value and is only known to the + client and the server. 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. @@ -254,10 +257,11 @@ Selects a file from which the identity (private key) for RSA or DSA authentication is read. The default is $HOME/.ssh/identity 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 identi- - ties specified in configuration files). + $HOME/.ssh/id_dsa for protocol version 2. For protocol version 2 + is possible identity to contain in addition a x509 certificate. + Identity files may also be specified on a per-host basis in the + configuration file. It is possible to have multiple -i options + (and multiple identities specified in configuration files). -I smartcard_device Specifies which smartcard device to use. The argument is the @@ -460,23 +464,29 @@ $HOME/.ssh/identity, $HOME/.ssh/id_dsa, $HOME/.ssh/id_rsa Contains the authentication identity of the user. They are for 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 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. + It is possible protocol version 2 identity to contain identity + plus x509 certificate. 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 others. 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. $HOME/.ssh/identity.pub, $HOME/.ssh/id_dsa.pub, $HOME/.ssh/id_rsa.pub Contains the public key for authentication (public part of the - identity file in human-readable form). The contents of the + identity file in human-readable form). Note that protocol ver- + sion 2 while a identity contain private key and x509 certificate + this file must contain that certificate. 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 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 + authentication. In case with x509 certificates user can use + ``new style''. Instead to add content of file to authorized_keys + user can write certificate ``Distinguished Name''. See sshd(8) + manual page. These files are not sensitive and can (but need 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. @@ -486,12 +496,12 @@ configuration options are described in ssh_config(5). $HOME/.ssh/authorized_keys - Lists the public keys (RSA/DSA) that can be used for logging in - as this user. The format of this file is described in the - sshd(8) manual page. In the simplest form the format is the same - as the .pub identity files. This file is not highly sensitive, - but the recommended permissions are read/write for the user, and - not accessible by others. + Lists the public keys (RSA/DSA) or certificates that can be used + for logging in as this user. The format of this file is + described in the sshd(8) manual page. In the simplest form the + format is the same as the .pub identity files. This file is not + highly sensitive, but the recommended permissions are read/write + for the user, and not accessible by others. /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared @@ -499,10 +509,12 @@ 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, pub- - lic key and optional comment field. When different names are - 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. + lic key and optional comment field. When a x509 certificate is + used as host key instead of public key line contain certificate + (old style) or certificate ``Distinguished Name''. When differ- + ent names are used for the same machine, all such names should be + listed, separated by commas. The format is described on the + sshd(8) manual page. The canonical system name (as returned by name servers) is used by sshd(8) to verify the client host when logging in; other names @@ -519,12 +531,39 @@ /etc/ssh/ssh_host_rsa_key These three files contain the private parts of the host keys and are used for RhostsRSAAuthentication and HostbasedAuthentication. - If the protocol version 1 RhostsRSAAuthentication method is used, - ssh must be setuid root, since the host key is readable only by - root. For protocol version 2, ssh uses ssh-keysign(8) to access - the host keys for HostbasedAuthentication. This eliminates the - requirement that ssh be setuid root when that authentication - method is used. By default ssh is not setuid root. + It is possible files to contain private part plus x509 certifi- + cate for protocol version 2 keys. If the protocol version 1 + RhostsRSAAuthentication method is used, ssh must be setuid root, + since the host key is readable only by root. For protocol ver- + sion 2, ssh uses ssh-keysign(8) to access the host keys for + HostbasedAuthentication. This eliminates the requirement that + ssh be setuid root when that authentication method is used. By + default ssh is not setuid root. When a certificate is used as + host key for hostbased authentication that certificate must have + client purpose too or server configuration must permit connection + without client purpose. For allowed client certificate purposes + see sshd_config(5). + + /etc/ssh/ca/ca-bundle.crt and /etc/ssh/ca/ca-bundle.crl + Part of systemwide ``X509 store''. The first file contain multi- + ple certificates and the second ``Certificate Revocation List'' + (CRLs) of certificate signers in PEM format concatenated + together. Used in verification of server host key certificate. + + /etc/ssh/ca/crt and /etc/ssh/ca/crl + Part of systemwide ``X509 store''. ``Hash dirs'' with certifi- + cates, the first file or CLRs, the second of certificate signers. + Each certificate should be stored in separate file with name + [HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where [HASH] is + certificate or CRL hash value and [NUMBER] is an integer starting + from zero. Used in verification of server host key certificate. + + ~/.ssh/ca/ca-bundle.crt and ~/.ssh/ca/ca-bundle.crl + Part of user ``X509 store''. Same as above systemwide files. + + ~/.ssh/ca/crt and ~/.ssh/ca/crl + Part of user ``X509 store''. Same as above systemwide directo- + ries. $HOME/.rhosts This file is used in .rhosts authentication to list the host/user @@ -589,7 +628,8 @@ Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo 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 rsh(1), scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), diff -ruN openssh-3.4p1+x509e/ssh.1 openssh-3.4p1+x509f/ssh.1 --- openssh-3.4p1+x509e/ssh.1 2002-06-23 03:32:12.000000000 +0300 +++ openssh-3.4p1+x509f/ssh.1 2003-01-30 09:06:00.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.1,v 1.160 2002/06/22 11:51:39 naddy Exp $ +.\" $OpenBSD$ .Dd September 25, 1999 .Dt SSH 1 .Os @@ -222,10 +223,15 @@ .Pa $HOME/.ssh/id_dsa or .Pa $HOME/.ssh/id_rsa , +which can contain a x509 certificate in addition to key to sign the session identifier and sends the result to the server. -The server checks whether the matching public key is listed in +The server checks whether the matching public key or certificate +is listed in .Pa $HOME/.ssh/authorized_keys and grants access if both the key is found and the signature is correct. +In case with x509 certificate server perform additional verification of +that certificate through database with certificates and CRLs of certificate +signers. The session identifier is derived from a shared Diffie-Hellman value and is only known to the client and the server. .Pp @@ -458,6 +464,8 @@ and .Pa $HOME/.ssh/id_dsa for protocol version 2. +For protocol version 2 is possible identity to contain in addition +a x509 certificate. Identity files may also be specified on a per-host basis in the configuration file. It is possible to have multiple @@ -754,6 +762,8 @@ .It Pa $HOME/.ssh/identity, $HOME/.ssh/id_dsa, $HOME/.ssh/id_rsa Contains the authentication identity of the user. They are for protocol 1 RSA, protocol 2 DSA, and protocol 2 RSA, respectively. +It is possible protocol version 2 identity to contain identity plus +x509 certificate. These files contain sensitive data and should be readable by the user but not accessible by others (read/write/execute). @@ -766,6 +776,8 @@ .It Pa $HOME/.ssh/identity.pub, $HOME/.ssh/id_dsa.pub, $HOME/.ssh/id_rsa.pub Contains the public key for authentication (public part of the identity file in human-readable form). +Note that protocol version 2 while a identity contain private key and +x509 certificate this file must contain that certificate. The contents of the .Pa $HOME/.ssh/identity.pub file should be added to @@ -780,6 +792,14 @@ .Pa $HOME/.ssh/authorized_keys on all machines where the user wishes to log in using protocol version 2 DSA/RSA authentication. +In case with x509 certificates user can use +.Dq "new style" . +Instead to add content of file to authorized_keys user can write +certificate +.Dq "Distinguished Name" . +See +.Xr sshd 8 +manual page. These files are not sensitive and can (but need not) be readable by anyone. These files are @@ -790,7 +810,8 @@ The file format and configuration options are described in .Xr ssh_config 5 . .It Pa $HOME/.ssh/authorized_keys -Lists the public keys (RSA/DSA) that can be used for logging in as this user. +Lists the public keys (RSA/DSA) or certificates that can be used for +logging in as this user. The format of this file is described in the .Xr sshd 8 manual page. @@ -807,6 +828,9 @@ This file contains public keys, one per line, in the following format (fields separated by spaces): system name, public key and optional comment field. +When a x509 certificate is used as host key instead of public key line +contain certificate (old style) or certificate +.Dq "Distinguished Name" . When different names are used for the same machine, all such names should be listed, separated by commas. @@ -831,6 +855,8 @@ .Cm RhostsRSAAuthentication and .Cm HostbasedAuthentication . +It is possible files to contain private part plus x509 certificate for +protocol version 2 keys. If the protocol version 1 .Cm RhostsRSAAuthentication method is used, @@ -848,6 +874,37 @@ By default .Nm is not setuid root. +When a certificate is used as host key for hostbased authentication +that certificate must have client purpose too or server configuration +must permit connection without client purpose. For allowed client +certificate purposes see +.Xr sshd_config 5 . +.It Pa "/etc/ssh/ca/ca-bundle.crt" and "/etc/ssh/ca/ca-bundle.crl" +Part of systemwide +.Dq "X509 store" . +The first file contain multiple certificates and the second +.Dq "Certificate Revocation List" +(CRLs) of certificate signers in PEM format concatenated together. +Used in verification of server host key certificate. +.It Pa "/etc/ssh/ca/crt" and Pa "/etc/ssh/ca/crl" +Part of systemwide +.Dq "X509 store" . +.Dq "Hash dirs" +with certificates, the first file or CLRs, the second of +certificate signers. +Each certificate should be stored in separate file with name +[HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where [HASH] is +certificate or CRL hash value and [NUMBER] is an integer starting +from zero. +Used in verification of server host key certificate. +.It Pa "~/.ssh/ca/ca-bundle.crt" and "~/.ssh/ca/ca-bundle.crl" +Part of user +.Dq "X509 store" . +Same as above systemwide files. +.It Pa "~/.ssh/ca/crt" and Pa "~/.ssh/ca/crl" +Part of user +.Dq "X509 store" . +Same as above systemwide directories. .It Pa $HOME/.rhosts This file is used in .Pa \&.rhosts @@ -944,6 +1001,7 @@ 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 rsh 1 , .Xr scp 1 , diff -ruN openssh-3.4p1+x509e/ssh-add.0 openssh-3.4p1+x509f/ssh-add.0 --- openssh-3.4p1+x509e/ssh-add.0 2002-11-18 17:38:39.000000000 +0200 +++ openssh-3.4p1+x509f/ssh-add.0 2003-01-30 09:06:00.000000000 +0200 @@ -55,11 +55,13 @@ $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of - the user. + the user. It is possible to contain identity plus x509 certifi- + cate. $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of - the user. + the user. It is possible to contain identity plus x509 certifi- + cate. Identity files should not be readable by anyone but the user. Note that ssh-add ignores identity files if they are accessible by others. @@ -88,7 +90,8 @@ Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo 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), ssh-agent(1), ssh-keygen(1), sshd(8) diff -ruN openssh-3.4p1+x509e/ssh-add.1 openssh-3.4p1+x509f/ssh-add.1 --- openssh-3.4p1+x509e/ssh-add.1 2002-06-21 03:41:52.000000000 +0300 +++ openssh-3.4p1+x509f/ssh-add.1 2003-01-30 09:06:00.000000000 +0200 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.35 2002/06/19 00:27:55 deraadt Exp $ +.\" $OpenBSD$ .\" .\" -*- nroff -*- .\" @@ -16,6 +16,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -106,8 +107,10 @@ Contains the protocol version 1 RSA authentication identity of the user. .It Pa $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. +It is possible to contain identity plus x509 certificate. .It Pa $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. +It is possible to contain identity plus x509 certificate. .El .Pp Identity files should not be readable by anyone but the user. @@ -157,6 +160,7 @@ 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 , .Xr ssh-agent 1 , diff -ruN openssh-3.4p1+x509e/ssh-agent.0 openssh-3.4p1+x509f/ssh-agent.0 --- openssh-3.4p1+x509e/ssh-agent.0 2002-11-18 17:38:39.000000000 +0200 +++ openssh-3.4p1+x509f/ssh-agent.0 2003-01-30 09:06:00.000000000 +0200 @@ -82,11 +82,13 @@ $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of - the user. + the user. It is possible to contain identity plus x509 certifi- + cate. $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of - the user. + the user. It is possible to contain identity plus x509 certifi- + cate. /tmp/ssh-XXXXXXXX/agent. Unix-domain sockets used to contain the connection to the authen- @@ -99,7 +101,8 @@ Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo 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), ssh-add(1), ssh-keygen(1), sshd(8) diff -ruN openssh-3.4p1+x509e/ssh-agent.1 openssh-3.4p1+x509f/ssh-agent.1 --- openssh-3.4p1+x509e/ssh-agent.1 2002-06-26 02:16:32.000000000 +0300 +++ openssh-3.4p1+x509f/ssh-agent.1 2003-01-30 09:06:00.000000000 +0200 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.35 2002/06/24 13:12:23 markus Exp $ +.\" $OpenBSD$ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -161,8 +162,10 @@ Contains the protocol version 1 RSA authentication identity of the user. .It Pa $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. +It is possible to contain identity plus x509 certificate. .It Pa $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. +It is possible to contain identity plus x509 certificate. .It Pa /tmp/ssh-XXXXXXXX/agent. Unix-domain sockets used to contain the connection to the authentication agent. @@ -178,6 +181,7 @@ 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 , .Xr ssh-add 1 , diff -ruN openssh-3.4p1+x509e/ssh_config.0 openssh-3.4p1+x509f/ssh_config.0 --- openssh-3.4p1+x509e/ssh_config.0 2002-11-18 17:38:42.000000000 +0200 +++ openssh-3.4p1+x509f/ssh_config.0 2003-01-30 09:06:00.000000000 +0200 @@ -71,20 +71,27 @@ 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 + This file contain multiple certificates of certificate signers 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 + ``Hash dir'' with certificates of certificate signers. Each cer- + tificate should be stored in separate file with name [HASH].[NUM- + BER], where [HASH] is certificate hash value and [NUMBER] is an + integer starting from zero. The default is /etc/ssh/ca/crt CARevocationFile - Reserved. The default is /etc/ssh/ca/ca-bundle.crl + This file contain multiple ``Certificate Revocation List'' (CRL) + of certificate signers in PEM format concatenated together. The + default is /etc/ssh/ca/ca-bundle.crl CARevocationPath - Reserved. The default is /etc/ssh/ca/crl + ``Hash dir'' with ``Certificate Revocation List'' (CRL) of cer- + tificate signers. Each CRL should be stored in separate file with + name [HASH].r[NUMBER], where [HASH] is CRL hash value and [NUM- + BER] is an integer starting from zero. The default is + /etc/ssh/ca/crl ChallengeResponseAuthentication Specifies whether to use challenge response authentication. The @@ -187,7 +194,7 @@ HostKeyAlgorithms Specifies the protocol version 2 host key algorithms that the client wants to use in order of preference. The default for this - option is: ``ssh-rsa,ssh-dss''. + option is: ``x509v3-sign-rsa,x509v3-sign-dss,ssh-rsa,ssh-dss''. HostKeyAlias Specifies an alias that should be used instead of the real host @@ -206,12 +213,13 @@ 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 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 direc- - tory. It is possible to have multiple identity files specified - in configuration files; all these identities will be tried in - sequence. + col version 2. For version 2 is possible identity file to con- + tain key plus x509 certificate. Additionally, any identities + represented by the authentication agent will be used for authen- + tication. The file name may use the tilde syntax to refer to a + user's home directory. It is possible to have multiple identity + files specified in configuration files; all these identities will + be tried in sequence. KeepAlive Specifies whether the system should send TCP keepalive messages @@ -378,17 +386,16 @@ mand line. UserCACertificateFile - User CACertificateFile , the default is $HOME/.ssh/ca-bundle.crt + User CACertificateFile , the default is ~/.ssh/ca-bundle.crt UserCACertificatePath - User CACertificatePath , the default is $HOME/.ssh/crt + User CACertificatePath , the default is ~/.ssh/crt UserCARevocationFile - Reserved. User CARevocationFile , the default is - $HOME/.ssh/ca-bundle.crl + User CARevocationFile , the default is ~/.ssh/ca-bundle.crl UserCARevocationPath - Reserved. User CARevocationPath , the default is $HOME/.ssh/crl + User CARevocationPath , the default is ~/.ssh/crl UserKnownHostsFile Specifies a file to use for the user host key database instead of diff -ruN openssh-3.4p1+x509e/ssh_config.5 openssh-3.4p1+x509f/ssh_config.5 --- openssh-3.4p1+x509e/ssh_config.5 2002-11-15 13:43:19.000000000 +0200 +++ openssh-3.4p1+x509f/ssh_config.5 2003-01-30 09:06:00.000000000 +0200 @@ -167,24 +167,32 @@ .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 +This file contain multiple certificates of certificate signers 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. +.Dq "Hash dir" +with certificates of certificate signers. Each certificate should be +stored in separate file with name [HASH].[NUMBER], where [HASH] is +certificate hash value and [NUMBER] is an integer starting from zero. The default is .Pa /etc/ssh/ca/crt .Pp .It Cm CARevocationFile -Reserved. The default is +This file contain multiple +.Dq "Certificate Revocation List" +(CRL) of certificate signers in PEM format concatenated together. +The default is .Pa /etc/ssh/ca/ca-bundle.crl .Pp .It Cm CARevocationPath -Reserved. The default is +.Dq "Hash dir" +with +.Dq "Certificate Revocation List" +(CRL) of certificate signers. Each CRL should be stored in separate +file with name [HASH].r[NUMBER], where [HASH] is CRL hash value and +[NUMBER] is an integer starting from zero. The default is .Pa /etc/ssh/ca/crl .It Cm ChallengeResponseAuthentication Specifies whether to use challenge response authentication. @@ -352,7 +360,7 @@ Specifies the protocol version 2 host key algorithms that the client wants to use in order of preference. The default for this option is: -.Dq ssh-rsa,ssh-dss . +.Dq x509v3-sign-rsa,x509v3-sign-dss,ssh-rsa,ssh-dss . .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key @@ -375,6 +383,7 @@ and .Pa $HOME/.ssh/id_dsa for protocol version 2. +For version 2 is possible identity file to contain key plus x509 certificate. Additionally, any identities represented by the authentication agent will be used for authentication. The file name may use the tilde @@ -635,25 +644,25 @@ User .Cm CACertificateFile , the default is -.Pa $HOME/.ssh/ca-bundle.crt +.Pa ~/.ssh/ca-bundle.crt .Pp .It Cm UserCACertificatePath User .Cm CACertificatePath , the default is -.Pa $HOME/.ssh/crt +.Pa ~/.ssh/crt .Pp .It Cm UserCARevocationFile -Reserved. User +User .Cm CARevocationFile , the default is -.Pa $HOME/.ssh/ca-bundle.crl +.Pa ~/.ssh/ca-bundle.crl .Pp .It Cm UserCARevocationPath -Reserved. User +User .Cm CARevocationPath , the default is -.Pa $HOME/.ssh/crl +.Pa ~/.ssh/crl .It Cm UserKnownHostsFile Specifies a file to use for the user host key database instead of diff -ruN openssh-3.4p1+x509e/sshd.0 openssh-3.4p1+x509f/sshd.0 --- openssh-3.4p1+x509e/sshd.0 2002-11-18 17:38:41.000000000 +0200 +++ openssh-3.4p1+x509f/sshd.0 2003-01-30 09:06:00.000000000 +0200 @@ -51,10 +51,10 @@ SSH protocol version 2 Version 2 works similarly: Each host has a host-specific key (RSA or DSA) - used to identify the host. However, when the daemon starts, it does not - generate a server key. Forward security is provided through a Diffie- - Hellman key agreement. This key agreement results in a shared session - key. + used to identify the host. It is possible host key to contain key plus + x509 certificate. However, when the daemon starts, it does not generate + a server key. Forward security is provided through a Diffie-Hellman key + agreement. This key agreement results in a shared session key. The rest of the session is encrypted using a symmetric cipher, currently 128 bit AES, Blowfish, 3DES, CAST128, Arcfour, 192 bit AES, or 256 bit @@ -126,7 +126,9 @@ /etc/ssh/ssh_host_key for protocol version 1, and /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. + for the different protocol versions and host key algorithms. It + is possible host key for protocol version 2 to contain key plus + x509 certificate. -i Specifies that sshd is being run from inetd. sshd is normally not run from inetd because it needs to generate the server key @@ -221,7 +223,9 @@ $HOME/.ssh/authorized_keys is the default file that lists the public keys that are permitted for RSA authentication in protocol version 1 and for public key authentication (PubkeyAuthentication) in protocol version 2. - AuthorizedKeysFile may be used to specify an alternative file. + It is posible for protocol version 2 to contain x509 certificate or cer- + tificate ``Distinguished Name''. AuthorizedKeysFile may be used to spec- + ify an alternative file. 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 @@ -233,7 +237,15 @@ 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''. + or ``ssh-rsa''. In addition for protocol version 2 user can use x509 + certificates. In that case keytype is ``x509v3-sign-rsa'' or + ``x509v3-sign-dss''. Instead of ``base64 encoded key'' line must contain + base64 encoded certicate (old style) or a keyword (new style), optional + followed by symbol equal `=' or colon , zero or more spaces and certifi- + cate ``Distinguished Name'' (Subject). Keyword is case insensitive and + can be one of `Subject' , `Distinguished Name' , `Distinguished-Name' , + `Distinguished_Name' , `DistinguishedName' or `DN'. Separator of Subject + items can be slash `/' , comma or mixed and order is not important. Note that lines in this file are usually several hundred bytes long (because of the size of the RSA key modulus). You don't want to type @@ -317,12 +329,15 @@ permitopen="10.2.1.55:80",permitopen="10.2.1.56:25" 1024 33 23...2323 + x509v3-sign-dss subject= /C=XX/ST=World/O=OpenSSH Test Team... + SSH_KNOWN_HOSTS FILE FORMAT The /etc/ssh/ssh_known_hosts, and $HOME/.ssh/known_hosts files contain - host public keys for all known hosts. The global file should be prepared - by the administrator (optional), and the per-user file is maintained - automatically: whenever the user connects from an unknown host its key is - added to the per-user file. + host public keys, certificates (old style) or certificate ``Distinguished + Name'' for all known hosts. The global file should be prepared by the + administrator (optional), and the per-user file is maintained automati- + cally: whenever the user connects from an unknown host its key is added + to the per-user file. Each line in these files contains the following fields: hostnames, bits, exponent, modulus, comment. The fields are separated by spaces. @@ -357,6 +372,7 @@ closenet,...,130.233.208.41 1024 37 159...93 closenet.hut.fi cvs.openbsd.org,199.185.137.3 ssh-rsa AAAA1234.....= + x509host x509v3-sign-rsa Subject:/C=XX..... FILES /etc/ssh/sshd_config @@ -365,19 +381,22 @@ /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key - These three files contain the private parts of the host keys. - These files should only be owned by root, readable only by root, - and not accessible to others. Note that sshd does not start if - this file is group/world-accessible. + These three files contain the private parts of the host keys. It + is possible to contain private part plus x509 certificate for + protocol version 2 keys. These files should only be owned by + root, readable only by root, and not accessible to others. Note + that sshd does not start if this file is group/world-accessible. /etc/ssh/ssh_host_key.pub, /etc/ssh/ssh_host_dsa_key.pub, /etc/ssh/ssh_host_rsa_key.pub These three files contain the public parts of the host keys. These files should be world-readable but writable only by root. - Their contents should match the respective private parts. These - files are not really used for anything; they are provided for the - convenience of the user so their contents can be copied to known - hosts files. These files are created using ssh-keygen(1). + Their contents should match the respective private parts. Note + that when corresponding host key contain a certificate in addi- + tion these file must contains that certificate. These files are + not really used for anything; they are provided for the conve- + nience of the user so their contents can be copied to known hosts + files. These files are created using ssh-keygen(1). /etc/moduli Contains Diffie-Hellman groups used for the "Diffie-Hellman Group @@ -397,25 +416,40 @@ able. $HOME/.ssh/authorized_keys - Lists the public keys (RSA or DSA) that can be used to log into - the user's account. This file must be readable by root (which - may on some machines imply it being world-readable if the user's - home directory resides on an NFS volume). It is recommended that - it not be accessible by others. The format of this file is - described above. Users will place the contents of their + Lists the public keys (RSA or DSA), certificates or certificate + ``Distinguished Names'' (recommendet) that can be used to log + into the user's account. This file must be readable by root + (which may on some machines imply it being world-readable if the + user's home directory resides on an NFS volume). It is recom- + mended that it not be accessible by others. The format of this + file is described above. Users will place the contents of their identity.pub, id_dsa.pub and/or id_rsa.pub files into this file, 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 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 - verify that it is connecting to the correct remote host. These - files should be writable only by root/the owner. + the public key or certificate of the host. The key must be + listed in one of these files to be accepted. The client uses the + same files to verify that it is connecting to the correct remote + host. These files should be writable only by root/the owner. /etc/ssh/ssh_known_hosts should be world-readable, and $HOME/.ssh/known_hosts can but need not be world-readable. + /etc/ssh/ca/ca-bundle.crt and /etc/ssh/ca/ca-bundle.crl + The first file contain multiple certificates and the second + ``Certificate Revocation List'' (CRLs) of certificate signers in + PEM format concatenated together. Used to verify client certifi- + cate. + + /etc/ssh/ca/crt and /etc/ssh/ca/crl + ``Hash dirs'' with certificates, the first directory or CLRs, the + second of certificate signers. Each certificate should be stored + in separate file with name [HASH].[NUMBER] or [HASH].r[NUMBER] + for the CRL, where [HASH] is certificate or CRL hash value and + [NUMBER] is an integer starting from zero. Used to verify client + certificate. + /etc/nologin If this file exists, sshd refuses to let anyone except root log in. The contents of the file are displayed to anyone trying to @@ -525,7 +559,8 @@ 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 scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), diff -ruN openssh-3.4p1+x509e/sshd.8 openssh-3.4p1+x509f/sshd.8 --- openssh-3.4p1+x509e/sshd.8 2002-06-23 03:35:26.000000000 +0300 +++ openssh-3.4p1+x509f/sshd.8 2003-01-30 09:06:00.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.8,v 1.186 2002/06/22 16:45:29 stevesk Exp $ +.\" $OpenBSD$ .Dd September 25, 1999 .Dt SSHD 8 .Os @@ -130,6 +131,7 @@ .Pp Version 2 works similarly: Each host has a host-specific key (RSA or DSA) used to identify the host. +It is possible host key to contain key plus x509 certificate. However, when the daemon starts, it does not generate a server key. Forward security is provided through a Diffie-Hellman key agreement. This key agreement results in a shared session key. @@ -222,6 +224,8 @@ for protocol version 2. It is possible to have multiple host key files for the different protocol versions and host key algorithms. +It is possible host key for protocol version 2 to contain key plus x509 +certificate. .It Fl i Specifies that .Nm @@ -373,6 +377,9 @@ permitted for RSA authentication in protocol version 1 and for public key authentication (PubkeyAuthentication) in protocol version 2. +It is posible for protocol version 2 to contain x509 certificate +or certificate +.Dq "Distinguished Name" . .Cm AuthorizedKeysFile may be used to specify an alternative file. .Pp @@ -396,6 +403,38 @@ .Dq ssh-dss or .Dq ssh-rsa . +In addition for protocol version 2 user can use x509 certificates. +In that case keytype is +.Dq x509v3-sign-rsa +or +.Dq x509v3-sign-dss . +Instead of +.Dq "base64 encoded key" +line must contain base64 encoded certicate (old style) or +a keyword (new style), optional followed by symbol equal +.Sq = +or colon +.\" .roumen:howto quote colon ? +.\" .Sq : work only in man2html +.\" .Sq \N'58' work only in GNU nroff +.\" +, zero or more spaces and certificate +.Dq "Distinguished Name" +(Subject). Keyword is case insensitive and can be one of +.Sq Subject +, +.Sq "Distinguished Name" +, +.Sq Distinguished-Name +, +.Sq Distinguished_Name +, +.Sq DistinguishedName +or +.Sq DN . +Separator of Subject items can be slash +.Sq / +, comma or mixed and order is not important. .Pp Note that lines in this file are usually several hundred bytes long (because of the size of the RSA key modulus). @@ -496,12 +535,16 @@ command="dump /home",no-pty,no-port-forwarding 1024 33 23.\|.\|.\|2323 backup.hut.fi .Pp permitopen="10.2.1.55:80",permitopen="10.2.1.56:25" 1024 33 23.\|.\|.\|2323 +.Pp +x509v3-sign-dss subject= /C=XX/ST=World/O=OpenSSH Test Team.\|.\|.\| .Sh SSH_KNOWN_HOSTS FILE FORMAT The .Pa /etc/ssh/ssh_known_hosts , and .Pa $HOME/.ssh/known_hosts -files contain host public keys for all known hosts. +files contain host public keys, certificates (old style) or certificate +.Dq "Distinguished Name" +for all known hosts. The global file should be prepared by the administrator (optional), and the per-user file is maintained automatically: whenever the user connects from an unknown host @@ -551,6 +594,7 @@ .Bd -literal closenet,.\|.\|.\|,130.233.208.41 1024 37 159.\|.\|.93 closenet.hut.fi cvs.openbsd.org,199.185.137.3 ssh-rsa AAAA1234.....= +x509host x509v3-sign-rsa Subject:/C=XX..... .Ed .Sh FILES .Bl -tag -width Ds @@ -561,6 +605,8 @@ .Xr sshd_config 5 . .It Pa /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key These three files contain the private parts of the host keys. +It is possible to contain private part plus x509 certificate for +protocol version 2 keys. These files should only be owned by root, readable only by root, and not accessible to others. Note that @@ -571,6 +617,8 @@ These files should be world-readable but writable only by root. Their contents should match the respective private parts. +Note that when corresponding host key contain a certificate +in addition these file must contains that certificate. These files are not really used for anything; they are provided for the convenience of the user so their contents can be copied to known hosts files. @@ -593,7 +641,10 @@ started last). The content of this file is not sensitive; it can be world-readable. .It Pa $HOME/.ssh/authorized_keys -Lists the public keys (RSA or DSA) that can be used to log into the user's account. +Lists the public keys (RSA or DSA), certificates or certificate +.Dq "Distinguished Names" +(recommendet) +that can be used to log into the user's account. This file must be readable by root (which may on some machines imply it being world-readable if the user's home directory resides on an NFS volume). @@ -609,7 +660,7 @@ .It Pa "/etc/ssh/ssh_known_hosts" and "$HOME/.ssh/known_hosts" These files are consulted when using rhosts with RSA host authentication or protocol version 2 hostbased authentication -to check the public key of the host. +to check the public key or certificate of the host. The key must be listed in one of these files to be accepted. The client uses the same files to verify that it is connecting to the correct remote host. @@ -618,6 +669,20 @@ should be world-readable, and .Pa $HOME/.ssh/known_hosts can but need not be world-readable. +.It Pa "/etc/ssh/ca/ca-bundle.crt" and "/etc/ssh/ca/ca-bundle.crl" +The first file contain multiple certificates and the second +.Dq "Certificate Revocation List" +(CRLs) of certificate signers in PEM format concatenated together. +Used to verify client certificate. +.It Pa "/etc/ssh/ca/crt" and Pa "/etc/ssh/ca/crl" +.Dq "Hash dirs" +with certificates, the first directory or CLRs, the second of +certificate signers. +Each certificate should be stored in separate file with name +[HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where [HASH] is +certificate or CRL hash value and [NUMBER] is an integer starting +from zero. +Used to verify client certificate. .It Pa /etc/nologin If this file exists, .Nm @@ -757,6 +822,7 @@ 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 scp 1 , .Xr sftp 1 , diff -ruN openssh-3.4p1+x509e/sshd_config openssh-3.4p1+x509f/sshd_config --- openssh-3.4p1+x509e/sshd_config 2002-11-15 13:41:52.000000000 +0200 +++ openssh-3.4p1+x509f/sshd_config 2003-01-30 09:06:00.000000000 +0200 @@ -29,16 +29,22 @@ # - "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. +# A file with multiple certificates of certificate signers +# 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. +# A directory with certificates of certificate signers. +# The certificates should have name of the form: [HASH].[NUMBER] +# or have symbolic links to them of this form. #CACertificatePath /etc/ssh/ca/crt +# A file with multiple CRL of certificate signers +# in PEM format concatenated together. #CARevocationFile /etc/ssh/ca/ca-bundle.crl + +# A directory with CRL of certificate signers. +# The CRL should have name of the form: [HASH].r[NUMBER] +# or have symbolic links to them of this form. #CARevocationPath /etc/ssh/ca/crl # Lifetime and size of ephemeral version 1 server key diff -ruN openssh-3.4p1+x509e/sshd_config.0 openssh-3.4p1+x509f/sshd_config.0 --- openssh-3.4p1+x509e/sshd_config.0 2002-11-18 17:38:42.000000000 +0200 +++ openssh-3.4p1+x509f/sshd_config.0 2003-01-30 09:06:00.000000000 +0200 @@ -71,20 +71,27 @@ 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 + This file contain multiple certificates of certificate signers 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 + ``Hash dir'' with certificates of certificate signers. Each cer- + tificate should be stored in separate file with name [HASH].[NUM- + BER], where [HASH] is certificate hash value and [NUMBER] is an + integer starting from zero. The default is /etc/ssh/ca/crt CARevocationFile - Reserved. The default is /etc/ssh/ca/ca-bundle.crl + This file contain multiple ``Certificate Revocation List'' (CRL) + of certificate signers in PEM format concatenated together. The + default is /etc/ssh/ca/ca-bundle.crl CARevocationPath - Reserved. The default is /etc/ssh/ca/crl + ``Hash dir'' with ``Certificate Revocation List'' (CRL) of cer- + tificate signers. Each CRL should be stored in separate file with + name [HASH].r[NUMBER], where [HASH] is CRL hash value and [NUM- + BER] is an integer starting from zero. The default is + /etc/ssh/ca/crl ChallengeResponseAuthentication Specifies whether challenge response authentication is allowed. @@ -168,7 +175,8 @@ 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 - ``rsa'' are used for version 2 of the SSH protocol. + ``rsa'' are used for version 2 of the SSH protocol. It is possi- + ble host key to contain key plus x509 certificate for version 2. IgnoreRhosts Specifies that .rhosts and .shosts files will not be used in diff -ruN openssh-3.4p1+x509e/sshd_config.5 openssh-3.4p1+x509f/sshd_config.5 --- openssh-3.4p1+x509e/sshd_config.5 2002-11-15 13:43:37.000000000 +0200 +++ openssh-3.4p1+x509f/sshd_config.5 2003-01-30 09:06:00.000000000 +0200 @@ -156,24 +156,32 @@ 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 +This file contain multiple certificates of certificate signers 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. +.Dq "Hash dir" +with certificates of certificate signers. Each certificate should be +stored in separate file with name [HASH].[NUMBER], where [HASH] is +certificate hash value and [NUMBER] is an integer starting from zero. The default is .Pa /etc/ssh/ca/crt .Pp .It Cm CARevocationFile -Reserved. The default is +This file contain multiple +.Dq "Certificate Revocation List" +(CRL) of certificate signers in PEM format concatenated together. +The default is .Pa /etc/ssh/ca/ca-bundle.crl .Pp .It Cm CARevocationPath -Reserved. The default is +.Dq "Hash dir" +with +.Dq "Certificate Revocation List" +(CRL) of certificate signers. Each CRL should be stored in separate +file with name [HASH].r[NUMBER], where [HASH] is CRL hash value and +[NUMBER] is an integer starting from zero. The default is .Pa /etc/ssh/ca/crl .Pp .It Cm ChallengeResponseAuthentication @@ -305,6 +313,8 @@ or .Dq rsa are used for version 2 of the SSH protocol. +It is possible host key to contain key plus x509 certificate +for version 2. .It Cm IgnoreRhosts Specifies that .Pa .rhosts diff -ruN openssh-3.4p1+x509e/ssh-keygen.0 openssh-3.4p1+x509f/ssh-keygen.0 --- openssh-3.4p1+x509e/ssh-keygen.0 2002-11-18 17:38:40.000000000 +0200 +++ openssh-3.4p1+x509f/ssh-keygen.0 2003-01-30 09:06:00.000000000 +0200 @@ -137,10 +137,11 @@ $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of - the user. This file should not be readable by anyone but the - user. It is possible to specify a passphrase when generating the - key; that passphrase will be used to encrypt the private part of - this file using 3DES. This file is not automatically accessed by + the user. It is possible to contain identity plus x509 certifi- + cate. This file should not be readable by anyone but the user. + It is possible to specify a passphrase when generating the key; + that passphrase will be used to encrypt the private part of this + file using 3DES. This file is not automatically accessed by ssh-keygen but it is offered as the default file for the private key. ssh(1) will read this file when a login attempt is made. @@ -149,14 +150,21 @@ 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 - keep the contents of this file secret. + keep the contents of this file secret. When file + $HOME/.ssh/id_dsa contain DSA identity plus X509 certificate this + file must contain user certificate! Use ssh-keygen(1) with option + -y to regenerate its content. Note in case with X509 certificate + you can append content to $HOME/.ssh/authorized_keys or to add + certificate ``Distinguished Name'' / ``Subject'' in corresponding + format to ``authorized keys'' file. See sshd(8). $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of - the user. This file should not be readable by anyone but the - user. It is possible to specify a passphrase when generating the - key; that passphrase will be used to encrypt the private part of - this file using 3DES. This file is not automatically accessed by + the user. It is possible to contain identity plus x509 certifi- + cate. This file should not be readable by anyone but the user. + It is possible to specify a passphrase when generating the key; + that passphrase will be used to encrypt the private part of this + file using 3DES. This file is not automatically accessed by ssh-keygen but it is offered as the default file for the private key. ssh(1) will read this file when a login attempt is made. @@ -165,14 +173,21 @@ 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 - keep the contents of this file secret. + keep the contents of this file secret. When file + $HOME/.ssh/id_rsa contain RSA identity plus X509 certificate this + file must contain user certificate! Use ssh-keygen(1) with option + -y to regenerate its content. Note in case with X509 certificate + you can append content to $HOME/.ssh/authorized_keys or to add + certificate ``Distinguished Name'' / ``Subject'' in corresponding + format to ``authorized keys'' file. See sshd(8). 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 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), ssh-add(1), ssh-agent(1), sshd(8) diff -ruN openssh-3.4p1+x509e/ssh-keygen.1 openssh-3.4p1+x509f/ssh-keygen.1 --- openssh-3.4p1+x509e/ssh-keygen.1 2002-06-21 03:41:52.000000000 +0300 +++ openssh-3.4p1+x509f/ssh-keygen.1 2003-01-30 09:06:00.000000000 +0200 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.54 2002/06/19 00:27:55 deraadt Exp $ +.\" $OpenBSD$ .\" .\" -*- nroff -*- .\" @@ -16,6 +16,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -240,6 +241,7 @@ There is no need to keep the contents of this file secret. .It Pa $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. +It is possible to contain identity plus x509 certificate. This file should not be readable by anyone but the user. It is possible to specify a passphrase when generating the key; that passphrase will be @@ -256,8 +258,25 @@ on all machines where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. +When file +.Pa $HOME/.ssh/id_dsa +contain DSA identity plus X509 certificate this file must contain +user certificate! Use +.Xr ssh-keygen 1 +with option -y to regenerate its content. +Note in case with X509 certificate you can append content to +.Pa $HOME/.ssh/authorized_keys +or to add certificate +.Dq Distinguished Name +/ +.Dq Subject +in corresponding format to +.Dq authorized keys +file. See +.Xr sshd 8 . .It Pa $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. +It is possible to contain identity plus x509 certificate. This file should not be readable by anyone but the user. It is possible to specify a passphrase when generating the key; that passphrase will be @@ -274,6 +293,22 @@ on all machines where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. +When file +.Pa $HOME/.ssh/id_rsa +contain RSA identity plus X509 certificate this file must contain +user certificate! Use +.Xr ssh-keygen 1 +with option -y to regenerate its content. +Note in case with X509 certificate you can append content to +.Pa $HOME/.ssh/authorized_keys +or to add certificate +.Dq Distinguished Name +/ +.Dq Subject +in corresponding format to +.Dq authorized keys +file. See +.Xr sshd 8 . .El .Sh AUTHORS OpenSSH is a derivative of the original and free @@ -284,6 +319,7 @@ 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 , .Xr ssh-add 1 , diff -ruN openssh-3.4p1+x509e/ssh-keyscan.0 openssh-3.4p1+x509f/ssh-keyscan.0 --- openssh-3.4p1+x509e/ssh-keyscan.0 2002-11-18 17:38:40.000000000 +0200 +++ openssh-3.4p1+x509f/ssh-keyscan.0 2003-01-30 09:06:00.000000000 +0200 @@ -35,9 +35,10 @@ -t type Specifies the type of the key to fetch from the scanned hosts. The possible values are ``rsa1'' for protocol version 1 and - ``rsa'' or ``dsa'' for protocol version 2. Multiple values may - be specified by separating them with commas. The default is - ``rsa1''. + ``rsa'' or ``ssh-rsa'' , ``dsa'' or ``ssh-rsa'' , + ``x509v3-sign-rsa'' or ``x509v3-sign-dss'' for protocol version + 2. Multiple values may be specified by separating them with com- + mas. The default is ``rsa1''. -f filename Read hosts or addrlist namelist pairs from this file, one per @@ -66,7 +67,7 @@ Find all hosts from the file ssh_hosts which have new or different keys from those in the sorted file ssh_known_hosts: - $ ssh-keyscan -t rsa,dsa -f ssh_hosts | \ + $ ssh-keyscan -t x509v3-sign-rsa,x509v3-sign-dss,rsa,dsa -f ssh_hosts | \ sort -u - ssh_known_hosts | diff ssh_known_hosts - FILES @@ -84,6 +85,12 @@ Where keytype is either ``ssh-rsa'' or ``ssh-dsa''. + Output format for rsa and dsa keys with x509 certificates: + + host-or-namelist keytype distinguished-name + + Where keytype is either ``x509v3-sign-rsa'' or ``x509v3-sign-dss''. + /etc/ssh/ssh_known_hosts BUGS @@ -98,6 +105,6 @@ AUTHORS David Mazieres wrote the initial version, and Wayne Davison added support for protocol version - 2. + 2. Roumen Petrov contributed support for x509 certificates. BSD January 1, 1996 BSD diff -ruN openssh-3.4p1+x509e/ssh-keyscan.1 openssh-3.4p1+x509f/ssh-keyscan.1 --- openssh-3.4p1+x509e/ssh-keyscan.1 2002-02-19 06:19:43.000000000 +0200 +++ openssh-3.4p1+x509f/ssh-keyscan.1 2003-01-30 09:06:00.000000000 +0200 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.14 2002/02/13 08:33:47 mpech Exp $ +.\" $OpenBSD$ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" @@ -6,6 +6,29 @@ .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" +.\" 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. +.\" .Dd January 1, 1996 .Dt SSH-KEYSCAN 1 .Os @@ -57,7 +80,15 @@ for protocol version 1 and .Dq rsa or +.Dq ssh-rsa +, .Dq dsa +or +.Dq ssh-rsa +, +.Dq x509v3-sign-rsa +or +.Dq x509v3-sign-dss for protocol version 2. Multiple values may be specified by separating them with commas. The default is @@ -112,7 +143,7 @@ which have new or different keys from those in the sorted file .Pa ssh_known_hosts : .Bd -literal -$ ssh-keyscan -t rsa,dsa -f ssh_hosts | \e\ +$ ssh-keyscan -t x509v3-sign-rsa,x509v3-sign-dss,rsa,dsa -f ssh_hosts | \e\ sort -u - ssh_known_hosts | diff ssh_known_hosts - .Ed .Sh FILES @@ -138,6 +169,18 @@ or .Dq ssh-dsa . .Pp +.Pa Output format for rsa and dsa keys with x509 certificates: +.Bd -literal +host-or-namelist keytype distinguished-name +.Ed +.Pp +Where +.Pa keytype +is either +.Dq x509v3-sign-rsa +or +.Dq x509v3-sign-dss . +.Pp .Pa /etc/ssh/ssh_known_hosts .Sh BUGS It generates "Connection closed by remote host" messages on the consoles @@ -152,3 +195,4 @@ wrote the initial version, and Wayne Davison added support for protocol version 2. +Roumen Petrov contributed support for x509 certificates. diff -ruN openssh-3.4p1+x509e/ssh-keyscan.c openssh-3.4p1+x509f/ssh-keyscan.c --- openssh-3.4p1+x509e/ssh-keyscan.c 2002-06-21 03:09:54.000000000 +0300 +++ openssh-3.4p1+x509f/ssh-keyscan.c 2003-01-30 09:06:01.000000000 +0200 @@ -4,10 +4,33 @@ * Modification and redistribution in source and binary forms is * permitted provided that due credit is given to the author and the * OpenBSD project by leaving this copyright notice intact. + * + * 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. */ #include "includes.h" -RCSID("$OpenBSD: ssh-keyscan.c,v 1.36 2002/06/16 21:30:58 itojun Exp $"); +RCSID("$OpenBSD$"); #include "openbsd-compat/fake-queue.h" @@ -42,6 +65,8 @@ #define KT_RSA1 1 #define KT_DSA 2 #define KT_RSA 4 +#define KT_X509DSA 8 +#define KT_X509RSA 16 int get_keytypes = KT_RSA1; /* Get only RSA1 keys by default */ @@ -79,7 +104,8 @@ int c_plen; /* Packet length field for ssh packet */ int c_len; /* Total bytes which must be read. */ int c_off; /* Length of data read so far. */ - int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ + int c_keytype; /* Only one of KT_RSA1, KT_DSA, KT_RSA, + KT_X509DSA or KT_X509RSA */ char *c_namebase; /* Address to free for c_name and c_namelist */ char *c_name; /* Hostname of connection for errors */ char *c_namelist; /* Pointer to other possible addresses */ @@ -345,8 +371,23 @@ packet_set_connection(c->c_fd, c->c_fd); enable_compat20(); +/* myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? "ssh-dss": "ssh-rsa"; +*/ + { + Key k; + switch (c->c_keytype) { + case KT_DSA: k.type = KEY_DSA; break; + case KT_RSA: k.type = KEY_RSA; break; + case KT_X509DSA: k.type = KEY_X509_RSA; break; + case KT_X509RSA: k.type = KEY_X509_DSA; break; + default: + fprintf(stderr, "keygrab_ssh2:Invalid keytype!\n"); + exit(1); + } + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = key_ssh_name(&k); + } c->c_kex = kex_setup(myproposal); c->c_kex->verify_host_key = hostjump; @@ -371,7 +412,12 @@ return; fprintf(stdout, "%s ", c->c_output_name ? c->c_output_name : c->c_name); - key_write(key, stdout); + if ((key->type == KEY_X509_RSA) || (key->type == KEY_X509_DSA)) { + /* key_write will print x509 certificate in blob format :-( */ + x509key_write_subject(key, stdout); + } else { + key_write(key, stdout); + } fputs("\n", stdout); } @@ -651,7 +697,7 @@ if (name == NULL) return; - for (j = KT_RSA1; j <= KT_RSA; j *= 2) { + for (j = KT_RSA1; j <= KT_X509RSA; j *= 2) { if (get_keytypes & j) { while (ncon >= MAXCON) conloop(); @@ -751,6 +797,12 @@ case KEY_RSA: get_keytypes |= KT_RSA; break; + case KEY_X509_DSA: + get_keytypes |= KT_X509DSA; + break; + case KEY_X509_RSA: + get_keytypes |= KT_X509RSA; + break; case KEY_UNSPEC: fatal("unknown key type %s", tname); } diff -ruN openssh-3.4p1+x509e/ssh-keysign.0 openssh-3.4p1+x509f/ssh-keysign.0 --- openssh-3.4p1+x509e/ssh-keysign.0 2002-06-26 17:08:08.000000000 +0300 +++ openssh-3.4p1+x509f/ssh-keysign.0 2003-01-30 09:06:00.000000000 +0200 @@ -19,7 +19,8 @@ generate the digital signature. They should be owned by root, readable only by root, and not accessible to others. Since they are readable only by root, ssh-keysign must be set-uid root if - hostbased authentication is used. + hostbased authentication is used. It is possible host key to + contain private parts plus x509 certificate. SEE ALSO ssh(1), ssh-keygen(1), sshd(8) diff -ruN openssh-3.4p1+x509e/ssh-keysign.8 openssh-3.4p1+x509f/ssh-keysign.8 --- openssh-3.4p1+x509e/ssh-keysign.8 2002-06-11 18:50:13.000000000 +0300 +++ openssh-3.4p1+x509f/ssh-keysign.8 2003-01-30 09:06:00.000000000 +0200 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keysign.8,v 1.2 2002/06/10 16:56:30 stevesk Exp $ +.\" $OpenBSD$ .\" .\" Copyright (c) 2002 Markus Friedl. All rights reserved. .\" @@ -54,6 +54,7 @@ Since they are readable only by root, .Nm must be set-uid root if hostbased authentication is used. +It is possible host key to contain private parts plus x509 certificate. .El .Sh SEE ALSO .Xr ssh 1 , diff -ruN openssh-3.4p1+x509e/ssh-x509.c openssh-3.4p1+x509f/ssh-x509.c --- openssh-3.4p1+x509e/ssh-x509.c 2002-11-21 14:52:43.000000000 +0200 +++ openssh-3.4p1+x509f/ssh-x509.c 2003-01-30 09:06:01.000000000 +0200 @@ -31,6 +31,7 @@ #include "bufaux.h" #include "x509store.h" + static char* x509key_find_subject(int _keytype, char* _cp) { static char *keywords[] = { @@ -88,8 +89,20 @@ for (; *p && isspace(*p); p++) {} if (!*p) break; - token = strchr(p, ','); - if (token == NULL) token = strchr(p, '/'); + + /* get shortest token */ + { + char *tokenA = strchr(p, ','); + char *tokenB = strchr(p, '/'); + + if (tokenA == NULL) { + token = tokenB; + } else if (tokenB == NULL) { + token = tokenA; + } else { + token = (tokenA < tokenB) ? tokenA : tokenB; + } + } if (token) { ch = *token; *token = 0; @@ -99,25 +112,43 @@ } q = strchr(p, '='); if (!q) { - error("x509key_str2X509NAME: cannot parse %.200s ...", p); + 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"); + if (nid == NID_undef) { + error("x509key_str2X509NAME: cannot get nid from string '%.200s'", p); ret = 0; - } else { /* add */ + } else { + p = q + 1; + if(!*p) { + error("x509key_str2X509NAME: no data"); + ret = 0; + } else { /* add */ + char save; + for(q = token - 1; (q >= p) && isspace(*q); q--) + {/*skip unexpected \n,etc. from end*/} + + save = *++q; + *q = 0; + ret = X509_NAME_add_entry_by_NID(_name, nid, MBSTRING_ASC, p, q - p, -1, 0); + if(ret <= 0) { + int ecode = ERR_get_error(); + error("x509key_str2X509NAME: X509_NAME_add_entry_by_NID" + " fail with errormsg='%.200s'" + " for nid=%d/%.32s" + " and data='%.128s'" + , ERR_error_string(ecode, NULL) + , nid, OBJ_nid2ln(nid) + , p); - 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)); + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + } + *q = save; } } *token = ch; @@ -184,6 +215,9 @@ if (env_pkey == NULL) { int ecode = ERR_get_error(); error("x509_to_key: X509_get_pubkey fail %.200s", ERR_error_string(ecode, NULL)); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); return key; } else { @@ -245,6 +279,9 @@ * 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)); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); } else { key = x509_to_key(x509); @@ -388,6 +425,9 @@ if (key->x509 == NULL) { int ecode = ERR_get_error(); debug3("x509key_load_cert: PEM_read_X509 fail %.200s", ERR_error_string(ecode, NULL)); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); } else { key->type = (key->type == KEY_RSA) ? KEY_X509_RSA : KEY_X509_DSA; @@ -436,6 +476,9 @@ if (!ret) { int ecode = ERR_get_error(); error("x509key_save_cert: PEM_write_bio_X509 fail %.200s", ERR_error_string(ecode, NULL)); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); } BIO_free_all(out); @@ -468,6 +511,203 @@ } +static int +ssh_ASN1_OBJECT_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { + int lmin = MIN(a->length, b->length); + + int ret = memcmp(a->data, b->data, lmin); + + return (ret == 0) + ? (b->length - a->length) + : ret; +} + + +static int +ssh_ASN1_STRING_casecmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ + int lmin = MIN(M_ASN1_STRING_length(a), M_ASN1_STRING_length(b)); + + int ret = strncasecmp(M_ASN1_STRING_data(a), M_ASN1_STRING_data(b), lmin); + + return (ret != 0) + ? (M_ASN1_STRING_length(b) - M_ASN1_STRING_length(a)) + : ret; +} + + +/* from RFC2459 + (d) attribute values in PrintableString are compared after + removing leading and trailing white space and converting internal + substrings of one or more consecutive white space characters to a + single space. +*/ + +static int +ssh_ASN1_PRINTABLESTRING_casecmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ + int la = M_ASN1_STRING_length(a); + u_char *pa = M_ASN1_STRING_data(a); + int lb = M_ASN1_STRING_length(b); + u_char *pb = M_ASN1_STRING_data(b); + + /* skip leading spaces */ + for (; la > 0 && isspace(*pa); la--, pa++); + for (; lb > 0 && isspace(*pb); lb--, pb++); + + /* skip trailing spaces */ + { + u_char *p; + for (p = pa + la - 1; la > 0 && isspace(*p); la--, p--); + for (p = pb + lb - 1; lb > 0 && isspace(*p); lb--, p--); + } + + while (la > 0 && lb > 0) + { + int chA = tolower(*pa); + int chB = tolower(*pb); + + if (chA != chB) + return (chB - chA); + + pa++; pb++; + la--; lb--; + if (isspace(chA)) { + for (; la > 0 && isspace(*pa); la--, pa++); + for (; lb > 0 && isspace(*pb); lb--, pb++); + } + } + return (lb - la); +} + + +/* +1.) + Since version 0.9.7.beta4 and 0.9.6h OpenSSL function X509_NAME_cmp + is more restrictive but more correct (!). + Problem is that some x509 implementation set X509_NAME entry + incorrectly to "Printable String" :-[ . + O.K. when one entry is "Printable String" we will compare + to corresponding entry as "Printable String". +2.) + OpenSSL functions X509_NAME_cmp check nids order in X509_NAME. + i.e. X509_NAME{"/C=XX/O=YY"} is not equal to X509_NAME{"/O=YY/C=XX"} +*/ +static int +ssh_X509_NAME_cmp(X509_NAME *a, X509_NAME *b) { + int k, n; + + k = sk_X509_NAME_ENTRY_num(a->entries); + n = sk_X509_NAME_ENTRY_num(b->entries); + + if (k != n) + return (n - k); + + for (--k; k >= 0; k--) { + X509_NAME_ENTRY *neA; + ASN1_STRING *nvA; + int nid; + X509_NAME_ENTRY *neB; + ASN1_STRING *nvB; + + neA = sk_X509_NAME_ENTRY_value(a->entries, k); + nid = OBJ_obj2nid(neA->object); + n = X509_NAME_get_index_by_NID(b, nid, -1); + if (n < 0) { + char buf1[X509KEY_SUBJECT_MAXLEN]; + char buf2[X509KEY_SUBJECT_MAXLEN]; + + X509_NAME_oneline(a, buf1, sizeof(buf1)); + X509_NAME_oneline(b, buf2, sizeof(buf2)); + debug3("ssh_X509_NAME_cmp: missing nid=%d(%.40s) in second name." + " na=%.*s, nb=%.*s", + nid, OBJ_nid2ln(nid), + (int) sizeof(buf1), buf1, + (int) sizeof(buf1), buf2); + return -1; + } + neB = sk_X509_NAME_ENTRY_value(b->entries, n); + + nvA = neA->value; + nvB = neB->value; + + if (nid == NID_pkcs9_emailAddress) { + int tag; + + tag = M_ASN1_STRING_type(nvA); + if (tag != V_ASN1_IA5STRING) + error("ssh_X509_NAME_cmp: incorrect type for emailAddress(a) %d(%.30s)", tag, ASN1_tag2str(tag)); + + tag = M_ASN1_STRING_type(nvB); + if (tag != V_ASN1_IA5STRING) + error("ssh_X509_NAME_cmp: incorrect type for emailAddress(b) %d(%.30s)", tag, ASN1_tag2str(tag)); + + n = ssh_ASN1_STRING_casecmp(nvA, nvB); + if (n == 0) continue; + + return n; + } + if ((M_ASN1_STRING_type(nvA) == V_ASN1_PRINTABLESTRING) || + (M_ASN1_STRING_type(nvB) == V_ASN1_PRINTABLESTRING) ) { + int tag; + + tag = M_ASN1_STRING_type(nvA); + if (tag != V_ASN1_PRINTABLESTRING) + debug("ssh_X509_NAME_cmp: X509_NAME_ENTRY(a)->type=%d(%.30s) is not PrintableString", tag, ASN1_tag2str(tag)); + + tag = M_ASN1_STRING_type(nvB); + if (tag != V_ASN1_PRINTABLESTRING) + debug("ssh_X509_NAME_cmp: X509_NAME_ENTRY(b)->type=%d(%.30s) is not PrintableString", tag, ASN1_tag2str(tag)); + + n = ssh_ASN1_PRINTABLESTRING_casecmp(nvA, nvB); + if (n == 0) continue; + + return n; + } + + n = M_ASN1_STRING_length(nvA) - M_ASN1_STRING_length(nvB); + if (n != 0) return n; + + n = M_ASN1_STRING_length(nvA); + n = memcmp(nvA->data, nvB->data, n); + if (n != 0) return n; + + /* openssl check object too */ + n = ssh_ASN1_OBJECT_cmp(neA->object, neB->object); + if (n != 0) return n; + } + + return 0; +} + +/* we can check only by Subject (Distinguished Name): + - sshd receive from client only x509 certificate !!! + - sshadd -d ... send only x509 certificate !!! + - otherwise Key might contain private key +*/ +int +ssh_x509_equal(Key *a, Key *b) { + if (!x509key_check("ssh_x509_equal", a)) + return 1; + if (!x509key_check("ssh_x509_equal", b)) + return -1; + +#if 1 +/* We must use own method to compare two X509_NAMEs + instead of OpenSSL function[s] ! See notes before + body of "ssh_X509_NAME_cmp()" . +*/ + { + X509_NAME *nameA = X509_get_subject_name(a->x509); + X509_NAME *nameB = X509_get_subject_name(b->x509); + return ssh_X509_NAME_cmp(nameA, nameB); + } +#else + return X509_subject_name_cmp(a->x509, b->x509); +#endif +} + + int ssh_x509_sign( Key * key, @@ -503,6 +743,9 @@ if (ret <= 0) { int ecode = ERR_get_error(); error("ssh_x509_sign: EVP_PKEY_set1_XXX: failed %.200s", ERR_error_string(ecode, NULL)); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); } } @@ -519,6 +762,9 @@ if (ret <= 0) { int ecode = ERR_get_error(); error("ssh_x509_sign: digest failed: %.200s", ERR_error_string(ecode, NULL)); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); } } } @@ -611,6 +857,9 @@ if (ret <= 0) { int ecode = ERR_get_error(); error("ssh_x509_verify: verify failed: %.200s", ERR_error_string(ecode, NULL)); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); ret = 0; } } @@ -626,3 +875,123 @@ debug3("ssh_x509_verify return %d", ret); return ret; } + + +u_int +ssh_x509_key_size(Key *key) { + EVP_PKEY *pkey=NULL; + int k = 0; + + if (!x509key_check("key_size", key)) + return 0; + + pkey=X509_get_pubkey(key->x509); + if (pkey != NULL) { + if (pkey->type == EVP_PKEY_RSA) + { + /* BN_num_bits return int (!): XXX */ + k = BN_num_bits(pkey->pkey.rsa->n); + } + if (pkey->type == EVP_PKEY_DSA) + { + /*OpenSSH like this*/ + k = BN_num_bits(pkey->pkey.dsa->p); + } + } + EVP_PKEY_free(pkey); + return (u_int) k; +} + + +#ifdef SSHX509TEST + +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif + + +#define DATA "test_certificate" +#define DATA2 "Test_Certificate" + +int +main (int argc, char *argv[]) { + X509_NAME* name; + + __progname = get_progname(argv[0]); + log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 1); + + name = X509_NAME_new(); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, DATA, -1, -1, 0); + { + X509_NAME* x = X509_NAME_new(); + X509_NAME_add_entry_by_txt(x, "CN", V_ASN1_PRINTABLESTRING, DATA, -1, -1, 0); + fprintf(stderr, "A1:ssh_X509_NAME_cmp return %d\n", ssh_X509_NAME_cmp(name, x)); + X509_NAME_free(x); + } + { + X509_NAME* x = X509_NAME_new(); + X509_NAME_add_entry_by_txt(x, "CN", V_ASN1_PRINTABLESTRING, " " DATA " ", -1, -1, 0); + fprintf(stderr, "A2:ssh_X509_NAME_cmp return %d\n", ssh_X509_NAME_cmp(name, x)); + X509_NAME_free(x); + } + { + X509_NAME* x = X509_NAME_new(); + X509_NAME_add_entry_by_txt(x, "CN", V_ASN1_PRINTABLESTRING, " " DATA2 " ", -1, -1, 0); + fprintf(stderr, "A3:ssh_X509_NAME_cmp return %d\n", ssh_X509_NAME_cmp(name, x)); + X509_NAME_free(x); + } + { + X509_NAME* x = X509_NAME_new(); + X509_NAME_add_entry_by_txt(x, "OU", V_ASN1_PRINTABLESTRING, " " DATA2 " ", -1, -1, 0); + fprintf(stderr, "A4:ssh_X509_NAME_cmp return %d\n", ssh_X509_NAME_cmp(name, x)); + X509_NAME_free(x); + } + { + X509_NAME* x = X509_NAME_new(); + X509_NAME_add_entry_by_txt(x, "CN", MBSTRING_ASC, " " DATA2 " ", -1, -1, 0); + fprintf(stderr, "A5:ssh_X509_NAME_cmp return %d\n", ssh_X509_NAME_cmp(name, x)); + X509_NAME_free(x); + } + X509_NAME_free(name); + + + name = X509_NAME_new(); + X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_ASC, DATA, -1, -1, 0); + { + X509_NAME* x = X509_NAME_new(); + X509_NAME_add_entry_by_txt(x, "emailAddress", V_ASN1_TELETEXSTRING, DATA2, -1, -1, 0); + fprintf(stderr, "A1:ssh_X509_NAME_cmp return %d\n", ssh_X509_NAME_cmp(name, x)); + X509_NAME_free(x); + } + { + X509_NAME* x = X509_NAME_new(); + X509_NAME_add_entry_by_txt(x, "emailAddress", V_ASN1_IA5STRING, DATA2, -1, -1, 0); + fprintf(stderr, "A2:ssh_X509_NAME_cmp return %d\n", ssh_X509_NAME_cmp(name, x)); + X509_NAME_free(x); + } + X509_NAME_free(name); + + name = X509_NAME_new(); + X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_ASC, DATA, -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, DATA, -1, -1, 0); + { + X509_NAME* x = X509_NAME_new(); + X509_NAME_add_entry_by_txt(x, "CN", V_ASN1_PRINTABLESTRING, " " DATA2 " ", -1, -1, 0); + X509_NAME_add_entry_by_txt(x, "emailAddress", V_ASN1_IA5STRING, DATA2, -1, -1, 0); + fprintf(stderr, "A3:ssh_X509_NAME_cmp return %d\n", ssh_X509_NAME_cmp(name, x)); + X509_NAME_free(x); + } + { + int flag = X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, DATA, -1, -1, 0); + if (flag <= 0) + fprintf(stderr, "OK:add_entry fail. return code is %d\n", flag); + else + fprintf(stderr, "add duplicate entry might fail, but return code is OK %d\n", flag); + } + X509_NAME_free(name); + exit(0); + return 0; +} +#endif diff -ruN openssh-3.4p1+x509e/ssh-x509.h openssh-3.4p1+x509f/ssh-x509.h --- openssh-3.4p1+x509e/ssh-x509.h 2002-11-18 11:59:25.000000000 +0200 +++ openssh-3.4p1+x509f/ssh-x509.h 2003-01-30 09:06:00.000000000 +0200 @@ -50,8 +50,10 @@ int x509key_save_pem(FILE *fp, Key *key, const EVP_CIPHER *cipher, u_char *passphrase, int len); +int ssh_x509_equal(Key *a, Key *b); 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); +u_int ssh_x509_key_size(Key *key); #endif /* SSH_X509_H */ diff -ruN openssh-3.4p1+x509e/tests/CA/1-cre_cadb.sh openssh-3.4p1+x509f/tests/CA/1-cre_cadb.sh --- openssh-3.4p1+x509e/tests/CA/1-cre_cadb.sh 2002-10-07 17:08:03.000000000 +0300 +++ openssh-3.4p1+x509f/tests/CA/1-cre_cadb.sh 2003-01-30 09:06:00.000000000 +0200 @@ -30,13 +30,15 @@ # === echo_CA_common_options () { + local type="$1" + cat < "$var/serial" } diff -ruN openssh-3.4p1+x509e/tests/CA/2-cre_cakeys.sh openssh-3.4p1+x509f/tests/CA/2-cre_cakeys.sh --- openssh-3.4p1+x509e/tests/CA/2-cre_cakeys.sh 2002-10-07 17:08:55.000000000 +0300 +++ openssh-3.4p1+x509f/tests/CA/2-cre_cakeys.sh 2003-01-30 09:06:00.000000000 +0200 @@ -130,11 +130,11 @@ echo echo ${val} echo ${val} | sed -e 's/./=/g' - openssl x509 -inform PEM -in "${2}" -fingerprint -noout + $OPENSSL x509 -inform PEM -in "${2}" -fingerprint -noout echo PEM data: - openssl x509 -inform PEM -in "${2}" -trustout + $OPENSSL x509 -inform PEM -in "${2}" -trustout echo Certificate Ingredients: - openssl x509 -inform PEM -in "${2}" -text -noout + $OPENSSL x509 -inform PEM -in "${2}" -text -noout } @@ -183,32 +183,24 @@ # === -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 + local HASH + local NAME + +#option -noout problem: +#exit code from .../openssl ... -noout ... is sometime nonzero !!! +#might only by .../openssl x509 ... -noout ... exit code is zero +#sample: +#a) exit code is one - INCORRECT +# .../openssl crl -in a_crl_file -hash -noout +#b) exit code is zero - correct +# .../openssl crl -in a_crl_file -hash -out /dev/null +# +#work around might is to use -out /dev/null :-/ + HASH=`$OPENSSL x509 -in "$1" -noout -hash` + NAME=`getNextFreeName ${HASH}.` || return $? + echo "creating link ${attn}${NAME}${norm} to ${attn}$1${norm}" + ln -sf "$1" ${NAME} } diff -ruN openssh-3.4p1+x509e/tests/CA/3-cre_certs.sh openssh-3.4p1+x509f/tests/CA/3-cre_certs.sh --- openssh-3.4p1+x509e/tests/CA/3-cre_certs.sh 2002-11-21 16:42:25.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/3-cre_certs.sh 2003-01-30 09:06:00.000000000 +0200 @@ -109,54 +109,51 @@ cat /dev/null > .delmy update_file .delmy "$OPENSSH_LOG" > /dev/null || exit $? + # === +cre_csr () { + local type="$1" + local subtype="$2" -echo_SSH_DN () { - type="$1" - cat <> "$OPENSSH_LOG" + ( 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" \ + -out "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.csr" \ 2>> "$OPENSSH_LOG" \ - ; show_status $? "creating new ${extd}CSR${norm} for ${attn}${SSH_BASE_DN_CN}(${type})${norm} ..." || return $? + ; show_status $? "creating new ${extd}CSR${norm} for ${attn}${SSH_BASE_DN_CN}(${type}${subtype})${norm} ..." || return $? + sync + return 0 } # === cre_crt () { local type="$1" + local subtype="$2" echo "=== create a new CRT ===" >> "$OPENSSH_LOG" - sync $OPENSSL ca -config "${SSH_CACFGFILE}" \ -batch \ - -in "${TMPDIR}/user-${type}.csr" \ + -in "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.csr" \ -name "CA_OpenSSH_${type}" \ -passin pass:$KEY_PASS \ - -out "${TMPDIR}/user-${type}.crt" \ + -out "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.crt" \ -extensions ${SSH_X509V3_EXTENSIONS} \ 2>> "$OPENSSH_LOG" \ - ; show_status $? "creating new ${extd}CRT${norm} for ${attn}${SSH_BASE_DN_CN}(${type})${norm} ..." || + ; show_status $? "creating new ${extd}CRT${norm} for ${attn}${SSH_BASE_DN_CN}(${type}${subtype})${norm} ..." || { status=$? printf '%s' "${warn}" grep 'ERROR:' "$OPENSSH_LOG" @@ -165,9 +162,13 @@ } 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" + $OPENSSL verify \ + -CAfile "${SSH_CACERTDIR}/${CAKEY_PREFIX}-${type}.crt.pem" \ + "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.crt" && + rm -f "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.csr" && + update_file \ + "${TMPDIR}/${SSH_X509V3_EXTENSIONS}-${type}${subtype}.crt" \ + "${SSH_BASE_KEY}-${type}${subtype}.crt" } @@ -175,35 +176,56 @@ cre_OpenSSH_Crt () { local type="$1" - printf '%s' "creating ${extd}OpenSSH certificate${norm} with signature ${attn}${type}${norm} ..." + local subtype="$2" + + printf '%s' "creating ${extd}OpenSSH certificate${norm} with signature ${attn}${type}${norm}${subtype} ..." ( 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}" \ + $OPENSSL x509 -in "${SSH_BASE_KEY}-${type}${subtype}.crt" -subject -issuer -alias + ) > "${SSH_BASE_KEY}-${type}${subtype}" && + chmod 600 "${SSH_BASE_KEY}-${type}${subtype}" \ ; show_status $? || 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" \ + local subtype="$2" + + printf '%s' "creating ${extd}OpenSSH public key for certificate${norm} with signature ${attn}${type}${norm}${subtype} ..." + "$TEST_SSH_SSHKEYGEN" -y -f "${SSH_BASE_KEY}-${type}${subtype}" \ + > "${SSH_BASE_KEY}-${type}${subtype}.pub" \ ; show_status $? || return $status } cre_P12_Crt () { local type="$1" - printf '%s' "creating ${extd}p12 certificate${norm} with signature ${attn}${type}${norm} ..." + local subtype="$2" + + printf '%s' "creating ${extd}p12 certificate${norm} with signature ${attn}${type}${norm}${subtype} ..." $OPENSSL pkcs12 \ -passin pass:"" \ -passout pass:"" \ - -in "${SSH_BASE_KEY}-${type}" \ - -out "${SSH_BASE_KEY}-${type}".p12 \ + -in "${SSH_BASE_KEY}-${type}${subtype}" \ + -out "${SSH_BASE_KEY}-${type}${subtype}".p12 \ -export \ ; show_status $? || return $status } +revoke_crt () { + local type="$1" + local subtype="$2" + + echo "=== revoke a CRT ===" >> "$OPENSSH_LOG" + printf '%s' "revoke ${extd}certificate${norm} with signature ${attn}${type}${norm}${subtype} ..." + $OPENSSL ca -config "${SSH_CACFGFILE}" \ + -name "CA_OpenSSH_${type}" \ + -passin pass:$KEY_PASS \ + -revoke "${SSH_BASE_KEY}-${type}${subtype}" \ + 2>> "$OPENSSH_LOG" \ + ; show_status $? || return $status +} + + # === cre_all2 () { local type="$1" @@ -216,11 +238,33 @@ # === +cre_all3 () { + local type="$1" + + cre_csr "${type}" "-revoked" && + cre_crt "${type}" "-revoked" && + cre_OpenSSH_Crt "${type}" "-revoked" && + cre_OpenSSH_PubKey "${type}" "-revoked" && + cre_P12_Crt "${type}" "-revoked" && + revoke_crt "${type}" "-revoked" +} + + +# === cre_all () { for DIGEST in ${RSA_DIGEST_LIST}; do - cre_all2 "rsa_${DIGEST}" || return 1 + cre_all2 "rsa_${DIGEST}" || return $? done - cre_all2 dsa + cre_all2 dsa || return $? + +if test "$SSH_X509V3_EXTENSIONS" == "usr_cert"; then + for DIGEST in ${RSA_DIGEST_LIST}; do + cre_all3 "rsa_${DIGEST}" || return $? + done + cre_all3 dsa || return $? +fi + + return 0 } # === diff -ruN openssh-3.4p1+x509e/tests/CA/4-cre_crls.sh openssh-3.4p1+x509f/tests/CA/4-cre_crls.sh --- openssh-3.4p1+x509e/tests/CA/4-cre_crls.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/4-cre_crls.sh 2003-01-30 09:06:00.000000000 +0200 @@ -0,0 +1,115 @@ +#!/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" CRLs. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/4-cre_crls.sh$//'` +. "${SCRIPTDIR}functions" +. "${SCRIPTDIR}config" + + +OPENSSH_LOG="$CWD/openssh_ca.log" +cat /dev/null > .delmy +update_file .delmy "$OPENSSH_LOG" > /dev/null || exit $? + + +# === +cre_crlfile() { + local type="$1" + local status=0 + +( cd "${SSH_CACRLDIR}" || exit $? + + FILE="${CAKEY_PREFIX}-${type}.crl.pem" + + printf '%s' "creating ${extd}CA CRL file${norm} for ${attn}${type}${norm} certificates..." + ${OPENSSL} ca -config "${SSH_CACFGFILE}" \ + -name "CA_OpenSSH_${type}" \ + -passin pass:$KEY_PASS \ + -gencrl \ + -out "${FILE}" \ + 2>> "$OPENSSH_LOG" \ + ; show_status $? || exit $? + + HASH=`${OPENSSL} crl -out /dev/null -in "${FILE}" -hash 2>> "$OPENSSH_LOG"` || exit $? + + NAME=`getNextFreeName "${HASH}.r"` || exit $? + + ln -s "${FILE}" "${NAME}" +) +} + + +# === +cre_crlindir () { + echo "=== create a new CRL ===" >> "$OPENSSH_LOG" + rm -f "${SSH_CACRLDIR}"/* 2>/dev/null + + for DIGEST in ${RSA_DIGEST_LIST}; do + cre_crlfile "rsa_${DIGEST}" || return $? + done + cre_crlfile "dsa" || return $? + + return 0 +} + + +# === +cre_CAcrlfile () { + local crlfile="${SSH_CAROOT}/${CACRLFILE}" + + cp /dev/null "${crlfile}" && + for DIGEST in ${RSA_DIGEST_LIST}; do + ( ${OPENSSL} crl \ + -in "${SSH_CACRLDIR}/${CAKEY_PREFIX}-rsa_${DIGEST}.crl.pem" \ + -text \ + 2>> "$OPENSSH_LOG" + echo; echo + ) >> "${crlfile}" || return $? + done + ( ${OPENSSL} crl \ + -in "${SSH_CACRLDIR}/${CAKEY_PREFIX}-dsa.crl.pem" \ + -text \ + 2>> "$OPENSSH_LOG" + echo; echo + ) >> "${crlfile}" || return $? + + return 0 +} + + +# === +cre_all () { + cre_crlindir || return $? + + printf '%s' "creating ${extd}CA CRL file${norm}..." + cre_CAcrlfile; show_status $? + +} + + +# === +cre_all; status=$? + +show_status $status "${extd}Creating ${warn}TEST${norm} ${attn}Certificate Authority${norm} CRL files ..." +exit $status diff -ruN openssh-3.4p1+x509e/tests/CA/config openssh-3.4p1+x509f/tests/CA/config --- openssh-3.4p1+x509e/tests/CA/config 2002-11-20 18:56:59.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/config 2003-01-30 09:06:00.000000000 +0200 @@ -22,46 +22,117 @@ # -# 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. +# === main variables: +# on some system (with pam?, AIX?, when port is below 1024, etc.) we +# might use sudo command to start sshd when current user isn`t root or +# to run tests as root. # Prefered user for tests is NOT root :-) ! SUDO= #SUDO=sudo -OPENSSL=`which openssl` -if test -z "$OPENSSL"; then - echo "openssl binary not found!"1>&2 +#Old BSD shells, including the Ultrix `sh', don't accept the colon +#for any shell substitution, and complain and die. +##TMPDIR="${TMPDIR:-/tmp}" + +if test -n "$TMPDIR"; then + if test ! -d "$TMPDIR"; then + echo "error: $TMPDIR is not directory" + exit 1 + fi + if test ! -w "$TMPDIR"; then + echo "error: $TMPDIR is not writable" + exit 1 + fi +else + for D in /tmp /var/tmp /usr/tmp; do + test -d $D || continue + test -w $D || continue + TMPDIR=$D + break + done + if test -z "$TMPDIR"; then + echo "error: cannot set TMPDIR" + exit 1 + fi +fi + + +if test -z "${SSH_X509TESTS}"; then +SSH_X509TESTS="\ + blob_auth + dn_auth_file + dn_auth_path + agent + crl +" +fi + + +# === openssl: + +if test -z "${OPENSSL}"; then + OPENSSL=`which openssl 2>/dev/null` + if test -z "${OPENSSL}"; then + echo "error:cannot find openssl is your path !" 1>&2 + exit 1 + fi +fi + +printf 'OpenSSL executable version: ' +"${OPENSSL}" version || exit $? + +# These are the known patent issues with OpenSSL: +# name # expires +# mdc2: 4,908,861 13/03/2007 + +if test -z "${RSA_DIGEST_LIST}"; then + for DIGEST in md5 sha1 md2 md4 rmd160; do + if "${OPENSSL}" dgst -${DIGEST} "${OPENSSL}" >/dev/null 2>&1; then + RSA_DIGEST_LIST="${RSA_DIGEST_LIST} ${DIGEST}" + fi + done +fi +if test -z "${RSA_DIGEST_LIST}"; then + echo "RSA_DIGEST_LIST is empty" 1>&2 exit 1 fi -TMPDIR="/tmp" +echo "RSA digest list: ${RSA_DIGEST_LIST}" -# === ssh server: + +# === server section: + +if test -z "${SSHD_PORT}"; then + SSHD_PORT=20022 +fi + +SSHD_LISTENADDRESS=127.0.0.1 +#SSHD_LISTENADDRESS=::1 #"yes" or "no" SSHSERVER_USEPRIVILEGESEPARATION="yes" -SSHSERVER_SYSLOGFACILITY=LOCAL1 +SSHSERVER_SYSLOGFACILITY=AUTH 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" +CACRLFILE="catest-bundle.crl" + SSH_CACERTDIR="${SSH_CAROOT}/crt" +SSH_CACRLDIR="${SSH_CAROOT}/crl" CACONFIG="catest.config" SSH_CACFGFILE="${SSH_CAROOT}/${CACONFIG}" diff -ruN openssh-3.4p1+x509e/tests/CA/functions openssh-3.4p1+x509f/tests/CA/functions --- openssh-3.4p1+x509e/tests/CA/functions 2002-11-12 21:54:49.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/functions 2003-01-30 09:06:00.000000000 +0200 @@ -44,7 +44,9 @@ if test -z "${LINES}" -o -z "${COLUMNS}" ; then eval `stty size 2>/dev/null | (read L C; \ - echo LINES=${L:-24} COLUMNS=${C:-80})` + if test x${L} == x; then L=24; fi; \ + if test x${C} == x; then C=80; fi; \ + echo LINES=${L} COLUMNS=${C} )` fi test ${LINES} -eq 0 && LINES=24 test ${COLUMNS} -eq 0 && COLUMNS=80 @@ -99,11 +101,17 @@ # === +printSeparator() { + echo "=======================================================================" +} + + +# === show_status () { if ! test -z "$2"; then printf '%s' "$2" fi - if test $1 == 0; then + if test $1 -eq 0; then echo "$msg_done" else echo "$msg_failed" @@ -113,26 +121,35 @@ # === -getNextFileName() { - var="$1" - count=0 +getNextFreeName() { + local var="$1" + local limit="$2" + + if test -z "${limit}"; then + limit=10 + fi + + local count=0 while true; do - test ! -f "${var}.${count}" && break + test ! -f "${var}${count}" && break let count=${count}+1 + if test ${count} -ge ${limit}; then + echo "getNextFreeName: ${warn}limit reached${norm} for file ${attn}${var}${norm}" 1>&2 + + echo "" + return 33 + fi done - if test ${count} -ge 10; then - echo "${warn}please remove ${attn}${var}${warn} backup files !${norm}" 1>&2 - return 33 - fi - echo $count + + echo "${var}${count}" return 0 } # === getNextDirName() { - var="$1" - count=0 + local var="$1" + local count=0 while true; do test ! -d "${var}.${count}" && break let count=${count}+1 @@ -148,12 +165,15 @@ # === update_file () { - var_new="$1" - var_old="$2" + local var_new="$1" + local var_old="$2" + local backup + local not_writable + if test ! -f "${var_old}"; then printf '%s' "creating file ${attn}${var_old}${norm} ... " mv "${var_new}" "${var_old}"; show_status $? - return + return $? fi test -r "${var_new}" || { error_file_not_readable "${var_new}"; return 1; } @@ -163,18 +183,18 @@ 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 $? + backup=`getNextFreeName "${var_old}."` || return $? + printf '%s' "saving old file as ${attn}${backup}${norm} ... " + cp -p "${var_old}" "${backup}"; show_status $? || return $? printf '%s' "updating file ${attn}${var_old}${norm} ... " if test ! -w "${var_old}"; then - chmod +w "${var_old}" + chmod u+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}" + chmod u-w "${var_old}" fi rm -f "${var_new}" return 0 @@ -182,4 +202,61 @@ # === +getSSHkeyType () { + local identity_file="$1" + if test ! -r "$identity_file"; then + error_file_not_readable "${identity_file}" 1>&2; return $? + fi + + local sshkeytype="unspec" + local status=0 + + sshkeytype=`"${TEST_SSH_SSHKEYGEN}" -f "${identity_file}" -y 2>/dev/null`; status=$? + if test $status -ne 0 ; then + echo "${warn}command${norm} ${TEST_SSH_SSHKEYGEN} ${warn}fail${norm}" 1>&2 + return $status + fi + echo "${sshkeytype}" | cut -d ' ' -f 1 + return 0 +} + + +# === +getSubject () { + local identity_file="$1" +#rest of arguments passed to openssl + + if test ! -r "$identity_file"; then + error_file_not_readable "${identity_file}" 1>&2 + return 1 + fi + shift + + local status=0 + +#bug or ?: when all is on only one line status is always zero :-/ !!! +# local subject=`"${OPENSSL}" x509 -noout -subject -in "${identity_file}" $*`; status=$? + local subject + subject=`"${OPENSSL}" x509 -noout -subject -in "${identity_file}" $* 2>/dev/null`; status=$? + if test $status -ne 0 ; then + echo "${warn}cannot get certificate subject${norm}" 1>&2 + return $status + fi + echo "$subject" | cut -d ' ' -f 2- +} + + +#=== +creX509AuthorizedKeysFile () { + local identity_file="$1" + local sshkeytype + local subject + + sshkeytype=`getSSHkeyType "${identity_file}"` || return $? + subject=`getSubject "${identity_file}"` || return $? + echo "${sshkeytype} subject ${subject}" > "${AUTHORIZEDKEYSFILE}" +} + + +# === FUNCTIONS_INCLUDED="yes" diff -ruN openssh-3.4p1+x509e/tests/CA/Makefile.in openssh-3.4p1+x509f/tests/CA/Makefile.in --- openssh-3.4p1+x509e/tests/CA/Makefile.in 2002-11-18 17:00:38.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/Makefile.in 2003-01-30 09:06:01.000000000 +0200 @@ -14,9 +14,8 @@ # === -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 +check-certs: ca_files host_keys rsa_keys dsa_keys crl_files + @sh $(srcdir)/openssh_tests.sh # === ca_files: ca-test/catest.config ca-test/catest-bundle.crt @@ -63,4 +62,9 @@ testid_dsa-rsa_md5: testid_dsa sh $(srcdir)/3-cre_certs.sh -f testid_dsa -t client -n "OpenSSH DSA test certificate" + +# === +crl_files: ca-test/catest-bundle.crl +ca-test/catest-bundle.crl: + sh $(srcdir)/4-cre_crls.sh diff -ruN openssh-3.4p1+x509e/tests/CA/openssh_tests.sh openssh-3.4p1+x509f/tests/CA/openssh_tests.sh --- openssh-3.4p1+x509e/tests/CA/openssh_tests.sh 2002-11-21 16:30:43.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/openssh_tests.sh 2003-01-30 09:06:00.000000000 +0200 @@ -28,66 +28,16 @@ . "${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 "x$TEST_SSH_SSH" == "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSH${norm}" ; exit 1; } +test "x$TEST_SSH_SSHD" == "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHD${norm}" ; exit 1; } +test "x$TEST_SSH_SSHAGENT" == "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHAGENT${norm}" ; exit 1; } +test "x$TEST_SSH_SSHADD" == "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHADD${norm}" ; exit 1; } +test "x$TEST_SSH_SSHKEYGEN" == "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHKEYGEN${norm}"; exit 1; } #TEST_SSH_SSHKEYSCAN #TEST_SSH_SFTP #TEST_SSH_SFTPSERVER - -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" @@ -95,7 +45,13 @@ SSH_ERRLOG="${CWD}/.ssh_x509.err.log" SSH_REPLY="${CWD}/.ssh_x509.reply" +SSH_EXTRA_OPTIONS="" + +TEST_SSH_CLIENTKEYS="\ + testid_rsa + testid_dsa +" #TEST_SSHD_HOSTKEY="${CWD}/testhostkey_rsa-rsa_md5" TEST_SSHD_HOSTKEY="${CWD}/testhostkey_rsa" @@ -114,13 +70,26 @@ # === runSSHdaemon() { echo "=======================================================================" >> "${SSHD_LOG}" + + if test -f "${SSHD_PID}"; then + echo "${warn}sshd pid file exist!${norm}" 1>&2 + fi + + #NOTES: + #- without -d option sshd run in daemon mode and this command always return 0 !!! + #- bug or ?: with option -e no log to stderr in daemon mode $SUDO "$TEST_SSH_SSHD" -f "${SSHD_CFG}" \ -o PidFile="${SSHD_PID}" \ -o SyslogFacility="${SSHSERVER_SYSLOGFACILITY}" \ -o LogLevel="${SSHSERVER_LOGLEVEL}" \ - >> "${SSHD_LOG}" 2>&1 || return $? - #NOTE: bug or ?: with option -e no log to stderr in daemon mode + >> "${SSHD_LOG}" 2>&1 + sleep 3 + if test ! -f "${SSHD_PID}"; then + printf "${warn}cannot start sshd:${norm} " 1>&2 + error_file_not_readable "${SSHD_PID}" + return 33 + fi } @@ -175,7 +144,7 @@ cat > "${SSHD_CFG}" < "${SSH_CFG}" < "${SSH_ERRLOG}" > "${SSH_REPLY}" } @@ -257,7 +232,7 @@ cat "${SSH_ERRLOG}"; printf '%s' "${norm}" else if test "x$must_fail" = "x1"; then - if ! grep 'Permission denied (publickey)' "${SSH_ERRLOG}" > /dev/null; then + if ! fgrep 'Permission denied (publickey)' "${SSH_ERRLOG}" > /dev/null; then status=33 printf '%s' "${warn}" else @@ -265,7 +240,7 @@ fi cat "${SSH_ERRLOG}"; printf '%s' "${norm}" else - if ! grep "$msg" "${SSH_REPLY}" > /dev/null; then + if ! fgrep "$msg" "${SSH_REPLY}" > /dev/null; then status=33 printf '%s' "${warn}" cat "${SSH_REPLY}"; printf '%s' "${norm}" @@ -279,11 +254,6 @@ # === 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 $? @@ -295,32 +265,33 @@ echo "${warn}Public host file ${attn}${TEST_SSHD_HOSTKEY}.pub${warn} not found !${norm}" return 3 fi - ( printf '%s' "localhost " + ( printf '%s' "${SSHD_LISTENADDRESS} " 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 + # call the test scripts + for LTEST in ${SSH_X509TESTS}; do ( - . ${SCRIPTDIR}${LTEST} && + . ${SCRIPTDIR}test-${LTEST}.sh.inc && do_test ) || return $? done - echo "=======================================================================" + printSeparator return 0 } # === +echo +echo "${extd}Testing OpenSSH client with certificates:${norm}" +printSeparator + do_all; status=$? -echo "${extd}Testing ${warn}OpenSSH client certificates${norm}" -echo " with base key_file name ${attn}${SSH_CLIENTKEY}${norm}" +echo +echo "${extd}Testing OpenSSH client with certificates finished.${norm}" show_status $status " ${extd}status${norm}:" echo diff -ruN openssh-3.4p1+x509e/tests/CA/test-agent.sh.inc openssh-3.4p1+x509f/tests/CA/test-agent.sh.inc --- openssh-3.4p1+x509e/tests/CA/test-agent.sh.inc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/test-agent.sh.inc 2003-01-30 09:06:00.000000000 +0200 @@ -0,0 +1,139 @@ +# +# 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: +# - add a key to agent; +# - list agent keys; +# - try to connect with key from agent; +# - remove the key from agent. + + +testAgent () { + local type="$1" + local identity_file="${SSH_CLIENTKEY}-${type}" + if test ! -r "${identity_file}"; then + error_file_not_readable "${identity_file}"; return $? + fi + + local sshkeytype + local subject + + sshkeytype=`getSSHkeyType "${identity_file}"` || return $? + subject=`getSubject "${identity_file}"` || return $? + + echo "${sshkeytype} Subject: ${subject}" > "${AUTHORIZEDKEYSFILE}" + +( +killAgent () { + "${TEST_SSH_SSHAGENT}" -k > /dev/null + sleep 1 + exit $1 +} + +checkEmptyListResponse () { + case $1 in + 1) return 0;; + 0) killAgent 99;; + *) killAgent $1;; + esac + return 33 +} + +showAgentMsg() { + show_status $1 "$2" + if test $1 -ne 0; then + printf '%s' "${warn}" + cat "${SSH_ERRLOG}" + printf '%s' "${norm}" + if test $1 -ne 2; then + killAgent $1 + fi + exit $1 + fi + + if test "x$3" != "x"; then + printf '%s' "${done}" + cat "$3" + printf '%s' "${norm}" + fi + return 0 +} + + eval `"${TEST_SSH_SSHAGENT}"` > /dev/null + + "${TEST_SSH_SSHADD}" -L >/dev/null; checkEmptyListResponse $? + + "${TEST_SSH_SSHADD}" "${identity_file}" 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + showAgentMsg $? " add identity ${extd}${SSH_CLIENTKEY}-${attn}${type}${norm} to agent ..." + + "${TEST_SSH_SSHADD}" -L 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + status=$? + if test $status -ne 0; then + showAgentMsg ${status} + else + printf " ${done}-${norm} " + cat "${SSH_REPLY}" + fi + + runTest "${type}" \ + "use-only-key-from-agent" \ + "key from agent ..." || + killAgent $? + + "${TEST_SSH_SSHADD}" -d "${identity_file}".pub \ + 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + showAgentMsg $? " remove identity ${extd}${SSH_CLIENTKEY}-${attn}${type}${norm} from agent ..." + + "${TEST_SSH_SSHADD}" -L > /dev/null; checkEmptyListResponse $? + + killAgent 0 +) || return $? + +} + +# === + +do_test () { + local status=0 + echo + echo "* ${extd}against ${attn}CACertificateFile${norm} and x509 key from ${attn}agent${norm}:" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" </dev/null > "$AUTHORIZEDKEYSFILE" || return $? + "$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" + local blob + blob=`cat "${AUTHORIZEDKEYSFILE}"` + echo $blob | cut -c 1-50 > "${AUTHORIZEDKEYSFILE}" runTest "${type}" "${identity_file}"\ "${warn}invalid${norm} blob" "Yes" || return $? @@ -51,20 +52,27 @@ do_test () { local status=0 - echo "=======================================================================" + echo echo "* ${extd}against ${attn}CACertificateFile${norm} and autorization by x509 ${attn}blob${norm}:" - + creTestSSHDcfgFile cat >> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" < /dev/null + local FILE="${SSH_CACRLDIR}/${CAKEY_PREFIX}-${crltype}.crl.pem" + local HASH + HASH=`${OPENSSL} crl -out /dev/null -in "${FILE}" -hash`; status=$? + if test $status -eq 0; then + hashfile="${CRL_TEST_DIR}/${HASH}.r0" + ln -s "${FILE}" "${hashfile}"; status=$? + fi + #printf "${norm}" + show_status $status || return $? + + if test $status -eq 0; then + ( + for DIGEST in ${RSA_DIGEST_LIST}; do + test_crlbytype0 "${crltype}" "rsa_${DIGEST}" || exit $? + done + test_crlbytype0 "${crltype}" "dsa" || exit $? + ); status=$? + fi + + if test $status -eq 0; then + rm -f "${hashfile}"; status=$? + else + rm -f "${hashfile}" + fi + return $status +} + + +#=== +test_onlyonecrl () { + local status=0 + local CRL_TEST_DIR="${SSH_CAROOT}/crl-test" + + printSeparator + echo "Begin test ${extd}with only ${attn}one CRL file${norm} in ${attn}CARevocationPath${norm}..." + + mkdir -p "${CRL_TEST_DIR}" || return $? + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" < /dev/null + if test $status -eq 0; then + rmdir "${CRL_TEST_DIR}"; status=$? + else + rmdir "${CRL_TEST_DIR}" + fi + return $status +} + + +#=== +do_test () { + + echo + echo "* ${extd}against ${attn}CA CRL${norm} file and/or hash-dir:" + + test_nocrl && + test_crlfile && + test_crldir && + test_onlyonecrl + + return $? +} diff -ruN openssh-3.4p1+x509e/tests/CA/test-dn_auth_file.sh.inc openssh-3.4p1+x509f/tests/CA/test-dn_auth_file.sh.inc --- openssh-3.4p1+x509e/tests/CA/test-dn_auth_file.sh.inc 2002-11-21 14:54:29.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/test-dn_auth_file.sh.inc 2003-01-30 09:06:00.000000000 +0200 @@ -21,7 +21,8 @@ # # DESCRIPTION: Test OpenSSH client authentication: # - "IdentityFile" contain private key and x509 certificate; -# - "AuthorizedKeysFile" contain certificate "Distinguished Name"/Subject with varios formats. +# - "AuthorizedKeysFile" contain certificate "Distinguished Name"/ +# "Subject" in varios formats. # @@ -32,15 +33,11 @@ error_file_not_readable "${identity_file}"; return $? fi - local sshkeytype="unspec" - local status=0 - - if ! sshkeytype=`"$TEST_SSH_SSHKEYGEN" -f "${identity_file}" -y 2>/dev/null`; then - return 33 - fi - sshkeytype=`echo "${sshkeytype}" | cut -d ' ' -f 1` + local sshkeytype + local subject - local subject=`$OPENSSL x509 -noout -subject -in "${identity_file}" | cut -d ' ' -f 2-` || return $? + sshkeytype=`getSSHkeyType "${identity_file}"` || return $? + subject=`getSubject "${identity_file}"` || return $? for subtype in\ "Subject:" \ @@ -52,23 +49,31 @@ "disTinguishednamE:" \ "dN:" \ ; do - echo "${sshkeytype} ${subtype} ${subject}" > "$AUTHORIZEDKEYSFILE" + echo "${sshkeytype} ${subtype} ${subject}" > "${AUTHORIZEDKEYSFILE}" runTest "${type} ${subtype}" "${identity_file}" "" || return $? done + subtype="subject" + subject=`getSubject "${identity_file}" -nameopt RFC2253` || return $? + echo "${sshkeytype} ${subtype} ${subject}" > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${subtype} in ${attn}RFC2253${norm} format" "${identity_file}" "" || return $? + + echo "${sshkeytype} ${subtype} ${subject}" | sed -e 's/,/\//'> "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${subtype} and mixed tag-separator symbol" "${identity_file}" "" || return $? + for subtype in\ "Invalid" \ "Subject-" \ ; do - echo "${sshkeytype} ${subtype} ${subject}" > "$AUTHORIZEDKEYSFILE" + echo "${sshkeytype} ${subtype} ${subject}" > "${AUTHORIZEDKEYSFILE}" runTest "${type} ${warn}${subtype}${norm}" "${identity_file}"\ "autorization type" "Yes" || return $? done subtype="Subject" - ( echo -n "${sshkeytype} ${subtype}" + ( printf "${sshkeytype} ${subtype}" echo "${subject}" | cut -c -40 - ) > "$AUTHORIZEDKEYSFILE" + ) > "${AUTHORIZEDKEYSFILE}" runTest "${type} ${warn}invalid${norm} ${subtype}" "${identity_file}"\ "" "Yes" || return $? @@ -80,20 +85,27 @@ do_test () { local status=0 - echo "=======================================================================" + 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 $? + return 0 } @@ -65,20 +56,9 @@ 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 + testDNautorizations2 "${catype}" "rsa_${DIGEST}" || return $? done - - type="dsa" - if test "${catype}" = "${type}"; then - testDNautorizations2 "${type}" || return $? - else - testDNautorizations2 "${type}" "yes" || return $? - fi + testDNautorizations2 "${catype}" "dsa" || return $? return 0 } @@ -88,42 +68,49 @@ do_test () { local status=0 - echo "=======================================================================" + 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" + runSSHdaemon || return $? + for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do + printSeparator + echo "Begin test with base key_file ${attn}${SSH_CLIENTKEY}${norm}..." + + if test ! -d "${CRT_TEST_DIR}"; then + mkdir "${CRT_TEST_DIR}" || return $? fi + rm -rf "${CRT_TEST_DIR}/"* 2>/dev/null + + for 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}" 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+x509e/tests/CA/verify.sh openssh-3.4p1+x509f/tests/CA/verify.sh --- openssh-3.4p1+x509e/tests/CA/verify.sh 2002-11-21 16:28:15.000000000 +0200 +++ openssh-3.4p1+x509f/tests/CA/verify.sh 2003-01-30 09:06:00.000000000 +0200 @@ -30,11 +30,11 @@ for VERIFY in \ - "$OPENSSL verify -CAfile ${SSH_CAROOT}/${CACERTFILE}" \ - "$OPENSSL verify -CApath ${SSH_CACERTDIR}" \ + "${OPENSSL} verify -CAfile ${SSH_CAROOT}/${CACERTFILE}" \ + "${OPENSSL} verify -CApath ${SSH_CACERTDIR}" \ ; do - echo ${attn}$VERIFY ....${norm} + echo ${attn}${VERIFY} ....${norm} for F in testid_*.crt testhostkey_*.crt; do - $VERIFY $F || exit 1 + ${VERIFY} "$F" || exit 1 done done diff -ruN openssh-3.4p1+x509e/x509store.c openssh-3.4p1+x509f/x509store.c --- openssh-3.4p1+x509e/x509store.c 2002-11-18 11:35:54.000000000 +0200 +++ openssh-3.4p1+x509f/x509store.c 2003-01-30 09:06:01.000000000 +0200 @@ -23,6 +23,7 @@ */ #include "x509store.h" #include "log.h" +#include "xmalloc.h" #include "openssl/e_os.h" #include "openssl/err.h" #include "includes.h" @@ -31,19 +32,63 @@ /* allowed client certificate purpose */ static int sshpurpose_index = -1; -static X509_STORE *x509store_ctx = NULL; +static X509_STORE *x509store = NULL; +#define SSH_CHECK_REVOKED + + +#ifdef SSH_CHECK_REVOKED +static X509_STORE *x509revoked = NULL; +static int ssh_x509revoked_cb(int ok, X509_STORE_CTX *ctx); + + +static char * +ssh_ASN1_INTEGER_2_string(ASN1_INTEGER *_asni) { + BIO *bio; + int k; + char *p; + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + fatal("ssh_ASN1_INTEGER_2_string: out of memory"); + return NULL; /* ;-) */ + } + + i2a_ASN1_INTEGER(bio, _asni); + k = BIO_pending(bio); + p = xmalloc(k + 1); + k = BIO_read(bio, p, k); + p[k] = '\0'; + BIO_free_all(bio); + + return p; +} + + +static int +ssh_x509store_lookup(X509_STORE *store, int type, X509_NAME *name, X509_OBJECT *xobj) { + X509_STORE_CTX ctx; + int ret; + + X509_STORE_CTX_init(&ctx, store, NULL, NULL); + ret = X509_STORE_get_by_subject(&ctx, type, name, xobj); + X509_STORE_CTX_cleanup(&ctx); + + return ret; +} +#endif /*def SSH_CHECK_REVOKED*/ static int MS_CALLBACK ssh_x509store_cb(int ok, X509_STORE_CTX *ctx) { if (!ok) { - char buf[256]; + char buf[512]; 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", + error("ssh_x509store_cb: subject='%.512s', 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 @@ -58,10 +103,11 @@ if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; #endif } - /* - if (!v_verbose) - ERR_clear_error(); - */ +#ifdef SSH_CHECK_REVOKED + if (ok) { + ok = ssh_x509revoked_cb(ok, ctx); + } +#endif return(ok); } @@ -151,86 +197,372 @@ 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); - } +ssh_x509store_setpurpose(int _sshpurpose_index) { sshpurpose_index = _sshpurpose_index; } +static void +ssh_x509store_initcontext() { + if (x509store == NULL) { + x509store = X509_STORE_new(); + if (x509store == NULL) { + fatal ("cannot create x509store context"); + } + X509_STORE_set_verify_cb_func(x509store, ssh_x509store_cb); + } +#ifdef SSH_CHECK_REVOKED + if (x509revoked == NULL) { + x509revoked = X509_STORE_new(); + if (x509revoked == NULL) { + fatal ("cannot create x509revoced context"); + } + } +#endif +} + + int -ssh_x509store_addlookup (int _cmd, const char* _path) { - X509_LOOKUP *lookup=NULL; - int ecode = 0; +ssh_x509store_addlocations (const X509StoreOptions *_locations) { + int flag = 0, flag2 = 0; - if (_path == NULL) { - error("ssh_x509store_addlookup: path is NULL"); + if (_locations == NULL) { + error("ssh_x509store_addlocations: _locations 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 ((_locations->certificate_path == NULL) && + (_locations->certificate_file == NULL)) { + error("ssh_x509store_addlocations: certificate path and file are NULLs"); + return 0; + } +#ifdef SSH_CHECK_REVOKED + if ((_locations->revocation_path == NULL) && + (_locations->revocation_file == NULL)) { + error("ssh_x509store_addlocations: revocation path and file are NULLs"); + return 0; } +#endif + ssh_x509store_initcontext(); + /* + Note: + After X509_LOOKUP_{add_dir|load_file} calls we must call + ERR_clear_error() otherwise when the first call to + X509_LOOKUP_XXXX fail the second call fail too ! + */ + if (_locations->certificate_path != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations:cannot add hash dir lookup !"); + return 0; /* ;-) */ + } + if (X509_LOOKUP_add_dir(lookup, _locations->certificate_path, X509_FILETYPE_PEM)) { + debug2( "hash dir '%.400s' added to x509 store", _locations->certificate_path); + flag = 1; + } + ERR_clear_error(); + } + if (_locations->certificate_file != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509store, X509_LOOKUP_file()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations:cannot add file lookup !"); + return 0; /* ;-) */ + } + if (X509_LOOKUP_load_file(lookup, _locations->certificate_file, X509_FILETYPE_PEM)) { + debug2( "file '%.400s' added to x509 store", _locations->certificate_file); + flag = 1; + } + ERR_clear_error(); + } +#ifdef SSH_CHECK_REVOKED + if (_locations->revocation_path != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509revoked, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations:cannot add hash dir revocation lookup !"); + return 0; /* ;-) */ + } + if (X509_LOOKUP_add_dir(lookup, _locations->revocation_path, X509_FILETYPE_PEM)) { + debug2( "hash dir '%.400s' added to x509 revocation store", _locations->revocation_path); + flag2 = 1; + } + ERR_clear_error(); + } + if (_locations->revocation_file != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509revoked, X509_LOOKUP_file()); + if (lookup == NULL) { + fatal("ssh_x509store_addlocations:cannot add file revocation lookup !"); + return 0; /* ;-) */ + } + if (X509_LOOKUP_load_file(lookup, _locations->revocation_file, X509_FILETYPE_PEM)) { + debug2( "file '%.400s' added to x509 revocation store", _locations->revocation_file); + flag2 = 1; + } + ERR_clear_error(); + } +#else + flag2 = 1; +#endif + return flag && flag2; +} - 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; + +static int +ssh_verify_cert (X509_STORE_CTX *_csc, X509 *_cert) { + X509_STORE_CTX_init(_csc, x509store, _cert, NULL); + + if(sshpurpose_index >= 0) { + X509_PURPOSE *xptmp = X509_PURPOSE_get0(sshpurpose_index); + if (X509_STORE_CTX_set_purpose(_csc, X509_PURPOSE_get_id(xptmp)) == 0) { + int ecode = X509_STORE_CTX_get_error(_csc); + error("ssh_x509store_check: purpose error, code=%d, msg='%.200s'" + , ecode + , X509_verify_cert_error_string(ecode)); + return -1; + } } + /* + if(issuer_checks) + X509_STORE_CTX_set_flags(_csc, X509_V_FLAG_CB_ISSUER_CHECK); + */ - ecode = ERR_get_error(); - debug("ssh_x509store_addlookup:X509_LOOKUP_ctrl failed with '%.200s' for '%.400s'", ERR_error_string(ecode, NULL), _path); + if(X509_verify_cert(_csc) == 0) { + int ecode = X509_STORE_CTX_get_error(_csc); + error("ssh_x509store_check: verify error, code=%d, msg='%.200s'" + , ecode + , X509_verify_cert_error_string(ecode)); + return -1; + } - ERR_clear_error(); /* XXX ??? */ - return 0; + return 1; } int ssh_x509store_check(X509 *_cert) { + X509_STORE_CTX *csc; 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); + if (x509store == NULL) { + error("ssh_x509store_check: context is NULL\n"); + return -1; + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char buf[512]; + X509_NAME_oneline( X509_get_subject_name(_cert), buf, sizeof(buf)); + debug3("ssh_x509store_check: for '%.512s'", buf); } + + 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)); + + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + return -1; + } + + ret = ssh_verify_cert(csc, _cert); + X509_STORE_CTX_free(csc); + debug3("ssh_x509store_check: return %d", ret); return (ret); } + + +#ifdef SSH_CHECK_REVOKED +static int +ssh_check_crl(X509_STORE_CTX *_ctx, X509_CRL *_crl) { + X509 *cert = NULL; + time_t *pcheck_time; + int k; + + if (_crl == NULL) { + return 1; + } + + cert = X509_STORE_CTX_get_current_cert(_ctx); + if (cert == NULL) { + error("ssh_check_crl: missing current certificate in x509store context"); + return 0; + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + BIO *bio; + char buf[512]; + char *p; + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + fatal("ssh_check_crl: out of memory"); + return 0; /* ;-) */ + } + + X509_NAME_oneline( X509_CRL_get_issuer(_crl), buf, sizeof(buf)); + + BIO_printf(bio, ", Last Update: "); + ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(_crl)); + + BIO_printf(bio, ", Next Update: "); + ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(_crl)); + + k = BIO_pending(bio); + p = xmalloc(k + 1); + k = BIO_read(bio, p, k); + p[k] = '\0'; + + debug3("ssh_check_crl: Issuer: %s%s", buf, p); + + xfree(p); + BIO_free(bio); + } + + { + EVP_PKEY *pkey = X509_get_pubkey(cert); + if(pkey == NULL) { + error("ssh_check_crl:unable to devode public key"); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY); + return 0; + } + + if (X509_CRL_verify(_crl, pkey) <= 0) { + error("ssh_check_crl:CRL has invalid signature"); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE); + return 0; + } + EVP_PKEY_free(pkey); + } + + + if (_ctx->flags & X509_V_FLAG_USE_CHECK_TIME) + pcheck_time = &_ctx->check_time; + else + pcheck_time = NULL; + + k = X509_cmp_time(X509_CRL_get_lastUpdate(_crl), pcheck_time); + if (k == 0) { + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD); + error("ssh_check_crl:CRL has invalid lastUpdate field"); + return 0; + } + if (k > 0) { + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_NOT_YET_VALID); + error("ssh_check_crl:CRL is not yet valid"); + return 0; + } + + k = X509_cmp_time(X509_CRL_get_nextUpdate(_crl), pcheck_time); + if (k == 0) { + error("ssh_check_crl:CRL has invalid nextUpdate field"); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); + return 0; + } + if (k < 0) { + error("ssh_check_crl:CRL is expired"); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_HAS_EXPIRED); + return 0; + } + + return 1; +} + + +static int +ssh_check_crl_cert(X509_STORE_CTX *_ctx, X509_CRL *_crl, X509 *_cert) { + X509_REVOKED revoked; + int k; + char *p, buf1[512], buf2[512]; + + if (_crl == NULL) return 1; + revoked.serialNumber = X509_get_serialNumber(_cert); + k = sk_X509_REVOKED_find(_crl->crl->revoked, &revoked); + if (k < 0) return 1; + + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CERT_REVOKED); + /* yes, revoked. print log and ...*/ + p = ssh_ASN1_INTEGER_2_string(revoked.serialNumber); + X509_NAME_oneline(X509_get_subject_name(_cert), buf1, sizeof(buf1)); + X509_NAME_oneline(X509_CRL_get_issuer (_crl ), buf2, sizeof(buf2)); + + log ("certificate '%.512s' with serial '%.40s' revoked from issuer '%.512s'", + buf1, p, buf2); + xfree (p); + + return 0; +} + + +static int +ssh_x509revoked_cb(int ok, X509_STORE_CTX *ctx) { + X509 *cert; + X509_OBJECT xobj; + + if (!ok) return 0; + if (x509revoked == NULL) + return ok; /* XXX:hmm */ + + cert = X509_STORE_CTX_get_current_cert(ctx); + if (cert == NULL) { + error("ssh_x509revoked_cb: missing current certificate in x509store context"); + return 0; + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char buf[512]; + + X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); + debug3("ssh_x509revoked_cb:issuer =%.512s", buf); + + X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); + debug3("ssh_x509revoked_cb:subject=%.512s", buf); + } + + memset(&xobj, 0, sizeof(xobj)); + if (ssh_x509store_lookup( + x509revoked, X509_LU_CRL, + X509_get_subject_name(cert), + &xobj) > 0) { +/* + In callback we cannot check CRL signature at this point when we use + X509_get_issuer_name(), because we don't know issuer public key! + Of course we can get the public key from X509_STORE defined by + static variable "x509store". + Of course we can check revocation outside callback, but we should + try to find public key in X509_STORE[s]. + + At this point we can get easy public key of "current certificate"! + + Method: "look forward" + At this call we check CLR (signature and other) issued with "current + certificate" ("CertA"). If all is OK with "CertA" by next call of + callback method "current certificate" is signed from "CertA" and the + CRL issued from "CertA", if any is already verified - cool ;-). + + Note that when a certificate is revoked all signed form that + certificate are revoked automatically too. With method "look forward" + we already know that all issuers of "current certificate" aren't + revoked. +*/ + ok = ssh_check_crl(ctx, xobj.data.crl); + } + X509_OBJECT_free_contents(&xobj); + if (!ok) return 0; + + memset(&xobj, 0, sizeof(xobj)); + if (ssh_x509store_lookup( + x509revoked, X509_LU_CRL, + X509_get_issuer_name(cert), + &xobj) > 0) { + ok = ssh_check_crl_cert(ctx, xobj.data.crl, cert); + } + X509_OBJECT_free_contents(&xobj); + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + + if (!ok) return 0; + + /**/ + return ok; +} +#endif diff -ruN openssh-3.4p1+x509e/x509store.h openssh-3.4p1+x509f/x509store.h --- openssh-3.4p1+x509e/x509store.h 2002-11-20 15:47:36.000000000 +0200 +++ openssh-3.4p1+x509f/x509store.h 2003-01-30 09:06:00.000000000 +0200 @@ -27,8 +27,9 @@ #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 :-) +/* Set 0 (above) to 1 for OpenSSL 0.9.7beta2/3 :-( or comment in openssl "des_old.h" all lines: + #define cript ... + This is commented in beta4 ;-) */ #ifdef crypt # undef crypt @@ -43,10 +44,6 @@ 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; @@ -55,5 +52,7 @@ char *revocation_path; } X509StoreOptions; +void ssh_x509store_setpurpose(int _sshpurpose_index); +int ssh_x509store_addlocations (const X509StoreOptions *_locations); #endif /* X509STORE_H */