diff -ruN openssh-4.2p1+x509-5.4/ssh-agent.c openssh-4.2p1+x509-5.5/ssh-agent.c --- openssh-4.2p1+x509-5.4/ssh-agent.c 2006-01-15 09:06:01.000000000 +0200 +++ openssh-4.2p1+x509-5.5/ssh-agent.c 2006-05-19 09:06:01.000000000 +0300 @@ -154,6 +154,25 @@ xfree(id); } +static int/*bool*/ +key_match(const Key *key, Key *found) { + int kt, ret; + + if (key->type == found->type) + return(key_equal(key, found)); + + kt = found->type; + switch(found->type) { + case KEY_X509_RSA: found->type = KEY_RSA; break; + case KEY_X509_DSA: found->type = KEY_DSA; break; + default: return(0); + } + + ret = key_equal(key, found); + found->type = kt; + return(ret); +} + /* return matching private key for given public key */ static Identity * lookup_identity(Key *key, int version) @@ -162,7 +181,7 @@ Idtab *tab = idtab_lookup(version); TAILQ_FOREACH(id, &tab->idlist, next) { - if (key_equal(key, id->key)) + if (key_match(key, id->key)) return (id); } return (NULL); @@ -307,8 +326,12 @@ key = key_from_blob(blob, blen); if (key != NULL) { Identity *id = lookup_identity(key, 2); - if (id != NULL && (!id->confirm || confirm_key(id) == 0)) + if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { + int kt = id->key->type; + id->key->type = key->type; ok = key_sign(id->key, &signature, &slen, data, dlen); + id->key->type = kt; + } } key_free(key); buffer_init(&msg); diff -ruN openssh-4.2p1+x509-5.4/ssh_config.0 openssh-4.2p1+x509-5.5/ssh_config.0 --- openssh-4.2p1+x509-5.4/ssh_config.0 2006-04-26 09:06:00.000000000 +0300 +++ openssh-4.2p1+x509-5.5/ssh_config.0 2006-05-19 09:06:00.000000000 +0300 @@ -446,7 +446,10 @@ authentication allowed to sent to the host. The default is all supported by client and depend from X509KeyAlgorithm, i.e. the option allow all specified by X509KeyAlgorithm plus ``ssh-rsa'' - and ``ssh-dss''. + and ``ssh-dss''. If a X.509 certificate is used as identity but + corresponding algorithm is not allowed the client will try algo- + rithm ( ``ssh-rsa'' or ``ssh-dss'' ) conforming to certificate + public key if allowed. PubkeyAuthentication Specifies whether to try public key authentication. The argument diff -ruN openssh-4.2p1+x509-5.4/ssh_config.5 openssh-4.2p1+x509-5.5/ssh_config.5 --- openssh-4.2p1+x509-5.4/ssh_config.5 2006-04-26 09:06:00.000000000 +0300 +++ openssh-4.2p1+x509-5.5/ssh_config.5 2006-05-19 09:06:00.000000000 +0300 @@ -772,6 +772,13 @@ .Dq ssh-rsa and .Dq ssh-dss . +If a X.509 certificate is used as identity +but corresponding algorithm is not allowed +the client will try algorithm ( +.Dq ssh-rsa +or +.Dq ssh-dss +) conforming to certificate public key if allowed. .It Cm PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be diff -ruN openssh-4.2p1+x509-5.4/sshconnect2.c openssh-4.2p1+x509-5.5/sshconnect2.c --- openssh-4.2p1+x509-5.4/sshconnect2.c 2006-04-26 09:06:01.000000000 +0300 +++ openssh-4.2p1+x509-5.5/sshconnect2.c 2006-05-19 09:06:01.000000000 +0300 @@ -156,7 +156,6 @@ TAILQ_ENTRY(identity) next; AuthenticationConnection *ac; /* set if agent supports key */ Key *key; /* public/private key */ - int pktype; /* reserved: public key-type to use */ char *filename; /* comment for agent-only keys */ int tried; int isprivate; /* key points to the private key */ @@ -841,6 +840,7 @@ /* load the private key from the file */ if ((prv = load_identity_file(id->filename)) == NULL) return (-1); + prv->type = id->key->type; ret = key_sign(prv, sigp, lenp, data, datalen); key_free(prv); return (ret); @@ -998,70 +998,6 @@ return private; } -static void -prepare_allowed(Idlist *preferred) -{ - int allowed[KEY_UNSPEC], pktype; - Identity *id; - - if (options.pubkey_algorithms == NULL) return; - - TAILQ_FOREACH(id, preferred, next) { - } - - memset(allowed, 0, sizeof(allowed)); - { /* prepare allowed key-types flags */ - char *s, *cp, *p; - s = cp = xstrdup(options.pubkey_algorithms); - for (p = strsep(&cp, ","); - p && *p != '\0'; - p = strsep(&cp, ",") - ) { - pktype = key_type_from_name(p); - allowed[pktype] = 1; - } - xfree(s); - } - -/* RUMEN TODO - - first remove (filter) keys - - second set a flag with key-type{-name(?)} to send -*/ - id = TAILQ_FIRST(preferred); - while (id != TAILQ_END(preferred)) { - pktype = id->key->type; - if (allowed[pktype]) goto nextid; - -#if 0 - /* TODO: check for ???stripe-down??? case */ - switch(pktype) { - case KEY_X509_RSA: pktype = KEY_RSA; break; - case KEY_X509_DSA: pktype = KEY_DSA; break; - } - if (allowed[pktype]) goto nextid; -#endif - - { /* remove current */ - Identity *idnext = TAILQ_NEXT(id, next); - - TAILQ_REMOVE(preferred, id, next); - debug2("key not allowed: %s (%p)", id->filename, (void*)id->key); - if (id->key) - key_free(id->key); - if (id->filename) - xfree(id->filename); - xfree(id); - id = idnext; - continue; - } - -nextid: - id->pktype = pktype; - id = TAILQ_NEXT(id, next); - } - -} - /* * try keys in the following order: * 1. agent keys that are found in the config file @@ -1093,7 +1029,6 @@ id = xmalloc(sizeof(*id)); memset(id, 0, sizeof(*id)); id->key = key; - id->pktype = id->key ? id->key->type : KEY_UNSPEC; id->filename = xstrdup(options.identity_files[i]); TAILQ_INSERT_TAIL(&files, id, next); } @@ -1119,13 +1054,9 @@ id = xmalloc(sizeof(*id)); memset(id, 0, sizeof(*id)); id->key = key; - id->pktype = id->key ? id->key->type : KEY_UNSPEC; id->filename = comment; id->ac = ac; TAILQ_INSERT_TAIL(&agent, id, next); - } else { - debug2("ignoring agent key: %s (%p)", - (comment ? comment : ""), (void*)key); } } /* append remaining agent keys */ @@ -1140,9 +1071,6 @@ TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); } - - prepare_allowed(preferred); - TAILQ_FOREACH(id, preferred, next) { debug2("key: %s (%p)", id->filename, id->key); } @@ -1166,11 +1094,70 @@ } } +static int +get_allowed_keytype(int type) { + static int allowed[KEY_UNSPEC] = { 0 }; + int pktype; + + switch(type) { + case KEY_RSA: + case KEY_DSA: + case KEY_X509_RSA: + case KEY_X509_DSA: + break; + default: + return(KEY_UNSPEC); + } + + if (options.pubkey_algorithms == NULL) return(type); + + if (allowed[KEY_UNSPEC] != 1) { + /* prepare allowed key-types flags */ + char *s, *cp, *p; + memset(allowed, 0, sizeof(allowed)); + s = cp = xstrdup(options.pubkey_algorithms); + for (p = strsep(&cp, ","); + p && *p != '\0'; + p = strsep(&cp, ",") + ) { + pktype = key_type_from_name(p); + allowed[pktype] = 1; + } + xfree(s); + allowed[KEY_UNSPEC] = 1; + } + + if (allowed[type]) return(type); + + switch(type) { + case KEY_X509_RSA: type = KEY_RSA; break; + case KEY_X509_DSA: type = KEY_DSA; break; + default: + return(KEY_UNSPEC); + } + + return(allowed[type] ? type : KEY_UNSPEC); +} + +static void +set_keytype(Key *k, int kt) { + const char *n1, *n2; + + if (k->type == kt) return; + + /* key_ssh_name return pointers to statics */ + n1 = key_ssh_name(k); + k->type = kt; + n2 = key_ssh_name(k); + debug("Offering key-type '%s', original was '%s'", n2, n1); +} + int userauth_pubkey(Authctxt *authctxt) { Identity *id; int sent = 0; + int kt_sent; while ((id = TAILQ_FIRST(&authctxt->keys))) { if (id->tried++) @@ -1184,13 +1171,27 @@ * private key instead */ if (id->key && id->key->type != KEY_RSA1) { + kt_sent = get_allowed_keytype(id->key->type); + if (kt_sent == KEY_UNSPEC) { + logit("non-allowed public key: %s", id->filename); + continue; + } debug("Offering public key: %s", id->filename); + set_keytype(id->key, kt_sent); sent = send_pubkey_test(authctxt, id); } else if (id->key == NULL) { debug("Trying private key: %s", id->filename); id->key = load_identity_file(id->filename); if (id->key != NULL) { id->isprivate = 1; + kt_sent = get_allowed_keytype(id->key->type); + if (kt_sent == KEY_UNSPEC) { + logit("non-allowed private key: %s", id->filename); + key_free(id->key); + id->key = NULL; + continue; + } + set_keytype(id->key, kt_sent); sent = sign_and_send_pubkey(authctxt, id); key_free(id->key); id->key = NULL; diff -ruN openssh-4.2p1+x509-5.4/ssh-ocsp.c openssh-4.2p1+x509-5.5/ssh-ocsp.c --- openssh-4.2p1+x509-5.4/ssh-ocsp.c 2006-03-18 21:52:12.000000000 +0200 +++ openssh-4.2p1+x509-5.5/ssh-ocsp.c 2006-05-18 21:02:45.000000000 +0300 @@ -27,8 +27,8 @@ # include "error: OCSP is disabled" #endif -#if 0 -# /* not yet implemented */ +#if 1 +# /* not yet fully implemented */ # define SSH_WITH_SSLOCSP #endif @@ -115,7 +115,7 @@ switch(va.type) { case SSHVA_NONE: case SSHVA_OCSP_CERT: - debug("ssh_set_validator: ingnore certificate file"); + debug("ssh_set_validator: ignore certificate file"); break; case SSHVA_OCSP_SPEC: va.certificate_file = xstrdup(_va->certificate_file); /*fatal on error*/ @@ -125,7 +125,7 @@ switch(va.type) { case SSHVA_NONE: case SSHVA_OCSP_CERT: - debug("ssh_set_validator: ingnore responder url"); + debug("ssh_set_validator: ignore responder url"); break; case SSHVA_OCSP_SPEC: if (_va->responder_url == NULL) { diff -ruN openssh-4.2p1+x509-5.4/ssh-xkalg.c openssh-4.2p1+x509-5.5/ssh-xkalg.c --- openssh-4.2p1+x509-5.4/ssh-xkalg.c 2006-03-12 23:34:38.000000000 +0200 +++ openssh-4.2p1+x509-5.5/ssh-xkalg.c 2006-05-12 00:36:42.000000000 +0300 @@ -138,12 +138,16 @@ } +#ifndef EVP_MD_FLAG_FIPS +# define EVP_MD_FLAG_FIPS 0 +#endif + static const EVP_MD dss1_md = { NID_dsa, NID_dsaWithSHA1, SHA_DIGEST_LENGTH, - 0, + EVP_MD_FLAG_FIPS, init, update, final,