diff -Nur ntp-4.2.4p8.orig/config.h.in ntp-4.2.4p8.new/config.h.in
--- ntp-4.2.4p8.orig/config.h.in	2009-12-08 18:43:06.000000000 +0530
+++ ntp-4.2.4p8.new/config.h.in	2011-11-10 18:57:55.654491024 +0530
@@ -322,6 +322,9 @@
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
 /* Use Rendezvous/DNS-SD registration */
 #undef HAVE_DNSREGISTRATION
 
@@ -412,6 +415,9 @@
 /* Do we have the curses library? */
 #undef HAVE_LIBCURSES
 
+/* Define to 1 if you have the `dl' library (-ldl). */
+#undef HAVE_LIBDL
+
 /* Do we have the edit library? */
 #undef HAVE_LIBEDIT
 
diff -Nur ntp-4.2.4p8.orig/configure.ac ntp-4.2.4p8.new/configure.ac
--- ntp-4.2.4p8.orig/configure.ac	2009-05-12 11:28:54.000000000 +0530
+++ ntp-4.2.4p8.new/configure.ac	2011-11-10 18:57:55.655491018 +0530
@@ -368,6 +368,8 @@
   AC_SEARCH_LIBS([openlog], [syslog], , , [$libxnet -lsocket])))
 AC_SEARCH_LIBS([MD5Init], [md5 md])
 AC_CHECK_FUNCS(MD5Init)
+AC_CHECK_LIB(dl, dlopen)
+AC_CHECK_HEADERS(dlfcn.h)
 
 # following block becomes on 4.2.5: NTP_LINEEDITLIBS
 dnl HMS: What a hack...
diff -Nur ntp-4.2.4p8.orig/include/ntp_authprov.h ntp-4.2.4p8.new/include/ntp_authprov.h
--- ntp-4.2.4p8.orig/include/ntp_authprov.h	1970-01-01 05:30:00.000000000 +0530
+++ ntp-4.2.4p8.new/include/ntp_authprov.h	2011-11-10 18:57:55.656491010 +0530
@@ -0,0 +1,74 @@
+/*
+ * ntp_authprov.h - definitions for authentication providers
+ */
+
+#ifndef _NTP_AUTHPROV_H
+#define _NTP_AUTHPROV_H
+
+/*
+ * An authentication provider backend, allocated by the provider's
+ * constructor.
+ */
+
+struct info_auth;
+
+#define	KEY_TYPE_MD5	4 /* type argument to setkey method */
+
+struct authkey_be {
+	void (*destructor)(struct authkey_be *be);
+	int (*getmac)(struct authkey_be *be, keyid_t keyno, u_int32 *pkt, int length);
+	int (*verifymac)(struct authkey_be *be, keyid_t keyno, u_int32 *pkt, int length, int size);
+	void (*agekeys)(struct authkey_be *be);
+	int (*havekey)(struct authkey_be *be, keyid_t keyno, int cache);
+	void (*trust)(struct authkey_be *be, keyid_t keyno, u_long trust);
+	int (*istrusted)(struct authkey_be *be, keyid_t keyno);
+	int (*setkey)(struct authkey_be *be, keyid_t keyno, int type, const u_char *key, const int len, u_long trust);
+	int (*refresh)(struct authkey_be *be);
+	int (*stats)(struct authkey_be *be, struct info_auth *stats);
+	void (*reset_stats)(struct authkey_be *be);
+};
+
+/*
+ * Current authentication provider version
+ */
+#define AUTHPROV_VERSION_V1	1
+#define AUTHPROV_VERSION	AUTHPROV_VERSION_V1
+
+/*
+ * Authentication provider constructor, allocates backend object
+ * (provider specific state can be stored at end of structure)
+ */
+typedef struct authkey_be *(*authkey_be_constructor)(int version, int argc, const char *argv[]);
+
+/*
+ * Authentication provider API
+ */
+extern	int	authprov_register P((void *, struct authkey_be *, keyid_t[2], int));
+extern	struct authkey_be *authprov_select P((keyid_t keyno));
+extern	int	authprov_load	P((const char *, keyid_t[2], int , const char *[]));
+extern	void	authprov_cleanup P((void));
+extern	void	authprov_refresh P((void));
+extern	int	authprov_stats	P((struct info_auth *ia));
+extern	void	authprov_reset_stats	P((void));
+extern	int	authprov_genkeyid P((void *, keyid_t *));
+
+/*
+ * Internal key file authentication provider
+ */
+
+#define KEYFILE_AUTHPROV_BE	((void *)0) /* for use with authprov_genkeyid() */
+
+extern	struct authkey_be *keyfile_authprov_init P((int, int, const char *[]));
+extern	void	keyfile_authprov_delkeys P((struct authkey_be *be));
+extern	int	keyfile_authprov_readkeys P((struct authkey_be *be, const char *file));
+
+/*
+ * Internal autokey authentication provider
+ */
+#define AUTOKEY_AUTHPROV_BE	((void *)~0) /* for use with authprov_genkeyid() */
+
+extern	struct authkey_be *autokey_authprov_init P((int, int, const char *[]));
+extern	int	autokey_iskeyid P((keyid_t));
+extern	void	autokey_untrust P((keyid_t keyid));
+
+#endif /* _NTP_AUTHPROV_H */
diff -Nur ntp-4.2.4p8.orig/include/ntp_config.h ntp-4.2.4p8.new/include/ntp_config.h
--- ntp-4.2.4p8.orig/include/ntp_config.h	2006-12-28 17:33:04.000000000 +0530
+++ ntp-4.2.4p8.new/include/ntp_config.h	2011-11-10 18:57:55.657491005 +0530
@@ -60,6 +60,7 @@
 #ifdef OPENSSL
 #define CONFIG_CRYPTO		39
 #endif /* OPENSSL */
+#define CONFIG_AUTHPROV		40
 
 /*
  * "peer", "server", "broadcast" modifier keywords
diff -Nur ntp-4.2.4p8.orig/include/ntp_crypto.h ntp-4.2.4p8.new/include/ntp_crypto.h
--- ntp-4.2.4p8.orig/include/ntp_crypto.h	2006-06-07 01:46:17.000000000 +0530
+++ ntp-4.2.4p8.new/include/ntp_crypto.h	2011-11-10 18:57:55.657491005 +0530
@@ -1,8 +1,13 @@
 /*
  * ntp_crypto.h - definitions for cryptographic operations
  */
+
+#ifndef _NTP_CRYPTO_H
+#define _NTP_CRYPTO_H
+
 #ifdef OPENSSL
 #include "openssl/evp.h"
+
 /*
  * The following bits are set by the CRYPTO_ASSOC message from
  * the server and are not modified by the client.
@@ -167,4 +172,7 @@
 extern	struct value hostval;	/* host name/value */
 extern	struct cert_info *cinfo; /* host certificate information */
 extern	struct value tai_leap;	/* leapseconds table */
+
 #endif /* OPENSSL */
+#endif /* _NTP_CRYPTO_H */
+
diff -Nur ntp-4.2.4p8.orig/include/ntp_stdlib.h ntp-4.2.4p8.new/include/ntp_stdlib.h
--- ntp-4.2.4p8.orig/include/ntp_stdlib.h	2006-12-28 17:33:05.000000000 +0530
+++ ntp-4.2.4p8.new/include/ntp_stdlib.h	2011-11-10 18:57:55.658491001 +0530
@@ -37,15 +37,16 @@
 extern	void netsyslog		P(());
 #endif
 
+extern	void	auth_agekeys	P((void));
 extern	void	auth_delkeys	P((void));
 extern	int	auth_havekey	P((keyid_t));
 extern	int	authdecrypt	P((keyid_t, u_int32 *, int, int));
 extern	int	authencrypt	P((keyid_t, u_int32 *, int));
 extern	int	authhavekey	P((keyid_t));
 extern	int	authistrusted	P((keyid_t));
-extern	int	authreadkeys	P((const char *));
 extern	void	authtrust	P((keyid_t, u_long));
 extern	int	authusekey	P((keyid_t, int, const u_char *));
+extern	int	authsetkey	P((keyid_t, int, const u_char *, const int, u_long));
 
 extern	u_long	calyearstart	P((u_long));
 extern	const char *clockname	P((int));
@@ -57,15 +58,14 @@
 extern	void *	emalloc		P((u_int));
 #endif
 extern	int	ntp_getopt	P((int, char **, const char *));
-extern	void	init_auth	P((void));
+extern	int	init_auth	P((const char *keyfile));
 extern	void	init_lib	P((void));
 extern	struct savekey *auth_findkey P((keyid_t));
 extern	int	auth_moremem	P((void));
 extern	int	ymd2yd		P((int, int, int));
 
-extern	int	MD5authdecrypt	P((u_char *, u_int32 *, int, int));
-extern	int	MD5authencrypt	P((u_char *, u_int32 *, int));
-extern	void	MD5auth_setkey	P((keyid_t, const u_char *, const int));
+extern	int	MD5authdecrypt	P((u_char *, u_int32, u_int32 *, int, int));
+extern	int	MD5authencrypt	P((u_char *, u_int32, u_int32 *, int));
 extern	u_int32	addr2refid	P((struct sockaddr_storage *));
 
 extern	int	atoint		P((const char *, long *));
@@ -100,9 +100,7 @@
 
 extern	void	signal_no_reset P((int, RETSIGTYPE (*func)(int)));
 
-extern	void	getauthkeys 	P((const char *));
-extern	void	auth_agekeys	P((void));
-extern	void	rereadkeys	P((void));
+extern	void	setauthkeyfile	P((const char *));
 
 /*
  * Variable declarations for libntp.
@@ -113,24 +111,6 @@
  */
 extern volatile int debug;		/* debugging flag */
 
