Bugzilla – Attachment 2539 Details for
Bug 2211
Too many hostbased authentication attempts
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
make HostbasedKeyTypes control order as well as select types sent
hostbasedkeytypes.diff (text/plain), 17.00 KB, created by
Damien Miller
on 2015-01-30 19:59:20 AEDT
(
hide
)
Description:
make HostbasedKeyTypes control order as well as select types sent
Filename:
MIME Type:
Creator:
Damien Miller
Created:
2015-01-30 19:59:20 AEDT
Size:
17.00 KB
patch
obsolete
>diff --git a/readconf.c b/readconf.c >index 5b330e1..15856f7 100644 >--- a/readconf.c >+++ b/readconf.c >@@ -145,7 +145,7 @@ typedef enum { > oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, > oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, > oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, >- oFingerprintHash, oUpdateHostkeys, >+ oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, > oIgnoredUnknownOption, oDeprecated, oUnsupported > } OpCodes; > >@@ -263,6 +263,7 @@ static struct { > { "revokedhostkeys", oRevokedHostKeys }, > { "fingerprinthash", oFingerprintHash }, > { "updatehostkeys", oUpdateHostkeys }, >+ { "hostbasedkeytypes", oHostbasedKeyTypes }, > { "ignoreunknown", oIgnoreUnknown }, > > { NULL, oBadOption } >@@ -1469,6 +1470,19 @@ parse_int: > intptr = &options->update_hostkeys; > goto parse_flag; > >+ case oHostbasedKeyTypes: >+ charptr = &options->hostbased_key_types; >+ arg = strdelim(&s); >+ if (!arg || *arg == '\0') >+ fatal("%.200s line %d: Missing argument.", >+ filename, linenum); >+ if (!sshkey_names_valid2(arg, 1)) >+ fatal("%s line %d: Bad key types '%s'.", >+ filename, linenum, arg ? arg : "<NONE>"); >+ if (*activep && *charptr == NULL) >+ *charptr = xstrdup(arg); >+ break; >+ > case oDeprecated: > debug("%s line %d: Deprecated option \"%s\"", > filename, linenum, keyword); >@@ -1648,6 +1662,7 @@ initialize_options(Options * options) > options->revoked_host_keys = NULL; > options->fingerprint_hash = -1; > options->update_hostkeys = -1; >+ options->hostbased_key_types = NULL; > } > > /* >@@ -1827,6 +1842,8 @@ fill_default_options(Options * options) > options->fingerprint_hash = SSH_FP_HASH_DEFAULT; > if (options->update_hostkeys == -1) > options->update_hostkeys = 1; >+ if (options->hostbased_key_types == NULL) >+ options->hostbased_key_types = xstrdup("*"); > > #define CLEAR_ON_NONE(v) \ > do { \ >@@ -2267,6 +2284,7 @@ dump_client_config(Options *o, const char *host) > dump_cfg_string(oControlPath, o->control_path); > dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG); > dump_cfg_string(oHostKeyAlias, o->host_key_alias); >+ dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); > dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); > dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); > dump_cfg_string(oLocalCommand, o->local_command); >@@ -2275,9 +2293,10 @@ dump_client_config(Options *o, const char *host) > dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); > dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); > dump_cfg_string(oProxyCommand, o->proxy_command); >- dump_cfg_string(oXAuthLocation, o->xauth_location); > dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); >+ dump_cfg_string(oXAuthLocation, o->xauth_location); > >+ /* Forwards */ > dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); > dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); > dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); >diff --git a/readconf.h b/readconf.h >index 7a8ae17..f2897c3 100644 >--- a/readconf.h >+++ b/readconf.h >@@ -150,6 +150,8 @@ typedef struct { > > int update_hostkeys; > >+ char *hostbased_key_types; >+ > char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ > } Options; > >diff --git a/scp.1 b/scp.1 >index b80ad8b..265b0d1 100644 >--- a/scp.1 >+++ b/scp.1 >@@ -150,6 +150,7 @@ For full details of the options listed below, and their possible values, see > .It HashKnownHosts > .It Host > .It HostbasedAuthentication >+.It HostbasedKeyTypes > .It HostKeyAlgorithms > .It HostKeyAlias > .It HostName >diff --git a/sftp.1 b/sftp.1 >index 9eed155..34c747e 100644 >--- a/sftp.1 >+++ b/sftp.1 >@@ -215,6 +215,7 @@ For full details of the options listed below, and their possible values, see > .It HashKnownHosts > .It Host > .It HostbasedAuthentication >+.It HostbasedKeyTypes > .It HostKeyAlgorithms > .It HostKeyAlias > .It HostName >diff --git a/ssh.1 b/ssh.1 >index 7e734ab..c3339f9 100644 >--- a/ssh.1 >+++ b/ssh.1 >@@ -445,6 +445,7 @@ For full details of the options listed below, and their possible values, see > .It HashKnownHosts > .It Host > .It HostbasedAuthentication >+.It HostbasedKeyTypes > .It HostKeyAlgorithms > .It HostKeyAlias > .It HostName >diff --git a/ssh.c b/ssh.c >index 108efd4..5c54fae 100644 >--- a/ssh.c >+++ b/ssh.c >@@ -1224,6 +1224,7 @@ main(int ac, char **av) > sensitive_data.external_keysign = 1; > } > } >+ > /* > * Get rid of any extra privileges that we may have. We will no > * longer need them. Also, extra privileges could make it very hard >diff --git a/ssh_config.5 b/ssh_config.5 >index 9c0b357..57d1e79 100644 >--- a/ssh_config.5 >+++ b/ssh_config.5 >@@ -777,6 +777,17 @@ The default is > This option applies to protocol version 2 only and > is similar to > .Cm RhostsRSAAuthentication . >+.It Cm HostbasedKeyTypes >+Specifies the key types that will be used for hostbased authentication >+as a comma-separated pattern list. >+The default >+.Dq * >+will allow all key types. >+The >+.Fl Q >+option of >+.Xr ssh 1 >+may be used to list supported key types. > .It Cm HostKeyAlgorithms > Specifies the protocol version 2 host key algorithms > that the client wants to use in order of preference. >diff --git a/sshconnect2.c b/sshconnect2.c >index 12515fd..d263013 100644 >--- a/sshconnect2.c >+++ b/sshconnect2.c >@@ -267,6 +267,8 @@ struct cauthctxt { > int agent_fd; > /* hostbased */ > Sensitive *sensitive; >+ char *oktypes, *ktypes; >+ const char *active_ktype; > /* kbd-interactive */ > int info_req_seen; > /* generic */ >@@ -395,6 +397,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, > authctxt.authlist = NULL; > authctxt.methoddata = NULL; > authctxt.sensitive = sensitive; >+ authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; > authctxt.info_req_seen = 0; > authctxt.agent_fd = -1; > if (authctxt.method == NULL) >@@ -1446,78 +1449,116 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt) > } > > static int >-ssh_keysign(Key *key, u_char **sigp, u_int *lenp, >- u_char *data, u_int datalen) >+ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp, >+ const u_char *data, size_t datalen) > { >- Buffer b; >+ struct sshbuf *b; > struct stat st; > pid_t pid; >- int to[2], from[2], status, version = 2; >+ int i, r, to[2], from[2], status, sock = packet_get_connection_in(); >+ u_char rversion = 0, version = 2; >+ void (*osigchld)(int); > >- debug2("ssh_keysign called"); >+ *sigp = NULL; >+ *lenp = 0; > > if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) { >- error("ssh_keysign: not installed: %s", strerror(errno)); >+ error("%s: not installed: %s", __func__, strerror(errno)); >+ return -1; >+ } >+ if (fflush(stdout) != 0) { >+ error("%s: fflush: %s", __func__, strerror(errno)); > return -1; > } >- if (fflush(stdout) != 0) >- error("ssh_keysign: fflush: %s", strerror(errno)); > if (pipe(to) < 0) { >- error("ssh_keysign: pipe: %s", strerror(errno)); >+ error("%s: pipe: %s", __func__, strerror(errno)); > return -1; > } > if (pipe(from) < 0) { >- error("ssh_keysign: pipe: %s", strerror(errno)); >+ error("%s: pipe: %s", __func__, strerror(errno)); > return -1; > } > if ((pid = fork()) < 0) { >- error("ssh_keysign: fork: %s", strerror(errno)); >+ error("%s: fork: %s", __func__, strerror(errno)); > return -1; > } >+ osigchld = signal(SIGCHLD, SIG_DFL); > if (pid == 0) { > /* keep the socket on exec */ >- fcntl(packet_get_connection_in(), F_SETFD, 0); >+ fcntl(sock, F_SETFD, 0); > permanently_drop_suid(getuid()); > close(from[0]); > if (dup2(from[1], STDOUT_FILENO) < 0) >- fatal("ssh_keysign: dup2: %s", strerror(errno)); >+ fatal("%s: dup2: %s", __func__, strerror(errno)); > close(to[1]); > if (dup2(to[0], STDIN_FILENO) < 0) >- fatal("ssh_keysign: dup2: %s", strerror(errno)); >+ fatal("%s: dup2: %s", __func__, strerror(errno)); > close(from[1]); > close(to[0]); >+ /* Close everything but stdio and the socket */ >+ for (i = STDERR_FILENO + 1; i < sock; i++) >+ close(i); >+ closefrom(sock + 1); >+ debug3("%s: [child] pid=%ld, exec %s", >+ __func__, (long)getpid(), _PATH_SSH_KEY_SIGN); > execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); >- fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN, >+ fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN, > strerror(errno)); > } > close(from[1]); > close(to[0]); > >- buffer_init(&b); >- buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */ >- buffer_put_string(&b, data, datalen); >- if (ssh_msg_send(to[1], version, &b) == -1) >- fatal("ssh_keysign: couldn't send request"); >- >- if (ssh_msg_recv(from[0], &b) < 0) { >- error("ssh_keysign: no reply"); >- buffer_free(&b); >- return -1; >- } >+ if ((b = sshbuf_new()) == NULL) >+ fatal("%s: sshbuf_new failed", __func__); >+ /* send # of sock, data to be signed */ >+ if ((r = sshbuf_put_u32(b, sock) != 0) || >+ (r = sshbuf_put_string(b, data, datalen)) != 0) >+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); >+ if (ssh_msg_send(to[1], version, b) == -1) >+ fatal("%s: couldn't send request", __func__); >+ sshbuf_reset(b); >+ r = ssh_msg_recv(from[0], b); > close(from[0]); > close(to[1]); >+ if (r < 0) { >+ error("%s: no reply", __func__); >+ goto fail; >+ } > >- while (waitpid(pid, &status, 0) < 0) >- if (errno != EINTR) >- break; >- >- if (buffer_get_char(&b) != version) { >- error("ssh_keysign: bad version"); >- buffer_free(&b); >+ errno = 0; >+ while (waitpid(pid, &status, 0) < 0) { >+ if (errno != EINTR) { >+ error("%s: waitpid %ld: %s", >+ __func__, (long)pid, strerror(errno)); >+ goto fail; >+ } >+ } >+ if (!WIFEXITED(status)) { >+ error("%s: exited abnormally", __func__); >+ goto fail; >+ } >+ if (WEXITSTATUS(status) != 0) { >+ error("%s: exited with status %d", >+ __func__, WEXITSTATUS(status)); >+ goto fail; >+ } >+ if ((r = sshbuf_get_u8(b, &rversion)) != 0) { >+ error("%s: buffer error: %s", __func__, ssh_err(r)); >+ goto fail; >+ } >+ if (rversion != version) { >+ error("%s: bad version", __func__); >+ goto fail; >+ } >+ if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { >+ error("%s: buffer error: %s", __func__, ssh_err(r)); >+ fail: >+ signal(SIGCHLD, osigchld); >+ sshbuf_free(b); > return -1; > } >- *sigp = buffer_get_string(&b, lenp); >- buffer_free(&b); >+ signal(SIGCHLD, osigchld); >+ sshbuf_free(b); > > return 0; > } >@@ -1525,100 +1566,149 @@ ssh_keysign(Key *key, u_char **sigp, u_int *lenp, > int > userauth_hostbased(Authctxt *authctxt) > { >- Key *private = NULL; >- Sensitive *sensitive = authctxt->sensitive; >- Buffer b; >- u_char *signature, *blob; >- char *chost, *pkalg, *p; >+ struct ssh *ssh = active_state; >+ struct sshkey *private = NULL; >+ struct sshbuf *b = NULL; > const char *service; >- u_int blen, slen; >- int ok, i, found = 0; >+ u_char *sig = NULL, *keyblob = NULL; >+ char *fp = NULL, *chost = NULL, *lname = NULL; >+ size_t siglen = 0, keylen = 0; >+ int i, r, success = 0; > >- /* XXX provide some way to allow user to specify key types attempted */ >+ if (authctxt->ktypes == NULL) { >+ authctxt->oktypes = xstrdup(options.hostbased_key_types); >+ authctxt->ktypes = authctxt->oktypes; >+ } > >- /* check for a useful key */ >- for (i = 0; i < sensitive->nkeys; i++) { >- private = sensitive->keys[i]; >- if (private && private->type != KEY_RSA1) { >- found = 1; >+ /* >+ * Work through each listed type pattern in HostbasedKeyTypes, >+ * trying each hostkey that matches the type in turn. >+ */ >+ for (;;) { >+ if (authctxt->active_ktype == NULL) >+ authctxt->active_ktype = strsep(&authctxt->ktypes, ","); >+ if (authctxt->active_ktype == NULL || >+ *authctxt->active_ktype == '\0') >+ break; >+ debug3("%s: trying key type %s", __func__, >+ authctxt->active_ktype); >+ >+ /* check for a useful key */ >+ private = NULL; >+ for (i = 0; i < authctxt->sensitive->nkeys; i++) { >+ if (authctxt->sensitive->keys[i] == NULL || >+ authctxt->sensitive->keys[i]->type == KEY_RSA1 || >+ authctxt->sensitive->keys[i]->type == KEY_UNSPEC) >+ continue; >+ if (match_pattern_list( >+ sshkey_ssh_name(authctxt->sensitive->keys[i]), >+ authctxt->active_ktype, >+ strlen(authctxt->active_ktype), 0) != 1) >+ continue; > /* we take and free the key */ >- sensitive->keys[i] = NULL; >+ private = authctxt->sensitive->keys[i]; >+ authctxt->sensitive->keys[i] = NULL; > break; > } >+ /* Found one */ >+ if (private != NULL) >+ break; >+ /* No more keys of this type; advance */ >+ authctxt->active_ktype = NULL; > } >- if (!found) { >+ if (private == NULL) { >+ free(authctxt->oktypes); >+ authctxt->oktypes = authctxt->ktypes = NULL; >+ authctxt->active_ktype = NULL; > debug("No more client hostkeys for hostbased authentication."); >- return 0; >+ goto out; > } > >- debug("%s: trying hostkey type %s", __func__, key_type(private)); >- >- if (key_to_blob(private, &blob, &blen) == 0) { >- key_free(private); >- return 0; >+ if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, >+ SSH_FP_DEFAULT)) == NULL) { >+ error("%s: sshkey_fingerprint failed", __func__); >+ goto out; > } >+ debug("%s: trying hostkey %s %s", >+ __func__, sshkey_ssh_name(private), fp); > > /* figure out a name for the client host */ >- p = get_local_name(packet_get_connection_in()); >- if (p == NULL) { >- error("userauth_hostbased: cannot get local ipaddr/name"); >- key_free(private); >- free(blob); >- return 0; >+ if ((lname = get_local_name(packet_get_connection_in())) == NULL) { >+ error("%s: cannot get local ipaddr/name", __func__); >+ goto out; > } >- xasprintf(&chost, "%s.", p); >- debug2("userauth_hostbased: chost %s", chost); >- free(p); >+ >+ /* XXX sshbuf_put_stringf? */ >+ xasprintf(&chost, "%s.", lname); >+ debug2("%s: chost %s", __func__, chost); > > service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : > authctxt->service; >- pkalg = xstrdup(key_ssh_name(private)); >- buffer_init(&b); >+ > /* construct data */ >- buffer_put_string(&b, session_id2, session_id2_len); >- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); >- buffer_put_cstring(&b, authctxt->server_user); >- buffer_put_cstring(&b, service); >- buffer_put_cstring(&b, authctxt->method->name); >- buffer_put_cstring(&b, pkalg); >- buffer_put_string(&b, blob, blen); >- buffer_put_cstring(&b, chost); >- buffer_put_cstring(&b, authctxt->local_user); >+ if ((b = sshbuf_new()) == NULL) { >+ error("%s: sshbuf_new failed", __func__); >+ goto out; >+ } >+ if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { >+ error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); >+ goto out; >+ } >+ if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || >+ (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || >+ (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || >+ (r = sshbuf_put_cstring(b, service)) != 0 || >+ (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || >+ (r = sshbuf_put_cstring(b, key_ssh_name(private))) != 0 || >+ (r = sshbuf_put_string(b, keyblob, keylen)) != 0 || >+ (r = sshbuf_put_cstring(b, chost)) != 0 || >+ (r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { >+ error("%s: buffer error: %s", __func__, ssh_err(r)); >+ goto out; >+ } >+ > #ifdef DEBUG_PK >- buffer_dump(&b); >+ sshbuf_dump(b, stderr); > #endif >- if (sensitive->external_keysign) >- ok = ssh_keysign(private, &signature, &slen, >- buffer_ptr(&b), buffer_len(&b)); >- else >- ok = key_sign(private, &signature, &slen, >- buffer_ptr(&b), buffer_len(&b)); >- key_free(private); >- buffer_free(&b); >- if (ok != 0) { >- error("key_sign failed"); >- free(chost); >- free(pkalg); >- free(blob); >- return 0; >+ if (authctxt->sensitive->external_keysign) >+ r = ssh_keysign(private, &sig, &siglen, >+ sshbuf_ptr(b), sshbuf_len(b)); >+ else if ((r = sshkey_sign(private, &sig, &siglen, >+ sshbuf_ptr(b), sshbuf_len(b), datafellows)) != 0) >+ debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); >+ if (r != 0) { >+ error("sign using hostkey %s %s failed", >+ sshkey_ssh_name(private), fp); >+ goto out; > } >- packet_start(SSH2_MSG_USERAUTH_REQUEST); >- packet_put_cstring(authctxt->server_user); >- packet_put_cstring(authctxt->service); >- packet_put_cstring(authctxt->method->name); >- packet_put_cstring(pkalg); >- packet_put_string(blob, blen); >- packet_put_cstring(chost); >- packet_put_cstring(authctxt->local_user); >- packet_put_string(signature, slen); >- explicit_bzero(signature, slen); >- free(signature); >+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || >+ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || >+ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || >+ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || >+ (r = sshpkt_put_cstring(ssh, key_ssh_name(private))) != 0 || >+ (r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 || >+ (r = sshpkt_put_cstring(ssh, chost)) != 0 || >+ (r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || >+ (r = sshpkt_put_string(ssh, sig, siglen)) != 0 || >+ (r = sshpkt_send(ssh)) != 0) { >+ error("%s: packet error: %s", __func__, ssh_err(r)); >+ goto out; >+ } >+ success = 1; >+ >+ out: >+ if (sig != NULL) { >+ explicit_bzero(sig, siglen); >+ free(sig); >+ } >+ free(keyblob); >+ free(lname); >+ free(fp); > free(chost); >- free(pkalg); >- free(blob); >+ sshkey_free(private); >+ sshbuf_free(b); > >- packet_send(); >- return 1; >+ return success; > } > > /* find auth method */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 2211
:
2529
|
2532
| 2539