runs-on: windows-latest
env:
KRB_INSTALL_DIR: C:\kfw
+ OPENSSL_DIR: C:\Program Files\OpenSSL
+ OPENSSL_VERSION: 1_1
steps:
- name: Checkout repository
uses: actions/checkout@v1
plugins/tls/k5tls \
kdc kadmin kprop clients appl tests \
config-files build-tools man doc @po@
-WINSUBDIRS=include util lib ccapi windows clients appl plugins\preauth\spake
+WINSUBDIRS=include util lib ccapi windows clients appl plugins\preauth\spake \
+ $(PKINIT_SUBDIR)
BUILDTOP=$(REL).
SRCS =
# $(MAKE) -$(MFLAGS)
# cd ..
+#
+# Build the pkinit plugin if OpenSSL was configured
+#
+##DOS##!ifdef OPENSSL_DIR
+##DOS##PKINIT_SUBDIR=plugins\preauth\pkinit
+##DOS##PKINIT_MAKEFILE=$(PKINIT_SUBDIR)\Makefile
+##DOS##!else
+##DOS##PKINIT_SUBDIR=
+##DOS##PKINIT_MAKEFILE=
+##DOS##!endif
+
#
# We need outpre-dir explicitly in here because we may
# try to build wconfig on a config-windows.
windows\Makefile windows\lib\Makefile windows\ms2mit\Makefile \
windows\kfwlogon\Makefile windows\leashdll\Makefile \
windows\leash\Makefile windows\leash\htmlhelp\Makefile \
- plugins\preauth\spake\Makefile
+ plugins\preauth\spake\Makefile $(PKINIT_MAKEFILE)
##DOS##Makefile-windows: $(MKFDEP) $(WINMAKEFILES)
##DOS## $(WCONFIG) config < $@.in > $@
##DOS##plugins\preauth\spake\Makefile: plugins\preauth\spake\Makefile.in $(MKFDEP)
##DOS## $(WCONFIG) config < $@.in > $@
+##DOS##plugins\preauth\pkinit\Makefile: plugins\preauth\pkinit\Makefile.in $(MKFDEP)
+##DOS## $(WCONFIG) config < $@.in > $@
clean-windows:: Makefile-windows
$(INSTALLDBGSYMS) clients\kswitch\$(OUTPRE)kswitch.pdb "$(KRB_INSTALL_DIR)\bin\."
copy plugins\preauth\spake\$(OUTPRE)$(SPAKELIB).dll "$(KRB_INSTALL_DIR)\bin\plugins\preauth\."
$(INSTALLDBGSYMS) plugins\preauth\spake\$(OUTPRE)$(SPAKELIB).pdb "$(KRB_INSTALL_DIR)\bin\plugins\preauth\."
+##DOS##!ifdef OPENSSL_DIR
+ copy plugins\preauth\pkinit\$(OUTPRE)$(PKINITLIB).dll "$(KRB_INSTALL_DIR)\bin\plugins\preauth\."
+ $(INSTALLDBGSYMS) plugins\preauth\pkinit\$(OUTPRE)$(PKINITLIB).pdb "$(KRB_INSTALL_DIR)\bin\plugins\preauth\."
+##DOS##!endif
check-prerecurse: runenv.py
$(RM) $(SKIPTESTS)
CC=cl
PDB_OPTS=-Fd$(OUTPRE)\ -FD
-CPPFLAGS=-I$(top_srcdir)\include -I$(top_srcdir)\include\krb5 $(DNSFLAGS) -DWIN32_LEAN_AND_MEAN -DKRB5_DEPRECATED=1 -DKRB5_PRIVATE -D_CRT_SECURE_NO_DEPRECATE $(KFWFLAGS) $(TIME_T_FLAGS)
+CPPFLAGS=-I$(top_srcdir)\include -I$(top_srcdir)\include\krb5 $(DNSFLAGS) -DWIN32_LEAN_AND_MEAN -DKRB5_DEPRECATED=1 -DKRB5_PRIVATE -D_CRT_SECURE_NO_DEPRECATE $(KFWFLAGS) $(TIME_T_FLAGS) $(OSSLINCLUDE)
# Treat the following warnings as errors:
# 4020: too many actual parameters
# 4024: different types for formal and actual parameter
CCLIB=krbcc$(BITS)
SPAKELIB=spake$(BITS)
+!ifdef OPENSSL_DIR
+OSSLLIB="$(OPENSSL_DIR)\lib\libcrypto.lib"
+OSSLINC="-I$(OPENSSL_DIR)\include"
+PKINITLIB=pkinit$(BITS)
+!else
+OSSLLIB=
+OSSLINC=
+PKINITLIB=
+!endif
+
KRB4_INCLUDES=-I$(BUILDTOP)/include/kerberosIV
COM_ERR_DEPS = $(BUILDTOP)/include/com_err.h
#define KRB5_CALLCONV_C
#endif
+#ifndef PKCS11_MODNAME
+#define PKCS11_MODNAME "C:\\Program Files\\OpenSC Project\\OpenSC\\pkcs11\\opensc-pkcs11.dll"
+#endif
+
#endif /* _KRB5_WIN_MAC_H */
k5_sname_compare @474 ; PRIVATE GSSAPI
krb5_kdc_sign_ticket @475 ;
krb5_kdc_verify_ticket @476 ;
+
+; new in 1.22
+; private symbols used by PKINIT module
+ encode_krb5_sp80056a_other_info @477 ; PRIVATE
+ encode_krb5_pkinit_supp_pub_info @478 ; PRIVATE
+ krb5int_copy_data_contents @479 ; PRIVATE
+ krb5_free_pa_data @480 ; PRIVATE
$(TOPLIBD)/libkrb5$(SHLIBEXT)
SHLIB_EXPLIBS= -lkrb5 $(COM_ERR_LIB) -lk5crypto -lcrypto $(DL_LIB) $(SUPPORT_LIB) $(LIBS)
+WINLIBS = $(KLIB) $(SLIB) $(PLIB) $(CLIB) $(OSSLLIB)
+OSSLINCLUDE = $(OSSLINC)
+
STLIBOBJS= \
pkinit_accessor.o \
pkinit_srv.o \
$(srcdir)/pkinit_matching.c \
$(srcdir)/pkinit_crypto_openssl.c
+#
+# Don't include pkinit_srv.c in the Windows object list since we
+# don't need it.
+#
+OBJS= $(OUTPRE)pkinit_accessor.$(OBJEXT) \
+ $(OUTPRE)pkinit_lib.$(OBJEXT) \
+ $(OUTPRE)pkinit_clnt.$(OBJEXT) \
+ $(OUTPRE)pkinit_constants.$(OBJEXT) \
+ $(OUTPRE)pkinit_profile.$(OBJEXT) \
+ $(OUTPRE)pkinit_identity.$(OBJEXT) \
+ $(OUTPRE)pkinit_matching.$(OBJEXT) \
+ $(OUTPRE)pkinit_crypto_openssl.$(OBJEXT)
+
all-unix: all-liblinks
install-unix: install-libs
clean-unix:: clean-liblinks clean-libs clean-libobjs
pkinit_kdf_test: pkinit_kdf_test.o $(STLIBOBJS) $(SHLIB_EXPDEPS)
$(CC_LINK) -o $@ pkinit_kdf_test.o $(STLIBOBJS) $(SHLIB_EXPLIBS)
+all-windows: $(OUTPRE)$(PKINITLIB).dll
+clean-windows::
+ $(RM) $(OUTPRE)$(PKINITLIB).dll
+
+$(OUTPRE)$(PKINITLIB).dll: pkinit.def $(OBJS)
+ link /dll $(LOPTS) -def:pkinit.def -out:$*.dll $(OBJS) $(WINLIBS)
+
@libnover_frag@
@libobj_frag@
--- /dev/null
+EXPORTS
+
+ clpreauth_pkinit_initvt
/* Solaris compiler doesn't grok __FUNCTION__
* hack for now. Fix all the uses eventually. */
+#ifndef _WIN32
#define __FUNCTION__ __func__
+#endif
/* Macros to deal with converting between various data types... */
#define PADATA_TO_KRB5DATA(pad, k5d) \
krb5_error_code
(*k5int_encode_krb5_kdc_req_body)(const krb5_kdc_req *rep, krb5_data **code);
-void KRB5_CALLCONV
-(*k5int_krb5_free_kdc_req)(krb5_context, krb5_kdc_req * );
+void
+(KRB5_CALLCONV *k5int_krb5_free_kdc_req)(krb5_context, krb5_kdc_req * );
void
(*k5int_set_prompt_types)(krb5_context, krb5_prompt_type *);
extern krb5_error_code (*k5int_encode_krb5_kdc_req_body)
(const krb5_kdc_req *rep, krb5_data **code);
-extern void KRB5_CALLCONV (*k5int_krb5_free_kdc_req)
+extern void (KRB5_CALLCONV *k5int_krb5_free_kdc_req)
(krb5_context, krb5_kdc_req * );
extern void (*k5int_set_prompt_types)
(krb5_context, krb5_prompt_type *);
#include "pkinit.h"
#include "k5-json.h"
-#include <unistd.h>
#include <sys/stat.h>
/**
#include "k5-err.h"
#include "k5-hex.h"
#include "pkinit.h"
-#include <dirent.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#ifdef DEBUG_SIG
print_buffer(sig, sig_len);
#endif
- free(abuf);
+ OPENSSL_free(abuf);
if (retval)
goto cleanup2;
krb5_principal princ)
{
krb5_error_code retval = ENOMEM;
- DIR *d = NULL;
- struct dirent *dentry = NULL;
- char certname[1024];
- char keyname[1024];
- int i = 0, len;
- char *dirname, *suf;
+ int ncreds = 0, len, i;
+ char *dirname, *suf, *name, **fnames = NULL;
+ char *certname = NULL, *keyname = NULL;
if (idopts->cert_filename == NULL) {
TRACE_PKINIT_NO_CERT(context);
}
dirname = idopts->cert_filename;
- d = opendir(dirname);
- if (d == NULL)
- return errno;
+ retval = k5_dir_filenames(dirname, &fnames);
+ if (retval)
+ return retval;
/*
* We'll assume that certs are named XXX.crt and the corresponding
* key is named XXX.key
*/
- while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) {
- /* Ignore subdirectories and anything starting with a dot */
-#ifdef DT_DIR
- if (dentry->d_type == DT_DIR)
- continue;
-#endif
- if (dentry->d_name[0] == '.')
+ for (i = 0; fnames[i] != NULL; i++) {
+ /* Ignore anything starting with a dot */
+ name = fnames[i];
+ if (name[0] == '.')
continue;
- len = strlen(dentry->d_name);
+ len = strlen(name);
if (len < 5)
continue;
- suf = dentry->d_name + (len - 4);
+ suf = name + (len - 4);
if (strncmp(suf, ".crt", 4) != 0)
continue;
- /* Checked length */
- if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) {
- pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
- __FUNCTION__, dirname, dentry->d_name);
- continue;
- }
- snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name);
- snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name);
+ retval = k5_path_join(dirname, name, &certname);
+ if (retval)
+ goto cleanup;
+ retval = k5_path_join(dirname, name, &keyname);
+ if (retval)
+ goto cleanup;
+
len = strlen(keyname);
keyname[len - 3] = 'k';
keyname[len - 2] = 'e';
keyname[len - 1] = 'y';
retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
- certname, keyname, i);
- if (retval == 0) {
- TRACE_PKINIT_LOADED_CERT(context, dentry->d_name);
- i++;
+ certname, keyname, ncreds);
+ free(certname);
+ free(keyname);
+ certname = keyname = NULL;
+ if (!retval) {
+ TRACE_PKINIT_LOADED_CERT(context, name);
+ if (++ncreds >= MAX_CREDS_ALLOWED)
+ break;
}
- else
- continue;
}
- if (!id_cryptoctx->defer_id_prompt && i == 0) {
+ if (!id_cryptoctx->defer_id_prompt && ncreds == 0) {
TRACE_PKINIT_NO_CERT_AND_KEY(context, idopts->cert_filename);
retval = ENOENT;
goto cleanup;
retval = 0;
cleanup:
- if (d)
- closedir(d);
-
+ k5_free_filenames(fnames);
+ free(certname);
+ free(keyname);
return retval;
}
char *dirname)
{
krb5_error_code retval = EINVAL;
- DIR *d = NULL;
- struct dirent *dentry = NULL;
- char filename[1024];
+ char **fnames = NULL, *filename;
+ int i;
if (dirname == NULL)
return EINVAL;
- d = opendir(dirname);
- if (d == NULL)
- return ENOENT;
+ retval = k5_dir_filenames(dirname, &fnames);
+ if (retval)
+ return retval;
- while ((dentry = readdir(d))) {
- if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) {
- pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
- __FUNCTION__, dirname, dentry->d_name);
- goto cleanup;
- }
- /* Ignore subdirectories and anything starting with a dot */
-#ifdef DT_DIR
- if (dentry->d_type == DT_DIR)
- continue;
-#endif
- if (dentry->d_name[0] == '.')
+ for (i = 0; fnames[i] != NULL; i++) {
+ /* Ignore anything starting with a dot */
+ if (fnames[i][0] == '.')
continue;
- snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name);
+
+ retval = k5_path_join(dirname, fnames[i], &filename);
+ if (retval)
+ goto cleanup;
retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
id_cryptoctx, catype, filename);
+ free(filename);
if (retval)
goto cleanup;
}
retval = 0;
cleanup:
- if (d != NULL)
- closedir(d);
-
+ k5_free_filenames(fnames);
return retval;
}
TRACE_PKINIT_DH_INVALID_MIN_BITS(context, str);
return PKINIT_DEFAULT_DH_MIN_BITS;
}
+
+#ifdef _WIN32
+BOOL WINAPI
+DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpvReserved)
+{
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ pkinit_openssl_init__auxinit();
+ return TRUE;
+}
+#endif /* _WIN32 */
*/
#include "pkinit.h"
-#include <dirent.h>
static void
free_list(char **list)
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <regex.h>
#include "pkinit.h"
+#include "k5-regex.h"
typedef struct _pkinit_cert_info pkinit_cert_info;
* A version of Visual Studio (at least 2013) which includes the
Microsoft Foundation Classes libraries. These instructions will
- work for Visual Studio 2017 Community or Professional, both of which
- include the MFC libraries if the "Visual C++ MFC" checkbox is
- selected after enabling the "Desktop development with C++" workload.
- If you do not plan to build the graphical ticket manager
- application, the MFC libraries are not required.
+ work for Visual Studio 2022 Community or Professional. Include
+ the following components:
-* A version of Perl.
+ - Under Workloads, select Desktop development with C++
+ - Under Individual components -> SDKs, libraries, and frameworks,
+ select "C++ MFC for latest v*** build tools (x86 & x64)". This
+ component is not required if you do not wish to build the
+ graphical ticket manager.
+ - Under Individual components -> Compilers, build tools, and
+ runtimes, select "C++ 20** Redistributable MSMs". This component
+ is not required if you do not wish to build the installer.
+
+* An OpenSSL installation, including the headers, DLLs, and import
+ .LIB files. This dependency is optional if you are not building
+ PKINIT. We recommend building OpenSSL from source code.
+
+* A version of Perl. We recommend Strawberry Perl as it will work
+ to build OpenSSL.
* Some common Unix utilities such as sed/awk/cp/cat installed in the
command-line path.
A simple way to get the necessary Unix utilities is to install Git
BASH from https://gitforwindows.org and configure it to add the Unix
-utilities to the command-line path. In some versions of Windows (not
-the most current versions), the Unix utilities can alternatively be
-obtained via the Utilities and SDK for UNIX-based Applications, which
-may be enabled as a Windows feature and then the components installed.
-Note that the Windows nmake will not find the SUA awk utility in the
-path unless it is named awk.exe; the permissions on the utility may
-need correcting if awk.exe is created as a copy of the original awk.
-
-Git BASH contains a version of Perl, which will work to build krb5 if
-the newlines in the source tree are not translated to native newlines.
-Strawberry Perl will work regardless of whether newlines are
-translated. If both Git BASH and Strawberry Perl are installed, you
-may need to adjust the command line path to ensure that the preferred
-Perl appears first.
+utilities to the command-line path.
+
+Git BASH contains a version of Perl, which will work to build krb5,
+but not to build OpenSSL from source. If both Git BASH and Strawberry
+Perl are installed, you may need to adjust the command line path to
+ensure that the preferred Perl appears first when building OpenSSL.
The krb5 source tree may be obtained either directly on the Windows
machine with a native git client cloning the krb5 public mirror at
near your build tree. The directory must exist before nmake install
is run.
+Set the environment variable OPENSSL_DIR to point to the root of the
+OpenSSL install tree, and the environment variable OPENSSL_VERSION to
+the version string as it apears in the DLL names (such as "1_1" or
+"3"). Include files should be in %OPENSSL_DIR%\include, import .LIB
+files should be in %OPENSSL_DIR%\lib, and the libcrypto DLL should be
+in %OPENSSL_DIR%\bin\libcrypto-%OPENSSL_VERSION%-x64.dll. These steps
+are optional if you do not wish to build PKINIT.
+
To skip building the graphical ticket manager, run "set NO_LEASH=1"
before building, and do not build the installer.
1) set PATH=%PATH%;"%WindowsSdkVerBinPath%"\x86 # To get uicc.exe
2) set KRB_INSTALL_DIR=\path\to\dir # Where bin/include/lib lives
- 3) cd xxx\src # Go to where source lives
- 4) nmake [NODEBUG=1] # Build the sources
- 5) nmake install [NODEBUG=1] # Copy libraries/executables
- 6) cd windows\installer\wix # Go to the installer source
- 7) nmake [NODEBUG=1] # Build the installer
+ 3) set OPENSSL_DIR=\path\to\openssl # Where OpenSSL lives
+ 4) set OPENSSL_VERSION=3 # Version of OpenSSL DLLs
+ 5) cd xxx\src # Go to where source lives
+ 6) nmake -f Makefile.in prep-windows # Create Makefile for Windows
+ 7) nmake [NODEBUG=1] # Build the sources
+ 8) nmake install [NODEBUG=1] # Copy libraries/executables
+ 9) cd windows\installer\wix # Go to the installer source
+10) nmake [NODEBUG=1] # Build the installer
Step 1 may be skipped if uicc is already in the command-line path (try
running "uicc" to see if you get a usage message or a not-found
<?define BinDir="$(env.KRB_INSTALL_DIR)\bin\"?>
<?define PreauthDir=$(env.KRB_INSTALL_DIR)\bin\plugins\preauth?>
<?define LibDir="$(env.KRB_INSTALL_DIR)\lib\"?>
+ <?define OpenSSLDir="$(env.OPENSSL_DIR)\bin"?>
+ <?define OpenSSLVer="$(env.OPENSSL_VERSION)"?>
<?define InstallerVersion="450"?>
<?ifndef env.VISUALSTUDIOVERSION?>
<?define VCVer="100"?>
<ComponentRef Id="cmf_krbcc64_dll" />
<ComponentRef Id="cmf_leashw64_dll" />
<ComponentRef Id="cmf_xpprof64_dll" />
+ <ComponentRef Id="cmf_openssl_crypto64_dll" />
<ComponentRef Id="cmf_spake64_dll" />
+ <ComponentRef Id="cmf_pkinit64_dll" />
<ComponentRef Id="cmf_gss_client_exe" />
<ComponentRef Id="cmf_gss_server_exe" />
<ComponentRef Id="cmf_kdestroy_exe" />
<Component Id="cmf_xpprof64_dll" Guid="$(var.cmf_xpprof64_dll_guid)" DiskId="1">
<File Id="fil_xpprof64_dll" Name="$(var.cmf_xpprof64_dll_name)" KeyPath="yes" />
</Component>
+ <Component Id="cmf_openssl_crypto64_dll" Guid="$(var.cmf_openssl_crypto64_dll)" DiskId="1">
+ <File Id="fil_openssl_crypto64_dll" Name="$(var.cmf_openssl_crypto64_dll_name)" Source="$(var.OpenSSLDir)\libcrypto-$(var.OpenSSLVer)-x64.dll" KeyPath="yes" />
+ </Component>
<!-- Debug symbols -->
<?ifdef DebugSyms?>
<Component Id="cmf_spake64_dll" Guid="$(var.cmf_spake64_dll_guid)" DiskId="1">
<File Id="fil_spake64_dll" Name="$(var.cmf_spake64_dll_name)" KeyPath="yes" />
</Component>
+ <Component Id="cmf_pkinit64_dll" Guid="$(var.cmf_pkinit64_dll_guid)" DiskId="1">
+ <File Id="fil_pkinit64_dll" Name="$(var.cmf_pkinit64_dll_name)" KeyPath="yes" />
+ </Component>
<?ifdef DebugSyms?>
<Component Id="cmf_preauth_debug" Guid="$(var.cmf_preauth_debug_guid)" DiskId="1">
+ <File Id="fil_pkinit64_pdb" Name="pkinit64.pdb" />
<File Id="fil_spake64_pdb" Name="spake64.pdb" />
</Component>
<?endif?>
<?define cmf_xpprof64_dll_name="xpprof64.dll"?>
<?define cmf_spake64_dll_guid="0E97B52A-EC8E-494C-BF5D-83AAACFEFDBA"?>
<?define cmf_spake64_dll_name="spake64.dll"?>
+ <?define cmf_pkinit64_dll_guid="5F7A1656-5A55-4067-842D-73380DF57442"?>
+ <?define cmf_pkinit64_dll_name="pkinit64.dll"?>
+ <?define cmf_openssl_crypto64_dll="6762F903-0B15-4F29-9128-1CEB4AFB99B3"?>
+ <?define cmf_openssl_crypto64_dll_name="libcrypto-$(var.OpenSSLVer)-x64.dll"?>
<?define cmf_krb5cred_dll_guid="CC182AB1-E333-4501-8DEA-5A8D4FD36D0D"?>
<?define cmf_krb5cred_dll_name="krb5cred.dll"?>
<?define cmf_krb5cred_en_us_dll_guid="223B7E9D-290F-40b8-89B3-F8337A8E082D"?>