-/* authkeys.c */
-extern u_long	authkeynotfound;	/* keys not found */
-extern u_long	authkeylookups;		/* calls to lookup keys */
-extern u_long	authnumkeys;		/* number of active keys */
-extern u_long	authkeyexpired;		/* key lifetime expirations */
-extern u_long	authkeyuncached;	/* cache misses */
-extern u_long	authencryptions;	/* calls to encrypt */
-extern u_long	authdecryptions;	/* calls to decrypt */
-
-extern int	authnumfreekeys;
-
-/*
- * The key cache. We cache the last key we looked at here.
- */
-extern keyid_t	cache_keyid;		/* key identifier */
-extern u_char *	cache_key;		/* key pointer */
-extern u_int	cache_keylen;		/* key length */
-
 /* getopt.c */
 extern char *	ntp_optarg;		/* global argument pointer */
 extern int	ntp_optind;		/* global argv index */
diff -Nur ntp-4.2.4p8.orig/libntp/Makefile.am ntp-4.2.4p8.new/libntp/Makefile.am
--- ntp-4.2.4p8.orig/libntp/Makefile.am	2006-06-07 01:46:25.000000000 +0530
+++ ntp-4.2.4p8.new/libntp/Makefile.am	2011-11-10 18:57:55.658491001 +0530
@@ -3,7 +3,7 @@
 noinst_LIBRARIES = libntp.a @MAKE_LIBNTPSIM@
 EXTRA_LIBRARIES = libntpsim.a
 libntp_a_SRCS = a_md5encrypt.c adjtime.c atoint.c atolfp.c atouint.c \
-	audio.c authkeys.c authreadkeys.c authusekey.c buftvtots.c \
+	audio.c authkeys.c authkeyprov.c authreadkeys.c authusekey.c buftvtots.c \
 	caljulian.c caltontp.c calyearstart.c clocktime.c \
 	clocktypes.c decodenetnum.c dofptoa.c dolfptoa.c emalloc.c \
 	findconfig.c fptoa.c fptoms.c getopt.c hextoint.c \
diff -Nur ntp-4.2.4p8.orig/libntp/a_md5encrypt.c ntp-4.2.4p8.new/libntp/a_md5encrypt.c
--- ntp-4.2.4p8.orig/libntp/a_md5encrypt.c	2006-06-07 01:46:25.000000000 +0530
+++ ntp-4.2.4p8.new/libntp/a_md5encrypt.c	2011-11-10 18:57:55.659490999 +0530
@@ -33,6 +33,7 @@
 int
 MD5authencrypt(
 	u_char *key,		/* key pointer */
+	u_int32 keylen,		/* key length */
 	u_int32 *pkt,		/* packet pointer */
 	int length		/* packet length */
 	)
@@ -44,7 +45,7 @@
 	 * MD5 with key identifier concatenated with packet.
 	 */
 	MD5Init(&md5);
-	MD5Update(&md5, key, (u_int)cache_keylen);
+	MD5Update(&md5, key, (u_int)keylen);
 	MD5Update(&md5, (u_char *)pkt, (u_int)length);
 	MD5Final(digest, &md5);
 	memmove((u_char *)pkt + length + 4, digest, 16);
