+static int
+userauth_hostbased(Authctxt *authctxt)
+{
+ Buffer b;
+ Key *key;
+ char *pkalg, *pkblob, *sig, *cuser, *chost, *service;
+ u_int alen, blen, slen;
+ int pktype;
+ int authenticated = 0;
+
+ if (!authctxt->valid) {
+ debug2("userauth_hostbased: disabled because of invalid user");
+ return 0;
+ }
+ pkalg = packet_get_string(&alen);
+ pkblob = packet_get_string(&blen);
+ chost = packet_get_string(NULL);
+ cuser = packet_get_string(NULL);
+ sig = packet_get_string(&slen);
+
+ debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
+ cuser, chost, pkalg, slen);
+#ifdef DEBUG_PK
+ debug("signature:");
+ buffer_init(&b);
+ buffer_append(&b, sig, slen);
+ buffer_dump(&b);
+ buffer_free(&b);
+#endif
+ pktype = key_type_from_name(pkalg);
+ if (pktype == KEY_UNSPEC) {
+ /* this is perfectly legal */
+ log("userauth_hostbased: unsupported "
+ "public key algorithm: %s", pkalg);
+ goto done;
+ }
+ key = key_from_blob(pkblob, blen);
+ if (key == NULL) {
+ debug("userauth_hostbased: cannot decode key: %s", pkalg);
+ goto done;
+ }
+ service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
+ authctxt->service;
+ buffer_init(&b);
+ buffer_put_string(&b, session_id2, session_id2_len);
+ /* reconstruct packet */
+ buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+ buffer_put_cstring(&b, authctxt->user);
+ buffer_put_cstring(&b, service);
+ buffer_put_cstring(&b, "hostbased");
+ buffer_put_string(&b, pkalg, alen);
+ buffer_put_string(&b, pkblob, blen);
+ buffer_put_cstring(&b, chost);
+ buffer_put_cstring(&b, cuser);
+#ifdef DEBUG_PK
+ buffer_dump(&b);
+#endif
+ /* test for allowed key and correct signature */
+ if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
+ key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
+ authenticated = 1;
+
+ buffer_clear(&b);
+ key_free(key);
+
+done:
+ debug2("userauth_hostbased: authenticated %d", authenticated);
+ xfree(pkalg);
+ xfree(pkblob);
+ xfree(cuser);
+ xfree(chost);
+ xfree(sig);
+ return authenticated;
+}
+