-/* $OpenBSD: auth2-pubkey.c,v 1.63 2017/05/30 08:52:19 markus Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.64 2017/05/30 14:10:53 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
#include "misc.h"
#include "servconf.h"
#include "compat.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "pathnames.h"
static int
userauth_pubkey(Authctxt *authctxt)
{
- Buffer b;
+ struct ssh *ssh = active_state; /* XXX */
+ struct sshbuf *b;
struct sshkey *key = NULL;
- char *pkalg, *userstyle, *fp = NULL;
- u_char *pkblob, *sig;
- u_int alen, blen, slen;
- int have_sig, pktype;
+ char *pkalg, *userstyle = NULL, *fp = NULL;
+ u_char *pkblob, *sig, have_sig;
+ size_t blen, slen;
+ int r, pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("%s: disabled because of invalid user", __func__);
return 0;
}
- have_sig = packet_get_char();
- if (datafellows & SSH_BUG_PKAUTH) {
+ if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0)
+ fatal("%s: sshpkt_get_u8 failed: %s", __func__, ssh_err(r));
+ if (ssh->compat & SSH_BUG_PKAUTH) {
debug2("%s: SSH_BUG_PKAUTH", __func__);
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
/* no explicit pkalg given */
- pkblob = packet_get_string(&blen);
- buffer_init(&b);
- buffer_append(&b, pkblob, blen);
/* so we have to extract the pkalg from the pkblob */
- pkalg = buffer_get_string(&b, &alen);
- buffer_free(&b);
+ /* XXX use sshbuf_from() */
+ if ((r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
+ (r = sshbuf_put(b, pkblob, blen)) != 0 ||
+ (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0)
+ fatal("%s: failed: %s", __func__, ssh_err(r));
+ sshbuf_free(b);
} else {
- pkalg = packet_get_string(&alen);
- pkblob = packet_get_string(&blen);
+ if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
+ (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
+ fatal("%s: sshpkt_get_cstring failed: %s",
+ __func__, ssh_err(r));
}
- pktype = key_type_from_name(pkalg);
+ pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
logit("%s: unsupported public key algorithm: %s",
__func__, pkalg);
goto done;
}
- key = key_from_blob(pkblob, blen);
+ if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
+ error("%s: could not parse key: %s", __func__, ssh_err(r));
+ goto done;
+ }
if (key == NULL) {
error("%s: cannot decode key: %s", __func__, pkalg);
goto done;
"(received %d, expected %d)", __func__, key->type, pktype);
goto done;
}
- if (key_type_plain(key->type) == KEY_RSA &&
- (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ if (sshkey_type_plain(key->type) == KEY_RSA &&
+ (ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
logit("Refusing RSA key because client uses unsafe "
"signature scheme");
goto done;
}
fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
if (auth2_userkey_already_used(authctxt, key)) {
- logit("refusing previously-used %s key", key_type(key));
+ logit("refusing previously-used %s key", sshkey_type(key));
goto done;
}
if (match_pattern_list(sshkey_ssh_name(key),
if (have_sig) {
debug3("%s: have signature for %s %s",
__func__, sshkey_type(key), fp);
- sig = packet_get_string(&slen);
- packet_check_eom();
- buffer_init(&b);
- if (datafellows & SSH_OLD_SESSIONID) {
- buffer_append(&b, session_id2, session_id2_len);
+ if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if (ssh->compat & SSH_OLD_SESSIONID) {
+ if ((r = sshbuf_put(b, session_id2,
+ session_id2_len)) != 0)
+ fatal("%s: sshbuf_put session id: %s",
+ __func__, ssh_err(r));
} else {
- buffer_put_string(&b, session_id2, session_id2_len);
+ if ((r = sshbuf_put_string(b, session_id2,
+ session_id2_len)) != 0)
+ fatal("%s: sshbuf_put_string session id: %s",
+ __func__, ssh_err(r));
}
/* reconstruct packet */
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
- buffer_put_cstring(&b, userstyle);
- free(userstyle);
- buffer_put_cstring(&b,
- datafellows & SSH_BUG_PKSERVICE ?
- "ssh-userauth" :
- authctxt->service);
- if (datafellows & SSH_BUG_PKAUTH) {
- buffer_put_char(&b, have_sig);
+ if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshbuf_put_cstring(b, userstyle)) != 0 ||
+ (r = sshbuf_put_cstring(b, ssh->compat & SSH_BUG_PKSERVICE ?
+ "ssh-userauth" : authctxt->service)) != 0)
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
+ if (ssh->compat & SSH_BUG_PKAUTH) {
+ if ((r = sshbuf_put_u8(b, have_sig)) != 0)
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
} else {
- buffer_put_cstring(&b, "publickey");
- buffer_put_char(&b, have_sig);
- buffer_put_cstring(&b, pkalg);
+ if ((r = sshbuf_put_cstring(b, "publickey")) != 0 ||
+ (r = sshbuf_put_u8(b, have_sig)) != 0 ||
+ (r = sshbuf_put_cstring(b, pkalg) != 0))
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
}
- buffer_put_string(&b, pkblob, blen);
+ if ((r = sshbuf_put_string(b, pkblob, blen)) != 0)
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
#ifdef DEBUG_PK
- buffer_dump(&b);
+ sshbuf_dump(b, stderr);
#endif
pubkey_auth_info(authctxt, key, NULL);
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
- buffer_len(&b))) == 1) {
+ PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
+ sshbuf_len(b), ssh->compat)) == 0) {
authenticated = 1;
/* Record the successful key to prevent reuse */
auth2_record_userkey(authctxt, key);
key = NULL; /* Don't free below */
}
- buffer_free(&b);
+ sshbuf_free(b);
free(sig);
} else {
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
__func__, sshkey_type(key), fp);
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
/* XXX fake reply and always send PK_OK ? */
/*
* issue? -markus
*/
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
- packet_start(SSH2_MSG_USERAUTH_PK_OK);
- packet_put_string(pkalg, alen);
- packet_put_string(pkblob, blen);
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK))
+ != 0 ||
+ (r = sshpkt_put_cstring(ssh, pkalg)) != 0 ||
+ (r = sshpkt_put_string(ssh, pkblob, blen)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ ssh_packet_write_wait(ssh);
authctxt->postponed = 1;
}
}
done:
debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
if (key != NULL)
- key_free(key);
+ sshkey_free(key);
+ free(userstyle);
free(pkalg);
free(pkblob);
free(fp);
i = vasprintf(&extra, fmt, ap);
va_end(ap);
if (i < 0 || extra == NULL)
- fatal("%s: vasprintf failed", __func__);
+ fatal("%s: vasprintf failed", __func__);
}
- if (key_is_cert(key)) {
+ if (sshkey_is_cert(key)) {
fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT);
auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
- key_type(key), key->cert->key_id,
+ sshkey_type(key), key->cert->key_id,
(unsigned long long)key->cert->serial,
- key_type(key->cert->signature_key),
+ sshkey_type(key->cert->signature_key),
fp == NULL ? "(null)" : fp,
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
free(fp);
} else {
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
- auth_info(authctxt, "%s %s%s%s", key_type(key),
+ auth_info(authctxt, "%s %s%s%s", sshkey_type(key),
fp == NULL ? "(null)" : fp,
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
free(fp);
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
-check_authkeys_file(FILE *f, char *file, struct sshkey* key, struct passwd *pw)
+check_authkeys_file(FILE *f, char *file, struct sshkey *key, struct passwd *pw)
{
char line[SSH_MAX_PUBKEY_BYTES];
int found_key = 0;
u_long linenum = 0;
- struct sshkey *found;
-
- found_key = 0;
+ struct sshkey *found = NULL;
- found = NULL;
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
char *cp, *key_options = NULL, *fp = NULL;
const char *reason = NULL;
if (found_key)
continue;
if (found != NULL)
- key_free(found);
- found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
+ sshkey_free(found);
+ found = sshkey_new(sshkey_is_cert(key) ? KEY_UNSPEC : key->type);
+ if (found == NULL)
+ goto done;
auth_clear_options();
/* Skip leading whitespace, empty and comment lines. */
if (!*cp || *cp == '\n' || *cp == '#')
continue;
- if (key_read(found, &cp) != 1) {
+ if (sshkey_read(found, &cp) != 0) {
/* no key? check if there are options for this key */
int quoted = 0;
debug2("user_key_allowed: check options: '%s'", cp);
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
- if (key_read(found, &cp) != 1) {
+ if (sshkey_read(found, &cp) != 0) {
debug2("user_key_allowed: advance: '%s'", cp);
/* still no key? advance to next line*/
continue;
}
}
- if (key_is_cert(key)) {
- if (!key_equal(found, key->cert->signature_key))
+ if (sshkey_is_cert(key)) {
+ if (!sshkey_equal(found, key->cert->signature_key))
continue;
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching CA found: file %s, line %lu, %s %s",
- file, linenum, key_type(found), fp);
+ file, linenum, sshkey_type(found), fp);
/*
* If the user has specified a list of principals as
* a key option, then prefer that list to matching
auth_debug_add("%s", reason);
continue;
}
- if (key_cert_check_authority(key, 0, 0,
+ if (sshkey_cert_check_authority(key, 0, 0,
authorized_principals == NULL ? pw->pw_name : NULL,
&reason) != 0)
goto fail_reason;
verbose("Accepted certificate ID \"%s\" (serial %llu) "
"signed by %s CA %s via %s", key->cert->key_id,
(unsigned long long)key->cert->serial,
- key_type(found), fp, file);
+ sshkey_type(found), fp, file);
free(fp);
found_key = 1;
break;
- } else if (key_equal(found, key)) {
+ } else if (sshkey_equal(found, key)) {
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
continue;
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching key found: file %s, line %lu %s %s",
- file, linenum, key_type(found), fp);
+ file, linenum, sshkey_type(found), fp);
free(fp);
found_key = 1;
continue;
}
}
+ done:
if (found != NULL)
- key_free(found);
+ sshkey_free(found);
if (!found_key)
debug2("key not found");
return found_key;
{
char *ca_fp, *principals_file = NULL;
const char *reason;
- int ret = 0, found_principal = 0, use_authorized_principals;
+ int r, ret = 0, found_principal = 0, use_authorized_principals;
- if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
+ if (!sshkey_is_cert(key) || options.trusted_user_ca_keys == NULL)
return 0;
if ((ca_fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
return 0;
- if (sshkey_in_file(key->cert->signature_key,
- options.trusted_user_ca_keys, 1, 0) != 0) {
- debug2("%s: CA %s %s is not listed in %s", __func__,
- key_type(key->cert->signature_key), ca_fp,
- options.trusted_user_ca_keys);
+ if ((r = sshkey_in_file(key->cert->signature_key,
+ options.trusted_user_ca_keys, 1, 0)) != 0) {
+ debug2("%s: CA %s %s is not listed in %s: %s", __func__,
+ sshkey_type(key->cert->signature_key), ca_fp,
+ options.trusted_user_ca_keys, ssh_err(r));
goto out;
}
/*
auth_debug_add("%s", reason);
goto out;
}
- if (key_cert_check_authority(key, 0, 1,
+ if (sshkey_cert_check_authority(key, 0, 1,
use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
goto fail_reason;
if (auth_cert_options(key, pw, &reason) != 0)
verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
"%s CA %s via %s", key->cert->key_id,
(unsigned long long)key->cert->serial,
- key_type(key->cert->signature_key), ca_fp,
+ sshkey_type(key->cert->signature_key), ca_fp,
options.trusted_user_ca_keys);
ret = 1;
if (auth_key_is_revoked(key))
return 0;
- if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
+ if (sshkey_is_cert(key) &&
+ auth_key_is_revoked(key->cert->signature_key))
return 0;
success = user_cert_trusted_ca(pw, key);
-/* $OpenBSD: monitor.c,v 1.168 2017/05/30 08:52:19 markus Exp $ */
+/* $OpenBSD: monitor.c,v 1.169 2017/05/30 14:10:53 markus Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
}
int
-mm_answer_keyverify(int sock, Buffer *m)
+mm_answer_keyverify(int sock, struct sshbuf *m)
{
struct sshkey *key;
u_char *signature, *data, *blob;
- u_int signaturelen, datalen, bloblen;
- int verified = 0;
- int valid_data = 0;
+ size_t signaturelen, datalen, bloblen;
+ int r, ret, valid_data = 0, encoded_ret;
- blob = buffer_get_string(m, &bloblen);
- signature = buffer_get_string(m, &signaturelen);
- data = buffer_get_string(m, &datalen);
+ if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 ||
+ (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 ||
+ (r = sshbuf_get_string(m, &data, &datalen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (hostbased_cuser == NULL || hostbased_chost == NULL ||
!monitor_allowed_key(blob, bloblen))
fatal("%s: bad key, not previously allowed", __func__);
- key = key_from_blob(blob, bloblen);
- if (key == NULL)
- fatal("%s: bad public key blob", __func__);
+ /* XXX use sshkey_froms here; need to change key_blob, etc. */
+ if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0)
+ fatal("%s: bad public key blob: %s", __func__, ssh_err(r));
switch (key_blobtype) {
case MM_USERKEY:
if (!valid_data)
fatal("%s: bad signature data blob", __func__);
- verified = key_verify(key, signature, signaturelen, data, datalen);
+ ret = sshkey_verify(key, signature, signaturelen, data, datalen,
+ active_state->compat);
debug3("%s: key %p signature %s",
- __func__, key, (verified == 1) ? "verified" : "unverified");
+ __func__, key, (ret == 0) ? "verified" : "unverified");
/* If auth was successful then record key to ensure it isn't reused */
- if (verified == 1 && key_blobtype == MM_USERKEY)
+ if (ret == 0 && key_blobtype == MM_USERKEY)
auth2_record_userkey(authctxt, key);
else
- key_free(key);
+ sshkey_free(key);
free(blob);
free(signature);
monitor_reset_key_state();
- buffer_clear(m);
- buffer_put_int(m, verified);
+ sshbuf_reset(m);
+
+ /* encode ret != 0 as positive integer, since we're sending u32 */
+ encoded_ret = (ret != 0);
+ if ((r = sshbuf_put_u32(m, encoded_ret)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
- return (verified == 1);
+ return ret == 0;
}
static void