@@ -60,6 +61,7 @@
 int
 MD5authdecrypt(
 	u_char *key,		/* key pointer */
+	u_int32 keylen,		/* key length */
 	u_int32 *pkt,		/* packet pointer */
 	int length,	 	/* packet length */
 	int size		/* MAC size */
@@ -72,7 +74,7 @@
 	 * MD5 with key identifier concatenated with packet.
 	 */
 	MD5Init(&md5);
-	MD5Update(&md5, key, (u_int)cache_keylen);
+	MD5Update(&md5, key, (u_int)keylen);
 	MD5Update(&md5, (u_char *)pkt, (u_int)length);
 	MD5Final(digest, &md5);
 	if (size != 16 + 4)
diff -Nur ntp-4.2.4p8.orig/libntp/authkeyprov.c ntp-4.2.4p8.new/libntp/authkeyprov.c
--- ntp-4.2.4p8.orig/libntp/authkeyprov.c	1970-01-01 05:30:00.000000000 +0530
+++ ntp-4.2.4p8.new/libntp/authkeyprov.c	2011-11-10 18:57:55.659490999 +0530
@@ -0,0 +1,583 @@
+/*
+ * authkeyprov.c - authentication key provider interface
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#include "ntp_types.h"
+#include "ntp_fp.h"
+#include "ntp.h"
+#include "ntpd.h"
+#include "ntp_string.h"
+#include "ntp_malloc.h"
+#include "ntp_stdlib.h"
+#include "ntp_authprov.h"
+#include "ntp_request.h"
+
+/*
+ * Allow dynamic linker flags to be overriden at configure time
+ * for very special cases.
+ */
+#ifndef NTP_AUTHPROV_RTLD_FLAGS
+#define NTP_AUTHPROV_RTLD_FLAGS	RTLD_LOCAL
+#endif
+
+struct authprov {
+	void *handle;
+	struct authkey_be *be;
+	keyid_t bounds[2];
+	struct authprov *next;
+};
+
+static struct authprov *authprovs = NULL;
+
+/*
+ * authprov_select - select authentication provider backend for a given key ID
+ */
+struct authkey_be *
+authprov_select(keyid_t keyno)
+{
+	struct authprov *ap;
+
+	if (keyno == 0) {
+		return (NULL);
+	}
+
+	for (ap = authprovs; ap != NULL; ap = ap->next) {
+		if (keyno >= ap->bounds[0] && keyno <= ap->bounds[1]) {
+			break;
+		}
+	}
+
+	if (ap == NULL) {
+		return (NULL);
+	}
+
+	return (ap->be);
+}
+
+/*
+ * init_auth - initialize default authentication provider list
+ *
+ * Note that builtin authentication providers can be explicitly
+ * instantiated with the "authprov" configuration file directive,
+ * which allows (for example) a different key file to be used
+ * for a portion of the key ID space. The default providers are
+ * always registered, but it is possible for the key ID space
+ * they manage to be completely obscured by user providers.
+ */
+int
+init_auth(const char *keyfile)
+{
+	struct authkey_be *be;
+	keyid_t bounds[2];
+
+	/*
+	 * Register keyfile authentication provider for key ID
+	 * space between 0 and NTP_MAXKEY.
+	 */
+	be = keyfile_authprov_init(AUTHPROV_VERSION, keyfile != NULL, &keyfile);
+	if (be == NULL) {
+		return (0);
+	}
+
+	bounds[0] = 0;
+	bounds[1] = NTP_MAXKEY;
+
+	if (!authprov_register(KEYFILE_AUTHPROV_BE, be, bounds, 0)) {
+		return (0);
+	}
+
+	/*
+	 * Register autokey authenetication provider for key ID
+	 * space from NTP_MAXKEY + 1.
+	 */
+	be = autokey_authprov_init(AUTHPROV_VERSION, 0, NULL);
+	if (be == NULL) {
+		return (0);
+	}
+
+	bounds[0] = NTP_MAXKEY + 1;
+	bounds[1] = NTP_MAXKEY * 2 + 1;
+
+	if (!authprov_register(AUTOKEY_AUTHPROV_BE, be, bounds, 0)) {
+		return (0);
+	}
+
+	return (1);
+}
+
+/*
+ * authprov_genkeyid - generate a key ID within bounds for an authentication
+ * provider. We can't call authprov_select() without a keyid, so instead
+ * this function takes a handle (which is typically a well known handle).
+ */
+int
+authprov_genkeyid(
+	void *handle,
+	keyid_t *pkeyid)
+{
+	struct authprov *ap;
+	keyid_t keyid;
+
+	for (ap = authprovs; ap != NULL; ap = ap->next) {
+		if (ap->handle == handle) {
+			break;
+		}
+	}
+
+	if (ap == NULL) {
+		return (0);
+	}
+
+	while (1) {
+		keyid = (ntp_random() + ap->bounds[0]);
+		if (keyid > ap->bounds[1])
+			keyid = ap->bounds[1];
+		/* This check is necessary in case of overlapping bounds */
+		if (authprov_select(keyid) != ap->be)
+			continue;
+		if (ap->be->havekey != NULL && (*ap->be->havekey)(ap->be, keyid, 1))
+			continue;
+		break;
+	}
+
+	*pkeyid = keyid;
+
+	return (1);
+}
+
+/*
+ * authprov_register - register a new authentication provider
+ */
+int
+authprov_register(
+	void *handle,
+	struct authkey_be *be,
+	keyid_t bounds[2],
+	int userprov
+	)
+{
+	struct authprov *ap, **app;
+
+	/*
+	 * Each authentication provider is assigned a portion of the keyid
+	 * space. For maximum flexibility, the space is configured by the
+	 * administrator rather than the provider itself.
+	 *
+	 * In the default case where no user providers are registered, the
+	 * NTP_MAXKEY pivot is preserved.
+	 */
+	for (app = &authprovs; *app != NULL; app = &(*app)->next) {
+		ap = *app;
+
+		/*
+		 * First registered provider wins in case of bounds overlap.
+		 * Internal providers are registered after user providers.
+		 *
+		 * Only print a warning if the overlap is between user providers.
+		 */
+		if (userprov &&
+		    (bounds[0] >= ap->bounds[0] || bounds[1] <= ap->bounds[1])) {
+			fprintf(stderr, "Warning: authentication provider bounds %u:%u "
+				"overlap existing bounds %u:%u\n",
+				bounds[0], bounds[1], ap->bounds[0], ap->bounds[1]);
+		}
+	}
+
+	ap = (struct authprov *)calloc(1, sizeof(*ap));
+	if (ap == NULL) {
+		return (0);
+	}	
+
+	ap->handle = handle;
+	ap->be = be;
+	ap->bounds[0] = bounds[0];
+	ap->bounds[1] = bounds[1];
+	ap->next = NULL;
+
+	*app = ap;
+
+	return (1);
+}
+
+/*
+ * authprov_destroy - cleanup a single authentication provider
+ */
+static void
+authprov_destroy(void *handle, struct authkey_be *be)
+{
+	if (be->destructor != NULL) {
+		(*be->destructor)(be);
+	}
+#ifdef HAVE_DLFCN_H
+	if (handle != KEYFILE_AUTHPROV_BE && handle != AUTOKEY_AUTHPROV_BE) {
+		dlclose(handle);
+	}
+#endif /* HAVE_DLFCN_H */
+}
+
+/* 
+ * authprov_cleanup - cleanup registered authentication providers
+ */
+void
+authprov_cleanup(void)
+{
+	struct authprov *ap, *next;
+
+	for (ap = authprovs; ap != NULL; ap = next) {
+		next = ap->next;
+		authprov_destroy(ap->handle, ap->be);
+		memset(ap, 0, sizeof(*ap));
+		free(ap);
+	}
+}
+
+/*
+ * authprov_refresh - refresh all authentication providers
+ */
+void
+authprov_refresh(void)
+{
+	struct authprov *ap;
+
+	for (ap = authprovs; ap != NULL; ap = ap->next) {
+		if (ap->be->refresh != NULL) {
+			(*ap->be->refresh)(ap->be);
+		}
+	}
+}
+
+/*
+ * authprov_load - load a new authentication provider
+ *
+ * Path is either a path to a dynamically loadable module (for platforms
+ * that support it) or one of the well known constants "keyfile" or
+ * "autokey"
+ */
+int
+authprov_load(
+	const char *path,
+	keyid_t bounds[2],
+	int argc,
+	const char *argv[]
+	)
+{
+	struct authkey_be *be;
+	void *handle;
+	const char *err;
+	authkey_be_constructor constr;
+
+	if (strcmp(path, "keyfile") == 0) {
+		constr = keyfile_authprov_init;
+		handle = KEYFILE_AUTHPROV_BE;
+	} else if (strcmp(path, "autokey") == 0) {
+		constr = autokey_authprov_init;
+		handle = AUTOKEY_AUTHPROV_BE;
+	} else {
+#ifdef HAVE_DLFCN_H
+		handle = dlopen(path, RTLD_NOW | NTP_AUTHPROV_RTLD_FLAGS);
+		if (handle == NULL) {
+			err = dlerror();
+			fprintf(stderr, "Failed to load library %s: %s\n", path,
+				err != NULL ? err : strerror(errno));
+			return (0);
+		}
+
+		dlerror();
+
+		/*
+		 * Each provider should export a symbol authprov_init, being a
+		 * constructor that returns an authkey_be structure.
+		 */
+		constr = (authkey_be_constructor)dlsym(handle, "authprov_init");
+		if (constr == NULL) {
+			err = dlerror();
+			fprintf(stderr, "Failed to resolve symbol authprov_init: %s",
+				err != NULL ? err : strerror(errno));
+			dlclose(handle);
+			return (0);
+		}
+#else
+		fprintf(stderr, "Loadable authentication providers not supported on this platform\n");
+		return (0);
+#endif /* HAVE_DLFCN_H */
+	}
+
+	be = (*constr)(AUTHPROV_VERSION_V1, argc, argv);
+	if (be == NULL) {
+		fprintf(stderr, "Failed to initialize NTP authentication provider %s\n",
+			path);
+		authprov_destroy(handle, be);
+		return (0);
+	}
+
+	if (!authprov_register(handle, be, bounds, 1)) {
+		fprintf(stderr, "Failed to register NTP authentication provider %s\n",
+			path);
+		authprov_destroy(handle, be);
+		return (0);
+	}
+
+	return (1);
+}
+
+/*
+ * authsetkey - associate a key with a key ID.
+ *
+ * If the trust argument is 0, the key is untrusted; if 1, the key is
+ * trusted; any other value denotes the trust lifetime in seconds.
+ */
+int
+authsetkey(
+	keyid_t keyno,
+	int type, /* should be KEY_TYPE_MD5 for now */
+	const u_char *key,
+	const int len,
+	u_long trust
+	)
+{
+	struct authkey_be *be;
+
+	be = authprov_select(keyno);
+	if (be == NULL) {
+		return (0);
+	}
+
+	if (be->setkey == NULL) {
+		return (0);
+	}
+
+	return (*be->setkey)(be, keyno, type, key, len, trust);
+}
+
+/*
+ * auth_havekey - returns one if the key is known
+ */
+int
+auth_havekey(
+	keyid_t keyno
+	)
+{
+	struct authkey_be *be;
+
+	be = authprov_select(keyno);
+	if (be == NULL) {
+		return (0);
+	}
+
+	if (be->havekey == NULL) {
+		return (0);
+	}
+
+	return (*be->havekey)(be, keyno, 0);
+}
+
+/*
+ * authhavekey - return one and cache the key, if known and trusted.
+ */
+int
+authhavekey(
+	keyid_t keyno
+	)
+{
+	struct authkey_be *be;
+
+	if (keyno == 0) {
+		return (1); /* to mirror existing behaviour */
+	}
+
+	be = authprov_select(keyno);
+	if (be == NULL) {
+		return (0);
+	}
+
+	if (be->havekey == NULL) {
+		return (0);
+	}
+
+	return (*be->havekey)(be, keyno, 1);
+}
+
+/*
+ * authtrust - declare a key to be trusted/untrusted
+ */
+void
+authtrust(
+	keyid_t keyno,
+	u_long trust
+	)
+{
+	struct authkey_be *be;
+
+	be = authprov_select(keyno);
+	if (be == NULL) {
+		return;
+	}
+
+	if (be->trust == NULL) {
+		return;
+	}
+
+	(*be->trust)(be, keyno, trust);
+}
+
+/*
+ * authistrusted - determine whether a key is trusted
+ */
+int
+authistrusted(
+	keyid_t keyno
+	)
+{
+	struct authkey_be *be;
+
+	be = authprov_select(keyno);
+	if (be == NULL) {
+		return (4);
+	}
+
+	if (be->istrusted == NULL) {
+		return (0);
+	}
+
+	return (*be->istrusted)(be, keyno);
+}
+
+/*
+ * auth_agekeys - delete keys whose lifetimes have expired
+ */
+void
+auth_agekeys(void)
+{
+	struct authprov *ap;
+
+	for (ap = authprovs; ap != NULL; ap = ap->next) {
+		if (ap->be->agekeys != NULL) {
+			(*ap->be->agekeys)(ap->be);
+		}
+	}
+}
+
+/*
+ * authencrypt - generate message authenticator
+ *
+ * Returns length of authenticator field, zero if key not found.
+ */
+int
+authencrypt(
+	keyid_t keyno,
+	u_int32 *pkt,
+	int length
+	)
+{
+	struct authkey_be *be;
+
+	pkt[length / 4] = htonl(keyno);
+
+	be = authprov_select(keyno);
+	if (be == NULL) {
+		return (4);
+	}
+
+	if (be->getmac == NULL) {
+		return (0);
+	}
+
+	return (*be->getmac)(be, keyno, pkt, length);
+}
+
+/*
+ * authdecrypt - verify message authenticator
+ *
+ * Returns one if authenticator valid, zero if invalid or key not found.
+ */
+int
+authdecrypt(
+	keyid_t keyno,
+	u_int32 *pkt,
+	int length,
+	int size
+	)
+{
+	struct authkey_be *be;
+
+	be = authprov_select(keyno);
+	if (be == NULL) {
+		return (0);
+	}
+
+	if (be->verifymac == NULL) {
+		return (0);
+	}
+
+	return (*be->verifymac)(be, keyno, pkt, length, size);
+}
+
+/*
+ * authprov_stats - gather aggregate statistics for authentication providers
+ */
+int
+authprov_stats(struct info_auth *ia)
+{
+	struct authprov *ap;
+	struct info_auth total_stats;
+
+	memset(&total_stats, 0, sizeof(total_stats));
+
+	for (ap = authprovs; ap != NULL; ap = ap->next) {
+		if (ap->be->stats != NULL) {
+			struct info_auth stats;
+
+			memset(&stats, 0, sizeof(stats));
+
+			if (!(*ap->be->stats)(ap->be, &stats)) {
+				continue;
+			}
+
+			total_stats.numkeys	+= stats.numkeys;
+			total_stats.numfreekeys	+= stats.numfreekeys;
+			total_stats.keylookups	+= stats.keylookups;
+			total_stats.keynotfound	+= stats.keynotfound;
+			total_stats.encryptions	+= stats.encryptions;
+			total_stats.decryptions	+= stats.decryptions;
+			total_stats.keyuncached	+= stats.keyuncached;
+			total_stats.expired	+= stats.expired;
+		}
+	}
+
+	ia->numkeys	= htonl((u_int32)total_stats.numkeys);
+	ia->numfreekeys	= htonl((u_int32)total_stats.numfreekeys);
+	ia->keylookups	= htonl((u_int32)total_stats.keylookups);
+	ia->keynotfound	= htonl((u_int32)total_stats.keynotfound);
+	ia->encryptions	= htonl((u_int32)total_stats.encryptions);
+	ia->decryptions	= htonl((u_int32)total_stats.decryptions);
+	ia->keyuncached	= htonl((u_int32)total_stats.keyuncached);
+	ia->expired	= htonl((u_int32)total_stats.expired);
+
+	return (1);
+}
+
+/*
+ * authprov_reset_stats - reset authentication provider statistics
+ */
+void
+authprov_reset_stats(void)
+{
+	struct authprov *ap;
+
+	for (ap = authprovs; ap != NULL; ap = ap->next) {
+		if (ap->be->reset_stats != NULL) {
+			(*ap->be->reset_stats)(ap->be);
+		}
+	}
+}
+
diff -Nur ntp-4.2.4p8.orig/libntp/authkeys.c ntp-4.2.4p8.new/libntp/authkeys.c
--- ntp-4.2.4p8.orig/libntp/authkeys.c	2004-02-25 11:28:03.000000000 +0530
+++ ntp-4.2.4p8.new/libntp/authkeys.c	2011-11-10 18:59:31.146491006 +0530
@@ -1,5 +1,5 @@
 /*
- * authkeys.c - routines to manage the storage of authentication keys
+ * authkeys.c - internal authentication providers
  */
 
 #ifdef HAVE_CONFIG_H
@@ -15,6 +15,8 @@
 #include "ntp_string.h"
 #include "ntp_malloc.h"
 #include "ntp_stdlib.h"
+#include "ntp_authprov.h"
+#include "ntp_request.h"
 
 /*
  * Structure to store keys in in the hash table.
@@ -42,126 +44,71 @@
 #define	HASHMASK	((HASHSIZE)-1)
 #define	KEYHASH(keyid)	((keyid) & HASHMASK)
 
-struct savekey *key_hash[HASHSIZE];
-
-u_long authkeynotfound;		/* keys not found */
-u_long authkeylookups;		/* calls to lookup keys */
-u_long authnumkeys;		/* number of active keys */
-u_long authkeyexpired;		/* key lifetime expirations */
-u_long authkeyuncached;		/* cache misses */
-u_long authnokey;		/* calls to encrypt with no key */
-u_long authencryptions;		/* calls to encrypt */
-u_long authdecryptions;		/* calls to decrypt */
-
-/*
- * Storage for free key structures.  We malloc() such things but
- * never free them.
- */
-struct savekey *authfreekeys;
-int authnumfreekeys;
-
 #define	MEMINC	12		/* number of new free ones to get */
 
 /*
- * The key cache. We cache the last key we looked at here.
- */
-keyid_t	cache_keyid;		/* key identifier */
-u_char	*cache_key;		/* key pointer */
-u_int	cache_keylen;		/* key length */
-u_short cache_flags;		/* flags that wave */
-
-
-/*
- * init_auth - initialize internal data
- */
-void
-init_auth(void)
-{
-	/*
-	 * Initialize hash table and free list
-	 */
-	memset((char *)key_hash, 0, sizeof key_hash);
-}
-
-
-/*
- * auth_findkey - find a key in the hash table
+ * Internal authentication provider, shared between keyfile
+ * and autokey backends.
  */
-struct savekey *
-auth_findkey(
-	keyid_t keyno
-	)
-{
-	struct savekey *sk;
-
-	sk = key_hash[KEYHASH(keyno)];
-	while (sk != 0) {
-		if (keyno == sk->keyid)
-			return (sk);
-
-		sk = sk->next;
-	}
-	return (0);
-}
+struct internal_authkey_be {
+	/* Method dispatch table */
+	struct authkey_be be;
+
+	/* Backend parameters */
+	char *keyfile;
+
+	/* Key cache */
+	keyid_t	cache_keyid;		/* key identifier */
+	u_char	*cache_key;		/* key pointer */
+	u_int	cache_keylen;		/* key length */
+	u_short cache_flags;		/* flags that wave */
+
+	/* Key storage */
+	struct savekey *key_hash[HASHSIZE];
+	struct savekey *authfreekeys;
 
+	/* Statistics */
+	struct info_auth stats;
+};
 
 /*
- * auth_havekey - return one if the key is known
+ * internal_authprov_havekey - return one and optionally cache the key, if known and trusted.
  */
-int
-auth_havekey(
-	keyid_t keyno
+static int
+internal_authprov_havekey(
+	struct authkey_be *be,
+	keyid_t keyno,
+	int cache
 	)
 {
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
 	struct savekey *sk;
 
-	if (keyno == 0 || (keyno == cache_keyid))
+	if (keyno == ibe->cache_keyid) {
 		return (1);
-
-	sk = key_hash[KEYHASH(keyno)];
-	while (sk != 0) {
-		if (keyno == sk->keyid)
-			return (1);
-
-		sk = sk->next;
 	}
-	return (0);
-}
-
 
-/*
- * authhavekey - return one and cache the key, if known and trusted.
- */
-int
-authhavekey(
-	keyid_t keyno
-	)
-{
-	struct savekey *sk;
-
-	authkeylookups++;
-	if (keyno == 0 || keyno == cache_keyid)
-		return (1);
-
-	authkeyuncached++;
-	sk = key_hash[KEYHASH(keyno)];
+	ibe->stats.keyuncached++;
+	sk = ibe->key_hash[KEYHASH(keyno)];
 	while (sk != 0) {
 		if (keyno == sk->keyid)
 		    break;
 		sk = sk->next;
 	}
 	if (sk == 0) {
-		authkeynotfound++;
+		ibe->stats.keynotfound++;
 		return (0);
+	} else if (cache == 0) {
+		/* Found key, not concerned whether it is trusted or not */
+		return (1);
 	} else if (!(sk->flags & KEY_TRUSTED)) {
-		authnokey++;
 		return (0);
 	}
-	cache_keyid = sk->keyid;
-	cache_flags = sk->flags;
+	ibe->cache_keyid = sk->keyid;
+	ibe->cache_flags = sk->flags;
 	if (sk->flags & KEY_MD5) {
-		cache_key = sk->k.MD5_key;
-		cache_keylen = sk->keylen;
+		ibe->cache_key = sk->k.MD5_key;
+		ibe->cache_keylen = sk->keylen;
 		return (1);
 	}
 	return (0);
@@ -169,10 +116,10 @@
 
 
 /*
- * auth_moremem - get some more free key structures
+ * internal_authprov_moremem - get some more free key structures
  */
-int
-auth_moremem(void)
+static int
+internal_authprov_moremem(struct internal_authkey_be *ibe)
 {
 	struct savekey *sk;
 	int i;
@@ -182,30 +129,32 @@
 		return (0);
 	
 	for (i = MEMINC; i > 0; i--) {
-		sk->next = authfreekeys;
-		authfreekeys = sk++;
+		sk->next = ibe->authfreekeys;
+		ibe->authfreekeys = sk++;
 	}
-	authnumfreekeys += MEMINC;
-	return (authnumfreekeys);
+	ibe->stats.numfreekeys += MEMINC;
+	return (ibe->stats.numfreekeys);
 }
 
 
 /*
- * authtrust - declare a key to be trusted/untrusted
+ * internal_authprov_trust - declare a key to be trusted/untrusted
  */
-void
-authtrust(
+static void
+internal_authprov_trust(
+	struct authkey_be *be,
 	keyid_t keyno,
 	u_long trust
 	)
 {
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
 	struct savekey *sk;
 
 #ifdef DEBUG
 	if (debug > 2)
 		printf("authtrust: keyid %08x life %lu\n", keyno, trust);
 #endif
-	sk = key_hash[KEYHASH(keyno)];
+	sk = ibe->key_hash[KEYHASH(keyno)];
 	while (sk != 0) {
 		if (keyno == sk->keyid)
 		    break;
@@ -216,9 +165,9 @@
 		return;
 	
 	if (sk != 0) {
-		if (cache_keyid == keyno) {
-			cache_flags = 0;
-			cache_keyid = 0;
+		if (ibe->cache_keyid == keyno) {
+			ibe->cache_flags = 0;
+			ibe->cache_keyid = 0;
 		}
 
 		if (trust > 0) {
@@ -230,39 +179,41 @@
 			return;
 		}
 
-		sk->flags &= ~KEY_TRUSTED; {
+		sk->flags &= ~KEY_TRUSTED;
+		{
 			struct savekey *skp;
 
-			skp = key_hash[KEYHASH(keyno)];
+			skp = ibe->key_hash[KEYHASH(keyno)];
 			if (skp == sk) {
-				key_hash[KEYHASH(keyno)] = sk->next;
+				ibe->key_hash[KEYHASH(keyno)] = sk->next;
 			} else {
 				while (skp->next != sk)
 				    skp = skp->next;
 				skp->next = sk->next;
 			}
-			authnumkeys--;
+			ibe->stats.numkeys--;
 
-			sk->next = authfreekeys;
-			authfreekeys = sk;
-			authnumfreekeys++;
+			sk->next = ibe->authfreekeys;
+			ibe->authfreekeys = sk;
+			ibe->stats.numfreekeys++;
 		}
 		return;
 	}
 
-	if (authnumfreekeys == 0)
-	    if (auth_moremem() == 0)
+	if (ibe->stats.numfreekeys == 0) {
+	    if (internal_authprov_moremem(ibe) == 0)
 		return;
+	}
 
-	sk = authfreekeys;
-	authfreekeys = sk->next;
-	authnumfreekeys--;
+	sk = ibe->authfreekeys;
+	ibe->authfreekeys = sk->next;
+	ibe->stats.numfreekeys--;
 
 	sk->keyid = keyno;
 	sk->flags = KEY_TRUSTED;
-	sk->next = key_hash[KEYHASH(keyno)];
-	key_hash[KEYHASH(keyno)] = sk;
-	authnumkeys++;
+	sk->next = ibe->key_hash[KEYHASH(keyno)];
+	ibe->key_hash[KEYHASH(keyno)] = sk;
+	ibe->stats.numkeys++;
 	return;
 }
 
@@ -270,48 +221,64 @@
 /*
  * authistrusted - determine whether a key is trusted
  */
-int
-authistrusted(
+static int
+internal_authprov_istrusted(
+	struct authkey_be *be,
 	keyid_t keyno
 	)
 {
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
 	struct savekey *sk;
 
-	if (keyno == cache_keyid)
-	    return ((cache_flags & KEY_TRUSTED) != 0);
+	if (keyno == ibe->cache_keyid)
+	    return ((ibe->cache_flags & KEY_TRUSTED) != 0);
 
-	authkeyuncached++;
-	sk = key_hash[KEYHASH(keyno)];
+	ibe->stats.keyuncached++;
+	sk = ibe->key_hash[KEYHASH(keyno)];
 	while (sk != 0) {
 		if (keyno == sk->keyid)
 		    break;
 		sk = sk->next;
 	}
 	if (sk == 0) {
-		authkeynotfound++;
+		ibe->stats.keynotfound++;
 		return (0);
 	} else if (!(sk->flags & KEY_TRUSTED)) {
-		authkeynotfound++;
+		ibe->stats.keynotfound++;
 		return (0);
 	}
 	return (1);
 }
 
-
-void
-MD5auth_setkey(
+/*
+ * internal_authprov_setkey - associate a key with a key ID
+ */
+static int
+internal_authprov_setkey(
+	struct authkey_be *be,
 	keyid_t keyno,
+	int type,
 	const u_char *key,
-	const int len
+	const int len,
+	u_long trust
 	)
 {
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
 	struct savekey *sk;
+
+	if (len == 0) {
+		return (1);
+	}
+
+	if (type != KEY_TYPE_MD5) {
+		return (0);
+	}
 	
 	/*
 	 * See if we already have the key.  If so just stick in the
 	 * new value.
 	 */
-	sk = key_hash[KEYHASH(keyno)];
+	sk = ibe->key_hash[KEYHASH(keyno)];
 	while (sk != 0) {
 		if (keyno == sk->keyid) {
 			strncpy((char *)sk->k.MD5_key, (const char *)key,
@@ -320,11 +287,11 @@
 			    sk->keylen = sizeof(sk->k.MD5_key);
 
 			sk->flags |= KEY_MD5;
-			if (cache_keyid == keyno) {
-				cache_flags = 0;
-				cache_keyid = 0;
+			if (ibe->cache_keyid == keyno) {
+				ibe->cache_flags = 0;
+				ibe->cache_keyid = 0;
 			}
-			return;
+			return (1);
 		}
 		sk = sk->next;
 	}
@@ -332,14 +299,14 @@
 	/*
 	 * Need to allocate new structure.  Do it.
 	 */
-	if (authnumfreekeys == 0) {
-		if (auth_moremem() == 0)
-		    return;
+	if (ibe->stats.numfreekeys == 0) {
+		if (internal_authprov_moremem(ibe) == 0)
+		    return (0);
 	}
 
-	sk = authfreekeys;
-	authfreekeys = sk->next;
-	authnumfreekeys--;
+	sk = ibe->authfreekeys;
+	ibe->authfreekeys = sk->next;
+	ibe->stats.numfreekeys--;
 
 	strncpy((char *)sk->k.MD5_key, (const char *)key,
 		sizeof(sk->k.MD5_key));
@@ -349,30 +316,137 @@
 	sk->keyid = keyno;
 	sk->flags = KEY_MD5;
 	sk->lifetime = 0;
-	sk->next = key_hash[KEYHASH(keyno)];
-	key_hash[KEYHASH(keyno)] = sk;
-	authnumkeys++;
-	return;
+	if (trust > 0) {
+		sk->flags |= KEY_TRUSTED;
+		if (trust > 1)
+			sk->lifetime = current_time + trust;
+	}
+	sk->next = ibe->key_hash[KEYHASH(keyno)];
+	ibe->key_hash[KEYHASH(keyno)] = sk;
+	ibe->stats.numkeys++;
+	return (1);
 }
-    
+
 /*
- * auth_delkeys - delete all known keys, in preparation for rereading
- *		  the keys file (presumably)
+ * internal_authprov_getmac - generate message authenticator
+ *
+ * Returns length of authenticator field, zero if key not found.
+ */
+static int
+internal_authprov_getmac(
+	struct authkey_be *be,
+	keyid_t keyno,
+	u_int32 *pkt,
+	int length
+	)
+{
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
+
+	ibe->stats.encryptions++;
+
+	if (!internal_authprov_havekey(be, keyno, 1)) {
+		return (0);
+	}
+
+	if (ibe->cache_flags & KEY_MD5) {
+		return (MD5authencrypt(ibe->cache_key, ibe->cache_keylen, pkt, length));
+	}
+
+	return (0);
+}
+
+/*
+ * internal_authprov_verifymac - verify message authenticator
+ *
+ * Returns one if authenticator valid, zero if invalid or key not found.
+ */
+static int
+internal_authprov_verifymac(
+	struct authkey_be *be,
+	keyid_t keyno,
+	u_int32 *pkt,
+	int length,
+	int size
+	)
+{
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
+
+	ibe->stats.decryptions++;
+
+	if (!internal_authprov_havekey(be, keyno, 1) || size < 4) {
+		return (0);
+	}
+
+	if (ibe->cache_flags & KEY_MD5) {
+		return (MD5authdecrypt(ibe->cache_key, ibe->cache_keylen, pkt, length, size));
+	}
+
+	return (0);
+}
+
+/* 
+ * internal_authprov_stats - get authentication provider statistics
+ */
+static int
+internal_authprov_stats(
+	struct authkey_be *be,
+	struct info_auth *ia)
+{
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
+
+	memcpy(ia, &ibe->stats, sizeof(*ia));
+
+	return (1);
+}
+
+/*
+ * internal_authprov_reset_stats - reset authentication provider statistics
+ */
+static void
+internal_authprov_reset_stats(struct authkey_be *be)
+{
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
+
+	ibe->stats.keylookups	= 0;
+	ibe->stats.keynotfound	= 0;
+	ibe->stats.encryptions	= 0;
+	ibe->stats.decryptions	= 0;
+	ibe->stats.keyuncached	= 0;
+}
+
+/**** Keyfile authentication provider backend ****/
+
+/*
+ * keyfile_authprov_destructor - destructor for internal providers
+ */
+static void
+keyfile_authprov_destructor(struct authkey_be *be)
+{
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
+
+	if (ibe->keyfile != NULL) {
+		free(ibe->keyfile);
+		ibe->keyfile = NULL;
+	}
+	free(ibe);
+}
+
+/*
+ * keyfile_auth_delkeys - delete all known keys, in preparation for rereading
+ *			  the keys file (presumably)
  */
 void
-auth_delkeys(void)
+keyfile_authprov_delkeys(struct authkey_be *be)
 {
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
 	struct savekey *sk;
 	struct savekey **skp;
 	int i;
 
 	for (i = 0; i < HASHSIZE; i++) {
-		skp = &(key_hash[i]);
-		sk = key_hash[i];
-		/*
-		 * Leave autokey keys alone.
-		 */
-		while (sk != 0 && sk->keyid <= NTP_MAXKEY) {
+		skp = &(ibe->key_hash[i]);
+		sk = ibe->key_hash[i];
+		while (sk != 0) {
 			/*
 			 * Don't lose info as to which keys are trusted.
 			 */
@@ -384,10 +458,10 @@
 				sk = sk->next;
 			} else {
 				*skp = sk->next;
-				authnumkeys--;
-				sk->next = authfreekeys;
-				authfreekeys = sk;
-				authnumfreekeys++;
+				ibe->stats.numkeys--;
+				sk->next = ibe->authfreekeys;
+				ibe->authfreekeys = sk;
+				ibe->stats.numfreekeys++;
 				sk = *skp;
 			}
 		}
@@ -395,94 +469,187 @@
 }
 
 /*
- * auth_agekeys - delete keys whose lifetimes have expired
+ * keyfile_authprov_refresh - reload keys from file
  */
+static int
+keyfile_authprov_refresh(struct authkey_be *be)
+{
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
+
+	if (ibe->keyfile != NULL) {
+		return keyfile_authprov_readkeys(be, ibe->keyfile);
+	}
+
+	return (1);
+}
+
 void
-auth_agekeys(void)
+keyfile_authprov_setkeyfile(struct authkey_be *be, char *filename)
+{
+
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
+
+	if (filename != NULL) {
+		ibe->keyfile = strdup(filename);
+		if (ibe->keyfile == NULL) {
+			return;
+		}
+		/* Load keys from keyfile */
+		(*ibe->be.refresh)((struct authkey_be *)ibe);
+	}
+	return;
+}
+
+/*
+ * keyfile_authprov_init - constructor for keyfile provider
+ */
+struct authkey_be *
+keyfile_authprov_init(int version, int argc, const char *argv[])
+{
+	struct internal_authkey_be *keyfile_be;
+
+	if (argc > 1) {
+		return (NULL);
+	}
+
+	keyfile_be = (struct internal_authkey_be *)calloc(1, sizeof(*keyfile_be));
+	if (keyfile_be == NULL) {
+		return (NULL);
+	}
+
+	keyfile_be->be.destructor	= keyfile_authprov_destructor;
+	keyfile_be->be.getmac		= internal_authprov_getmac;
+	keyfile_be->be.verifymac	= internal_authprov_verifymac;
+	keyfile_be->be.agekeys		= NULL; /* file keys do not age */
+	keyfile_be->be.havekey		= internal_authprov_havekey;
+	keyfile_be->be.trust		= internal_authprov_trust;
+	keyfile_be->be.istrusted	= internal_authprov_istrusted;
+	keyfile_be->be.setkey		= internal_authprov_setkey;
+	keyfile_be->be.refresh		= keyfile_authprov_refresh;
+	keyfile_be->be.stats		= internal_authprov_stats;
+	keyfile_be->be.reset_stats	= internal_authprov_reset_stats;
+
+	if (argc > 0) {
+		keyfile_be->keyfile = strdup(argv[0]);
+		if (keyfile_be->keyfile == NULL) {
+			(*keyfile_be->be.destructor)((struct authkey_be *)keyfile_be);
+			return (NULL);
+		}
+
+		/* Load keys from keyfile */
+		if ((*keyfile_be->be.refresh)((struct authkey_be *)keyfile_be) == 0) {
+			(*keyfile_be->be.destructor)((struct authkey_be *)keyfile_be);
+			return (NULL);
+		}
+	}
+
+	return (struct authkey_be *)keyfile_be;
+}
+
+/**** Autokey authentication provider backend ****/
+
+#define AUTOKEY_BE_P(be)	((be) != NULL && (be)->destructor == autokey_authprov_destructor)
+
+/*
+ * autokey_authprov_destructor - destructor for internal providers
+ */
+static void
+autokey_authprov_destructor(struct authkey_be *be)
+{
+	/* No keyfile */
+	free(be);
+}
+
+/*
+ * autokey_auth_agekeys - delete keys whose lifetimes have expired
+ *
+ * This is never called for keyfile keys because they do not expire
+ */
+static void
+autokey_authprov_agekeys(struct authkey_be *be)
 {
+	struct internal_authkey_be *ibe = (struct internal_authkey_be *)be;
 	struct savekey *sk;
 	struct savekey *skp;
 	int i;
 
 	for (i = 0; i < HASHSIZE; i++) {
-		sk = skp = key_hash[i];
+		sk = skp = ibe->key_hash[i];
 		while (sk != 0) {
 			skp = sk->next;
 			if (sk->lifetime > 0 && current_time >
 			    sk->lifetime) {
-				authtrust(sk->keyid, 0);
-				authkeyexpired++;
+				internal_authprov_trust(be, sk->keyid, 0);
+				ibe->stats.expired++;
 			}
 			sk = skp;
 		}
 	}
 #ifdef DEBUG
 	if (debug)
-		printf("auth_agekeys: at %lu keys %lu expired %lu\n",
-		    current_time, authnumkeys, authkeyexpired);
+		printf("auth_agekeys: at %lu keys %u expired %u\n",
+		    current_time, ibe->stats.numkeys, ibe->stats.expired);
 #endif
 }
 
 /*
- * authencrypt - generate message authenticator
- *
- * Returns length of authenticator field, zero if key not found.
+ * autokey_authprov_init - constructor for autokey provider
  */
-int
-authencrypt(
-	keyid_t keyno,
-	u_int32 *pkt,
-	int length
-	)
+struct authkey_be *
+autokey_authprov_init(int version, int argc, const char *argv[])
 {
+	struct internal_authkey_be *autokey_be;
 
-	/*
-	 * A zero key identifier means the sender has not verified
-	 * the last message was correctly authenticated. The MAC
-	 * consists of a single word with value zero.
-	 */
-	authencryptions++;
-	pkt[length / 4] = htonl(keyno);
-	if (keyno == 0) {
-		return (4);
+	if (argc != 0) {
+		return (NULL);
 	}
-	if (!authhavekey(keyno))
-		return (0);
 
-	if (cache_flags & KEY_MD5)
-		return (MD5authencrypt(cache_key, pkt, length));
+	autokey_be = (struct internal_authkey_be *)calloc(1, sizeof(*autokey_be));
+	if (autokey_be == NULL) {
+		return (NULL);
+	}
 
-	return (0);
+	autokey_be->be.destructor	= autokey_authprov_destructor;
+	autokey_be->be.getmac		= internal_authprov_getmac;
+	autokey_be->be.verifymac	= internal_authprov_verifymac;
+	autokey_be->be.agekeys		= autokey_authprov_agekeys;
+	autokey_be->be.havekey		= internal_authprov_havekey;
+	autokey_be->be.trust		= internal_authprov_trust;
+	autokey_be->be.istrusted	= internal_authprov_istrusted;
+	autokey_be->be.setkey		= internal_authprov_setkey;
+	autokey_be->be.refresh		= NULL;
+	autokey_be->be.stats		= internal_authprov_stats;
+	autokey_be->be.reset_stats	= internal_authprov_reset_stats;
+
+	return (struct authkey_be *)autokey_be;
 }
 
 /*
- * authdecrypt - verify message authenticator
- *
- * Returns one if authenticator valid, zero if invalid or key not found.
+ * autokey_iskeyid - returns one if the key ID is associated with the
+ *                   autokey authentication provider
  */
 int
-authdecrypt(
-	keyid_t keyno,
-	u_int32 *pkt,
-	int length,
-	int size
-	)
+autokey_iskeyid(keyid_t keyid)
 {
+	struct authkey_be *be;
 
-	/*
-	 * A zero key identifier means the sender has not verified
-	 * the last message was correctly authenticated. Nevertheless,
-	 * the authenticator itself is considered valid.
-	 */
-	authdecryptions++;
-	if (keyno == 0)
-		return (0);
+	be = authprov_select(keyid);
 
-	if (!authhavekey(keyno) || size < 4)
-		return (0);
+	return (AUTOKEY_BE_P(be));
+}
+
+/*
+ * autokey_untrust - untrust an autokey with a single provider lookup
+ */
+void
+autokey_untrust(keyid_t keyid)
+{
+	struct authkey_be *be;
 
-	if (cache_flags & KEY_MD5)
-		return (MD5authdecrypt(cache_key, pkt, length, size));
+	be = authprov_select(keyid);
 
-	return (0);
+	if (AUTOKEY_BE_P(be)) {
+		be->trust(be, keyid, 0);
+	}
 }
+
diff -Nur ntp-4.2.4p8.orig/libntp/authreadkeys.c ntp-4.2.4p8.new/libntp/authreadkeys.c
--- ntp-4.2.4p8.orig/libntp/authreadkeys.c	2004-02-25 11:28:03.000000000 +0530
+++ ntp-4.2.4p8.new/libntp/authreadkeys.c	2011-11-10 18:57:55.661491005 +0530
@@ -8,6 +8,7 @@
 #include "ntp.h"
 #include "ntp_syslog.h"
 #include "ntp_stdlib.h"
+#include "ntp_authprov.h"
 
 /*
  *  Arbitrary long string of ASCII characters.
@@ -65,7 +66,8 @@
  * authreadkeys - (re)read keys from a file.
  */
 int
-authreadkeys(
+keyfile_authprov_readkeys(
+	struct authkey_be *be,
 	const char *file
 	)
 {
@@ -88,7 +90,7 @@
 	/*
 	 * Remove all existing keys
 	 */
-	auth_delkeys();
+	keyfile_authprov_delkeys(be);
 
 	/*
 	 * Now read lines from the file, looking for key entries
@@ -148,8 +150,8 @@
 		} else {
 			switch(keytype) {
 			    case KEY_TYPE_MD5:
-				if (!authusekey(keyno, keytype,
-						(u_char *)token))
+				if (!authsetkey(keyno, keytype,
+						(u_char *)token, strlen(token), 0))
 				    msyslog(LOG_ERR,
 					    "format/parity error for MD5 key %ld, not used",
 					    keyno);
diff -Nur ntp-4.2.4p8.orig/libntp/authusekey.c ntp-4.2.4p8.new/libntp/authusekey.c
--- ntp-4.2.4p8.orig/libntp/authusekey.c	2004-02-25 11:28:03.000000000 +0530
+++ ntp-4.2.4p8.new/libntp/authusekey.c	2011-11-10 18:57:55.661491005 +0530
@@ -9,6 +9,10 @@
 #include "ntp_stdlib.h"
 
 /*
+ * NB: authsetkey() should be used in lieu of authusekey()
+ */
+
+/*
  * Types of ascii representations for keys.  "Standard" means a 64 bit
  * hex number in NBS format, i.e. with the low order bit of each byte
  * a parity bit.  "NTP" means a 64 bit key in NTP format, with the
@@ -16,8 +20,6 @@
  * character string whose ascii representation is used as the key.
  */
 
-#define	KEY_TYPE_MD5	4
-
 int
 authusekey(
 	keyid_t keyno,
@@ -25,23 +27,5 @@
 	const u_char *str
 	)
 {
-	const u_char *cp;
-	int len;
-
-	cp = str;
-	len = strlen((const char *)cp);
-	if (len == 0)
-	    return 0;
-
-	switch(keytype) {
-	    case KEY_TYPE_MD5:
-		MD5auth_setkey(keyno, str, (int)strlen((const char *)str));
-		break;
-
-	    default:
-		/* Oh, well */
-		return 0;
-	}
-
-	return 1;
+	return authsetkey(keyno, keytype, str, strlen((const char *)str), 0);
 }
diff -Nur ntp-4.2.4p8.orig/ntpd/cmd_args.c ntp-4.2.4p8.new/ntpd/cmd_args.c
--- ntp-4.2.4p8.orig/ntpd/cmd_args.c	2009-05-08 13:28:57.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/cmd_args.c	2011-11-10 18:57:55.662491008 +0530
@@ -102,7 +102,7 @@
 	}
 
 	if (HAVE_OPT( KEYFILE ))
-		getauthkeys(OPT_ARG( KEYFILE ));
+		setauthkeyfile(OPT_ARG( KEYFILE ));
 
 	if (HAVE_OPT( PIDFILE ))
 		stats_config(STATS_PID_FILE, OPT_ARG( PIDFILE ));
diff -Nur ntp-4.2.4p8.orig/ntpd/ntp_config.c ntp-4.2.4p8.new/ntpd/ntp_config.c
--- ntp-4.2.4p8.orig/ntpd/ntp_config.c	2008-08-10 16:32:39.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/ntp_config.c	2011-11-10 18:57:55.663491009 +0530
@@ -15,6 +15,7 @@
 #include "ntp_refclock.h"
 #include "ntp_filegen.h"
 #include "ntp_stdlib.h"
+#include "ntp_authprov.h"
 #include <ntp_random.h>
 #include <isc/net.h>
 #include <isc/result.h>
@@ -51,6 +52,7 @@
 #include "ntp_cmdargs.h"
 
 extern int priority_done;
+extern char *key_file_name;
 
 /*
  * These routines are used to read the configuration file at
@@ -111,6 +113,7 @@
 	{ "trap",		CONFIG_TRAP },
 	{ "trustedkey",		CONFIG_TRUSTEDKEY },
 	{ "ttl",		CONFIG_TTL },
+	{ "authprov",		CONFIG_AUTHPROV },
 	{ "",			CONFIG_UNKNOWN }
 };
 
@@ -562,6 +565,8 @@
 	(void) sprintf(line, "settimeofday=\"%s\"", set_tod_using);
 	set_sys_var(line, strlen(line)+1, RO);
 
+	init_auth(key_file_name); /* moved here so we have key_file_name */
+
 	/*
 	 * Initialize the loop.
 	 */
@@ -1036,7 +1041,7 @@
 
 		    case CONFIG_KEYS:
 			if (ntokens >= 2) {
-				getauthkeys(tokens[1]);
+				setauthkeyfile(tokens[1]);
 			}
 			break;
 
@@ -1861,7 +1866,46 @@
 			}
 			break;
 
+		   case CONFIG_AUTHPROV: {
+			keyid_t bounds[2];
+			int ap_argc = 0;
+			const char **ap_argv = NULL;
+
+			bounds[0] = 0;
+			bounds[1] = NTP_MAXKEY;
+
+			if (ntokens < 2) {
+				msyslog(LOG_ERR,
+					"authprov no library specified");
+				errflg = 1;
+				break;
+			}
+			if (ntokens > 2) {
+				/* Default bounds are used if argument is omitted or argument is a dash */
+				if (strcmp(tokens[2], "-") != 0 &&
+				    sscanf(tokens[2], "%u:%u", &bounds[0], &bounds[1]) != 2) {
+					msyslog(LOG_ERR,
+						"invalid bounds pair %s",
+						tokens[2]);
+					errflg = 1;
+					break;
+				}
+			}
+			if (ntokens > 3) {
+				ap_argc = ntokens - 3;
+				ap_argv = (const char **)&tokens[3];
+			}
+			if (!authprov_load(tokens[1], bounds, ap_argc, ap_argv)) {
+				msyslog(LOG_ERR,
+					"failed to load authentication provider '%s'",
+					tokens[1]);
+				errflg = 1;
+				break;
+			}
+			break;
+		   }
 		}
+		
 	}
 	if (fp[0])
 		(void)fclose(fp[0]);
@@ -1871,6 +1915,7 @@
 		free_netinfo_config(config_netinfo);
 #endif /* HAVE_NETINFO */
 
+
 #if !defined(VMS) && !defined(SYS_VXWORKS)
 	/* find a keyid */
 	if (info_auth_keyid == 0)
@@ -1883,15 +1928,14 @@
 		char rankey[9];
 		int j;
 
-		for (i = 0; i < 8; i++)
+		for (i = 0; i < 8; i++) {
 			for (j = 1; j < 100; ++j) {
 				rankey[i] = (char) (ntp_random() & 0xff);
 				if (rankey[i] != 0) break;
 			}
+		}
 		rankey[8] = 0;
-		authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
-		authtrust(req_keyid, 1);
-		if (!authhavekey(req_keyid)) {
+		if (!authsetkey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey, 8, 1)) {
 			msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
 			/* HMS: Should this be fatal? */
 		}
diff -Nur ntp-4.2.4p8.orig/ntpd/ntp_crypto.c ntp-4.2.4p8.new/ntpd/ntp_crypto.c
--- ntp-4.2.4p8.orig/ntpd/ntp_crypto.c	2009-05-18 13:51:17.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/ntp_crypto.c	2011-11-10 18:57:55.664491008 +0530
@@ -14,6 +14,7 @@
 
 #include "ntpd.h"
 #include "ntp_stdlib.h"
+#include "ntp_authprov.h"
 #include "ntp_unixtime.h"
 #include "ntp_string.h"
 #include <ntp_random.h>
@@ -226,8 +227,7 @@
 	memcpy(&keyid, dgst, 4);
 	keyid = ntohl(keyid);
 	if (lifetime != 0) {
-		MD5auth_setkey(keyno, dgst, len);
-		authtrust(keyno, lifetime);
+		authsetkey(keyno, KEY_TYPE_MD5, dgst, len, lifetime);
 	}
 #ifdef DEBUG
 	if (debug > 1)
@@ -282,15 +282,9 @@
 
 	/*
 	 * Generate an initial key ID which is unique and greater than
-	 * NTP_MAXKEY.
+	 * within the configured key ID bounds for autokey.
 	 */
-	while (1) {
-		keyid = (ntp_random() + NTP_MAXKEY + 1) & ((1 <<
-		    sizeof(keyid_t)) - 1);
-		if (authhavekey(keyid))
-			continue;
-		break;
-	}
+	(void) authprov_genkeyid(AUTOKEY_AUTHPROV_BE, &keyid);
 
 	/*
 	 * Generate up to NTP_MAXSESSION session keys. Stop if the
@@ -311,7 +305,7 @@
 		keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
 		    cookie, lifetime);
 		lifetime -= mpoll;
-		if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
+		if (auth_havekey(keyid) || !autokey_iskeyid(keyid) ||
 		    lifetime <= mpoll)
 			break;
 	}
@@ -4181,6 +4175,7 @@
 		leap_file = emalloc(strlen(cp) + 1);
 		strcpy(leap_file, cp);
 		break;
+
 	}
 	crypto_flags |= CRYPTO_FLAG_ENAB;
 }
diff -Nur ntp-4.2.4p8.orig/ntpd/ntp_peer.c ntp-4.2.4p8.new/ntpd/ntp_peer.c
--- ntp-4.2.4p8.orig/ntpd/ntp_peer.c	2008-08-10 16:32:40.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/ntp_peer.c	2011-11-10 18:57:55.665491007 +0530
@@ -10,6 +10,7 @@
 
 #include "ntpd.h"
 #include "ntp_stdlib.h"
+#include "ntp_authprov.h"
 #include <ntp_random.h>
 #ifdef OPENSSL
 #include "openssl/rand.h"
@@ -800,7 +801,7 @@
 	}
 	if (key != 0)
 		peer->flags |= FLAG_AUTHENABLE;
-	if (key > NTP_MAXKEY)
+	if (autokey_iskeyid(key))
 		peer->flags |= FLAG_SKEY;
 	peer->cast_flags = cast_flags;
 	peer->ttl = (u_char)ttl;
diff -Nur ntp-4.2.4p8.orig/ntpd/ntp_proto.c ntp-4.2.4p8.new/ntpd/ntp_proto.c
--- ntp-4.2.4p8.orig/ntpd/ntp_proto.c	2006-12-28 17:33:32.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/ntp_proto.c	2011-11-10 18:57:55.667491005 +0530
@@ -13,6 +13,7 @@
 #include "ntp_unixtime.h"
 #include "ntp_control.h"
 #include "ntp_string.h"
+#include "ntp_authprov.h"
 
 #include <stdio.h>
 
@@ -562,7 +563,7 @@
 		 * and install in the key cache. Use the socket
 		 * broadcast or unicast address as appropriate.
 		 */
-		if (skeyid > NTP_MAXKEY) {
+		if (autokey_iskeyid(skeyid)) {
 		
 			/*
 			 * More on the autokey dance (AKD). A cookie is
@@ -653,8 +654,7 @@
 			is_authentic = AUTH_OK;
 		}
 #ifdef OPENSSL
-		if (skeyid > NTP_MAXKEY)
-			authtrust(skeyid, 0);
+		autokey_untrust(skeyid);
 #endif /* OPENSSL */
 #ifdef DEBUG
 		if (debug)
@@ -819,7 +819,7 @@
 			    NULL)
 				return;		/* system error */
 #ifdef OPENSSL
-			if (skeyid > NTP_MAXKEY)
+			if (autokey_iskeyid(skeyid))
 				crypto_recv(peer, rbufp);
 #endif /* OPENSSL */
 			return;			/* hooray */
@@ -834,7 +834,7 @@
 			 * If a two-way exchange is not possible,
 			 * neither is Autokey.
 			 */
-			if (skeyid > NTP_MAXKEY) {
+			if (autokey_iskeyid(skeyid)) {
 				msyslog(LOG_INFO,
 				    "receive: autokey requires two-way communication");
 				return;		/* no autokey */
@@ -2725,7 +2725,7 @@
 			session_key(&peer->dstadr->sin, &peer->srcadr,
 			    xkeyid, 0, 2);
 		} else if (peer->flash & TEST9) {
-			authtrust(xkeyid, 0);
+			autokey_untrust(xkeyid);
 			return;
 		}
 	} 
@@ -2750,8 +2750,7 @@
 	}
 	sendlen += authlen;
 #ifdef OPENSSL
-	if (xkeyid > NTP_MAXKEY)
-		authtrust(xkeyid, 0);
+	autokey_untrust(xkeyid);
 #endif /* OPENSSL */
 	get_systime(&xmt_tx);
 	if (sendlen > sizeof(xpkt)) {
@@ -2938,7 +2937,7 @@
 	 * source-destination-key ID combination.
 	 */
 #ifdef OPENSSL
-	if (xkeyid > NTP_MAXKEY) {
+	if (autokey_iskeyid(xkeyid)) {
 		keyid_t cookie;
 
 		/*
@@ -2973,8 +2972,7 @@
 	authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
 	sendlen += authlen;
 #ifdef OPENSSL
-	if (xkeyid > NTP_MAXKEY)
-		authtrust(xkeyid, 0);
+	autokey_untrust(xkeyid);
 #endif /* OPENSSL */
 	get_systime(&xmt_tx);
 	if (sendlen > sizeof(xpkt)) {
@@ -3019,7 +3017,7 @@
 
 	if (peer->keylist != NULL) {
 		for (i = 0; i <= peer->keynumber; i++)
-			authtrust(peer->keylist[i], 0);
+			autokey_untrust(peer->keylist[i]);
 		free(peer->keylist);
 		peer->keylist = NULL;
 	}
diff -Nur ntp-4.2.4p8.orig/ntpd/ntp_request.c ntp-4.2.4p8.new/ntpd/ntp_request.c
--- ntp-4.2.4p8.orig/ntpd/ntp_request.c	2009-12-08 17:25:28.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/ntp_request.c	2011-11-10 18:57:55.668491005 +0530
@@ -13,6 +13,7 @@
 #include "ntp_refclock.h"
 #include "ntp_if.h"
 #include "ntp_stdlib.h"
+#include "ntp_authprov.h"
 
 #include <stdio.h>
 #include <stddef.h>
@@ -2150,7 +2151,7 @@
 	struct req_pkt *inpkt
 	)
 {
-	rereadkeys();
+	authprov_refresh();
 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
 }
 
@@ -2220,29 +2221,11 @@
 {
 	register struct info_auth *ia;
 
-	/*
-	 * Importations from the authentication module
-	 */
-	extern u_long authnumkeys;
-	extern int authnumfreekeys;
-	extern u_long authkeylookups;
-	extern u_long authkeynotfound;
-	extern u_long authencryptions;
-	extern u_long authdecryptions;
-	extern u_long authkeyuncached;
-	extern u_long authkeyexpired;
-
 	ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt,
 					     sizeof(struct info_auth));
 
-	ia->numkeys = htonl((u_int32)authnumkeys);
-	ia->numfreekeys = htonl((u_int32)authnumfreekeys);
-	ia->keylookups = htonl((u_int32)authkeylookups);
-	ia->keynotfound = htonl((u_int32)authkeynotfound);
-	ia->encryptions = htonl((u_int32)authencryptions);
-	ia->decryptions = htonl((u_int32)authdecryptions);
-	ia->keyuncached = htonl((u_int32)authkeyuncached);
-	ia->expired = htonl((u_int32)authkeyexpired);
+	(void) authprov_stats(ia);
+
 	ia->timereset = htonl((u_int32)(current_time - auth_timereset));
 	
 	(void) more_pkt();
@@ -2258,20 +2241,7 @@
 static void
 reset_auth_stats(void)
 {
-	/*
-	 * Importations from the authentication module
-	 */
-	extern u_long authkeylookups;
-	extern u_long authkeynotfound;
-	extern u_long authencryptions;
-	extern u_long authdecryptions;
-	extern u_long authkeyuncached;
-
-	authkeylookups = 0;
-	authkeynotfound = 0;
-	authencryptions = 0;
-	authdecryptions = 0;
-	authkeyuncached = 0;
+	authprov_reset_stats();
 	auth_timereset = current_time;
 }
 
diff -Nur ntp-4.2.4p8.orig/ntpd/ntp_util.c ntp-4.2.4p8.new/ntpd/ntp_util.c
--- ntp-4.2.4p8.orig/ntpd/ntp_util.c	2006-12-28 17:33:34.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/ntp_util.c	2011-11-10 18:57:55.669491005 +0530
@@ -12,6 +12,7 @@
 #include "ntp_filegen.h"
 #include "ntp_if.h"
 #include "ntp_stdlib.h"
+#include "ntp_authprov.h"
 
 #include <stdio.h>
 #include <ctype.h>
@@ -46,7 +47,7 @@
 /*
  * Name of the keys file
  */
-static	char *key_file_name;
+char *key_file_name;
 
 /*
  * The name of the drift_comp file and the temporary.
@@ -692,11 +693,12 @@
  * getauthkeys - read the authentication keys from the specified file
  */
 void
-getauthkeys(
+setauthkeyfile(
 	const char *keyfile
 	)
 {
 	int len;
+	struct authkey_be *be = NULL;
 
 	len = strlen(keyfile);
 	if (len == 0)
@@ -726,20 +728,15 @@
 	}
 #endif /* SYS_WINNT */
 
-	authreadkeys(key_file_name);
-}
-
+	be = authprov_select(1);
+	if (be == NULL) {
+		return;
+	}
 
-/*
- * rereadkeys - read the authentication key file over again.
- */
-void
-rereadkeys(void)
-{
-	if (key_file_name != 0)
-	    authreadkeys(key_file_name);
+	keyfile_authprov_setkeyfile(be, key_file_name);
 }
 
+
 /*
  * sock_hash - hash an sockaddr_storage structure
  */
diff -Nur ntp-4.2.4p8.orig/ntpd/ntpd.c ntp-4.2.4p8.new/ntpd/ntpd.c
--- ntp-4.2.4p8.orig/ntpd/ntpd.c	2009-12-08 17:25:58.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/ntpd.c	2011-11-10 18:57:55.670491005 +0530
@@ -10,6 +10,7 @@
 #include "ntpd.h"
 #include "ntp_io.h"
 #include "ntp_stdlib.h"
+#include "ntp_authprov.h"
 #include <ntp_random.h>
 
 #ifdef SIM
@@ -808,7 +809,6 @@
 	 *
 	 * Exactly what command-line options are we expecting here?
 	 */
-	init_auth();
 	init_util();
 	init_restrict();
 	init_mon();
@@ -1142,6 +1142,7 @@
 
 	msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
 	write_stats();
+	authprov_cleanup();
 #ifdef HAVE_DNSREGISTRATION
 	if (mdns != NULL)
 	DNSServiceRefDeallocate(mdns);
diff -Nur ntp-4.2.4p8.orig/ntpd/ntpsim.c ntp-4.2.4p8.new/ntpd/ntpsim.c
--- ntp-4.2.4p8.orig/ntpd/ntpsim.c	2006-12-28 17:33:41.000000000 +0530
+++ ntp-4.2.4p8.new/ntpd/ntpsim.c	2011-11-10 18:57:55.671491005 +0530
@@ -60,7 +60,7 @@
 	 * Initialize ntp variables
 	 */
 	initializing = 1;
-        init_auth();
+        init_auth(NULL);
         init_util();
         init_restrict();
         init_mon();
diff -Nur ntp-4.2.4p8.orig/ntpdate/ntpdate.c ntp-4.2.4p8.new/ntpdate/ntpdate.c
--- ntp-4.2.4p8.orig/ntpdate/ntpdate.c	2008-03-22 16:33:22.000000000 +0530
+++ ntp-4.2.4p8.new/ntpdate/ntpdate.c	2011-11-10 18:57:55.671491005 +0530
@@ -534,8 +534,7 @@
 	 * Initialize the time of day routines and the I/O subsystem
 	 */
 	if (sys_authenticate) {
-		init_auth();
-		if (!authreadkeys(key_file)) {
+		if (!init_auth(key_file)) {
 			msyslog(LOG_ERR, "no key file <%s>, exiting", key_file);
 			exit(1);
 		}
diff -Nur ntp-4.2.4p8.orig/ntpdate/ntptimeset.c ntp-4.2.4p8.new/ntpdate/ntptimeset.c
--- ntp-4.2.4p8.orig/ntpdate/ntptimeset.c	2006-06-07 01:47:00.000000000 +0530
+++ ntp-4.2.4p8.new/ntpdate/ntptimeset.c	2011-11-10 18:57:55.672491005 +0530
@@ -580,7 +580,6 @@
 	 * Initialize the time of day routines and the I/O subsystem
 	 */
 	if (sys_authenticate) {
-		init_auth();
 #ifdef SYS_WINNT
 		if (!key_file) key_file = KEYFILE;
 		if (!ExpandEnvironmentStrings(key_file, key_file_storage, MAX_PATH))
@@ -592,7 +591,7 @@
 		}
 #endif /* SYS_WINNT */
 
-		if (!authreadkeys(key_file)) {
+		if (!init_auth(key_file)) {
 			msyslog(LOG_ERR, "no key file, exiting");
 			exit(1);
 		}
diff -Nur ntp-4.2.4p8.orig/ntpdc/ntpdc.c ntp-4.2.4p8.new/ntpdc/ntpdc.c
--- ntp-4.2.4p8.orig/ntpdc/ntpdc.c	2009-12-08 17:25:59.000000000 +0530
+++ ntp-4.2.4p8.new/ntpdc/ntpdc.c	2011-11-10 18:57:55.673491005 +0530
@@ -321,6 +321,8 @@
 
 	progname = argv[0];
 
+	init_auth(NULL);
+
 	{
 		int optct = optionProcess(&ntpdcOptions, argc, argv);
 		argc -= optct;
@@ -967,8 +969,7 @@
 				return (1);
 			}
 		}
-		authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass);
-		authtrust(info_auth_keyid, 1);
+		authsetkey(info_auth_keyid, info_auth_keytype, (const u_char *)pass, strlen(pass), 1);
 		qpkt.auth_seq = AUTH_SEQ(1, 0);
 		qpktail->keyid = htonl(info_auth_keyid);
 		get_systime(&ts);
@@ -1836,17 +1837,16 @@
 		}
 	}
 	if (!interactive) {
-		authusekey(info_auth_keyid, info_auth_keytype,
-			   (u_char *)pcmd->argval[0].string);
-		authtrust(info_auth_keyid, 1);
+		authsetkey(info_auth_keyid, info_auth_keytype,
+			   (u_char *)pcmd->argval[0].string,
+			   strlen(pcmd->argval[0].string), 1);
 	} else {
 		pass = getpass("MD5 Password: ");
 		if (*pass == '\0')
 		    (void) fprintf(fp, "Password unchanged\n");
 		else {
-		    authusekey(info_auth_keyid, info_auth_keytype,
-			       (u_char *)pass);
-		    authtrust(info_auth_keyid, 1);
+		    authsetkey(info_auth_keyid, info_auth_keytype,
+			       (u_char *)pass, strlen(pass), 1);
 		}
 	}
 }
diff -Nur ntp-4.2.4p8.orig/ntpq/ntpq.c ntp-4.2.4p8.new/ntpq/ntpq.c
--- ntp-4.2.4p8.orig/ntpq/ntpq.c	2009-12-08 17:25:59.000000000 +0530
+++ ntp-4.2.4p8.new/ntpq/ntpq.c	2011-11-10 18:57:55.674491005 +0530
@@ -1252,8 +1252,7 @@
 				return (1);
 			}
 		}
-		authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass);
-		authtrust(info_auth_keyid, 1);
+		authsetkey(info_auth_keyid, info_auth_keytype, (const u_char *)pass, strlen(pass), 1);
 
 		/*
 		 * Stick the keyid in the packet where
@@ -2351,8 +2350,7 @@
 	if (*pass == '\0')
 	    (void) fprintf(fp, "Password unchanged\n");
 	else {
-	    authusekey(info_auth_keyid, info_auth_keytype, (u_char *)pass);
-	    authtrust(info_auth_keyid, 1);
+	    authsetkey(info_auth_keyid, info_auth_keytype, (u_char *)pass, strlen(pass), 1);
 	}
 }
 
