summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ssh/sshd/auth2-pubkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/ssh/sshd/auth2-pubkey.c')
-rw-r--r--usr/src/cmd/ssh/sshd/auth2-pubkey.c109
1 files changed, 108 insertions, 1 deletions
diff --git a/usr/src/cmd/ssh/sshd/auth2-pubkey.c b/usr/src/cmd/ssh/sshd/auth2-pubkey.c
index 658634c195..c1c5f540e4 100644
--- a/usr/src/cmd/ssh/sshd/auth2-pubkey.c
+++ b/usr/src/cmd/ssh/sshd/auth2-pubkey.c
@@ -26,6 +26,8 @@
* Use is subject to license terms.
*/
+#include <dlfcn.h>
+
#include "includes.h"
RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
@@ -54,6 +56,13 @@ extern ServerOptions options;
extern u_char *session_id2;
extern int session_id2_len;
+/* global plugin function requirements */
+static const char *RSA_SYM_NAME = "sshd_user_rsa_key_allowed";
+static const char *DSA_SYM_NAME = "sshd_user_rsa_key_allowed";
+typedef int (*RSA_SYM)(struct passwd *, RSA *, const char *);
+typedef int (*DSA_SYM)(struct passwd *, DSA *, const char *);
+
+
static void
userauth_pubkey(Authctxt *authctxt)
{
@@ -309,7 +318,98 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
return found_key;
}
-/* check whether given key is in .ssh/authorized_keys* */
+/**
+ * Checks whether or not access is allowed based on a plugin specified
+ * in sshd_config (PubKeyPlugin).
+ *
+ * Note that this expects a symbol in the loaded library that takes
+ * the current user (pwd entry), the current RSA key and it's fingerprint.
+ * The symbol is expected to return 1 on success and 0 on failure.
+ *
+ * While we could optimize this code to dlopen once in the process' lifetime,
+ * sshd is already a slow beast, so this is really not a concern.
+ * The overhead is basically a rounding error compared to everything else, and
+ * it keeps this code minimally invasive.
+ */
+static int
+user_key_allowed_from_plugin(struct passwd *pw, Key *key)
+{
+ RSA_SYM rsa_sym = NULL;
+ DSA_SYM dsa_sym = NULL;
+ char *fp = NULL;
+ void *handle = NULL;
+ int success = 0;
+
+ if (options.pubkey_plugin == NULL || pw == NULL || key == NULL ||
+ (key->type != KEY_RSA && key->type != KEY_RSA1 &&
+ key->type != KEY_DSA && key->type != KEY_ECDSA))
+ return success;
+
+ handle = dlopen(options.pubkey_plugin, RTLD_NOW);
+ if ((handle == NULL)) {
+ debug("Unable to open library %s: %s", options.pubkey_plugin,
+ dlerror());
+ goto out;
+ }
+
+ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ if (fp == NULL) {
+ debug("failed to generate fingerprint");
+ goto out;
+ }
+
+ switch (key->type) {
+ case KEY_RSA1:
+ case KEY_RSA:
+ rsa_sym = (RSA_SYM)dlsym(handle, RSA_SYM_NAME);
+ if (rsa_sym == NULL) {
+ debug("Unable to resolve symbol %s: %s", RSA_SYM_NAME,
+ dlerror());
+ goto out;
+ }
+ debug2("Invoking %s from %s", RSA_SYM_NAME,
+ options.pubkey_plugin);
+ success = (*rsa_sym)(pw, key->rsa, fp);
+ break;
+ case KEY_DSA:
+ case KEY_ECDSA:
+ dsa_sym = (DSA_SYM)dlsym(handle, RSA_SYM_NAME);
+ if (dsa_sym == NULL) {
+ debug("Unable to resolve symbol %s: %s", DSA_SYM_NAME,
+ dlerror());
+ goto out;
+ }
+ debug2("Invoking %s from %s", DSA_SYM_NAME,
+ options.pubkey_plugin);
+ success = (*dsa_sym)(pw, key->dsa, fp);
+ break;
+ default:
+ debug2("user_key_plugins only support RSA keys");
+ }
+
+ debug("sshd_plugin returned: %d", success);
+
+out:
+ if (handle != NULL) {
+ dlclose(handle);
+ dsa_sym = NULL;
+ rsa_sym = NULL;
+ handle = NULL;
+ }
+
+ if (success)
+ verbose("Found matching %s key: %s", key_type(key), fp);
+
+ if (fp != NULL) {
+ xfree(fp);
+ fp = NULL;
+ }
+
+ return success;
+}
+
+
+/* check whether given key is in .ssh/authorized_keys or a plugin */
int
user_key_allowed(struct passwd *pw, Key *key)
{
@@ -329,6 +429,13 @@ user_key_allowed(struct passwd *pw, Key *key)
file = authorized_keys_file2(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
+
+ if (success)
+ return success;
+
+ /* try from a plugin */
+ success = user_key_allowed_from_plugin(pw, key);
+
return success;
}