krb5 commit: Build PKINIT on Windows

ghudson at mit.edu ghudson at mit.edu
Thu Feb 27 17:28:50 EST 2025


https://github.com/krb5/krb5/commit/1bea471f6ec445a80d966de4233b270c4c2801c4
commit 1bea471f6ec445a80d966de4233b270c4c2801c4
Author: Ken Hornstein <kenh at cmf.nrl.navy.mil>
Date:   Fri Dec 6 15:29:33 2024 -0500

    Build PKINIT on Windows
    
    Include PKINIT in the Windows build if OPENSSL_DIR is set.
    
    In the installer, require PKINIT to be built, and require
    OPENSSL_VERSION to be set in the environment.  Include the PKINIT
    module and a copy of the OpenSSL libcrypto DLL.
    
    Document the OpenSSL dependency in windows/README.  Also clarify the
    Visual Studio dependencies, and restore the prep-windows build step
    which was accidentally removed by commit
    5f33fb2cf19562175c8271cb9c54a67212f63b93.
    
    [ghudson at mit.edu: added CI and installer integration; edited README
    and commit message]
    
    ticket: 9162 (new)

 .github/workflows/build.yml                        |   2 +
 src/Makefile.in                                    |  22 +++-
 src/config/win-pre.in                              |  12 ++-
 src/include/win-mac.h                              |   4 +
 src/lib/krb5_32.def                                |   7 ++
 src/plugins/preauth/pkinit/Makefile.in             |  23 ++++
 src/plugins/preauth/pkinit/pkinit.def              |   3 +
 src/plugins/preauth/pkinit/pkinit.h                |   2 +
 src/plugins/preauth/pkinit/pkinit_accessor.c       |   4 +-
 src/plugins/preauth/pkinit/pkinit_accessor.h       |   2 +-
 src/plugins/preauth/pkinit/pkinit_clnt.c           |   1 -
 src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 116 ++++++++++-----------
 src/plugins/preauth/pkinit/pkinit_identity.c       |   1 -
 src/plugins/preauth/pkinit/pkinit_matching.c       |   3 +-
 src/windows/README                                 |  64 +++++++-----
 src/windows/installer/wix/config.wxi               |   2 +
 src/windows/installer/wix/features.wxi             |   2 +
 src/windows/installer/wix/files.wxi                |   7 ++
 src/windows/installer/wix/platform.wxi             |   4 +
 19 files changed, 186 insertions(+), 95 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 183b7c293..c16e77c43 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -70,6 +70,8 @@ jobs:
         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 at v1
diff --git a/src/Makefile.in b/src/Makefile.in
index e2286c5ee..01fb060f7 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -32,7 +32,8 @@ SUBDIRS=util include lib \
 	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 =  
@@ -105,6 +106,17 @@ config-windows: Makefile-windows
 #	$(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.
@@ -154,7 +166,7 @@ WINMAKEFILES=Makefile \
 	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)
 
@@ -278,6 +290,8 @@ WINMAKEFILES=Makefile \
 ##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
 
@@ -485,6 +499,10 @@ install-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)
diff --git a/src/config/win-pre.in b/src/config/win-pre.in
index 753fde7cc..0bcb280df 100644
--- a/src/config/win-pre.in
+++ b/src/config/win-pre.in
@@ -117,7 +117,7 @@ KFWFLAGS=-DUSE_LEASH=1 -DDEBUG -D_CRTDBG_MAP_ALLOC
 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
@@ -189,6 +189,16 @@ GLIB=$(BUILDTOP)\lib\$(OUTPRE)gssapi$(BITS).lib
 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
diff --git a/src/include/win-mac.h b/src/include/win-mac.h
index 0fd3a29e5..b2a460131 100644
--- a/src/include/win-mac.h
+++ b/src/include/win-mac.h
@@ -236,4 +236,8 @@ HINSTANCE get_lib_instance(void);
 #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 */
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
index b1610974b..c5a460185 100644
--- a/src/lib/krb5_32.def
+++ b/src/lib/krb5_32.def
@@ -510,3 +510,10 @@ EXPORTS
 	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
