krb5 commit: Add regexp support on Windows using std::regex
ghudson at mit.edu
ghudson at mit.edu
Tue Dec 24 14:32:05 EST 2024
https://github.com/krb5/krb5/commit/04b22c1c2dfbf7954b6cb114527a50a95ebccad3
commit 04b22c1c2dfbf7954b6cb114527a50a95ebccad3
Author: Ken Hornstein <kenh at cmf.nrl.navy.mil>
Date: Fri Nov 29 20:34:53 2024 -0500
Add regexp support on Windows using std::regex
Provide glue code in libkrb5support to emulate the POSIX regex(3)
interface by calling into the C++ std::regex classes.
Eliminate compatibility code for pre-POSIX regex functions.
[ghudson at mit.edu: additional cleanup of regexp callers; minor style
adjustments; removed regerrlen field; edited commit message]
src/aclocal.m4 | 48 ------------
src/build-tools/krb5-config.in | 4 +-
src/config/pre.in | 5 +-
src/configure.ac | 11 +--
src/include/k5-platform.h | 8 ++
src/include/k5-regex.h | 118 ++++++++++++++++++++++++++++++
src/kadmin/dbutil/dump.c | 47 +-----------
src/kadmin/dbutil/kdb5_mkey.c | 63 ++--------------
src/lib/kadm5/srv/Makefile.in | 2 +-
src/lib/kadm5/srv/svr_iters.c | 53 ++------------
src/lib/krb5/Makefile.in | 2 +-
src/lib/krb5/os/localauth_rule.c | 15 +---
src/util/support/Makefile.in | 17 ++++-
src/util/support/regex.cpp | 153 +++++++++++++++++++++++++++++++++++++++
14 files changed, 311 insertions(+), 235 deletions(-)
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index 4b57d3bd0..7397bdcc2 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -714,53 +714,6 @@ KRB5_NEED_PROTO([#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif],daemon,1)])dnl
-dnl
-dnl KRB5_AC_NEED_LIBGEN --- check if libgen needs to be linked in for
-dnl compile/step
-dnl
-dnl
-AC_DEFUN(KRB5_AC_NEED_LIBGEN,[
-AC_REQUIRE([AC_PROG_CC])dnl
-dnl
-dnl regcomp is present but non-functional on Solaris 2.4
-dnl
-AC_MSG_CHECKING(for working regcomp)
-AC_CACHE_VAL(ac_cv_func_regcomp,
-[AC_RUN_IFELSE(
- [AC_LANG_PROGRAM(
- [[#include <sys/types.h>
- #include <regex.h>
- regex_t x; regmatch_t m;]],
- [[return regcomp(&x,"pat.*",0) || regexec(&x,"pattern",1,&m,0);]])],
- [ac_cv_func_regcomp=yes], [ac_cv_func_regcomp=no],
- [AC_MSG_ERROR([Cannot test regcomp when cross compiling])])])
-AC_MSG_RESULT($ac_cv_func_regcomp)
-test $ac_cv_func_regcomp = yes && AC_DEFINE(HAVE_REGCOMP,1,[Define if regcomp exists and functions])
-dnl
-dnl Check for the compile and step functions - only if regcomp is not available
-dnl
-if test $ac_cv_func_regcomp = no; then
- save_LIBS="$LIBS"
- LIBS=-lgen
-dnl this will fail if there's no compile/step in -lgen, or if there's
-dnl no -lgen. This is fine.
- AC_CHECK_FUNCS(compile step)
- LIBS="$save_LIBS"
-dnl
-dnl Set GEN_LIB if necessary
-dnl
- AC_CHECK_LIB(gen, compile, GEN_LIB=-lgen, GEN_LIB=)
- AC_SUBST(GEN_LIB)
-fi
-])
-dnl
-dnl KRB5_AC_REGEX_FUNCS --- check for different regular expression
-dnl support functions
-dnl
-AC_DEFUN(KRB5_AC_REGEX_FUNCS,[
-AC_CHECK_FUNCS(re_comp re_exec regexec)
-AC_REQUIRE([KRB5_AC_NEED_LIBGEN])dnl
-])dnl
dnl
dnl WITH_HESIOD
dnl
@@ -850,7 +803,6 @@ dnl Set variables to build a program.
AC_DEFUN(KRB5_BUILD_PROGRAM,
[AC_REQUIRE([KRB5_LIB_AUX])dnl
-AC_REQUIRE([KRB5_AC_NEED_LIBGEN])dnl
AC_SUBST(CC_LINK)
AC_SUBST(CXX_LINK)
AC_SUBST(RPATH_FLAG)
diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
index 8e6eb8660..2cb439887 100755
--- a/src/build-tools/krb5-config.in
+++ b/src/build-tools/krb5-config.in
@@ -42,7 +42,6 @@ DEFKTNAME='@DEFKTNAME@'
DEFCKTNAME='@DEFCKTNAME@'
LIBS='@LIBS@'
-GEN_LIB=@GEN_LIB@
# Defaults for program
library=krb5
@@ -253,8 +252,7 @@ if test -n "$do_libs"; then
fi
# If we ever support a flag to generate output suitable for static
- # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB"
- # here.
+ # linking, we would output "-lkrb5support $LIBS $DL_LIB" here.
echo $lib_flags
fi
diff --git a/src/config/pre.in b/src/config/pre.in
index 39c417e43..1197c1ffd 100644
--- a/src/config/pre.in
+++ b/src/config/pre.in
@@ -348,9 +348,6 @@ VERTO_DEPS-k5 = $(BUILDTOP)/include/verto.h
# LIBS gets substituted in... e.g. -lnsl -lsocket
-# GEN_LIB is -lgen if needed for regexp
-GEN_LIB = @GEN_LIB@
-
# Editline or readline flags and libraries.
RL_CFLAGS = @RL_CFLAGS@
RL_LIBS = @RL_LIBS@
@@ -380,7 +377,7 @@ SUPPORT_LIB = -l$(SUPPORT_LIBNAME)
# HESIOD_LIBS is -lhesiod...
HESIOD_LIBS = @HESIOD_LIBS@
-KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
+KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(LIBS) $(DL_LIB)
KDB5_LIBS = $(KDB5_LIB) $(GSSRPC_LIBS)
GSS_LIBS = $(GSS_KRB5_LIB)
# needs fixing if ever used on macOS!
diff --git a/src/configure.ac b/src/configure.ac
index 9d4e08a70..4325fae99 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -490,18 +490,9 @@ AC_SUBST(GETTIMEOFDAY_ST_OBJ)
AC_SUBST(EXTRA_SUPPORT_SYMS)
DECLARE_SYS_ERRLIST
-AC_CHECK_HEADERS(unistd.h paths.h regex.h regexpr.h fcntl.h memory.h ifaddrs.h sys/filio.h byteswap.h machine/endian.h machine/byte_order.h sys/bswap.h endian.h pwd.h arpa/inet.h alloca.h dlfcn.h limits.h sys/random.h)
-AC_CHECK_HEADER(regexp.h, [], [],
-[#define INIT char *sp = instring;
-#define GETC() (*sp++)
-#define PEEKC() (*sp)
-#define UNGETC(c) (--sp)
-#define RETURN(c) return(c)
-#define ERROR(c)
-])
+AC_CHECK_HEADERS(unistd.h paths.h fcntl.h memory.h ifaddrs.h sys/filio.h byteswap.h machine/endian.h machine/byte_order.h sys/bswap.h endian.h pwd.h arpa/inet.h alloca.h dlfcn.h limits.h sys/random.h)
AC_CHECK_MEMBERS([struct stat.st_mtimensec,struct stat.st_mtimespec.tv_nsec,struct stat.st_mtim.tv_nsec],,,[#include <sys/types.h>
#include <sys/stat.h>])
-KRB5_AC_REGEX_FUNCS
AC_TYPE_OFF_T
# Fancy caching of perror result...
diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h
index 77bd6e18a..0a19b3668 100644
--- a/src/include/k5-platform.h
+++ b/src/include/k5-platform.h
@@ -70,6 +70,10 @@
#include <unistd.h>
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ifdef _WIN32
#define CAN_COPY_VA_LIST
#endif
@@ -1151,4 +1155,8 @@ extern char *k5_secure_getenv(const char *name);
int k5_dir_filenames(const char *dirname, char ***fnames_out);
void k5_free_filenames(char **fnames);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* K5_PLATFORM_H */
diff --git a/src/include/k5-regex.h b/src/include/k5-regex.h
new file mode 100644
index 000000000..e43f65c71
--- /dev/null
+++ b/src/include/k5-regex.h
@@ -0,0 +1,118 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-regex.h - Compatibility glue for std::regex on Windows */
+
+/*
+ * Copyright (C) 2024 United States Government as represented by the
+ * Secretary of the Navy.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * On POSIX platforms we can use the standardized regcomp()/regexec() function
+ * calls. Windows does not provide POSIX regex functions, but does provide a
+ * C++ interface (std::regex) that has the same functionality.
+ */
+
+#ifndef _K5_REGEX_H_
+#define _K5_REGEX_H_
+
+#ifndef _WIN32
+
+/* On POSIX platforms, just include regex.h. */
+#include <regex.h>
+
+#else /* _WIN32 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* On Windows, emulate the POSIX interface using functions from
+ * libkrb5support. */
+
+typedef struct {
+ size_t re_nsub; /* Number of subexpressions */
+ void *regex; /* Pointer to std::basic_regex */
+ char errmsg[128]; /* Regular expression error message */
+} regex_t;
+
+typedef ssize_t regoff_t;
+
+typedef struct {
+ regoff_t rm_so;
+ regoff_t rm_eo;
+} regmatch_t;
+
+/*
+ * Flags to k5_regcomp()
+ */
+
+#define REG_BASIC 0x00 /* Basic regular expressions */
+#define REG_EXTENDED 0x01 /* Extended regular expressions */
+#define REG_ICASE 0x02 /* Case-insensitive match */
+#define REG_NOSUB 0x04 /* Do not do submatching */
+
+/*
+ * Flags to k5_regexec()
+ */
+
+#define REG_NOTBOL 0x01 /* First character not at beginning of line */
+#define REG_NOTEOL 0x02 /* Last character not at end of line */
+
+/*
+ * Error return codes for k5_regcomp()/k5_regexec()
+ *
+ * We only define REG_NOMATCH and REG_BADPAT, since no Kerberos code looks
+ * for anything other than success and REG_NOMATCH.
+ */
+
+#define REG_NOMATCH 1
+#define REG_BADPAT 2
+
+/*
+ * Note that we don't follow the POSIX API exactly because k5_regexec()
+ * doesn't declare regex_t as const; that's so we can store an error
+ * string.
+ */
+int k5_regcomp(regex_t *preg, const char *pattern, int flags);
+int k5_regexec(regex_t *preg, const char *string, size_t,
+ regmatch_t pmatch[], int flags);
+size_t k5_regerror(int code, const regex_t *preg, char *errmsg,
+ size_t errmsg_size);
+void k5_regfree(regex_t *preg);
+
+#define regcomp k5_regcomp
+#define regexec k5_regexec
+#define regerror k5_regerror
+#define regfree k5_regfree
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _WIN32 */
+#endif /* _K5_REGEX_H_ */
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
index f964e5ca9..e45551a20 100644
--- a/src/kadmin/dbutil/dump.c
+++ b/src/kadmin/dbutil/dump.c
@@ -34,9 +34,7 @@
#include <kdb.h>
#include <com_err.h>
#include "kdb5_util.h"
-#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
-#include <regex.h>
-#endif /* HAVE_REGEX_H */
+#include "k5-regex.h"
/* Needed for master key conversion. */
static krb5_boolean mkey_convert;
@@ -47,18 +45,6 @@ krb5_kvno new_mkvno;
#define K5Q(x) K5Q1(x)
#define K5CONST_WIDTH_SCANF_STR(x) "%" K5Q(x) "s"
-/* Use compile(3) if no regcomp present. */
-#if !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H)
-#define INIT char *sp = instring;
-#define GETC() (*sp++)
-#define PEEKC() (*sp)
-#define UNGETC(c) (--sp)
-#define RETURN(c) return(c)
-#define ERROR(c)
-#define RE_BUF_SIZE 1024
-#include <regexp.h>
-#endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */
-
typedef krb5_error_code (*dump_func)(krb5_context context,
krb5_db_entry *entry, const char *name,
FILE *fp, krb5_boolean verbose,
@@ -236,23 +222,15 @@ update_ok_file(krb5_context context, int fd)
static int
name_matches(char *name, struct dump_args *args)
{
-#if HAVE_REGCOMP
regex_t reg;
regmatch_t rmatch;
int st;
char errmsg[BUFSIZ];
-#elif HAVE_REGEXP_H
- char regexp_buffer[RE_BUF_SIZE];
-#elif HAVE_RE_COMP
- extern char *re_comp();
- char *re_result;
-#endif /* HAVE_RE_COMP */
int i, match;
/* Check each regular expression in args. */
match = args->nnames ? 0 : 1;
for (i = 0; i < args->nnames && !match; i++) {
-#if HAVE_REGCOMP
/* Compile the regular expression. */
st = regcomp(®, args->names[i], REG_EXTENDED);
if (st) {
@@ -274,29 +252,6 @@ name_matches(char *name, struct dump_args *args)
break;
}
regfree(®);
-#elif HAVE_REGEXP_H
- /* Compile the regular expression. */
- compile(args->names[i], regexp_buffer, ®exp_buffer[RE_BUF_SIZE],
- '\0');
- if (step(name, regexp_buffer)) {
- if (loc1 == name && loc2 == &name[strlen(name)])
- match = 1;
- }
-#elif HAVE_RE_COMP
- /* Compile the regular expression. */
- re_result = re_comp(args->names[i]);
- if (re_result) {
- fprintf(stderr, _("%s: regular expression error: %s\n"), progname,
- re_result);
- break;
- }
- if (re_exec(name))
- match = 1;
-#else /* HAVE_RE_COMP */
- /* If no regular expression support, then just compare the strings. */
- if (!strcmp(args->names[i], name))
- match = 1;
-#endif /* HAVE_REGCOMP */
}
return match;
}
diff --git a/src/kadmin/dbutil/kdb5_mkey.c b/src/kadmin/dbutil/kdb5_mkey.c
index aceb0a9b8..0088c8eaf 100644
--- a/src/kadmin/dbutil/kdb5_mkey.c
+++ b/src/kadmin/dbutil/kdb5_mkey.c
@@ -11,22 +11,7 @@
#include <adm_proto.h>
#include "kdb5_util.h"
#include <time.h>
-
-#if defined(HAVE_COMPILE) && defined(HAVE_STEP)
-#define SOLARIS_REGEXPS
-#elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC)
-#define POSIX_REGEXPS
-#elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC)
-#define BSD_REGEXPS
-#else
-#error I cannot find any regexp functions
-#endif
-#ifdef SOLARIS_REGEXPS
-#include <regexpr.h>
-#endif
-#ifdef POSIX_REGEXPS
-#include <regex.h>
-#endif
+#include "k5-regex.h"
extern krb5_keyblock master_keyblock; /* current mkey */
extern krb5_kvno master_kvno;
@@ -644,15 +629,7 @@ struct update_enc_mkvno {
unsigned int updated;
unsigned int dry_run : 1;
unsigned int verbose : 1;
-#ifdef SOLARIS_REGEXPS
- char *expbuf;
-#endif
-#ifdef POSIX_REGEXPS
regex_t preg;
-#endif
-#if !defined(SOLARIS_REGEXPS) && !defined(POSIX_REGEXPS)
- unsigned char placeholder;
-#endif
};
/* XXX Duplicated in libkadm5srv! */
@@ -667,10 +644,10 @@ struct update_enc_mkvno {
*
* Effects:
*
- * regexp is filled in with allocated memory contained a regular
- * expression to be used with re_comp/compile that matches what the
- * shell-style glob would match. If glob does not contain an "@"
- * character and realm is not NULL, "@*" is appended to the regexp.
+ * regexp is filled in with allocated memory containing a regular
+ * expression that matches what the shell-style glob would match.
+ * If glob does not contain an "@" character and realm is not
+ * NULL, "@*" is appended to the regexp.
*
* Conversion algorithm:
*
@@ -745,7 +722,6 @@ update_princ_encryption_1(void *cb, krb5_db_entry *ent)
struct update_enc_mkvno *p = cb;
char *pname = 0;
krb5_error_code retval;
- int match;
krb5_timestamp now;
int result;
krb5_kvno old_mkvno;
@@ -761,18 +737,8 @@ update_princ_encryption_1(void *cb, krb5_db_entry *ent)
goto skip;
}
-#ifdef SOLARIS_REGEXPS
- match = (step(pname, p->expbuf) != 0);
-#endif
-#ifdef POSIX_REGEXPS
- match = (regexec(&p->preg, pname, 0, NULL, 0) == 0);
-#endif
-#ifdef BSD_REGEXPS
- match = (re_exec(pname) != 0);
-#endif
- if (!match) {
+ if (regexec(&p->preg, pname, 0, NULL, 0) != 0)
goto skip;
- }
p->re_match_count++;
retval = krb5_dbe_get_mkvno(util_context, ent, &old_mkvno);
if (retval) {
@@ -868,9 +834,6 @@ kdb5_update_princ_encryption(int argc, char *argv[])
krb5_error_code retval;
krb5_actkvno_node *actkvno_list = 0;
krb5_db_entry *master_entry = NULL;
-#ifdef BSD_REGEXPS
- char *msg;
-#endif
char *regexp = NULL;
krb5_keyblock *act_mkey;
krb5_keylist_node *master_keylist = krb5_db_mkey_list_alias(util_context);
@@ -917,17 +880,7 @@ kdb5_update_princ_encryption(int argc, char *argv[])
goto cleanup;
}
- if (
-#ifdef SOLARIS_REGEXPS
- ((data.expbuf = compile(regexp, NULL, NULL)) == NULL)
-#endif
-#ifdef POSIX_REGEXPS
- ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0)
-#endif
-#ifdef BSD_REGEXPS
- ((msg = (char *) re_comp(regexp)) != NULL)
-#endif
- ) {
+ if (regcomp(&data.preg, regexp, REG_NOSUB) != 0) {
/* XXX syslog msg or regerr(regerrno) */
com_err(progname, 0, _("error compiling converted regexp '%s'"),
regexp);
@@ -1004,9 +957,7 @@ kdb5_update_princ_encryption(int argc, char *argv[])
cleanup:
krb5_db_free_principal(util_context, master_entry);
free(regexp);
-#ifdef POSIX_REGEXPS
regfree(&data.preg);
-#endif
memset(&new_master_keyblock, 0, sizeof(new_master_keyblock));
krb5_dbe_free_actkvno_list(util_context, actkvno_list);
}
diff --git a/src/lib/kadm5/srv/Makefile.in b/src/lib/kadm5/srv/Makefile.in
index d218ea487..9e173b048 100644
--- a/src/lib/kadm5/srv/Makefile.in
+++ b/src/lib/kadm5/srv/Makefile.in
@@ -21,7 +21,7 @@ SHLIB_EXPDEPS=\
$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
$(COM_ERR_DEPLIB) $(SUPPORT_LIBDEP)
SHLIB_EXPLIBS = -lgssrpc -lgssapi_krb5 -lkdb5 $(KDB5_DB_LIB) -lkrb5 \
- -lk5crypto $(SUPPORT_LIB) $(COM_ERR_LIB) @GEN_LIB@ $(LIBS)
+ -lk5crypto $(SUPPORT_LIB) $(COM_ERR_LIB) $(LIBS)
RELDIR=kadm5/srv
SRCS = $(srcdir)/pwqual.c \
diff --git a/src/lib/kadm5/srv/svr_iters.c b/src/lib/kadm5/srv/svr_iters.c
index d5a99dea0..4b26bc939 100644
--- a/src/lib/kadm5/srv/svr_iters.c
+++ b/src/lib/kadm5/srv/svr_iters.c
@@ -6,25 +6,11 @@
*/
#include "autoconf.h"
-#if defined(HAVE_COMPILE) && defined(HAVE_STEP)
-#define SOLARIS_REGEXPS
-#elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC)
-#define POSIX_REGEXPS
-#elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC)
-#define BSD_REGEXPS
-#else
-#error I cannot find any regexp functions
-#endif
#include <sys/types.h>
#include <string.h>
#include <kadm5/admin.h>
-#ifdef SOLARIS_REGEXPS
-#include <regexpr.h>
-#endif
-#ifdef POSIX_REGEXPS
-#include <regex.h>
-#endif
+#include "k5-regex.h"
#include <stdlib.h>
#include "server_internal.h"
@@ -35,12 +21,7 @@ struct iter_data {
int n_names, sz_names;
unsigned int malloc_failed;
char *exp;
-#ifdef SOLARIS_REGEXPS
- char *expbuf;
-#endif
-#ifdef POSIX_REGEXPS
regex_t preg;
-#endif
};
/* XXX Duplicated in kdb5_util! */
@@ -56,9 +37,9 @@ struct iter_data {
* Effects:
*
* regexp is filled in with allocated memory contained a regular
- * expression to be used with re_comp/compile that matches what the
- * shell-style glob would match. If glob does not contain an "@"
- * character and realm is not NULL, "@*" is appended to the regexp.
+ * expression that matches what the shell-style glob would match.
+ * If glob does not contain an "@" character and realm is not
+ * NULL, "@*" is appended to the regexp.
*
* Conversion algorithm:
*
@@ -130,15 +111,7 @@ static kadm5_ret_t glob_to_regexp(char *glob, char *realm, char **regexp)
static void get_either_iter(struct iter_data *data, char *name)
{
int match;
-#ifdef SOLARIS_REGEXPS
- match = (step(name, data->expbuf) != 0);
-#endif
-#ifdef POSIX_REGEXPS
match = (regexec(&data->preg, name, 0, NULL, 0) == 0);
-#endif
-#ifdef BSD_REGEXPS
- match = (re_exec(name) != 0);
-#endif
if (match) {
if (data->n_names == data->sz_names) {
int new_sz = data->sz_names * 2;
@@ -184,9 +157,6 @@ static kadm5_ret_t kadm5_get_either(int princ,
int *count)
{
struct iter_data data;
-#ifdef BSD_REGEXPS
- char *msg;
-#endif
char *regexp = NULL;
int i, ret;
kadm5_server_handle_t handle = server_handle;
@@ -202,18 +172,7 @@ static kadm5_ret_t kadm5_get_either(int princ,
®exp)) != KADM5_OK)
return ret;
- if (
-#ifdef SOLARIS_REGEXPS
- ((data.expbuf = compile(regexp, NULL, NULL)) == NULL)
-#endif
-#ifdef POSIX_REGEXPS
- ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0)
-#endif
-#ifdef BSD_REGEXPS
- ((msg = (char *) re_comp(regexp)) != NULL)
-#endif
- )
- {
+ if (regcomp(&data.preg, regexp, REG_NOSUB) != 0) {
/* XXX syslog msg or regerr(regerrno) */
free(regexp);
return EINVAL;
@@ -236,9 +195,7 @@ static kadm5_ret_t kadm5_get_either(int princ,
}
free(regexp);
-#ifdef POSIX_REGEXPS
regfree(&data.preg);
-#endif
if ( !ret && data.malloc_failed)
ret = ENOMEM;
if ( ret ) {
diff --git a/src/lib/krb5/Makefile.in b/src/lib/krb5/Makefile.in
index 67fd7c009..ece308460 100644
--- a/src/lib/krb5/Makefile.in
+++ b/src/lib/krb5/Makefile.in
@@ -45,7 +45,7 @@ RELDIR=krb5
SHLIB_EXPDEPS = \
$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
$(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
-SHLIB_EXPLIBS=-lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) @GEN_LIB@ \
+SHLIB_EXPLIBS=-lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) \
@MACOS_FRAMEWORK@ $(LIBS)
all-unix: all-liblinks
diff --git a/src/lib/krb5/os/localauth_rule.c b/src/lib/krb5/os/localauth_rule.c
index 056857633..860a1e40e 100644
--- a/src/lib/krb5/os/localauth_rule.c
+++ b/src/lib/krb5/os/localauth_rule.c
@@ -68,9 +68,7 @@
#include "os-proto.h"
#include <krb5/localauth_plugin.h>
#include <ctype.h>
-
-#ifdef HAVE_REGEX_H
-#include <regex.h>
+#include "k5-regex.h"
/* Process the match portion of a rule and update *contextp. Return
* KRB5_LNAME_NOTRANS if selstring doesn't match the regexp. */
@@ -303,17 +301,6 @@ cleanup:
return ret;
}
-#else /* HAVE_REGEX_H */
-
-static krb5_error_code
-an2ln_rule(krb5_context context, krb5_localauth_moddata data, const char *type,
- const char *rule, krb5_const_principal aname, char **lname_out)
-{
- return KRB5_LNAME_NOTRANS;
-}
-
-#endif
-
static void
freestr(krb5_context context, krb5_localauth_moddata data, char *str)
{
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
index 86d5a950a..f63e44a4d 100644
--- a/src/util/support/Makefile.in
+++ b/src/util/support/Makefile.in
@@ -58,6 +58,11 @@ SECURE_GETENV_OBJ= @SECURE_GETENV_OBJ@
##DOS##SECURE_GETENV_ST_OBJ=
##DOS##SECURE_GETENV_OBJ=
+K5_REGEX_ST_OBJ=
+K5_REGEX_OBJ=
+##DOS##K5_REGEX_ST_OBJ= regex.o
+##DOS##K5_REGEX_OBJ= $(OUTPRE)regex.$(OBJEXT)
+
IPC_ST_OBJ=
IPC_OBJ=
##DOS##IPC_ST_OBJ= ipc_stream.o
@@ -99,7 +104,8 @@ STLIBOBJS= \
$(MKSTEMP_ST_OBJ) \
$(GETOPT_ST_OBJ) \
$(GETOPT_LONG_ST_OBJ) \
- $(SECURE_GETENV_OBJ)
+ $(SECURE_GETENV_OBJ) \
+ $(K5_REGEX_ST_OBJ)
LIBOBJS= \
$(OUTPRE)threads.$(OBJEXT) \
@@ -128,7 +134,8 @@ LIBOBJS= \
$(MKSTEMP_OBJ) \
$(GETOPT_OBJ) \
$(GETOPT_LONG_OBJ) \
- $(SECURE_GETENV_OBJ)
+ $(SECURE_GETENV_OBJ) \
+ $(K5_REGEX_OBJ)
SRCS=\
$(srcdir)/threads.c \
@@ -164,7 +171,8 @@ SRCS=\
$(srcdir)/t_utf16.c \
$(srcdir)/getopt.c \
$(srcdir)/getopt_long.c \
- $(srcdir)/secure_getenv.c
+ $(srcdir)/secure_getenv.c \
+ $(srcdir)/regex.c
SHLIB_EXPDEPS =
# Add -lm if dumping thread stats, for sqrt.
@@ -193,7 +201,8 @@ SHLIB_EXPORT_FILE=libkrb5support.exports
EXTRA_SUPPORT_SYMS= @EXTRA_SUPPORT_SYMS@
##DOS##EXTRA_SUPPORT_SYMS= krb5int_mkstemp krb5int_strlcpy krb5int_strlcat \
##DOS## k5_getopt k5_getopt_long \
-##DOS## krb5int_vasprintf krb5int_asprintf krb5int_gettimeofday $(IPC_SYMS)
+##DOS## krb5int_vasprintf krb5int_asprintf krb5int_gettimeofday $(IPC_SYMS) \
+##DOS## k5_regcomp k5_regexec k5_regerror k5_regfree
##DOS##DATA_SUPPORT_SYMS= k5_opterr k5_optind k5_optopt k5_optarg
##DOS##!if 0
diff --git a/src/util/support/regex.cpp b/src/util/support/regex.cpp
new file mode 100644
index 000000000..5b6ef0344
--- /dev/null
+++ b/src/util/support/regex.cpp
@@ -0,0 +1,153 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* regex.cpp - Glue routines to std::regex functions */
+
+/*
+ * Copyright (C) 2024 United States Government as represented by the
+ * Secretary of the Navy.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * These functions provide a mostly-complete POSIX regex(3)
+ * implementation using C++ std::regex. Deficiencies are noted below.
+ */
+
+#include "k5-platform.h"
+#include "k5-regex.h"
+
+#include <regex>
+
+/*
+ * Our implementation of regcomp() which calls into std::regex. We implement
+ * the standard flags, but not the non-portable extensions present on some
+ * platforms.
+ */
+extern "C" int
+k5_regcomp(regex_t *preg, const char *pattern, int cflags)
+{
+ std::regex *r;
+ std::regex_constants::syntax_option_type flags;
+
+ memset(preg, 0, sizeof(*preg));
+
+ flags = (cflags & REG_EXTENDED) ? std::regex::extended : std::regex::basic;
+ if (cflags & REG_ICASE)
+ flags |= std::regex::icase;
+ if (cflags & REG_NOSUB)
+ flags |= std::regex::nosubs;
+
+ try {
+ r = new std::regex(pattern, flags);
+ preg->regex = r;
+ preg->re_nsub = r->mark_count();
+ } catch (std::regex_error& e) {
+ /* Save the error message in errmsg. We don't actually use the
+ * error code for anything; return REG_BADPAT for everything. */
+ strlcpy(preg->errmsg, e.what(), sizeof(preg->errmsg));
+ return REG_BADPAT;
+ }
+
+ return 0;
+}
+
+extern "C" int
+k5_regexec(regex_t *preg, const char *string, size_t nmatch,
+ regmatch_t pmatch[], int eflags)
+{
+ size_t i;
+ std::cmatch cm;
+ std::regex_constants::match_flag_type flags;
+ std::regex *r = static_cast<std::regex *>(preg->regex);
+
+ flags = std::regex_constants::match_default;
+ if (eflags & REG_NOTBOL)
+ flags |= std::regex_constants::match_not_bol;
+ if (eflags & REG_NOTEOL)
+ flags |= std::regex_constants::match_not_eol;
+
+ try {
+ if (!std::regex_search(string, cm, *r, flags))
+ return REG_NOMATCH;
+
+ /*
+ * If given, fill in pmatch with the full match string and any
+ * sub-matches. If we set nosub previously we shouldn't have any
+ * submatches, but should still have the first element which refers to
+ * the whole match string.
+ */
+
+ for (i = 0; i < nmatch; i++) {
+ /*
+ * If we're past the end of the match list (cm.size()) or
+ * this sub-match didn't match (!cm[i].matched()) then
+ * return -1 for those array members.
+ */
+ if (i >= cm.size() || !cm[i].matched) {
+ pmatch[i].rm_so = pmatch[i].rm_eo = -1;
+ } else {
+ pmatch[i].rm_so = cm.position(i);
+ pmatch[i].rm_eo = cm.position(i) + cm.length(i);
+ }
+ }
+ } catch (std::regex_error& e) {
+ /* See above. */
+ strlcpy(preg->errmsg, e.what(), sizeof(preg->errmsg));
+ return REG_BADPAT;
+ }
+
+ return 0;
+}
+
+/*
+ * Report back an error string. We don't use the errcode for anything, just
+ * the error string stored in regex_t. If we don't have an error string,
+ * return an "unknown error" message.
+ */
+extern "C" size_t
+k5_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+{
+ const char *err;
+ size_t errlen;
+
+ err = preg->errmsg;
+ if (*err == '\0')
+ err = "Unknown regular expression error";
+
+ if (errbuf != NULL && errbuf_size > 0)
+ strlcpy(errbuf, err, errbuf_size);
+ return strlen(err);
+}
+
+extern "C" void
+k5_regfree(regex_t *preg)
+{
+ if (preg->regex == NULL)
+ return;
+ delete static_cast<std::regex *>(preg->regex);
+ memset(preg, 0, sizeof(*preg));
+}
More information about the cvs-krb5
mailing list