diff --git a/build/package/rpm/lightwave.spec b/build/package/rpm/lightwave.spec
index d0949c8..262d77a 100644
--- a/build/package/rpm/lightwave.spec
+++ b/build/package/rpm/lightwave.spec
@@ -1075,6 +1075,7 @@ Lightwave POST service
%{_lib64dir}/libgssapi_ntlm.so*
%{_lib64dir}/libgssapi_srp.so*
%{_lib64dir}/libgssapi_unix.so*
+%{_lib64dir}/libgssapi_unix_creds.so*
%{_lib64dir}/libvmdnsclient.so*
%{_lib64dir}/libcfgutils.so*
%{_lib64dir}/libidm.so*
@@ -1164,6 +1165,7 @@ Lightwave POST service
%{_includedir}/vmdns.h
%{_includedir}/vmdnstypes.h
%{_includedir}/vmmetrics.h
+%{_includedir}/gssapi_creds_plugin.h
%{_lib64dir}/libcdcjni.a
%{_lib64dir}/libcdcjni.la
diff --git a/configure.ac b/configure.ac
index 374c252..72a5510 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1597,6 +1597,9 @@ AC_CONFIG_FILES([Makefile
vmdir/thirdparty/heimdal/ntlm/Makefile
vmdir/thirdparty/csrp/Makefile
vmdir/gssapi-plugins/Makefile
+ vmdir/gssapi-plugins/include/Makefile
+ vmdir/gssapi-plugins/include/public/Makefile
+ vmdir/gssapi-plugins/common/Makefile
vmdir/gssapi-plugins/ntlm/Makefile
vmdir/gssapi-plugins/srp/Makefile
vmdir/gssapi-plugins/unix/Makefile
diff --git a/vmdir/gssapi-plugins/Makefile.am b/vmdir/gssapi-plugins/Makefile.am
index 577f179..1d39035 100644
--- a/vmdir/gssapi-plugins/Makefile.am
+++ b/vmdir/gssapi-plugins/Makefile.am
@@ -1,4 +1,6 @@
SUBDIRS = \
+ include \
+ common \
ntlm \
srp
diff --git a/vmdir/gssapi-plugins/common/Makefile.am b/vmdir/gssapi-plugins/common/Makefile.am
new file mode 100644
index 0000000..2631b62
--- /dev/null
+++ b/vmdir/gssapi-plugins/common/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LTLIBRARIES = libgssapi_common.la
+
+libgssapi_common_la_CPPFLAGS = \
+ -I$(top_srcdir)/vmdir/gssapi-plugins/include/public
+
+libgssapi_common_la_SOURCES = \
+ creds_plugin.c
+
+libgssapi_common_la_LIBADD = \
+ -ldl
+
+libgssapi_common_la_LDFLAGS = \
+ -static
diff --git a/vmdir/gssapi-plugins/common/creds_plugin.c b/vmdir/gssapi-plugins/common/creds_plugin.c
new file mode 100644
index 0000000..edd6cad
--- /dev/null
+++ b/vmdir/gssapi-plugins/common/creds_plugin.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright © 2012-2015 VMware, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the “License”); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an “AS IS” BASIS, without
+ * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "includes.h"
+
+//free plugin struct
+static
+void
+free_creds_plugin(
+ PCREDS_PLUGIN pPlugin
+ )
+{
+ if(!pPlugin)
+ {
+ return;
+ }
+ if(pPlugin->pHandle)
+ {
+ dlclose(pPlugin->pHandle);
+ }
+ free(pPlugin);
+}
+
+/*
+ Load credentials plugin and initialize interface.
+*/
+static
+int
+load_creds_plugin(
+ const char *creds_plugin,
+ PCREDS_PLUGIN *ppPlugin
+ )
+{
+ int sts = 0;
+ char *error_str = NULL;
+ PCREDS_PLUGIN pPlugin = NULL;
+
+ if(!creds_plugin || !ppPlugin)
+ {
+ sts = EINVAL;
+ goto error;
+ }
+
+ srp_debug_printf("load_creds_plugin : %s\n", creds_plugin);
+
+ pPlugin = (PCREDS_PLUGIN)malloc(sizeof(CREDS_PLUGIN));
+ if(!pPlugin)
+ {
+ sts = ENOMEM;
+ goto error;
+ }
+
+ //clear error
+ dlerror();
+
+ pPlugin->pHandle = dlopen(creds_plugin, RTLD_NOW);
+ if(!pPlugin->pHandle)
+ {
+ sts = ENOENT;
+ goto error;
+ }
+
+ pPlugin->pfnLoad = dlsym(pPlugin->pHandle, CREDS_PLUGIN_LOAD_INTERFACE);
+ if(!pPlugin->pfnLoad)
+ {
+ sts = ENOSYS;
+ goto error;
+ }
+
+ sts = pPlugin->pfnLoad(&pPlugin->pInterface);
+ if(sts)
+ {
+ goto error;
+ }
+
+ *ppPlugin = pPlugin;
+
+cleanup:
+ return sts;
+
+error:
+ srp_debug_printf("creds plugin error: %d\n", sts);
+
+ if(ppPlugin)
+ {
+ *ppPlugin = NULL;
+ }
+ free_creds_plugin(pPlugin);
+
+ error_str = dlerror();
+ if(error_str)
+ {
+ srp_debug_printf("creds plugin load: %s\n", error_str);
+ }
+ goto cleanup;
+}
+
+int
+get_creds_plugin_for_type(
+ int plugin_type,
+ const char **pcreds_plugin
+ )
+{
+ int sts = 0;
+ const char *creds_plugin = NULL;
+ #define ACCESS_TYPES 2//privileged and non privileged
+ const int PRIVILEGED = 0;
+ const int NON_PRIVILEGED = 1;
+ int access_type = PRIVILEGED;
+ struct stPluginTable
+ {
+ const char *plugin_override_env;
+ const char *default_plugin_name;
+ }
+ all_plugins_array[][ACCESS_TYPES] =
+ {
+ //privileged access path
+ {
+ {GSSAPI_UNIX_CREDS_OVERRIDE, GSSAPI_UNIX_CREDS_DEFAULT_SO},
+ {GSSAPI_SRP_CREDS_OVERRIDE, GSSAPI_SRP_CREDS_DEFAULT_SO}
+ },
+ //non privileged access path
+ {
+ {GSSAPI_UNIX_PRIVSEP_CREDS_OVERRIDE,
+ GSSAPI_UNIX_PRIVSEP_CREDS_DEFAULT_SO},
+ {GSSAPI_SRP_PRIVSEP_CREDS_OVERRIDE,
+ GSSAPI_SRP_PRIVSEP_CREDS_DEFAULT_SO}
+ }
+ };
+ struct stPluginTable *plugins_array = NULL;
+
+ if(!pcreds_plugin ||
+ (plugin_type <= PLUGIN_TYPE_MIN || plugin_type >= PLUGIN_TYPE_MAX))
+ {
+ sts = EINVAL;
+ goto error;
+ }
+
+ //determine which access type
+ access_type = getuid() == 0 ? PRIVILEGED : NON_PRIVILEGED;
+ plugins_array = all_plugins_array[access_type];
+
+ srp_debug_printf(
+ "creds plugin type: %s\n",
+ access_type == PRIVILEGED ? "Privileged" : "Non Privileged");
+
+ //If there is an override, use it
+ creds_plugin = getenv(plugins_array[plugin_type].plugin_override_env);
+
+ //if not, use the default.
+ if(!creds_plugin)
+ {
+ creds_plugin = plugins_array[plugin_type].default_plugin_name;
+ }
+
+ if(!creds_plugin)
+ {
+ sts = EINVAL;
+ goto error;
+ }
+
+ *pcreds_plugin = creds_plugin;
+
+cleanup:
+ return sts;
+
+error:
+ if(pcreds_plugin)
+ {
+ *pcreds_plugin = NULL;
+ }
+ goto cleanup;
+}
+
+/*
+ Do implementation specific creds lookup and return
+ salt and srp v and s values as applicable.
+*/
+int
+get_hashed_creds(
+ int plugin_type,
+ const char *username,
+ char **ret_salt,
+ unsigned char **ret_bytes_s,
+ int *ret_len_s,
+ unsigned char **ret_bytes_v,
+ int *ret_len_v
+ )
+{
+ int sts = 0;
+ char *username_salt = NULL;
+ PCREDS_PLUGIN pPlugin = NULL;
+ PCREDS_PLUGIN_INTERFACE pInterface = NULL;
+ unsigned char *bytes_s = NULL;
+ int len_s = 0;
+ unsigned char *bytes_v = NULL;
+ int len_v = 0;
+ const char *creds_plugin = NULL;
+
+ if(!username ||
+ !ret_salt ||
+ !ret_bytes_s ||
+ !ret_len_s ||
+ !ret_bytes_v ||
+ !ret_len_v)
+ {
+ sts = -1;
+ goto error;
+ }
+
+ sts = get_creds_plugin_for_type(plugin_type, &creds_plugin);
+ if(sts)
+ {
+ goto error;
+ }
+
+ sts = load_creds_plugin(creds_plugin, &pPlugin);
+ if(sts)
+ {
+ goto error;
+ }
+
+ pInterface = pPlugin->pInterface;
+
+ if(!pInterface->pfnGetHashedCreds)
+ {
+ sts = -1;
+ goto error;
+ }
+
+ sts = pInterface->pfnGetHashedCreds(
+ plugin_type,
+ username,
+ &username_salt,
+ &bytes_s,
+ &len_s,
+ &bytes_v,
+ &len_v);
+ if(sts)
+ {
+ goto error;
+ }
+
+ *ret_salt = username_salt;
+ *ret_bytes_s = bytes_s;
+ *ret_len_s = len_s;
+ *ret_bytes_v = bytes_v;
+ *ret_len_v = len_v;
+
+cleanup:
+ if(pPlugin)
+ {
+ free_creds_plugin(pPlugin);
+ }
+ return sts;
+error:
+ if(username_salt)
+ {
+ free(username_salt);
+ }
+ goto cleanup;
+}
diff --git a/vmdir/gssapi-plugins/common/defines.h b/vmdir/gssapi-plugins/common/defines.h
new file mode 100644
index 0000000..2ce12a3
--- /dev/null
+++ b/vmdir/gssapi-plugins/common/defines.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright © 2012-2015 VMware, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the “License”); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an “AS IS” BASIS, without
+ * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+#pragma once
+
diff --git a/vmdir/gssapi-plugins/common/includes.h b/vmdir/gssapi-plugins/common/includes.h
new file mode 100644
index 0000000..abf4151
--- /dev/null
+++ b/vmdir/gssapi-plugins/common/includes.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2012-2015 VMware, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the “License”); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an “AS IS” BASIS, without
+ * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+#pragma once
+
+#include "stdio.h"
+#include <stdlib.h>
+#include <errno.h>
+#include <dlfcn.h>
+
+#include "defines.h"
+#include <gssapi_creds_plugin.h>
diff --git a/vmdir/gssapi-plugins/include/Makefile.am b/vmdir/gssapi-plugins/include/Makefile.am
new file mode 100644
index 0000000..5248dac
--- /dev/null
+++ b/vmdir/gssapi-plugins/include/Makefile.am
@@ -0,0 +1,3 @@
+
+SUBDIRS = public
+
diff --git a/vmdir/gssapi-plugins/include/public/Makefile.am b/vmdir/gssapi-plugins/include/public/Makefile.am
new file mode 100644
index 0000000..70737d8
--- /dev/null
+++ b/vmdir/gssapi-plugins/include/public/Makefile.am
@@ -0,0 +1,2 @@
+vmwincludedir=$(includedir)
+vmwinclude_HEADERS=gssapi_creds_plugin.h
diff --git a/vmdir/gssapi-plugins/include/public/gssapi_creds_plugin.h b/vmdir/gssapi-plugins/include/public/gssapi_creds_plugin.h
new file mode 100644
index 0000000..bb36037
--- /dev/null
+++ b/vmdir/gssapi-plugins/include/public/gssapi_creds_plugin.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2017 VMware, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the “License”); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an “AS IS” BASIS, without
+ * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+#pragma once
+
+//default name for unix creds lib
+#define GSSAPI_UNIX_CREDS_DEFAULT_SO "libgssapi_unix_creds.so"
+
+//env variable to override default unix creds lib
+#define GSSAPI_UNIX_CREDS_OVERRIDE "GSSAPI_UNIX_CREDS_OVERRIDE"
+
+//default name for unix creds lib that will provide privilege separation
+//for processes that use gssapi_unix without privileges for shadow apis
+#define GSSAPI_UNIX_PRIVSEP_CREDS_DEFAULT_SO "libgssapi_unix_privsep_creds.so"
+
+//env variable to override default unix privilege separation creds lib
+#define GSSAPI_UNIX_PRIVSEP_CREDS_OVERRIDE "GSSAPI_UNIX_PRIVSEP_CREDS_OVERRIDE"
+
+//default name for srp creds lib
+#define GSSAPI_SRP_CREDS_DEFAULT_SO "libgssapi_srp_creds.so"
+
+//env variable to override default srp creds lib
+#define GSSAPI_SRP_CREDS_OVERRIDE "GSSAPI_SRP_CREDS_OVERRIDE"
+
+//default name for srp creds lib that will provide privilege separation
+//for processes that use gssapi_srp without privileges for shadow apis
+#define GSSAPI_SRP_PRIVSEP_CREDS_DEFAULT_SO "libgssapi_unix_privsep_creds.so"
+
+//env variable to override default srp rivilege separation creds lib
+#define GSSAPI_SRP_PRIVSEP_CREDS_OVERRIDE "GSSAPI_SRP_PRIVSEP_CREDS_OVERRIDE"
+
+//supported types. used to lookup creds lib
+typedef enum
+{
+ PLUGIN_TYPE_MIN = -1,
+ PLUGIN_TYPE_UNIX,
+ PLUGIN_TYPE_SRP,
+ //Add new types before PLUGIN_TYPE_MAX
+ PLUGIN_TYPE_MAX
+}GSSAPI_PLUGIN_TYPE;
+
+//creds lib implements this function.
+//takes in plugin type, username,
+//returns salt and srp s and v values.
+typedef
+int
+(*PFN_GET_HASHED_CREDS)(
+ int plugin_type,
+ const char *user_name,
+ char **ret_salt,
+ unsigned char **ret_bytes_s,
+ int *ret_len_s,
+ unsigned char **ret_bytes_v,
+ int *ret_len_v
+ );
+
+typedef struct _CREDS_PLUGIN_INTERFACE_
+{
+ PFN_GET_HASHED_CREDS pfnGetHashedCreds;
+}CREDS_PLUGIN_INTERFACE, *PCREDS_PLUGIN_INTERFACE;
+
+//Function name defs
+#define CREDS_PLUGIN_LOAD_INTERFACE "creds_plugin_load_interface"
+#define CREDS_PLUGIN_UNLOAD_INTERFACE "creds_plugin_unload_interface"
+
+//load
+typedef int
+(*PFN_CREDS_PLUGIN_LOAD_INTERFACE)(
+ PCREDS_PLUGIN_INTERFACE *ppCredsInterface
+ );
+
+//unload
+typedef int
+(*PFN_CREDS_PLUGIN_UNLOAD_INTERFACE)(
+ PCREDS_PLUGIN_INTERFACE pCredsInterface
+ );
+
+typedef struct _CREDS_PLUGIN_
+{
+ //dlopen handle
+ void *pHandle;
+
+ //Mandatory entry point
+ PFN_CREDS_PLUGIN_LOAD_INTERFACE pfnLoad;
+ //Optional unload
+ PFN_CREDS_PLUGIN_UNLOAD_INTERFACE pfnUnload;
+
+ //interface fn table returned by load.
+ PCREDS_PLUGIN_INTERFACE pInterface;
+}CREDS_PLUGIN, *PCREDS_PLUGIN;
+
+
+
+int
+get_hashed_creds(
+ int nPluginType,
+ const char *username,
+ char **ret_salt,
+ unsigned char **ret_bytes_s,
+ int *ret_len_s,
+ unsigned char **ret_bytes_v,
+ int *ret_len_v
+ );
diff --git a/vmdir/gssapi-plugins/unix/Makefile.am b/vmdir/gssapi-plugins/unix/Makefile.am
index a70c240..778876c 100644
--- a/vmdir/gssapi-plugins/unix/Makefile.am
+++ b/vmdir/gssapi-plugins/unix/Makefile.am
@@ -13,12 +13,36 @@ unix_srp_CPPFLAGS = \
unix_srp_LDADD = \
$(top_builddir)/vmdir/thirdparty/csrp/libcsrp.la \
- $(top_builddir)/vmdir/thirdparty/csrp/libcsrp.la \
@CRYPT_LIBS@ \
@OPENSSL_LDFLAGS@ \
@CRYPTO_LIBS@
-lib_LTLIBRARIES = libgssapi_unix.la
+lib_LTLIBRARIES = libgssapi_unix.la libgssapi_unix_creds.la
+
+libgssapi_unix_creds_la_CPPFLAGS = \
+ -D_MIT_KRB5_1_11 \
+ -D_MIT_KRB5_1_12 \
+ -I. \
+ -I$(top_srcdir)/vmdir/gssapi-plugins/include/public \
+ -I$(top_srcdir)/vmdir/thirdparty \
+ @OPENSSL_INCLUDES@ \
+ @LW_INCLUDES@
+
+libgssapi_unix_creds_la_SOURCES = \
+ unix_creds_plugin.c \
+ unix_crypt.c
+
+libgssapi_unix_creds_la_LIBADD = \
+ $(top_builddir)/vmdir/client/libvmdirclient.la \
+ $(top_builddir)/vmdir/thirdparty/csrp/libcsrp.la \
+ $(top_builddir)/vmdir/client/libvmdirclient_la-srp_verifier_cstub.lo \
+ @OPENSSL_LDFLAGS@ \
+ @CRYPT_LIBS@ \
+ @CRYPTO_LIBS@ \
+ @PTHREAD_LIBS@
+
+libgssapi_unix_creds_la_LDFLAGS = \
+ @LW_LDFLAGS@
libgssapi_unix_la_CPPFLAGS = \
-D_MIT_KRB5_1_11 \
@@ -30,6 +54,7 @@ libgssapi_unix_la_CPPFLAGS = \
-I$(top_srcdir)/vmdir/include/public \
-I$(top_srcdir)/vmdir/thirdparty \
-I$(top_builddir)/vmdir/client \
+ -I$(top_srcdir)/vmdir/gssapi-plugins/include/public \
@OPENSSL_INCLUDES@ \
@LW_INCLUDES@
@@ -48,10 +73,10 @@ libgssapi_unix_la_SOURCES = \
unix_unwrap_iov.c \
unix_util.c \
unixregutils.c \
- unixreg.c \
- unix_crypt.c
+ unixreg.c
libgssapi_unix_la_LIBADD = \
+ $(top_builddir)/vmdir/gssapi-plugins/common/libgssapi_common.la \
$(top_builddir)/vmdir/client/libvmdirclient.la \
$(top_builddir)/vmdir/thirdparty/csrp/libcsrp.la \
$(top_builddir)/vmdir/client/libvmdirclient_la-srp_verifier_cstub.lo \
diff --git a/vmdir/gssapi-plugins/unix/gssapiP_unix.h b/vmdir/gssapi-plugins/unix/gssapiP_unix.h
index 41a69f6..7dd9da9 100644
--- a/vmdir/gssapi-plugins/unix/gssapiP_unix.h
+++ b/vmdir/gssapi-plugins/unix/gssapiP_unix.h
@@ -165,10 +165,13 @@ typedef struct {
#endif
HMAC_CTX hmac_ctx;
char *unix_username; /* UNIX username */
- char *username_hash; /* user shadow pwd file hash */
char *upn_name; /* Kerberos UPN Name */
unsigned char *srp_session_key;
int srp_session_key_len;
+ unsigned char *bytes_v;
+ int len_v;
+ unsigned char *bytes_s;
+ int len_s;
} srp_gss_ctx_id_rec, *srp_gss_ctx_id_t;
diff --git a/vmdir/gssapi-plugins/unix/unix_accept_sec_ctx.c b/vmdir/gssapi-plugins/unix/unix_accept_sec_ctx.c
index 2df7ce2..a6f8b80 100644
--- a/vmdir/gssapi-plugins/unix/unix_accept_sec_ctx.c
+++ b/vmdir/gssapi-plugins/unix/unix_accept_sec_ctx.c
@@ -33,9 +33,9 @@
#include <vmdirdefines.h>
#include "includes.h"
-#include "unix_crypt.h"
#include <config.h>
+#include <gssapi_creds_plugin.h>
#ifdef _WIN32
@@ -176,55 +176,6 @@ error:
}
-/* Create the temporary SRP secret using username shadow pwd entry */
-static int
-_srpVerifierInit(
- char *username,
- char *password,
- unsigned char **ret_bytes_s,
- int *ret_len_s,
- unsigned char **ret_bytes_v,
- int *ret_len_v)
-{
- int sts = 0;
- const unsigned char *bytes_s = NULL;
- int len_s = 0;
- const unsigned char *bytes_v = NULL;
- int len_v = 0;
-
- if (!username || !password || !ret_bytes_s || !ret_bytes_v)
- {
- sts = -1;
- goto error;
- }
-
- srp_create_salted_verification_key(
- G_alg,
- G_ng_type,
- username,
- (const unsigned char *) password,
- (int) strlen(password),
- &bytes_s,
- &len_s,
- &bytes_v,
- &len_v,
- G_n_hex,
- G_g_hex);
-
- srp_print_hex(bytes_s, len_s,
- "_srpVerifierInit(accept_sec_context): bytes_s");
- srp_print_hex(bytes_v, len_v,
- "_srpVerifierInit(accept_sec_context): bytes_v");
-
- *ret_bytes_s = (unsigned char *) bytes_s;
- *ret_len_s = len_s;
-
- *ret_bytes_v = (unsigned char *) bytes_v;
- *ret_len_v = len_v;
-
-error:
- return 0;
-}
static
struct SRPVerifier *
@@ -300,6 +251,7 @@ error:
return sts;
}
+
/*
* Read SRP_AUTH_INIT token, verify version is compatible. Retrieve
* user salt value from the /etc/shadow password file, then format
@@ -328,7 +280,10 @@ _unix_gss_auth_init(
int berror = 0;
char *unix_username = NULL;
char *username_salt = NULL;
- char *username_hash = NULL;
+ unsigned char *bytes_v = NULL;
+ int len_v = 0;
+ unsigned char *bytes_s = NULL;
+ int len_s = 0;
ber_ctx.bv_val = (void *) input_token->value;
ber_ctx.bv_len = input_token->length;
@@ -392,18 +347,33 @@ _unix_gss_auth_init(
srp_debug_printf("_unix_gss_auth_init(): username=%s\n", unix_username);
/* Retrieve the salt value from the shadow password file */
- sts = get_sp_salt(unix_username, &username_salt, &username_hash);
+ //sts = get_sp_salt(unix_username, &username_salt, &username_hash);
+ //Retrieve salt value and "V" verifier value in one go
+ //This is done via a credentials provider plugin
+ sts = get_hashed_creds(
+ PLUGIN_TYPE_UNIX,
+ unix_username,
+ &username_salt,
+ &bytes_s,
+ &len_s,
+ &bytes_v,
+ &len_v);
if (sts)
{
maj = GSS_S_FAILURE;
goto error;
}
- srp_debug_printf("_unix_gss_auth_init(): salt=%s hash=%s\n",
- username_salt, username_hash);
- srp_context_handle->username_hash = username_hash;
+ srp_debug_printf("_unix_gss_auth_init(): salt=%s\n", username_salt);
srp_context_handle->unix_username = unix_username;
- username_hash = NULL;
+ srp_context_handle->bytes_v = bytes_v;
+ srp_context_handle->len_v = len_v;
+ srp_context_handle->bytes_s = bytes_s;
+ srp_context_handle->len_s = len_s;
unix_username = NULL;
+ bytes_v = NULL;
+ len_v = 0;
+ bytes_s = NULL;
+ len_s = 0;
ber_resp = ber_alloc_t(LBER_USE_DER);
if (!ber_resp)
@@ -462,6 +432,14 @@ error:
free(username_salt);
}
+ if (bytes_v)
+ {
+ free(bytes_v);
+ }
+ if (bytes_s)
+ {
+ free(bytes_s);
+ }
ber_bvfree(flatten);
ber_free(ber, 1);
ber_free(ber_resp, 1);
@@ -485,10 +463,6 @@ _unix_gss_salt_resp(
{
OM_uint32 maj = 0;
OM_uint32 min = 0;
- unsigned char *bytes_s = NULL;
- int len_s = 0;
- unsigned char *bytes_v = NULL;
- int len_v = 0;
struct berval *flatten = NULL;
BerElement *ber = NULL;
BerElement *ber_resp = NULL;
@@ -503,28 +477,10 @@ _unix_gss_salt_resp(
int len_B = 0;
int sts = 0;
- /*
- * This call creates the temporary server-side SRP secret
- *
- * bytes_s: SRP salt, publically known to client/server
- * bytes_v: SRP secret, privately known only by server
- */
- sts = _srpVerifierInit(
- srp_context_handle->unix_username,
- srp_context_handle->username_hash,
- &bytes_s,
- &len_s,
- &bytes_v,
- &len_v);
- if (sts)
- {
- maj = GSS_S_FAILURE;
- goto error;
- }
- srp_debug_printf("_unix_gss_salt_resp(): salt len=%d", len_s);
- srp_print_hex(bytes_s, len_s,
+ srp_debug_printf("_unix_gss_salt_resp(): salt len=%d", srp_context_handle->len_s);
+ srp_print_hex(srp_context_handle->bytes_s, srp_context_handle->len_s,
"_srp_gss_auth_init(accept_sec_context): bytes_s");
- srp_print_hex(bytes_v, len_v,
+ srp_print_hex(srp_context_handle->bytes_v, srp_context_handle->len_v,
"_srp_gss_auth_init(accept_sec_context): bytes_v");
@@ -567,10 +523,10 @@ _unix_gss_salt_resp(
ver = _srpServerNew(
srp_context_handle->unix_username,
- bytes_s,
- len_s,
- bytes_v,
- len_v,
+ srp_context_handle->bytes_s,
+ srp_context_handle->len_s,
+ srp_context_handle->bytes_v,
+ srp_context_handle->len_v,
ber_bytes_A->bv_val,
(int) ber_bytes_A->bv_len,
&bytes_B,
@@ -593,8 +549,8 @@ _unix_gss_salt_resp(
/* TBD: Make this a macro */
"SHA-1",
(ber_len_t) strlen("SHA-1"),
- bytes_s,
- (ber_len_t) len_s,
+ srp_context_handle->bytes_s,
+ (ber_len_t) srp_context_handle->len_s,
bytes_B,
(ber_len_t) len_B);
if (berror == -1)
@@ -664,14 +620,6 @@ error:
ber_bvfree(flatten);
ber_free(ber, 1);
ber_free(ber_resp, 1);
- if (bytes_v)
- {
- free(bytes_v);
- }
- if (bytes_s)
- {
- free(bytes_s);
- }
if (maj)
{
diff --git a/vmdir/gssapi-plugins/unix/unix_creds_plugin.c b/vmdir/gssapi-plugins/unix/unix_creds_plugin.c
new file mode 100644
index 0000000..b4a6a97
--- /dev/null
+++ b/vmdir/gssapi-plugins/unix/unix_creds_plugin.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2012-2015 VMware, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the “License”); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an “AS IS” BASIS, without
+ * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "unix_crypt.h"
+#include <gssapi_creds_plugin.h>
+
+/*
+ * plugin load
+*/
+int
+creds_plugin_load_interface(
+ PCREDS_PLUGIN_INTERFACE *ppInterface
+ )
+{
+ int sts = 0;
+ PCREDS_PLUGIN_INTERFACE pInterface = NULL;
+
+ if(!ppInterface)
+ {
+ sts = EINVAL;
+ goto error;
+ }
+
+ pInterface = (PCREDS_PLUGIN_INTERFACE)
+ malloc(sizeof(CREDS_PLUGIN_INTERFACE));
+ if(!pInterface)
+ {
+ sts = ENOMEM;
+ goto error;
+ }
+
+ pInterface->pfnGetHashedCreds = get_salt_and_v_value;
+ *ppInterface = pInterface;
+
+cleanup:
+ return sts;
+
+error:
+ if(ppInterface)
+ {
+ *ppInterface = NULL;
+ }
+ if(pInterface)
+ {
+ free(pInterface);
+ }
+ goto cleanup;
+}
diff --git a/vmdir/gssapi-plugins/unix/unix_crypt.c b/vmdir/gssapi-plugins/unix/unix_crypt.c
index 7a5d6f9..c5af2b8 100644
--- a/vmdir/gssapi-plugins/unix/unix_crypt.c
+++ b/vmdir/gssapi-plugins/unix/unix_crypt.c
@@ -28,6 +28,8 @@
#include <crypt.h>
#include <stdio.h>
+#include <csrp/srp.h>
+#include <dlfcn.h>
#define CRYPT_MD5 "$1$"
#define CRYPT_BLOWFISH_2A "$2a$"
@@ -37,25 +39,16 @@
#define CRYPT_SHA_256 "$5$"
#define CRYPT_SHA_512 "$6$"
-#ifdef _WIN32
-int get_sp_salt(const char *username,
- char **ret_salt,
- char **ret_encpwd)
-{
- /*
- * This cannot be supported on Windows, as there is no
- * /etc shadow password file. The equivalent "local provider"
- * hash is not accessable, making this functionality impossible to
- * support on Win32 platforms.
- */
- return ERROR_NOT_SUPPORTED;
-}
-#else
+static SRP_HashAlgorithm G_alg = SRP_SHA1;
+static SRP_NGType G_ng_type = SRP_NG_2048;
+static const char *G_n_hex = 0;
+static const char *G_g_hex = 0;
+
/*
* This function looks up "username" in the shadow password file, determines
* the hash algorithm type, and returns the salt and the password
* hash for that user.
- *
+ *
* Given the salt and the user password, then the hash can be created.
* The generated hash is used as an SRP password (client side), and
* the generator for the SRP secret (server side).
@@ -98,7 +91,7 @@ int get_sp_salt(const char *username,
char *encpwd = NULL;
char *sp = NULL;
int cur_uid = 0;
-
+
if (!username || !ret_salt || !ret_encpwd)
{
st = -1;
@@ -153,7 +146,7 @@ int get_sp_salt(const char *username,
ulckpwdf();
seteuid(cur_uid);
is_locked = 0;
-
+
/* CRYPT_DES hash is not supported; how to test? */
/* Determine the hash algorithn, and therefore the salt length */
@@ -212,4 +205,132 @@ error:
}
return st;
}
-#endif
+
+/* Create the temporary SRP secret using username shadow pwd entry */
+static int
+_srpVerifierInit(
+ char *username,
+ char *password,
+ unsigned char **ret_bytes_s,
+ int *ret_len_s,
+ unsigned char **ret_bytes_v,
+ int *ret_len_v)
+{
+ int sts = 0;
+ const unsigned char *bytes_s = NULL;
+ int len_s = 0;
+ const unsigned char *bytes_v = NULL;
+ int len_v = 0;
+
+ if (!username ||
+ !password ||
+ !ret_bytes_s ||
+ !ret_len_s ||
+ !ret_bytes_v ||
+ !ret_len_v)
+ {
+ sts = -1;
+ goto error;
+ }
+
+ srp_create_salted_verification_key(
+ G_alg,
+ G_ng_type,
+ username,
+ (const unsigned char *) password,
+ (int) strlen(password),
+ &bytes_s,
+ &len_s,
+ &bytes_v,
+ &len_v,
+ G_n_hex,
+ G_g_hex);
+
+ *ret_bytes_s = (unsigned char *) bytes_s;
+ *ret_len_s = len_s;
+
+ *ret_bytes_v = (unsigned char *) bytes_v;
+ *ret_len_v = len_v;
+
+error:
+ return sts;
+}
+
+int
+get_salt_and_v_value(
+ int plugin_type,
+ const char *username,
+ char **ret_salt,
+ unsigned char **ret_bytes_s,
+ int *ret_len_s,
+ unsigned char **ret_bytes_v,
+ int *ret_len_v
+ )
+{
+ int sts = 0;
+ char *user_salt = NULL;
+ char *encpwd = NULL;
+ unsigned char *bytes_s = NULL;
+ int len_s = 0;
+ unsigned char *bytes_v = NULL;
+ int len_v = 0;
+
+ if(!username ||
+ !ret_salt ||
+ !ret_bytes_s ||
+ !ret_len_s ||
+ !ret_bytes_v ||
+ !ret_len_v)
+ {
+ sts = EINVAL;
+ goto error;
+ }
+
+ //Check if we have privileges
+ if(getuid() != 0)
+ {
+ sts = EPERM;
+ goto error;
+ }
+
+ sts = get_sp_salt(username, &user_salt, &encpwd);
+ if(sts)
+ {
+ goto error;
+ }
+
+ /*
+ * This call creates the temporary server-side SRP secret
+ *
+ * bytes_s: SRP salt, publically known to client/server
+ * bytes_v: SRP secret, privately known only by server
+ */
+ sts = _srpVerifierInit(
+ (char *)username,
+ encpwd,
+ &bytes_s,
+ &len_s,
+ &bytes_v,
+ &len_v);
+ if (sts)
+ {
+ goto error;
+ }
+
+ *ret_salt = user_salt;
+ *ret_bytes_s = bytes_s;
+ *ret_len_s = len_s;
+ *ret_bytes_v = bytes_v;
+ *ret_len_v = len_v;
+cleanup:
+ return sts;
+
+error:
+ if(ret_salt)
+ {
+ *ret_salt = NULL;
+ }
+ free(user_salt);
+ free(encpwd);
+ goto cleanup;
+}
diff --git a/vmdir/gssapi-plugins/unix/unix_crypt.h b/vmdir/gssapi-plugins/unix/unix_crypt.h
index 243d453..dbd5a52 100644
--- a/vmdir/gssapi-plugins/unix/unix_crypt.h
+++ b/vmdir/gssapi-plugins/unix/unix_crypt.h
@@ -19,4 +19,14 @@ int get_sp_salt(const char *username,
char **ret_salt,
char **ret_encpwd);
+int
+get_salt_and_v_value(
+ int plugin_type,
+ const char *username,
+ char **ret_salt,
+ unsigned char **ret_bytes_s,
+ int *ret_len_s,
+ unsigned char **ret_bytes_v,
+ int *ret_len_v
+ );
#endif
diff --git a/vmdir/gssapi-plugins/unix/unix_del_sec_ctx.c b/vmdir/gssapi-plugins/unix/unix_del_sec_ctx.c
index deb0715..d946f13 100644
--- a/vmdir/gssapi-plugins/unix/unix_del_sec_ctx.c
+++ b/vmdir/gssapi-plugins/unix/unix_del_sec_ctx.c
@@ -42,7 +42,7 @@ srp_gss_delete_sec_context(
OM_uint32 tmp_minor = GSS_S_COMPLETE;
OM_uint32 ret = GSS_S_COMPLETE;
- if (context_handle == NULL)
+ if (context_handle == NULL || *context_handle == NULL)
{
return (GSS_S_FAILURE);
}
@@ -58,10 +58,6 @@ srp_gss_delete_sec_context(
{
free(srp_ctx->unix_username);
}
- if (srp_ctx->username_hash)
- {
- free(srp_ctx->username_hash);
- }
if (srp_ctx->srp_session_key)
{
@@ -110,6 +106,14 @@ srp_gss_delete_sec_context(
}
#endif
+ if (srp_ctx->bytes_v)
+ {
+ free(srp_ctx->bytes_v);
+ }
+ if (srp_ctx->bytes_s)
+ {
+ free(srp_ctx->bytes_s);
+ }
free(*context_handle);
*context_handle = NULL;
return (ret);