--- /dev/null	Wed Feb 10 16:25:01 2016
+++ new/build/openssh/patches/0021-PubKeyPlugin-support.patch	Wed Feb 10 16:25:01 2016
@@ -0,0 +1,259 @@
+From 3940b5d3e954d472b52da4aed4f8e6f3725411d2 Mon Sep 17 00:00:00 2001
+From: Alex Wilson <alex.wilson@joyent.com>
+Date: Mon, 3 Aug 2015 16:27:44 -0700
+Subject: [PATCH 21/36] PubKeyPlugin support
+
+This adds the PubKeyPlugin directive and associated code from
+SunSSH, allowing an in-process shared library to be called
+into to check public keys for authentication.
+---
+ auth2-pubkey.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ servconf.c     |  15 +++++++
+ servconf.h     |   1 +
+ 3 files changed, 155 insertions(+)
+
+diff --git a/auth2-pubkey.c b/auth2-pubkey.c
+index 5aa319c..77b00f7 100644
+--- a/auth2-pubkey.c
++++ b/auth2-pubkey.c
+@@ -22,6 +22,11 @@
+  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  */
++/*
++ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
++ * Copyright 2015 Joyent, Inc.
++ * Use is subject to license terms.
++ */
+ 
+ #include "includes.h"
+ 
+@@ -42,11 +47,13 @@
+ #include <time.h>
+ #include <unistd.h>
+ #include <limits.h>
++#include <dlfcn.h>
+ 
+ #include "xmalloc.h"
+ #include "ssh.h"
+ #include "ssh2.h"
+ #include "packet.h"
++#include "digest.h"
+ #include "buffer.h"
+ #include "log.h"
+ #include "misc.h"
+@@ -74,6 +81,15 @@ extern ServerOptions options;
+ extern u_char *session_id2;
+ extern u_int session_id2_len;
+ 
++static const char *RSA_SYM_NAME = "sshd_user_rsa_key_allowed";
++static const char *ECDSA_SYM_NAME = "sshd_user_ecdsa_key_allowed";
++typedef int (*RSA_SYM)(struct passwd *, RSA *, const char *);
++typedef int (*ECDSA_SYM)(struct passwd *, EC_KEY *, const char *);
++
++static const char *UNIV_SYM_NAME = "sshd_user_key_allowed";
++typedef int (*UNIV_SYM)(struct passwd *, const char *,
++    const u_char *, size_t);
++
+ static int
+ userauth_pubkey(Authctxt *authctxt)
+ {
+@@ -1030,6 +1046,125 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
+ 	return found_key;
+ }
+ 
++/**
++ * 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;
++	ECDSA_SYM ecdsa_sym = NULL;
++	UNIV_SYM univ_sym = NULL;
++	char *fp = NULL;
++	char *argfp = 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;
++	}
++
++	/*
++	 * If we have the new-style universal symbol for checking keys, use
++	 * that instead of the old-style per-key-type symbols.
++	 */
++	univ_sym = (UNIV_SYM)dlsym(handle, UNIV_SYM_NAME);
++	if (univ_sym != NULL) {
++		u_char *blob;
++		const char *type = sshkey_type(key);
++		size_t len = 0;
++		if (sshkey_to_blob(key, &blob, &len) != 0) {
++			debug("failed to convert key to rfc4253 format");
++			goto out;
++		}
++		debug("Invoking %s from %s", UNIV_SYM_NAME,
++		    options.pubkey_plugin);
++		success = (*univ_sym)(pw, type, blob, len);
++		debug("pubkeyplugin returned: %d", success);
++		goto out;
++	}
++
++	/* Otherwise, continue with the old-style fingerprint symbols. */
++	fp = sshkey_fingerprint(key, SSH_DIGEST_MD5, SSH_FP_HEX);
++	if (fp == NULL) {
++		debug("failed to generate fingerprint");
++		goto out;
++	}
++	if (strncmp(fp, "MD5:", 4) != 0) {
++		debug("fingerprint not in MD5:hex format");
++		goto out;
++	}
++	/* give the plugin the string without leading MD5: */
++	argfp = fp + 4;
++
++	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, argfp);
++		break;
++	case KEY_ECDSA:
++		ecdsa_sym = (ECDSA_SYM)dlsym(handle, ECDSA_SYM_NAME);
++		if (ecdsa_sym == NULL) {
++			debug("Unable to resolve symbol %s: %s", ECDSA_SYM_NAME,
++			dlerror());
++			goto out;
++		}
++		debug2("Invoking %s from %s", ECDSA_SYM_NAME,
++		    options.pubkey_plugin);
++		success = (*ecdsa_sym)(pw, key->ecdsa, argfp);
++		break;
++	default:
++		debug2("user_key_plugins only support RSA and ECDSA keys");
++	}
++
++	debug("pubkeyplugin returned: %d", success);
++
++out:
++	if (handle != NULL) {
++		dlclose(handle);
++		ecdsa_sym = NULL;
++		rsa_sym = NULL;
++		univ_sym = NULL;
++		handle = NULL;
++	}
++
++	if (success)
++		verbose("Found matching %s key: %s", key_type(key), fp);
++
++	if (fp != NULL) {
++		free(fp);
++		fp = NULL;
++	}
++
++	return success;
++}
++
+ /*
+  * Check whether key authenticates and authorises the user.
+  */
+@@ -1048,6 +1183,10 @@ user_key_allowed(struct passwd *pw, Key *key, int auth_attempt)
+ 	if (success)
+ 		return success;
+ 
++	success = user_key_allowed_from_plugin(pw, key);
++	if (success > 0)
++		return success;
++
+ 	success = user_key_command_allowed2(pw, key);
+ 	if (success > 0)
+ 		return success;
+diff --git a/servconf.c b/servconf.c
+index 53146af..dca59fd 100644
+--- a/servconf.c
++++ b/servconf.c
+@@ -182,6 +182,7 @@ initialize_server_options(ServerOptions *options)
+ 	 */
+ 	options->pam_service_per_authmethod = 1;
+ #endif
++	options->pubkey_plugin = NULL;
+ }
+ 
+ /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
+@@ -465,6 +466,7 @@ typedef enum {
+ 	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
+ 	sStreamLocalBindMask, sStreamLocalBindUnlink,
+ 	sAllowStreamLocalForwarding, sFingerprintHash,
++	sPubKeyPlugin,
+ 	sDeprecated, sUnsupported
+ } ServerOpCodes;
+ 
+@@ -640,6 +642,7 @@ static struct {
+ 	{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
+ 	{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
+ 	{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
++	{ "pubkeyplugin", sPubKeyPlugin, SSHCFG_ALL },
+ 	{ NULL, sBadOption, 0 }
+ };
+ 
+@@ -1966,6 +1969,18 @@ process_server_config_line(ServerOptions *options, char *line,
+ 		}
+ 		break;
+ 
++	case sPubKeyPlugin:
++		/*
++		 * Can't use parse_filename, as we need to support plain
++		 * names which dlopen will find on our lib path.
++		 */
++		arg = strdelim(&cp);
++		if (!arg || *arg == '\0')
++			fatal("%s line %d: missing file name.",
++			    filename, linenum);
++		options->pubkey_plugin = xstrdup(arg);
++		break;
++
+ 	case sDeprecated:
+ 		logit("%s line %d: Deprecated option %s",
+ 		    filename, linenum, arg);
+diff --git a/servconf.h b/servconf.h
+index 2175645..80e152f 100644
+--- a/servconf.h
++++ b/servconf.h
+@@ -206,6 +206,7 @@ typedef struct {
+ #endif
+         
+ 	int	fingerprint_hash;
++	char   *pubkey_plugin;
+ }       ServerOptions;
+ 
+ /* Information about the incoming connection as used by Match */
+-- 
+2.5.4 (Apple Git-61)
+
