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 +#include +#include + +#include "defines.h" +#include 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 #include "includes.h" -#include "unix_crypt.h" #include +#include #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 +#include +#include +#include "unix_crypt.h" +#include + +/* + * 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 #include +#include +#include #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);