diff --git a/src/plugins/preauth/pkinit/Makefile.in b/src/plugins/preauth/pkinit/Makefile.in
index 86f143d72..d57088c4d 100644
--- a/src/plugins/preauth/pkinit/Makefile.in
+++ b/src/plugins/preauth/pkinit/Makefile.in
@@ -12,6 +12,9 @@ SHLIB_EXPDEPS = \
 	$(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 \
@@ -35,6 +38,19 @@ SRCS= \
 	$(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
@@ -48,6 +64,13 @@ check-unix: pkinit_kdf_test
 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@
 
diff --git a/src/plugins/preauth/pkinit/pkinit.def b/src/plugins/preauth/pkinit/pkinit.def
new file mode 100644
index 000000000..4736e35e8
--- /dev/null
+++ b/src/plugins/preauth/pkinit/pkinit.def
@@ -0,0 +1,3 @@
+EXPORTS
+
+	clpreauth_pkinit_initvt
diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
index 7ba7155bb..200e75afe 100644
--- a/src/plugins/preauth/pkinit/pkinit.h
+++ b/src/plugins/preauth/pkinit/pkinit.h
@@ -97,7 +97,9 @@ static inline void pkiDebug (const char *fmt, ...) { }
 
 /* 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) \
diff --git a/src/plugins/preauth/pkinit/pkinit_accessor.c b/src/plugins/preauth/pkinit/pkinit_accessor.c
index 0908f1b9b..5d9463e84 100644
--- a/src/plugins/preauth/pkinit/pkinit_accessor.c
+++ b/src/plugins/preauth/pkinit/pkinit_accessor.c
@@ -69,8 +69,8 @@ krb5_error_code
 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 *);
diff --git a/src/plugins/preauth/pkinit/pkinit_accessor.h b/src/plugins/preauth/pkinit/pkinit_accessor.h
index e510ab624..37e2b5307 100644
--- a/src/plugins/preauth/pkinit/pkinit_accessor.h
+++ b/src/plugins/preauth/pkinit/pkinit_accessor.h
@@ -66,7 +66,7 @@ extern krb5_error_code (*k5int_decode_krb5_td_trusted_certifiers)
 
 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 *);
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
index 305a59da3..9312ff4b1 100644
--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
@@ -33,7 +33,6 @@
 #include "pkinit.h"
 #include "k5-json.h"
 
-#include <unistd.h>
 #include <sys/stat.h>
 
 /**
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 14370ae34..8098028eb 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -34,7 +34,6 @@
 #include "k5-err.h"
 #include "k5-hex.h"
 #include "pkinit.h"
-#include <dirent.h>
 
 #include <openssl/bn.h>
 #include <openssl/dh.h>
@@ -1867,7 +1866,7 @@ cms_signeddata_create(krb5_context context,
 #ifdef DEBUG_SIG
         print_buffer(sig, sig_len);
 #endif
-        free(abuf);
+        OPENSSL_free(abuf);
         if (retval)
             goto cleanup2;
 
@@ -4304,12 +4303,9 @@ pkinit_get_certs_dir(krb5_context context,
                      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);
@@ -4317,53 +4313,51 @@ pkinit_get_certs_dir(krb5_context 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;
@@ -4372,9 +4366,9 @@ pkinit_get_certs_dir(krb5_context context,
     retval = 0;
 
 cleanup:
-    if (d)
-        closedir(d);
-
+    k5_free_filenames(fnames);
+    free(certname);
+    free(keyname);
     return retval;
 }
 
@@ -5166,34 +5160,28 @@ load_cas_and_crls_dir(krb5_context context,
                       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;
     }
@@ -5201,9 +5189,7 @@ load_cas_and_crls_dir(krb5_context context,
     retval = 0;
 
 cleanup:
-    if (d != NULL)
-        closedir(d);
-
+    k5_free_filenames(fnames);
     return retval;
 }
 
@@ -5712,3 +5698,13 @@ parse_dh_min_bits(krb5_context context, const char *str)
     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 */
diff --git a/src/plugins/preauth/pkinit/pkinit_identity.c b/src/plugins/preauth/pkinit/pkinit_identity.c
index 2e29a8c45..0dcfcfc46 100644
--- a/src/plugins/preauth/pkinit/pkinit_identity.c
+++ b/src/plugins/preauth/pkinit/pkinit_identity.c
@@ -30,7 +30,6 @@
  */
 
 #include "pkinit.h"
-#include <dirent.h>
 
 static void
 free_list(char **list)
diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
index b42485a50..0ea072c88 100644
--- a/src/plugins/preauth/pkinit/pkinit_matching.c
+++ b/src/plugins/preauth/pkinit/pkinit_matching.c
@@ -33,9 +33,8 @@
 #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;
 
diff --git a/src/windows/README b/src/windows/README
index 5ceff9adc..7ca84a8ee 100644
--- a/src/windows/README
+++ b/src/windows/README
@@ -10,13 +10,24 @@ To build Kerberos 5 on Windows, you will need the following:
 
 * 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.
@@ -28,20 +39,12 @@ To build Kerberos 5 on Windows, you will need the following:
 
 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
@@ -75,6 +78,14 @@ the MSI installer, this directory should be a temporary staging area in or
 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.
 
@@ -82,11 +93,14 @@ Run the following commands in a Visual Studio command prompt:
 
  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
diff --git a/src/windows/installer/wix/config.wxi b/src/windows/installer/wix/config.wxi
index ea6e610a0..ffd68d9cd 100644
--- a/src/windows/installer/wix/config.wxi
+++ b/src/windows/installer/wix/config.wxi
@@ -38,6 +38,8 @@
     <?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"?>
diff --git a/src/windows/installer/wix/features.wxi b/src/windows/installer/wix/features.wxi
index 3405dc482..de99ad7ed 100644
--- a/src/windows/installer/wix/features.wxi
+++ b/src/windows/installer/wix/features.wxi
@@ -63,7 +63,9 @@
             <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" />
diff --git a/src/windows/installer/wix/files.wxi b/src/windows/installer/wix/files.wxi
index 805856eae..675eea803 100644
--- a/src/windows/installer/wix/files.wxi
+++ b/src/windows/installer/wix/files.wxi
@@ -272,6 +272,9 @@
                   <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?>
@@ -305,8 +308,12 @@
                       <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?>
diff --git a/src/windows/installer/wix/platform.wxi b/src/windows/installer/wix/platform.wxi
index 006e35544..470400aa1 100644
--- a/src/windows/installer/wix/platform.wxi
+++ b/src/windows/installer/wix/platform.wxi
@@ -73,6 +73,10 @@
   <?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"?>


More information about the cvs-krb5 mailing list