diff options
author | Cy Schubert <cy@FreeBSD.org> | 2018-04-03 19:36:00 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2018-04-03 19:36:00 +0000 |
commit | b0e4d68d5124581ae353493d69bea352de4cff8a (patch) | |
tree | 43300ec43e83eccd367fd76fdfdefba2dcd7d8f4 /src | |
parent | 33a9b234e7087f573ef08cd7318c6497ba08b439 (diff) | |
download | src-vendor/krb5.tar.gz src-vendor/krb5.zip |
Import MIT KRB5 1.16.vendor/krb5/1.16vendor/krb5
Notes
Notes:
svn path=/vendor-crypto/krb5/dist/; revision=331939
svn path=/vendor-crypto/krb5/1.16/; revision=331941; tag=vendor/krb5/1.16
Diffstat (limited to 'src')
415 files changed, 21898 insertions, 14289 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 2ebf2fb4d0c2..ac9a2a060485 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -12,14 +12,17 @@ SUBDIRS=util include lib \ plugins/audit/test \ @audit_plugin@ \ plugins/kadm5_hook/test \ + plugins/kadm5_auth/test \ plugins/hostrealm/test \ plugins/localauth/test \ plugins/pwqual/test \ plugins/authdata/greet_server \ plugins/authdata/greet_client \ + plugins/certauth/test \ plugins/kdb/db2 \ @ldap_plugin_dir@ \ plugins/kdb/test \ + plugins/kdcpolicy/test \ plugins/preauth/otp \ plugins/preauth/pkinit \ plugins/preauth/test \ @@ -501,7 +504,7 @@ check-pytests-no: check-postrecurse $(SKIPTESTS) check-cmocka-no: check-postrecurse - @echo 'Skipped cmocka tests due to missing library or header file' >> \ + @echo 'Skipped cmocka tests: cmocka library or header not found' >> \ $(SKIPTESTS) # Create a test realm and spawn a shell in an environment pointing to it. @@ -520,6 +523,7 @@ pyrunenv.vals: Makefile done > $@ echo "tls_impl = '$(TLS_IMPL)'" >> $@ echo "have_sasl = '$(HAVE_SASL)'" >> $@ + echo "sizeof_time_t = $(SIZEOF_TIME_T)" >> $@ runenv.py: pyrunenv.vals echo 'env = {}' > $@ diff --git a/src/aclocal.m4 b/src/aclocal.m4 index 9c46da4b5956..d6d1279c3f4f 100644 --- a/src/aclocal.m4 +++ b/src/aclocal.m4 @@ -169,7 +169,7 @@ if test "$enable_thread_support" = yes ; then fi dnl Maybe this should be inside the conditional above? Doesn't cache.... if test "$enable_thread_support" = yes; then - ACX_PTHREAD(,[AC_MSG_ERROR([cannot determine options for enabling thread support; try --disable-thread-support])]) + AX_PTHREAD(,[AC_MSG_ERROR([cannot determine options for enabling thread support; try --disable-thread-support])]) AC_MSG_NOTICE(PTHREAD_CC = $PTHREAD_CC) AC_MSG_NOTICE(PTHREAD_CFLAGS = $PTHREAD_CFLAGS) AC_MSG_NOTICE(PTHREAD_LIBS = $PTHREAD_LIBS) @@ -450,13 +450,13 @@ krb5_ac_warn_cflags_set=${WARN_CFLAGS+set} krb5_ac_warn_cxxflags_set=${WARN_CXXFLAGS+set} ]) dnl -AC_DEFUN(TRY_WARN_CC_FLAG,[dnl +AC_DEFUN(TRY_WARN_CC_FLAG_1,[dnl cachevar=`echo "krb5_cv_cc_flag_$1" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[[^a-zA-Z0-9_]]/_/g` AC_CACHE_CHECK([if C compiler supports $1], [$cachevar], [# first try without, then with AC_TRY_COMPILE([], 1;, [old_cflags="$CFLAGS" - CFLAGS="$CFLAGS $1" + CFLAGS="$CFLAGS $cflags_warning_test_flags $1" AC_TRY_COMPILE([], 1;, eval $cachevar=yes, eval $cachevar=no) CFLAGS="$old_cflags"], [AC_MSG_ERROR(compiling simple test program with $CFLAGS failed)])]) @@ -466,6 +466,21 @@ AC_DEFUN(TRY_WARN_CC_FLAG,[dnl eval flag_supported='${'$cachevar'}' ])dnl dnl +dnl Are additional flags needed to make unsupported warning options +dnl get reported as errors? +AC_DEFUN(CHECK_CC_WARNING_TEST_FLAGS,[dnl + cflags_warning_test_flags= + TRY_WARN_CC_FLAG_1(-Werror=unknown-warning-option) + if test $flag_supported = yes; then + cflags_warning_test_flags=-Werror=unknown-warning-option + fi +])dnl +dnl +AC_DEFUN(TRY_WARN_CC_FLAG,[dnl +AC_REQUIRE([CHECK_CC_WARNING_TEST_FLAGS])dnl +TRY_WARN_CC_FLAG_1($1)dnl +])dnl +dnl AC_DEFUN(WITH_CC,[dnl AC_REQUIRE([KRB5_AC_CHECK_FOR_CFLAGS])dnl AC_REQUIRE([AC_PROG_CC])dnl @@ -528,7 +543,7 @@ if test "$GCC" = yes ; then TRY_WARN_CC_FLAG(-Wno-format-zero-length) # Other flags here may not be supported on some versions of # gcc that people want to use. - for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof error=uninitialized error=pointer-arith error=int-conversion error=incompatible-pointer-types error=discarded-qualifiers ; do + for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof error=uninitialized no-maybe-uninitialized error=pointer-arith error=int-conversion error=incompatible-pointer-types error=discarded-qualifiers error=implicit-int ; do TRY_WARN_CC_FLAG(-W$flag) done # old-style-definition? generates many, many warnings @@ -615,8 +630,16 @@ else # works, but it also means that declaration-in-code warnings won't # be issued. # -v -fd -errwarn=E_DECLARATION_IN_CODE ... - WARN_CFLAGS="-errtags=yes -errwarn=E_BAD_PTR_INT_COMBINATION,E_BAD_PTR_INT_COMB_ARG,E_PTR_TO_VOID_IN_ARITHMETIC,E_NO_IMPLICIT_DECL_ALLOWED,E_ATTRIBUTE_PARAM_UNDEFINED" - WARN_CXXFLAGS="-errtags=yes +w +w2 -xport64" + if test "x$krb5_ac_warn_cflags_set" = xset ; then + AC_MSG_NOTICE(not adding extra warning flags because WARN_CFLAGS was set) + else + WARN_CFLAGS="-errtags=yes -errwarn=E_BAD_PTR_INT_COMBINATION,E_BAD_PTR_INT_COMB_ARG,E_PTR_TO_VOID_IN_ARITHMETIC,E_NO_IMPLICIT_DECL_ALLOWED,E_ATTRIBUTE_PARAM_UNDEFINED" + fi + if test "x$krb5_ac_warn_cxxflags_set" = xset ; then + AC_MSG_NOTICE(not adding extra warning flags because WARN_CXXFLAGS was set) + else + WARN_CXXFLAGS="-errtags=yes +w +w2 -xport64" + fi fi fi AC_SUBST(WARN_CFLAGS) @@ -1352,7 +1375,6 @@ dnl ============================================================= dnl Internal function for testing for getpeername prototype dnl AC_DEFUN([KRB5_GETPEERNAME_ARGS],[ -AC_DEFINE([GETPEERNAME_ARG2_TYPE],GETSOCKNAME_ARG2_TYPE,[Type of getpeername second argument.]) AC_DEFINE([GETPEERNAME_ARG3_TYPE],GETSOCKNAME_ARG3_TYPE,[Type of getpeername second argument.]) ]) dnl @@ -1397,7 +1419,6 @@ if test "$sock_set" = no; then fi res1=`echo "$res1" | tr -d '*' | sed -e 's/ *$//'` res2=`echo "$res2" | tr -d '*' | sed -e 's/ *$//'` -AC_DEFINE_UNQUOTED([GETSOCKNAME_ARG2_TYPE],$res1,[Type of pointer target for argument 2 to getsockname]) AC_DEFINE_UNQUOTED([GETSOCKNAME_ARG3_TYPE],$res2,[Type of pointer target for argument 3 to getsockname]) ]) dnl @@ -1634,8 +1655,8 @@ if test $krb5_cv_pragma_weak_ref = yes ; then fi]) dnl dnl -m4_include(config/ac-archive/acx_pthread.m4) -m4_include(config/ac-archive/relpaths.m4) +m4_include(config/ac-archive/ax_pthread.m4) +m4_include(config/ac-archive/ax_recursive_eval.m4) dnl dnl dnl diff --git a/src/appl/gss-sample/t_gss_sample.py b/src/appl/gss-sample/t_gss_sample.py index 8a6b0304f890..0299e45904b8 100755 --- a/src/appl/gss-sample/t_gss_sample.py +++ b/src/appl/gss-sample/t_gss_sample.py @@ -31,22 +31,20 @@ gss_server = os.path.join(appdir, 'gss-server') # Run a gss-server process and a gss-client process, with additional # gss-client flags given by options and additional gss-server flags # given by server_options. Return the output of gss-client. -def run_client_server(realm, options, server_options, expected_code=0): +def run_client_server(realm, options, server_options, **kwargs): portstr = str(realm.server_port()) server_args = [gss_server, '-export', '-port', portstr] server_args += server_options + ['host'] server = realm.start_server(server_args, 'starting...') - out = realm.run([gss_client, '-port', portstr] + options + - [hostname, 'host', 'testmsg'], expected_code=expected_code) + realm.run([gss_client, '-port', portstr] + options + + [hostname, 'host', 'testmsg'], **kwargs) stop_daemon(server) - return out # Run a gss-server and gss-client process, and verify that gss-client # displayed the expected output for a successful negotiation. def server_client_test(realm, options, server_options): - out = run_client_server(realm, options, server_options) - if 'Signature verified.' not in out: - fail('Expected message not seen in gss-client output') + run_client_server(realm, options, server_options, + expected_msg='Signature verified.') # Make up a filename to hold user's initial credentials. def ccache_savefile(realm): @@ -81,10 +79,10 @@ def pw_test(realm, options, server_options=[]): # IAKERB, gss_aqcuire_cred_with_password() otherwise). def wrong_pw_test(realm, options, server_options=[], iakerb=False): options = options + ['-user', realm.user_princ, '-pass', 'wrongpw'] - out = run_client_server(realm, options, server_options, expected_code=1) failed_op = 'initializing context' if iakerb else 'acquiring creds' - if 'GSS-API error ' + failed_op not in out: - fail('Expected error not seen in gss-client output') + msg = 'GSS-API error ' + failed_op + run_client_server(realm, options, server_options, expected_code=1, + expected_msg=msg) # Perform a test of the server and client with initial credentials # obtained with the client keytab diff --git a/src/appl/simple/client/sim_client.c b/src/appl/simple/client/sim_client.c index bd3c38c72aa7..cda7d220c406 100644 --- a/src/appl/simple/client/sim_client.c +++ b/src/appl/simple/client/sim_client.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) { int sock, i; - unsigned int len; + socklen_t len; int flags = 0; /* flags for sendto() */ struct servent *serv; struct hostent *host; diff --git a/src/appl/simple/server/sim_server.c b/src/appl/simple/server/sim_server.c index fce5a9c6fd69..f09489c35d30 100644 --- a/src/appl/simple/server/sim_server.c +++ b/src/appl/simple/server/sim_server.c @@ -33,6 +33,7 @@ */ #include "krb5.h" +#include "port-sockets.h" #include <stdio.h> #include <string.h> #include <unistd.h> @@ -64,7 +65,7 @@ int main(int argc, char *argv[]) { int sock, i; - unsigned int len; + socklen_t len; int flags = 0; /* for recvfrom() */ int on = 1; struct servent *serv; diff --git a/src/appl/user_user/t_user2user.py b/src/appl/user_user/t_user2user.py index 8bdef8e07b90..2a7d03f8dc87 100755 --- a/src/appl/user_user/t_user2user.py +++ b/src/appl/user_user/t_user2user.py @@ -10,9 +10,9 @@ for realm in multipass_realms(): else: srv_output = realm.start_server(['./uuserver', '9999'], 'Server started') - output = realm.run(['./uuclient', hostname, 'testing message', '9999']) - if 'uu-client: server says \"Hello, other end of connection.\"' not in output: - fail('Message not echoed back.') + msg = 'uu-client: server says "Hello, other end of connection."' + realm.run(['./uuclient', hostname, 'testing message', '9999'], + expected_msg=msg) success('User-2-user test programs') diff --git a/src/ccapi/server/mac/ccs_os_pipe.c b/src/ccapi/server/mac/ccs_os_pipe.c index 67f90307a230..5d9fff20755d 100644 --- a/src/ccapi/server/mac/ccs_os_pipe.c +++ b/src/ccapi/server/mac/ccs_os_pipe.c @@ -27,7 +27,7 @@ #include "ccs_os_pipe.h" #include <mach/port.h> -/* On Mac OS X ccs_pipe_t is a mach_port_t */ +/* On macOS ccs_pipe_t is a mach_port_t */ /* ------------------------------------------------------------------------ */ @@ -73,7 +73,7 @@ cc_int32 ccs_os_pipe_release (ccs_pipe_t io_pipe) { cc_int32 err = 0; - /* Nothing to do here on Mac OS X */ + /* Nothing to do here on macOS */ return cci_check_error (err); } diff --git a/src/clients/kcpytkt/kcpytkt.c b/src/clients/kcpytkt/kcpytkt.c index 47147cdc3207..0b8802261e9e 100644 --- a/src/clients/kcpytkt/kcpytkt.c +++ b/src/clients/kcpytkt/kcpytkt.c @@ -7,26 +7,29 @@ #include "k5-platform.h" static char *prog; +static int quiet = 0; -static void xusage() +static void +xusage() { - fprintf(stderr, "xusage: %s [-c from_ccache] [-e etype] [-f flags] dest_ccache service1 service2 ...\n", prog); + fprintf(stderr, "xusage: %s [-c from_ccache] [-e etype] [-f flags] " + "dest_ccache service1 service2 ...\n", prog); exit(1); } -int quiet = 0; +static void +do_kcpytkt(int argc, char *argv[], char *fromccachestr, char *etypestr, + int flags); -static void do_kcpytkt (int argc, char *argv[], char *fromccachestr, char *etypestr, int flags); - -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { int option; - char *etypestr = 0; - char *fromccachestr = 0; + char *etypestr = NULL, *fromccachestr = NULL; int flags = 0; prog = strrchr(argv[0], '/'); - prog = prog ? (prog + 1) : argv[0]; + prog = (prog != NULL) ? prog + 1 : argv[0]; while ((option = getopt(argc, argv, "c:e:f:hq")) != -1) { switch (option) { @@ -49,25 +52,24 @@ int main(int argc, char *argv[]) } } - if ((argc - optind) < 2) + if (argc - optind < 2) xusage(); do_kcpytkt(argc - optind, argv + optind, fromccachestr, etypestr, flags); return 0; } -static void do_kcpytkt (int count, char *names[], - char *fromccachestr, char *etypestr, int flags) +static void +do_kcpytkt(int count, char *names[], const char *fromccachestr, char *etypestr, + int flags) { krb5_context context; krb5_error_code ret; - int i, errors; krb5_enctype etype; - krb5_ccache fromccache; - krb5_ccache destccache; + krb5_ccache fromccache, destccache; krb5_principal me; krb5_creds in_creds, out_creds; - int retflags; + int i, errors, retflags; char *princ; ret = krb5_init_context(&context); @@ -75,8 +77,7 @@ static void do_kcpytkt (int count, char *names[], com_err(prog, ret, "while initializing krb5 library"); exit(1); } - - if (etypestr) { + if (etypestr != NULL) { ret = krb5_string_to_enctype(etypestr, &etype); if (ret) { com_err(prog, ret, "while converting etype"); @@ -88,7 +89,7 @@ static void do_kcpytkt (int count, char *names[], retflags = KRB5_TC_MATCH_SRV_NAMEONLY; } - if (fromccachestr) + if (fromccachestr != NULL) ret = krb5_cc_resolve(context, fromccachestr, &fromccache); else ret = krb5_cc_default(context, &fromccache); @@ -118,9 +119,10 @@ static void do_kcpytkt (int count, char *names[], ret = krb5_parse_name(context, names[i], &in_creds.server); if (ret) { - if (!quiet) + if (!quiet) { fprintf(stderr, "%s: %s while parsing principal name\n", names[i], error_message(ret)); + } errors++; continue; } @@ -140,24 +142,18 @@ static void do_kcpytkt (int count, char *names[], if (ret) { fprintf(stderr, "%s: %s while retrieving credentials\n", princ, error_message(ret)); - krb5_free_unparsed_name(context, princ); - errors++; continue; } ret = krb5_cc_store_cred(context, destccache, &out_creds); - krb5_free_principal(context, in_creds.server); - if (ret) { fprintf(stderr, "%s: %s while removing credentials\n", princ, error_message(ret)); - krb5_free_cred_contents(context, &out_creds); krb5_free_unparsed_name(context, princ); - errors++; continue; } diff --git a/src/clients/kdeltkt/kdeltkt.c b/src/clients/kdeltkt/kdeltkt.c index 9c7a549f970b..cd0bf637db69 100644 --- a/src/clients/kdeltkt/kdeltkt.c +++ b/src/clients/kdeltkt/kdeltkt.c @@ -7,26 +7,28 @@ #include "k5-platform.h" static char *prog; +static int quiet = 0; -static void xusage() +static void +xusage() { - fprintf(stderr, "xusage: %s [-c ccache] [-e etype] [-f flags] service1 service2 ...\n", prog); + fprintf(stderr, "xusage: %s [-c ccache] [-e etype] [-f flags] service1 " + "service2 ...\n", prog); exit(1); } -int quiet = 0; +static void +do_kdeltkt(int argc, char *argv[], char *ccachestr, char *etypestr, int flags); -static void do_kdeltkt (int argc, char *argv[], char *ccachestr, char *etypestr, int flags); - -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { int option; - char *etypestr = 0; - char *ccachestr = 0; + char *etypestr = NULL, *ccachestr = NULL; int flags = 0; prog = strrchr(argv[0], '/'); - prog = prog ? (prog + 1) : argv[0]; + prog = (prog != NULL) ? prog + 1 : argv[0]; while ((option = getopt(argc, argv, "c:e:f:hq")) != -1) { switch (option) { @@ -49,15 +51,16 @@ int main(int argc, char *argv[]) } } - if ((argc - optind) < 1) + if (argc - optind < 1) xusage(); do_kdeltkt(argc - optind, argv + optind, ccachestr, etypestr, flags); return 0; } -static void do_kdeltkt (int count, char *names[], - char *ccachestr, char *etypestr, int flags) +static void +do_kdeltkt(int count, char *names[], const char *ccachestr, char *etypestr, + int flags) { krb5_context context; krb5_error_code ret; @@ -75,7 +78,7 @@ static void do_kdeltkt (int count, char *names[], exit(1); } - if (etypestr) { + if (etypestr != NULL) { ret = krb5_string_to_enctype(etypestr, &etype); if (ret) { com_err(prog, ret, "while converting etype"); @@ -111,9 +114,10 @@ static void do_kdeltkt (int count, char *names[], ret = krb5_parse_name(context, names[i], &in_creds.server); if (ret) { - if (!quiet) + if (!quiet) { fprintf(stderr, "%s: %s while parsing principal name\n", names[i], error_message(ret)); + } errors++; continue; } @@ -133,9 +137,7 @@ static void do_kdeltkt (int count, char *names[], if (ret) { fprintf(stderr, "%s: %s while retrieving credentials\n", princ, error_message(ret)); - krb5_free_unparsed_name(context, princ); - errors++; continue; } @@ -147,14 +149,11 @@ static void do_kdeltkt (int count, char *names[], if (ret) { fprintf(stderr, "%s: %s while removing credentials\n", princ, error_message(ret)); - krb5_free_cred_contents(context, &out_creds); krb5_free_unparsed_name(context, princ); - errors++; continue; } - krb5_free_unparsed_name(context, princ); krb5_free_cred_contents(context, &out_creds); } diff --git a/src/clients/kdestroy/kdestroy.c b/src/clients/kdestroy/kdestroy.c index f95554903ece..0bf83586c14f 100644 --- a/src/clients/kdestroy/kdestroy.c +++ b/src/clients/kdestroy/kdestroy.c @@ -41,7 +41,7 @@ extern int optind; extern char *optarg; #ifndef _WIN32 -#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x)) +#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x)) #else #define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) #endif @@ -49,10 +49,9 @@ extern char *optarg; char *progname; -static void usage() +static void +usage() { -#define KRB_AVAIL_STRING(x) ((x)?"available":"not available") - fprintf(stderr, _("Usage: %s [-A] [-q] [-c cache_name]\n"), progname); fprintf(stderr, _("\t-A destroy all credential caches in collection\n")); fprintf(stderr, _("\t-q quiet mode\n")); @@ -64,18 +63,18 @@ static void usage() static void print_remaining_cc_warning(krb5_context context) { - krb5_error_code retval; + krb5_error_code ret; krb5_ccache cache; krb5_cccol_cursor cursor; - retval = krb5_cccol_cursor_new(context, &cursor); - if (retval) { - com_err(progname, retval, _("while listing credential caches")); + ret = krb5_cccol_cursor_new(context, &cursor); + if (ret) { + com_err(progname, ret, _("while listing credential caches")); exit(1); } - retval = krb5_cccol_cursor_next(context, cursor, &cache); - if (retval == 0 && cache != NULL) { + ret = krb5_cccol_cursor_next(context, cursor, &cache); + if (ret == 0 && cache != NULL) { fprintf(stderr, _("Other credential caches present, use -A to destroy all\n")); krb5_cc_close(context, cache); @@ -85,20 +84,14 @@ print_remaining_cc_warning(krb5_context context) } int -main(argc, argv) - int argc; - char **argv; +main(int argc, char *argv[]) { - krb5_context kcontext; - krb5_error_code retval; - int c; + krb5_context context; + krb5_error_code ret; krb5_ccache cache = NULL; krb5_cccol_cursor cursor; char *cache_name = NULL; - int code = 0; - int errflg = 0; - int quiet = 0; - int all = 0; + int code = 0, errflg = 0, quiet = 0, all = 0, c; setlocale(LC_ALL, ""); progname = GET_PROGNAME(argv[0]); @@ -135,62 +128,61 @@ main(argc, argv) if (optind != argc) errflg++; - if (errflg) { + if (errflg) usage(); - } - retval = krb5_init_context(&kcontext); - if (retval) { - com_err(progname, retval, _("while initializing krb5")); + ret = krb5_init_context(&context); + if (ret) { + com_err(progname, ret, _("while initializing krb5")); exit(1); } + if (cache_name != NULL) { + code = krb5_cc_set_default_name(context, cache_name); + if (code) { + com_err(progname, code, _("while setting default cache name")); + exit(1); + } + } + if (all) { - code = krb5_cccol_cursor_new(kcontext, &cursor); + code = krb5_cccol_cursor_new(context, &cursor); if (code) { com_err(progname, code, _("while listing credential caches")); exit(1); } - while ((code = krb5_cccol_cursor_next(kcontext, cursor, - &cache)) == 0 && cache != NULL) { - code = krb5_cc_get_full_name(kcontext, cache, &cache_name); + while (krb5_cccol_cursor_next(context, cursor, &cache) == 0 && + cache != NULL) { + code = krb5_cc_get_full_name(context, cache, &cache_name); if (code) { com_err(progname, code, _("composing ccache name")); exit(1); } - code = krb5_cc_destroy(kcontext, cache); + code = krb5_cc_destroy(context, cache); if (code && code != KRB5_FCC_NOFILE) { com_err(progname, code, _("while destroying cache %s"), cache_name); } - krb5_free_string(kcontext, cache_name); + krb5_free_string(context, cache_name); } - krb5_cccol_cursor_free(kcontext, &cursor); - krb5_free_context(kcontext); + krb5_cccol_cursor_free(context, &cursor); + krb5_free_context(context); return 0; } - if (cache_name) { - code = krb5_cc_resolve (kcontext, cache_name, &cache); - if (code != 0) { - com_err(progname, code, _("while resolving %s"), cache_name); - exit(1); - } - } else { - code = krb5_cc_default(kcontext, &cache); - if (code) { - com_err(progname, code, _("while getting default ccache")); - exit(1); - } + code = krb5_cc_default(context, &cache); + if (code) { + com_err(progname, code, _("while resolving ccache")); + exit(1); } - code = krb5_cc_destroy (kcontext, cache); + code = krb5_cc_destroy(context, cache); if (code != 0) { - com_err (progname, code, _("while destroying cache")); + com_err(progname, code, _("while destroying cache")); if (code != KRB5_FCC_NOFILE) { - if (quiet) + if (quiet) { fprintf(stderr, _("Ticket cache NOT destroyed!\n")); - else { + } else { fprintf(stderr, _("Ticket cache %cNOT%c destroyed!\n"), BELL_CHAR, BELL_CHAR); } @@ -199,8 +191,9 @@ main(argc, argv) } if (!quiet && !errflg) - print_remaining_cc_warning(kcontext); + print_remaining_cc_warning(context); + + krb5_free_context(context); - krb5_free_context(kcontext); return errflg; } diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c index f1cd1b73db60..a518284ea568 100644 --- a/src/clients/kinit/kinit.c +++ b/src/clients/kinit/kinit.c @@ -26,7 +26,7 @@ #include "autoconf.h" #include <k5-int.h> -#include "k5-platform.h" /* for asprintf and getopt */ +#include "k5-platform.h" /* For asprintf and getopt */ #include <krb5.h> #include "extern.h" #include <locale.h> @@ -37,40 +37,41 @@ #include <com_err.h> #ifndef _WIN32 -#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x)) +#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x)) #else #define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) #endif #ifdef HAVE_PWD_H #include <pwd.h> -static -char * get_name_from_os() +static char * +get_name_from_os() { struct passwd *pw; - if ((pw = getpwuid((int) getuid()))) - return pw->pw_name; - return 0; + + pw = getpwuid(getuid()); + return (pw != NULL) ? pw->pw_name : NULL; } #else /* HAVE_PWD_H */ #ifdef _WIN32 -static -char * get_name_from_os() +static char * +get_name_from_os() { static char name[1024]; DWORD name_size = sizeof(name); + if (GetUserName(name, &name_size)) { - name[sizeof(name)-1] = 0; /* Just to be extra safe */ + name[sizeof(name) - 1] = '\0'; /* Just to be extra safe */ return name; } else { - return 0; + return NULL; } } #else /* _WIN32 */ -static -char * get_name_from_os() +static char * +get_name_from_os() { - return 0; + return NULL; } #endif /* _WIN32 */ #endif /* HAVE_PWD_H */ @@ -81,7 +82,7 @@ typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type; struct k_opts { - /* in seconds */ + /* In seconds */ krb5_deltat starttime; krb5_deltat lifetime; krb5_deltat rlife; @@ -99,11 +100,11 @@ struct k_opts int verbose; - char* principal_name; - char* service_name; - char* keytab_name; - char* k5_in_cache_name; - char* k5_out_cache_name; + char *principal_name; + char *service_name; + char *keytab_name; + char *k5_in_cache_name; + char *k5_out_cache_name; char *armor_ccache; action_type action; @@ -121,46 +122,39 @@ struct k5_data krb5_context ctx; krb5_ccache in_cc, out_cc; krb5_principal me; - char* name; + char *name; krb5_boolean switch_to_cache; }; -/* if struct[2] == NULL, then long_getopt acts as if the short flag - struct[3] was specified. If struct[2] != NULL, then struct[3] is - stored in *(struct[2]), the array index which was specified is - stored in *index, and long_getopt() returns 0. */ - +/* + * If struct[2] == NULL, then long_getopt acts as if the short flag struct[3] + * were specified. If struct[2] != NULL, then struct[3] is stored in + * *(struct[2]), the array index which was specified is stored in *index, and + * long_getopt() returns 0. + */ const char *shopts = "r:fpFPn54aAVl:s:c:kit:T:RS:vX:CEI:"; +#define USAGE_BREAK "\n\t" + static void usage() { -#define USAGE_BREAK "\n\t" - -#define USAGE_LONG_FORWARDABLE " | --forwardable | --noforwardable" -#define USAGE_LONG_PROXIABLE " | --proxiable | --noproxiable" -#define USAGE_LONG_ADDRESSES " | --addresses | --noaddresses" -#define USAGE_LONG_CANONICALIZE " | --canonicalize" -#define USAGE_LONG_ENTERPRISE " | --enterprise" -#define USAGE_LONG_REQUESTPAC "--request-pac | --no-request-pac" -#define USAGE_BREAK_LONG USAGE_BREAK - fprintf(stderr, "Usage: %s [-V] " "[-l lifetime] [-s start_time] " USAGE_BREAK "[-r renewable_life] " - "[-f | -F" USAGE_LONG_FORWARDABLE "] " - USAGE_BREAK_LONG - "[-p | -P" USAGE_LONG_PROXIABLE "] " - USAGE_BREAK_LONG + "[-f | -F | --forwardable | --noforwardable] " + USAGE_BREAK + "[-p | -P | --proxiable | --noproxiable] " + USAGE_BREAK "-n " - "[-a | -A" USAGE_LONG_ADDRESSES "] " - USAGE_BREAK_LONG - "[" USAGE_LONG_REQUESTPAC "] " - USAGE_BREAK_LONG - "[-C" USAGE_LONG_CANONICALIZE "] " + "[-a | -A | --addresses | --noaddresses] " USAGE_BREAK - "[-E" USAGE_LONG_ENTERPRISE "] " + "[--request-pac | --no-request-pac] " + USAGE_BREAK + "[-C | --canonicalize] " + USAGE_BREAK + "[-E | --enterprise] " USAGE_BREAK "[-v] [-R] " "[-k [-i|-t keytab_file]] " @@ -199,15 +193,17 @@ usage() } static krb5_context errctx; -static void extended_com_err_fn (const char *myprog, errcode_t code, - const char *fmt, va_list args) +static void +extended_com_err_fn(const char *myprog, errcode_t code, const char *fmt, + va_list args) { const char *emsg; - emsg = krb5_get_error_message (errctx, code); - fprintf (stderr, "%s: %s ", myprog, emsg); - krb5_free_error_message (errctx, emsg); - vfprintf (stderr, fmt, args); - fprintf (stderr, "\n"); + + emsg = krb5_get_error_message(errctx, code); + fprintf(stderr, "%s: %s ", myprog, emsg); + krb5_free_error_message(errctx, emsg); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); } static int @@ -215,18 +211,13 @@ add_preauth_opt(struct k_opts *opts, char *av) { char *sep, *v; krb5_gic_opt_pa_data *p, *x; + size_t newsize = (opts->num_pa_opts + 1) * sizeof(*opts->pa_opts); + + x = realloc(opts->pa_opts, newsize); + if (x == NULL) + return ENOMEM; + opts->pa_opts = x; - if (opts->num_pa_opts == 0) { - opts->pa_opts = malloc(sizeof(krb5_gic_opt_pa_data)); - if (opts->pa_opts == NULL) - return ENOMEM; - } else { - size_t newsize = (opts->num_pa_opts + 1) * sizeof(krb5_gic_opt_pa_data); - x = realloc(opts->pa_opts, newsize); - if (x == NULL) - return ENOMEM; - opts->pa_opts = x; - } p = &opts->pa_opts[opts->num_pa_opts]; sep = strchr(av, '='); if (sep) { @@ -242,10 +233,7 @@ add_preauth_opt(struct k_opts *opts, char *av) } static char * -parse_options(argc, argv, opts) - int argc; - char **argv; - struct k_opts* opts; +parse_options(int argc, char **argv, struct k_opts *opts) { struct option long_options[] = { { "noforwardable", 0, NULL, 'F' }, @@ -260,7 +248,7 @@ parse_options(argc, argv, opts) { "no-request-pac", 0, &opts->not_request_pac, 1 }, { NULL, 0, NULL, 0 } }; - krb5_error_code code; + krb5_error_code ret; int errflg = 0; int i; @@ -271,16 +259,16 @@ parse_options(argc, argv, opts) break; case 'l': /* Lifetime */ - code = krb5_string_to_deltat(optarg, &opts->lifetime); - if (code != 0 || opts->lifetime == 0) { + ret = krb5_string_to_deltat(optarg, &opts->lifetime); + if (ret || opts->lifetime == 0) { fprintf(stderr, _("Bad lifetime value %s\n"), optarg); errflg++; } break; case 'r': /* Renewable Time */ - code = krb5_string_to_deltat(optarg, &opts->rlife); - if (code != 0 || opts->rlife == 0) { + ret = krb5_string_to_deltat(optarg, &opts->rlife); + if (ret || opts->rlife == 0) { fprintf(stderr, _("Bad lifetime value %s\n"), optarg); errflg++; } @@ -307,18 +295,18 @@ parse_options(argc, argv, opts) opts->no_addresses = 1; break; case 's': - code = krb5_string_to_deltat(optarg, &opts->starttime); - if (code != 0 || opts->starttime == 0) { + ret = krb5_string_to_deltat(optarg, &opts->starttime); + if (ret || opts->starttime == 0) { /* Parse as an absolute time; intentionally undocumented * but left for backwards compatibility. */ krb5_timestamp abs_starttime; - code = krb5_string_to_timestamp(optarg, &abs_starttime); - if (code != 0 || abs_starttime == 0) { + ret = krb5_string_to_timestamp(optarg, &abs_starttime); + if (ret || abs_starttime == 0) { fprintf(stderr, _("Bad start time value %s\n"), optarg); errflg++; } else { - opts->starttime = abs_starttime - time(0); + opts->starttime = ts_delta(abs_starttime, time(NULL)); } } break; @@ -332,8 +320,7 @@ parse_options(argc, argv, opts) opts->use_client_keytab = 1; break; case 't': - if (opts->keytab_name) - { + if (opts->keytab_name != NULL) { fprintf(stderr, _("Only one -t option allowed.\n")); errflg++; } else { @@ -341,10 +328,12 @@ parse_options(argc, argv, opts) } break; case 'T': - if (opts->armor_ccache) { + if (opts->armor_ccache != NULL) { fprintf(stderr, _("Only one armor_ccache\n")); errflg++; - } else opts->armor_ccache = optarg; + } else { + opts->armor_ccache = optarg; + } break; case 'R': opts->action = RENEW; @@ -353,8 +342,7 @@ parse_options(argc, argv, opts) opts->action = VALIDATE; break; case 'c': - if (opts->k5_out_cache_name) - { + if (opts->k5_out_cache_name != NULL) { fprintf(stderr, _("Only one -c option allowed\n")); errflg++; } else { @@ -362,7 +350,7 @@ parse_options(argc, argv, opts) } break; case 'I': - if (opts->k5_in_cache_name) { + if (opts->k5_in_cache_name != NULL) { fprintf(stderr, _("Only one -I option allowed\n")); errflg++; } else { @@ -370,10 +358,9 @@ parse_options(argc, argv, opts) } break; case 'X': - code = add_preauth_opt(opts, optarg); - if (code) - { - com_err(progname, code, _("while adding preauth option")); + ret = add_preauth_opt(opts, optarg); + if (ret) { + com_err(progname, ret, _("while adding preauth option")); errflg++; } break; @@ -398,59 +385,49 @@ parse_options(argc, argv, opts) } } - if (opts->forwardable && opts->not_forwardable) - { + if (opts->forwardable && opts->not_forwardable) { fprintf(stderr, _("Only one of -f and -F allowed\n")); errflg++; } - if (opts->proxiable && opts->not_proxiable) - { + if (opts->proxiable && opts->not_proxiable) { fprintf(stderr, _("Only one of -p and -P allowed\n")); errflg++; } - if (opts->request_pac && opts->not_request_pac) - { + if (opts->request_pac && opts->not_request_pac) { fprintf(stderr, _("Only one of --request-pac and --no-request-pac " "allowed\n")); errflg++; } - if (opts->addresses && opts->no_addresses) - { + if (opts->addresses && opts->no_addresses) { fprintf(stderr, _("Only one of -a and -A allowed\n")); errflg++; } - if (opts->keytab_name != NULL && opts->use_client_keytab == 1) - { + if (opts->keytab_name != NULL && opts->use_client_keytab == 1) { fprintf(stderr, _("Only one of -t and -i allowed\n")); errflg++; } if ((opts->keytab_name != NULL || opts->use_client_keytab == 1) && - opts->action != INIT_KT) - { + opts->action != INIT_KT) { opts->action = INIT_KT; fprintf(stderr, _("keytab specified, forcing -k\n")); } - if (argc - optind > 1) { fprintf(stderr, _("Extra arguments (starting with \"%s\").\n"), - argv[optind+1]); + argv[optind + 1]); errflg++; } - if (errflg) { + if (errflg) usage(); - } - opts->principal_name = (optind == argc-1) ? argv[optind] : 0; + opts->principal_name = (optind == argc - 1) ? argv[optind] : 0; return opts->principal_name; } static int -k5_begin(opts, k5) - struct k_opts* opts; - struct k5_data* k5; +k5_begin(struct k_opts *opts, struct k5_data *k5) { - krb5_error_code code = 0; + krb5_error_code ret; int success = 0; int flags = opts->enterprise ? KRB5_PRINCIPAL_PARSE_ENTERPRISE : 0; krb5_ccache defcache = NULL; @@ -459,17 +436,17 @@ k5_begin(opts, k5) const char *deftype = NULL; char *defrealm, *name; - code = krb5_init_context(&k5->ctx); - if (code) { - com_err(progname, code, _("while initializing Kerberos 5 library")); + ret = krb5_init_context(&k5->ctx); + if (ret) { + com_err(progname, ret, _("while initializing Kerberos 5 library")); return 0; } errctx = k5->ctx; if (opts->k5_out_cache_name) { - code = krb5_cc_resolve(k5->ctx, opts->k5_out_cache_name, &k5->out_cc); - if (code != 0) { - com_err(progname, code, _("resolving ccache %s"), + ret = krb5_cc_resolve(k5->ctx, opts->k5_out_cache_name, &k5->out_cc); + if (ret) { + com_err(progname, ret, _("resolving ccache %s"), opts->k5_out_cache_name); goto cleanup; } @@ -480,9 +457,9 @@ k5_begin(opts, k5) } else { /* Resolve the default ccache and get its type and default principal * (if it is initialized). */ - code = krb5_cc_default(k5->ctx, &defcache); - if (code) { - com_err(progname, code, _("while getting default ccache")); + ret = krb5_cc_default(k5->ctx, &defcache); + if (ret) { + com_err(progname, ret, _("while getting default ccache")); goto cleanup; } deftype = krb5_cc_get_type(k5->ctx, defcache); @@ -493,59 +470,58 @@ k5_begin(opts, k5) /* Choose a client principal name. */ if (opts->principal_name != NULL) { /* Use the specified principal name. */ - code = krb5_parse_name_flags(k5->ctx, opts->principal_name, flags, - &k5->me); - if (code) { - com_err(progname, code, _("when parsing name %s"), + ret = krb5_parse_name_flags(k5->ctx, opts->principal_name, flags, + &k5->me); + if (ret) { + com_err(progname, ret, _("when parsing name %s"), opts->principal_name); goto cleanup; } } else if (opts->anonymous) { /* Use the anonymous principal for the local realm. */ - code = krb5_get_default_realm(k5->ctx, &defrealm); - if (code) { - com_err(progname, code, _("while getting default realm")); + ret = krb5_get_default_realm(k5->ctx, &defrealm); + if (ret) { + com_err(progname, ret, _("while getting default realm")); goto cleanup; } - code = krb5_build_principal_ext(k5->ctx, &k5->me, - strlen(defrealm), defrealm, - strlen(KRB5_WELLKNOWN_NAMESTR), - KRB5_WELLKNOWN_NAMESTR, - strlen(KRB5_ANONYMOUS_PRINCSTR), - KRB5_ANONYMOUS_PRINCSTR, - 0); + ret = krb5_build_principal_ext(k5->ctx, &k5->me, + strlen(defrealm), defrealm, + strlen(KRB5_WELLKNOWN_NAMESTR), + KRB5_WELLKNOWN_NAMESTR, + strlen(KRB5_ANONYMOUS_PRINCSTR), + KRB5_ANONYMOUS_PRINCSTR, 0); krb5_free_default_realm(k5->ctx, defrealm); - if (code) { - com_err(progname, code, _("while building principal")); + if (ret) { + com_err(progname, ret, _("while building principal")); goto cleanup; } } else if (opts->action == INIT_KT && opts->use_client_keytab) { /* Use the first entry from the client keytab. */ - code = krb5_kt_client_default(k5->ctx, &keytab); - if (code) { - com_err(progname, code, + ret = krb5_kt_client_default(k5->ctx, &keytab); + if (ret) { + com_err(progname, ret, _("When resolving the default client keytab")); goto cleanup; } - code = k5_kt_get_principal(k5->ctx, keytab, &k5->me); + ret = k5_kt_get_principal(k5->ctx, keytab, &k5->me); krb5_kt_close(k5->ctx, keytab); - if (code) { - com_err(progname, code, + if (ret) { + com_err(progname, ret, _("When determining client principal name from keytab")); goto cleanup; } } else if (opts->action == INIT_KT) { /* Use the default host/service name. */ - code = krb5_sname_to_principal(k5->ctx, NULL, NULL, KRB5_NT_SRV_HST, - &k5->me); - if (code) { - com_err(progname, code, + ret = krb5_sname_to_principal(k5->ctx, NULL, NULL, KRB5_NT_SRV_HST, + &k5->me); + if (ret) { + com_err(progname, ret, _("when creating default server principal name")); goto cleanup; } if (k5->me->realm.data[0] == 0) { - code = krb5_unparse_name(k5->ctx, k5->me, &k5->name); - if (code == 0) { + ret = krb5_unparse_name(k5->ctx, k5->me, &k5->name); + if (ret == 0) { com_err(progname, KRB5_ERR_HOST_REALM_UNKNOWN, _("(principal %s)"), k5->name); } else { @@ -574,23 +550,22 @@ k5_begin(opts, k5) fprintf(stderr, _("Unable to identify user\n")); goto cleanup; } - code = krb5_parse_name_flags(k5->ctx, name, flags, &k5->me); - if (code) { - com_err(progname, code, _("when parsing name %s"), - name); + ret = krb5_parse_name_flags(k5->ctx, name, flags, &k5->me); + if (ret) { + com_err(progname, ret, _("when parsing name %s"), name); goto cleanup; } } if (k5->out_cc == NULL && krb5_cc_support_switch(k5->ctx, deftype)) { /* Use an existing cache for the client principal if we can. */ - code = krb5_cc_cache_match(k5->ctx, k5->me, &k5->out_cc); - if (code != 0 && code != KRB5_CC_NOTFOUND) { - com_err(progname, code, _("while searching for ccache for %s"), + ret = krb5_cc_cache_match(k5->ctx, k5->me, &k5->out_cc); + if (ret && ret != KRB5_CC_NOTFOUND) { + com_err(progname, ret, _("while searching for ccache for %s"), opts->principal_name); goto cleanup; } - if (code == 0) { + if (!ret) { if (opts->verbose) { fprintf(stderr, _("Using existing cache: %s\n"), krb5_cc_get_name(k5->ctx, k5->out_cc)); @@ -599,9 +574,9 @@ k5_begin(opts, k5) } else if (defcache_princ != NULL) { /* Create a new cache to avoid overwriting the initialized default * cache. */ - code = krb5_cc_new_unique(k5->ctx, deftype, NULL, &k5->out_cc); - if (code) { - com_err(progname, code, _("while generating new ccache")); + ret = krb5_cc_new_unique(k5->ctx, deftype, NULL, &k5->out_cc); + if (ret) { + com_err(progname, ret, _("while generating new ccache")); goto cleanup; } if (opts->verbose) { @@ -623,9 +598,9 @@ k5_begin(opts, k5) } if (opts->k5_in_cache_name) { - code = krb5_cc_resolve(k5->ctx, opts->k5_in_cache_name, &k5->in_cc); - if (code != 0) { - com_err(progname, code, _("resolving ccache %s"), + ret = krb5_cc_resolve(k5->ctx, opts->k5_in_cache_name, &k5->in_cc); + if (ret) { + com_err(progname, ret, _("resolving ccache %s"), opts->k5_in_cache_name); goto cleanup; } @@ -635,10 +610,9 @@ k5_begin(opts, k5) } } - - code = krb5_unparse_name(k5->ctx, k5->me, &k5->name); - if (code) { - com_err(progname, code, _("when unparsing name")); + ret = krb5_unparse_name(k5->ctx, k5->me, &k5->name); + if (ret) { + com_err(progname, ret, _("when unparsing name")); goto cleanup; } if (opts->verbose) @@ -656,33 +630,22 @@ cleanup: } static void -k5_end(k5) - struct k5_data* k5; +k5_end(struct k5_data *k5) { - if (k5->name) - krb5_free_unparsed_name(k5->ctx, k5->name); - if (k5->me) - krb5_free_principal(k5->ctx, k5->me); - if (k5->in_cc) + krb5_free_unparsed_name(k5->ctx, k5->name); + krb5_free_principal(k5->ctx, k5->me); + if (k5->in_cc != NULL) krb5_cc_close(k5->ctx, k5->in_cc); - if (k5->out_cc) + if (k5->out_cc != NULL) krb5_cc_close(k5->ctx, k5->out_cc); - if (k5->ctx) - krb5_free_context(k5->ctx); + krb5_free_context(k5->ctx); errctx = NULL; memset(k5, 0, sizeof(*k5)); } -static krb5_error_code -KRB5_CALLCONV -kinit_prompter( - krb5_context ctx, - void *data, - const char *name, - const char *banner, - int num_prompts, - krb5_prompt prompts[] -) +static krb5_error_code KRB5_CALLCONV +kinit_prompter(krb5_context ctx, void *data, const char *name, + const char *banner, int num_prompts, krb5_prompt prompts[]) { krb5_boolean *pwprompt = data; krb5_prompt_type *ptypes; @@ -694,34 +657,27 @@ kinit_prompter( if (ptypes != NULL && ptypes[i] == KRB5_PROMPT_TYPE_PASSWORD) *pwprompt = TRUE; } - return krb5_prompter_posix(ctx, data, name, banner, num_prompts, prompts); } static int -k5_kinit(opts, k5) - struct k_opts* opts; - struct k5_data* k5; +k5_kinit(struct k_opts *opts, struct k5_data *k5) { int notix = 1; krb5_keytab keytab = 0; krb5_creds my_creds; - krb5_error_code code = 0; + krb5_error_code ret; krb5_get_init_creds_opt *options = NULL; krb5_boolean pwprompt = FALSE; + krb5_address **addresses = NULL; int i; memset(&my_creds, 0, sizeof(my_creds)); - code = krb5_get_init_creds_opt_alloc(k5->ctx, &options); - if (code) + ret = krb5_get_init_creds_opt_alloc(k5->ctx, &options); + if (ret) goto cleanup; - /* - From this point on, we can goto cleanup because my_creds is - initialized. - */ - if (opts->lifetime) krb5_get_init_creds_opt_set_tkt_life(options, opts->lifetime); if (opts->rlife) @@ -738,63 +694,61 @@ k5_kinit(opts, k5) krb5_get_init_creds_opt_set_canonicalize(options, 1); if (opts->anonymous) krb5_get_init_creds_opt_set_anonymous(options, 1); - if (opts->addresses) - { - krb5_address **addresses = NULL; - code = krb5_os_localaddr(k5->ctx, &addresses); - if (code != 0) { - com_err(progname, code, _("getting local addresses")); + if (opts->addresses) { + ret = krb5_os_localaddr(k5->ctx, &addresses); + if (ret) { + com_err(progname, ret, _("getting local addresses")); goto cleanup; } krb5_get_init_creds_opt_set_address_list(options, addresses); } if (opts->no_addresses) krb5_get_init_creds_opt_set_address_list(options, NULL); - if (opts->armor_ccache) - krb5_get_init_creds_opt_set_fast_ccache_name(k5->ctx, options, opts->armor_ccache); + if (opts->armor_ccache != NULL) { + krb5_get_init_creds_opt_set_fast_ccache_name(k5->ctx, options, + opts->armor_ccache); + } if (opts->request_pac) krb5_get_init_creds_opt_set_pac_request(k5->ctx, options, TRUE); if (opts->not_request_pac) krb5_get_init_creds_opt_set_pac_request(k5->ctx, options, FALSE); - if ((opts->action == INIT_KT) && opts->keytab_name) - { + if (opts->action == INIT_KT && opts->keytab_name != NULL) { #ifndef _WIN32 if (strncmp(opts->keytab_name, "KDB:", 4) == 0) { - code = kinit_kdb_init(&k5->ctx, - krb5_princ_realm(k5->ctx, k5->me)->data); - if (code != 0) { - com_err(progname, code, + ret = kinit_kdb_init(&k5->ctx, k5->me->realm.data); + if (ret) { + com_err(progname, ret, _("while setting up KDB keytab for realm %s"), - krb5_princ_realm(k5->ctx, k5->me)->data); + k5->me->realm.data); goto cleanup; } } #endif - code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab); - if (code != 0) { - com_err(progname, code, _("resolving keytab %s"), + ret = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab); + if (ret) { + com_err(progname, ret, _("resolving keytab %s"), opts->keytab_name); goto cleanup; } if (opts->verbose) fprintf(stderr, _("Using keytab: %s\n"), opts->keytab_name); } else if (opts->action == INIT_KT && opts->use_client_keytab) { - code = krb5_kt_client_default(k5->ctx, &keytab); - if (code != 0) { - com_err(progname, code, _("resolving default client keytab")); + ret = krb5_kt_client_default(k5->ctx, &keytab); + if (ret) { + com_err(progname, ret, _("resolving default client keytab")); goto cleanup; } } for (i = 0; i < opts->num_pa_opts; i++) { - code = krb5_get_init_creds_opt_set_pa(k5->ctx, options, - opts->pa_opts[i].attr, - opts->pa_opts[i].value); - if (code != 0) { - com_err(progname, code, _("while setting '%s'='%s'"), + ret = krb5_get_init_creds_opt_set_pa(k5->ctx, options, + opts->pa_opts[i].attr, + opts->pa_opts[i].value); + if (ret) { + com_err(progname, ret, _("while setting '%s'='%s'"), opts->pa_opts[i].attr, opts->pa_opts[i].value); goto cleanup; } @@ -804,43 +758,39 @@ k5_kinit(opts, k5) } } if (k5->in_cc) { - code = krb5_get_init_creds_opt_set_in_ccache(k5->ctx, options, - k5->in_cc); - if (code) + ret = krb5_get_init_creds_opt_set_in_ccache(k5->ctx, options, + k5->in_cc); + if (ret) goto cleanup; } - code = krb5_get_init_creds_opt_set_out_ccache(k5->ctx, options, - k5->out_cc); - if (code) + ret = krb5_get_init_creds_opt_set_out_ccache(k5->ctx, options, k5->out_cc); + if (ret) goto cleanup; switch (opts->action) { case INIT_PW: - code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me, - 0, kinit_prompter, &pwprompt, - opts->starttime, - opts->service_name, - options); + ret = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me, 0, + kinit_prompter, &pwprompt, + opts->starttime, opts->service_name, + options); break; case INIT_KT: - code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me, - keytab, - opts->starttime, - opts->service_name, - options); + ret = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me, keytab, + opts->starttime, opts->service_name, + options); break; case VALIDATE: - code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->out_cc, - opts->service_name); + ret = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->out_cc, + opts->service_name); break; case RENEW: - code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->out_cc, - opts->service_name); + ret = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->out_cc, + opts->service_name); break; } - if (code) { - char *doing = 0; + if (ret) { + char *doing = NULL; switch (opts->action) { case INIT_PW: case INIT_KT: @@ -856,41 +806,40 @@ k5_kinit(opts, k5) /* If reply decryption failed, or if pre-authentication failed and we * were prompted for a password, assume the password was wrong. */ - if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY || - (pwprompt && code == KRB5KDC_ERR_PREAUTH_FAILED)) { + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY || + (pwprompt && ret == KRB5KDC_ERR_PREAUTH_FAILED)) { fprintf(stderr, _("%s: Password incorrect while %s\n"), progname, doing); } else { - com_err(progname, code, _("while %s"), doing); + com_err(progname, ret, _("while %s"), doing); } goto cleanup; } - if ((opts->action != INIT_PW) && (opts->action != INIT_KT)) { - code = krb5_cc_initialize(k5->ctx, k5->out_cc, opts->canonicalize ? - my_creds.client : k5->me); - if (code) { - com_err(progname, code, _("when initializing cache %s"), - opts->k5_out_cache_name?opts->k5_out_cache_name:""); + if (opts->action != INIT_PW && opts->action != INIT_KT) { + ret = krb5_cc_initialize(k5->ctx, k5->out_cc, opts->canonicalize ? + my_creds.client : k5->me); + if (ret) { + com_err(progname, ret, _("when initializing cache %s"), + opts->k5_out_cache_name ? opts->k5_out_cache_name : ""); goto cleanup; } if (opts->verbose) fprintf(stderr, _("Initialized cache\n")); - code = krb5_cc_store_cred(k5->ctx, k5->out_cc, &my_creds); - if (code) { - com_err(progname, code, _("while storing credentials")); + ret = krb5_cc_store_cred(k5->ctx, k5->out_cc, &my_creds); + if (ret) { + com_err(progname, ret, _("while storing credentials")); goto cleanup; } if (opts->verbose) fprintf(stderr, _("Stored credentials\n")); } notix = 0; - if (k5->switch_to_cache) { - code = krb5_cc_switch(k5->ctx, k5->out_cc); - if (code) { - com_err(progname, code, _("while switching to new ccache")); + ret = krb5_cc_switch(k5->ctx, k5->out_cc); + if (ret) { + com_err(progname, ret, _("while switching to new ccache")); goto cleanup; } } @@ -901,24 +850,21 @@ cleanup: #endif if (options) krb5_get_init_creds_opt_free(k5->ctx, options); - if (my_creds.client == k5->me) { + if (my_creds.client == k5->me) my_creds.client = 0; - } if (opts->pa_opts) { free(opts->pa_opts); opts->pa_opts = NULL; opts->num_pa_opts = 0; } krb5_free_cred_contents(k5->ctx, &my_creds); - if (keytab) + if (keytab != NULL) krb5_kt_close(k5->ctx, keytab); - return notix?0:1; + return notix ? 0 : 1; } int -main(argc, argv) - int argc; - char **argv; +main(int argc, char *argv[]) { struct k_opts opts; struct k5_data k5; @@ -928,11 +874,11 @@ main(argc, argv) progname = GET_PROGNAME(argv[0]); /* Ensure we can be driven from a pipe */ - if(!isatty(fileno(stdin))) + if (!isatty(fileno(stdin))) setvbuf(stdin, 0, _IONBF, 0); - if(!isatty(fileno(stdout))) + if (!isatty(fileno(stdout))) setvbuf(stdout, 0, _IONBF, 0); - if(!isatty(fileno(stderr))) + if (!isatty(fileno(stderr))) setvbuf(stderr, 0, _IONBF, 0); memset(&opts, 0, sizeof(opts)); @@ -940,7 +886,7 @@ main(argc, argv) memset(&k5, 0, sizeof(k5)); - set_com_err_hook (extended_com_err_fn); + set_com_err_hook(extended_com_err_fn); parse_options(argc, argv, &opts); diff --git a/src/clients/kinit/kinit_kdb.c b/src/clients/kinit/kinit_kdb.c index 47baf9010a7b..fbd174bf0c45 100644 --- a/src/clients/kinit/kinit_kdb.c +++ b/src/clients/kinit/kinit_kdb.c @@ -36,38 +36,36 @@ #include <kdb.h> #include "extern.h" -/** Server handle */ +/* Server handle */ static void *server_handle; -/** - * @internal Initialize KDB for given realm - * @param context pointer to context that will be re-initialized - * @@param realm name of realm to initialize - */ +/* Free and reinitialize *pcontext with the KDB opened to the given realm, so + * that it can be used with the KDB keytab type. */ krb5_error_code kinit_kdb_init(krb5_context *pcontext, char *realm) { kadm5_config_params config; - krb5_error_code retval = 0; + krb5_error_code ret; if (*pcontext) { krb5_free_context(*pcontext); *pcontext = NULL; } memset(&config, 0, sizeof config); - retval = kadm5_init_krb5_context(pcontext); - if (retval) - return retval; + + ret = kadm5_init_krb5_context(pcontext); + if (ret) + return ret; + config.mask = KADM5_CONFIG_REALM; config.realm = realm; - retval = kadm5_init(*pcontext, "kinit", NULL /*pass*/, - "kinit", &config, - KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, NULL, - &server_handle); - if (retval) - return retval; - retval = krb5_db_register_keytab(*pcontext); - return retval; + ret = kadm5_init(*pcontext, "kinit", NULL, "kinit", &config, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, NULL, + &server_handle); + if (ret) + return ret; + + return krb5_db_register_keytab(*pcontext); } void diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c index ba19788a25c4..e9e76d8f3be6 100644 --- a/src/clients/klist/klist.c +++ b/src/clients/klist/klist.c @@ -32,13 +32,14 @@ #include <string.h> #include <stdio.h> #include <time.h> + /* Need definition of INET6 before network headers, for IRIX. */ #if defined(HAVE_ARPA_INET_H) #include <arpa/inet.h> #endif #ifndef _WIN32 -#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x)) +#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x)) #else #define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) #endif @@ -56,34 +57,33 @@ int show_adtype = 0, show_all = 0, list_all = 0, use_client_keytab = 0; int show_config = 0; char *defname; char *progname; -krb5_int32 now; +krb5_timestamp now; unsigned int timestamp_width; -krb5_context kcontext; +krb5_context context; -krb5_boolean is_local_tgt (krb5_principal princ, krb5_data *realm); -char * etype_string (krb5_enctype ); -void show_credential (krb5_creds *); +static krb5_boolean is_local_tgt(krb5_principal princ, krb5_data *realm); +static char *etype_string(krb5_enctype ); +static void show_credential(krb5_creds *); -void list_all_ccaches (void); -int list_ccache (krb5_ccache); -void show_all_ccaches (void); -void do_ccache_name (char *); -int show_ccache (krb5_ccache); -int check_ccache (krb5_ccache); -void do_keytab (char *); -void printtime (time_t); -void one_addr (krb5_address *); -void fillit (FILE *, unsigned int, int); +static void list_all_ccaches(void); +static int list_ccache(krb5_ccache); +static void show_all_ccaches(void); +static void do_ccache(void); +static int show_ccache(krb5_ccache); +static int check_ccache(krb5_ccache); +static void do_keytab(const char *); +static void printtime(krb5_timestamp); +static void one_addr(krb5_address *); +static void fillit(FILE *, unsigned int, int); #define DEFAULT 0 #define CCACHE 1 #define KEYTAB 2 -static void usage() +static void +usage() { -#define KRB_AVAIL_STRING(x) ((x)?"available":"not available") - fprintf(stderr, _("Usage: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] " "[-a [-n]]] [-k [-t] [-K]] [name]\n"), progname); fprintf(stderr, _("\t-c specifies credentials cache\n")); @@ -114,21 +114,19 @@ extended_com_err_fn(const char *prog, errcode_t code, const char *fmt, { const char *msg; - msg = krb5_get_error_message(kcontext, code); + msg = krb5_get_error_message(context, code); fprintf(stderr, "%s: %s%s", prog, msg, (*fmt == '\0') ? "" : " "); - krb5_free_error_message(kcontext, msg); + krb5_free_error_message(context, msg); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); } int -main(argc, argv) - int argc; - char **argv; +main(int argc, char *argv[]) { - int c; - char *name; - int mode; + krb5_error_code ret; + char *name, tmp[BUFSIZ]; + int c, mode; setlocale(LC_ALL, ""); progname = GET_PROGNAME(argv[0]); @@ -136,7 +134,7 @@ main(argc, argv) name = NULL; mode = DEFAULT; - /* V=version so v can be used for verbose later if desired. */ + /* V = version so v can be used for verbose later if desired. */ while ((c = getopt(argc, argv, "dfetKsnacki45lAVC")) != -1) { switch (c) { case 'd': @@ -164,11 +162,13 @@ main(argc, argv) show_addresses = 1; break; case 'c': - if (mode != DEFAULT) usage(); + if (mode != DEFAULT) + usage(); mode = CCACHE; break; case 'k': - if (mode != DEFAULT) usage(); + if (mode != DEFAULT) + usage(); mode = KEYTAB; break; case 'i': @@ -198,9 +198,8 @@ main(argc, argv) } } - if (no_resolve && !show_addresses) { + if (no_resolve && !show_addresses) usage(); - } if (mode == DEFAULT || mode == CCACHE) { if (show_time || show_keys) @@ -215,7 +214,7 @@ main(argc, argv) if (argc - optind > 1) { fprintf(stderr, _("Extra arguments (starting with \"%s\").\n"), - argv[optind+1]); + argv[optind + 1]); usage(); } @@ -228,77 +227,82 @@ main(argc, argv) exit(0); } - name = (optind == argc-1) ? argv[optind] : 0; - + name = (optind == argc - 1) ? argv[optind] : NULL; now = time(0); - { - char tmp[BUFSIZ]; - if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) || - !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), - (char *) NULL)) - timestamp_width = (int) strlen(tmp); - else - timestamp_width = 15; + if (!krb5_timestamp_to_sfstring(now, tmp, 20, NULL) || + !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), NULL)) + timestamp_width = (int)strlen(tmp); + else + timestamp_width = 15; + + ret = krb5_init_context(&context); + if (ret) { + com_err(progname, ret, _("while initializing krb5")); + exit(1); } - { - krb5_error_code retval; - retval = krb5_init_context(&kcontext); - if (retval) { - com_err(progname, retval, _("while initializing krb5")); + if (name != NULL && mode != KEYTAB) { + ret = krb5_cc_set_default_name(context, name); + if (ret) { + com_err(progname, ret, _("while setting default cache name")); exit(1); } - - if (list_all) - list_all_ccaches(); - else if (show_all) - show_all_ccaches(); - else if (mode == DEFAULT || mode == CCACHE) - do_ccache_name(name); - else - do_keytab(name); } + if (list_all) + list_all_ccaches(); + else if (show_all) + show_all_ccaches(); + else if (mode == DEFAULT || mode == CCACHE) + do_ccache(); + else + do_keytab(name); return 0; } -void do_keytab(name) - char *name; +static void +do_keytab(const char *name) { + krb5_error_code ret; krb5_keytab kt; krb5_keytab_entry entry; krb5_kt_cursor cursor; - char buf[BUFSIZ]; /* hopefully large enough for any type */ + unsigned int i; + char buf[BUFSIZ]; /* Hopefully large enough for any type */ char *pname; - int code; if (name == NULL && use_client_keytab) { - if ((code = krb5_kt_client_default(kcontext, &kt))) { - com_err(progname, code, _("while getting default client keytab")); + ret = krb5_kt_client_default(context, &kt); + if (ret) { + com_err(progname, ret, _("while getting default client keytab")); exit(1); } } else if (name == NULL) { - if ((code = krb5_kt_default(kcontext, &kt))) { - com_err(progname, code, _("while getting default keytab")); + ret = krb5_kt_default(context, &kt); + if (ret) { + com_err(progname, ret, _("while getting default keytab")); exit(1); } } else { - if ((code = krb5_kt_resolve(kcontext, name, &kt))) { - com_err(progname, code, _("while resolving keytab %s"), name); + ret = krb5_kt_resolve(context, name, &kt); + if (ret) { + com_err(progname, ret, _("while resolving keytab %s"), name); exit(1); } } - if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) { - com_err(progname, code, _("while getting keytab name")); + ret = krb5_kt_get_name(context, kt, buf, BUFSIZ); + if (ret) { + com_err(progname, ret, _("while getting keytab name")); exit(1); } printf("Keytab name: %s\n", buf); - if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) { - com_err(progname, code, _("while starting keytab scan")); + ret = krb5_kt_start_seq_get(context, kt, &cursor); + if (ret) { + com_err(progname, ret, _("while starting keytab scan")); exit(1); } @@ -314,12 +318,14 @@ void do_keytab(name) printf("\n"); } else { printf("KVNO Principal\n"); - printf("---- --------------------------------------------------------------------------\n"); + printf("---- ------------------------------------------------" + "--------------------------\n"); } - while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) { - if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) { - com_err(progname, code, _("while unparsing principal name")); + while ((ret = krb5_kt_next_entry(context, kt, &entry, &cursor)) == 0) { + ret = krb5_unparse_name(context, entry.principal, &pname); + if (ret) { + com_err(progname, ret, _("while unparsing principal name")); exit(1); } printf("%4d ", entry.vno); @@ -332,40 +338,38 @@ void do_keytab(name) printf(" (%s) " , etype_string(entry.key.enctype)); if (show_keys) { printf(" (0x"); - { - unsigned int i; - for (i = 0; i < entry.key.length; i++) - printf("%02x", entry.key.contents[i]); - } + for (i = 0; i < entry.key.length; i++) + printf("%02x", entry.key.contents[i]); printf(")"); } printf("\n"); - krb5_free_unparsed_name(kcontext, pname); - krb5_free_keytab_entry_contents(kcontext, &entry); + krb5_free_unparsed_name(context, pname); + krb5_free_keytab_entry_contents(context, &entry); } - if (code && code != KRB5_KT_END) { - com_err(progname, code, _("while scanning keytab")); + if (ret && ret != KRB5_KT_END) { + com_err(progname, ret, _("while scanning keytab")); exit(1); } - if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) { - com_err(progname, code, _("while ending keytab scan")); + ret = krb5_kt_end_seq_get(context, kt, &cursor); + if (ret) { + com_err(progname, ret, _("while ending keytab scan")); exit(1); } exit(0); } -void -list_all_ccaches(void) +static void +list_all_ccaches() { - krb5_error_code code; + krb5_error_code ret; krb5_ccache cache; krb5_cccol_cursor cursor; int exit_status; - code = krb5_cccol_cursor_new(kcontext, &cursor); - if (code) { + ret = krb5_cccol_cursor_new(context, &cursor); + if (ret) { if (!status_only) - com_err(progname, code, _("while listing ccache collection")); + com_err(progname, ret, _("while listing ccache collection")); exit(1); } @@ -373,31 +377,31 @@ list_all_ccaches(void) printf("%-30s %s\n", "Principal name", "Cache name"); printf("%-30s %s\n", "--------------", "----------"); exit_status = 1; - while (!(code = krb5_cccol_cursor_next(kcontext, cursor, &cache)) && + while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 && cache != NULL) { exit_status = list_ccache(cache) && exit_status; - krb5_cc_close(kcontext, cache); + krb5_cc_close(context, cache); } - krb5_cccol_cursor_free(kcontext, &cursor); + krb5_cccol_cursor_free(context, &cursor); exit(exit_status); } -int +static int list_ccache(krb5_ccache cache) { - krb5_error_code code; + krb5_error_code ret; krb5_principal princ = NULL; char *princname = NULL, *ccname = NULL; int expired, status = 1; - code = krb5_cc_get_principal(kcontext, cache, &princ); - if (code) /* Uninitialized cache file, probably. */ + ret = krb5_cc_get_principal(context, cache, &princ); + if (ret) /* Uninitialized cache file, probably. */ goto cleanup; - code = krb5_unparse_name(kcontext, princ, &princname); - if (code) + ret = krb5_unparse_name(context, princ, &princname); + if (ret) goto cleanup; - code = krb5_cc_get_full_name(kcontext, cache, &ccname); - if (code) + ret = krb5_cc_get_full_name(context, cache, &ccname); + if (ret) goto cleanup; expired = check_ccache(cache); @@ -408,87 +412,82 @@ list_ccache(krb5_ccache cache) printf("\n"); status = 0; + cleanup: - krb5_free_principal(kcontext, princ); - krb5_free_unparsed_name(kcontext, princname); - krb5_free_string(kcontext, ccname); + krb5_free_principal(context, princ); + krb5_free_unparsed_name(context, princname); + krb5_free_string(context, ccname); return status; } -void +static void show_all_ccaches(void) { - krb5_error_code code; + krb5_error_code ret; krb5_ccache cache; krb5_cccol_cursor cursor; krb5_boolean first; int exit_status, st; - code = krb5_cccol_cursor_new(kcontext, &cursor); - if (code) { + ret = krb5_cccol_cursor_new(context, &cursor); + if (ret) { if (!status_only) - com_err(progname, code, _("while listing ccache collection")); + com_err(progname, ret, _("while listing ccache collection")); exit(1); } exit_status = 1; first = TRUE; - while (!(code = krb5_cccol_cursor_next(kcontext, cursor, &cache)) && + while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 && cache != NULL) { if (!status_only && !first) printf("\n"); first = FALSE; st = status_only ? check_ccache(cache) : show_ccache(cache); exit_status = st && exit_status; - krb5_cc_close(kcontext, cache); + krb5_cc_close(context, cache); } - krb5_cccol_cursor_free(kcontext, &cursor); + krb5_cccol_cursor_free(context, &cursor); exit(exit_status); } -void -do_ccache_name(char *name) +static void +do_ccache() { - krb5_error_code code; + krb5_error_code ret; krb5_ccache cache; - if (name == NULL) { - if ((code = krb5_cc_default(kcontext, &cache))) { - if (!status_only) - com_err(progname, code, _("while getting default ccache")); - exit(1); - } - } else { - if ((code = krb5_cc_resolve(kcontext, name, &cache))) { - if (!status_only) - com_err(progname, code, _("while resolving ccache %s"), - name); - exit(1); - } + ret = krb5_cc_default(context, &cache); + if (ret) { + if (!status_only) + com_err(progname, ret, _("while resolving ccache")); + exit(1); } exit(status_only ? check_ccache(cache) : show_ccache(cache)); } /* Display the contents of cache. */ -int +static int show_ccache(krb5_ccache cache) { krb5_cc_cursor cur; krb5_creds creds; krb5_principal princ; - krb5_error_code code; + krb5_error_code ret; - if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) { - com_err(progname, code, ""); + ret = krb5_cc_get_principal(context, cache, &princ); + if (ret) { + com_err(progname, ret, ""); return 1; } - if ((code = krb5_unparse_name(kcontext, princ, &defname))) { - com_err(progname, code, _("while unparsing principal name")); + ret = krb5_unparse_name(context, princ, &defname); + if (ret) { + com_err(progname, ret, _("while unparsing principal name")); return 1; } printf(_("Ticket cache: %s:%s\nDefault principal: %s\n\n"), - krb5_cc_get_type(kcontext, cache), - krb5_cc_get_name(kcontext, cache), defname); + krb5_cc_get_type(context, cache), krb5_cc_get_name(context, cache), + defname); /* XXX Translating would disturb table alignment; skip for now. */ fputs("Valid starting", stdout); fillit(stdout, timestamp_width - sizeof("Valid starting") + 3, (int) ' '); @@ -496,32 +495,34 @@ show_ccache(krb5_ccache cache) fillit(stdout, timestamp_width - sizeof("Expires") + 3, (int) ' '); fputs("Service principal\n", stdout); - if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) { - com_err(progname, code, _("while starting to retrieve tickets")); + ret = krb5_cc_start_seq_get(context, cache, &cur); + if (ret) { + com_err(progname, ret, _("while starting to retrieve tickets")); return 1; } - while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) { - if (show_config || !krb5_is_config_principal(kcontext, creds.server)) + while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) { + if (show_config || !krb5_is_config_principal(context, creds.server)) show_credential(&creds); - krb5_free_cred_contents(kcontext, &creds); + krb5_free_cred_contents(context, &creds); } - krb5_free_principal(kcontext, princ); - krb5_free_unparsed_name(kcontext, defname); + krb5_free_principal(context, princ); + krb5_free_unparsed_name(context, defname); defname = NULL; - if (code == KRB5_CC_END) { - if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) { - com_err(progname, code, _("while finishing ticket retrieval")); + if (ret == KRB5_CC_END) { + ret = krb5_cc_end_seq_get(context, cache, &cur); + if (ret) { + com_err(progname, ret, _("while finishing ticket retrieval")); return 1; } return 0; } else { - com_err(progname, code, _("while retrieving a ticket")); + com_err(progname, ret, _("while retrieving a ticket")); return 1; } } /* Return 0 if cache is accessible, present, and unexpired; return 1 if not. */ -int +static int check_ccache(krb5_ccache cache) { krb5_error_code ret; @@ -530,26 +531,26 @@ check_ccache(krb5_ccache cache) krb5_principal princ; krb5_boolean found_tgt, found_current_tgt, found_current_cred; - if (krb5_cc_get_principal(kcontext, cache, &princ) != 0) + if (krb5_cc_get_principal(context, cache, &princ) != 0) return 1; - if (krb5_cc_start_seq_get(kcontext, cache, &cur) != 0) + if (krb5_cc_start_seq_get(context, cache, &cur) != 0) return 1; found_tgt = found_current_tgt = found_current_cred = FALSE; - while (!(ret = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) { + while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) { if (is_local_tgt(creds.server, &princ->realm)) { found_tgt = TRUE; - if (creds.times.endtime > now) + if (ts_after(creds.times.endtime, now)) found_current_tgt = TRUE; - } else if (!krb5_is_config_principal(kcontext, creds.server) && - creds.times.endtime > now) { + } else if (!krb5_is_config_principal(context, creds.server) && + ts_after(creds.times.endtime, now)) { found_current_cred = TRUE; } - krb5_free_cred_contents(kcontext, &creds); + krb5_free_cred_contents(context, &creds); } - krb5_free_principal(kcontext, princ); + krb5_free_principal(context, princ); if (ret != KRB5_CC_END) return 1; - if (krb5_cc_end_seq_get(kcontext, cache, &cur) != 0) + if (krb5_cc_end_seq_get(context, cache, &cur) != 0) return 1; /* If the cache contains at least one local TGT, require that it be @@ -560,7 +561,7 @@ check_ccache(krb5_ccache cache) } /* Return true if princ is the local krbtgt principal for local_realm. */ -krb5_boolean +static krb5_boolean is_local_tgt(krb5_principal princ, krb5_data *realm) { return princ->length == 2 && data_eq(princ->realm, *realm) && @@ -568,24 +569,20 @@ is_local_tgt(krb5_principal princ, krb5_data *realm) data_eq(princ->data[1], *realm); } -char * -etype_string(enctype) - krb5_enctype enctype; +static char * +etype_string(krb5_enctype enctype) { static char buf[100]; - krb5_error_code retval; + krb5_error_code ret; - if ((retval = krb5_enctype_to_name(enctype, FALSE, buf, sizeof(buf)))) { - /* XXX if there's an error != EINVAL, I should probably report it */ + ret = krb5_enctype_to_name(enctype, FALSE, buf, sizeof(buf)); + if (ret) snprintf(buf, sizeof(buf), "etype %d", enctype); - } - return buf; } static char * -flags_string(cred) - register krb5_creds *cred; +flags_string(krb5_creds *cred) { static char buf[32]; int i = 0; @@ -615,27 +612,21 @@ flags_string(cred) if (cred->ticket_flags & TKT_FLG_TRANSIT_POLICY_CHECKED) buf[i++] = 'T'; if (cred->ticket_flags & TKT_FLG_OK_AS_DELEGATE) - buf[i++] = 'O'; /* D/d are taken. Use short strings? */ + buf[i++] = 'O'; /* D/d are taken. Use short strings? */ if (cred->ticket_flags & TKT_FLG_ANONYMOUS) buf[i++] = 'a'; buf[i] = '\0'; - return(buf); + return buf; } -void -printtime(tv) - time_t tv; +static void +printtime(krb5_timestamp ts) { - char timestring[BUFSIZ]; - char fill; - - fill = ' '; - if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv, - timestring, - timestamp_width+1, - &fill)) { + char timestring[BUFSIZ], fill = ' '; + + if (!krb5_timestamp_to_sfstring(ts, timestring, timestamp_width + 1, + &fill)) printf("%s", timestring); - } } static void @@ -663,35 +654,35 @@ print_config_data(int col, krb5_data *data) putchar('\n'); } -void -show_credential(cred) - register krb5_creds * cred; +static void +show_credential(krb5_creds *cred) { - krb5_error_code retval; + krb5_error_code ret; krb5_ticket *tkt; char *name, *sname, *flags; int extra_field = 0, ccol = 0, i; - retval = krb5_unparse_name(kcontext, cred->client, &name); - if (retval) { - com_err(progname, retval, _("while unparsing client name")); + ret = krb5_unparse_name(context, cred->client, &name); + if (ret) { + com_err(progname, ret, _("while unparsing client name")); return; } - retval = krb5_unparse_name(kcontext, cred->server, &sname); - if (retval) { - com_err(progname, retval, _("while unparsing server name")); - krb5_free_unparsed_name(kcontext, name); + ret = krb5_unparse_name(context, cred->server, &sname); + if (ret) { + com_err(progname, ret, _("while unparsing server name")); + krb5_free_unparsed_name(context, name); return; } if (!cred->times.starttime) cred->times.starttime = cred->times.authtime; - if (!krb5_is_config_principal(kcontext, cred->server)) { + if (!krb5_is_config_principal(context, cred->server)) { printtime(cred->times.starttime); - putchar(' '); putchar(' '); + putchar(' '); + putchar(' '); printtime(cred->times.endtime); - putchar(' '); putchar(' '); - + putchar(' '); + putchar(' '); printf("%s\n", sname); } else { fputs("config: ", stdout); @@ -712,7 +703,7 @@ show_credential(cred) extra_field++; } - if (krb5_is_config_principal(kcontext, cred->server)) + if (krb5_is_config_principal(context, cred->server)) print_config_data(ccol, &cred->ticket); if (cred->times.renew_till) { @@ -748,8 +739,8 @@ show_credential(cred) } if (show_etype) { - retval = krb5_decode_ticket(&cred->ticket, &tkt); - if (retval) + ret = krb5_decode_ticket(&cred->ticket, &tkt); + if (ret) goto err_tkt; if (!extra_field) @@ -758,13 +749,12 @@ show_credential(cred) fputs(", ",stdout); printf(_("Etype (skey, tkt): %s, "), etype_string(cred->keyblock.enctype)); - printf("%s ", - etype_string(tkt->enc_part.enctype)); + printf("%s ", etype_string(tkt->enc_part.enctype)); extra_field++; err_tkt: if (tkt != NULL) - krb5_free_ticket(kcontext, tkt); + krb5_free_ticket(context, tkt); } if (show_adtype) { @@ -783,19 +773,18 @@ show_credential(cred) } } - /* if any additional info was printed, extra_field is non-zero */ + /* If any additional info was printed, extra_field is non-zero. */ if (extra_field) putchar('\n'); - if (show_addresses) { - if (!cred->addresses || !cred->addresses[0]) { + if (cred->addresses == NULL || cred->addresses[0] == NULL) { printf(_("\tAddresses: (none)\n")); } else { printf(_("\tAddresses: ")); one_addr(cred->addresses[0]); - for (i=1; cred->addresses[i]; i++) { + for (i = 1; cred->addresses[i] != NULL; i++) { printf(", "); one_addr(cred->addresses[i]); } @@ -804,45 +793,45 @@ show_credential(cred) } } - krb5_free_unparsed_name(kcontext, name); - krb5_free_unparsed_name(kcontext, sname); + krb5_free_unparsed_name(context, name); + krb5_free_unparsed_name(context, sname); } #include "port-sockets.h" -#include "socket-utils.h" /* for ss2sin etc */ +#include "socket-utils.h" /* For ss2sin etc. */ #include "fake-addrinfo.h" -void one_addr(a) - krb5_address *a; +static void +one_addr(krb5_address *a) { struct sockaddr_storage ss; + struct sockaddr_in *sinp; + struct sockaddr_in6 *sin6p; int err; char namebuf[NI_MAXHOST]; - memset (&ss, 0, sizeof (ss)); + memset(&ss, 0, sizeof(ss)); switch (a->addrtype) { case ADDRTYPE_INET: if (a->length != 4) { - broken: printf(_("broken address (type %d length %d)"), a->addrtype, a->length); return; } - { - struct sockaddr_in *sinp = ss2sin (&ss); - sinp->sin_family = AF_INET; - memcpy (&sinp->sin_addr, a->contents, 4); - } + sinp = ss2sin(&ss); + sinp->sin_family = AF_INET; + memcpy(&sinp->sin_addr, a->contents, 4); break; case ADDRTYPE_INET6: - if (a->length != 16) - goto broken; - { - struct sockaddr_in6 *sin6p = ss2sin6 (&ss); - sin6p->sin6_family = AF_INET6; - memcpy (&sin6p->sin6_addr, a->contents, 16); + if (a->length != 16) { + printf(_("broken address (type %d length %d)"), + a->addrtype, a->length); + return; } + sin6p = ss2sin6(&ss); + sin6p->sin6_family = AF_INET6; + memcpy(&sin6p->sin6_addr, a->contents, 16); break; default: printf(_("unknown addrtype %d"), a->addrtype); @@ -850,25 +839,22 @@ void one_addr(a) } namebuf[0] = 0; - err = getnameinfo (ss2sa (&ss), sa_socklen (ss2sa (&ss)), - namebuf, sizeof (namebuf), 0, 0, - no_resolve ? NI_NUMERICHOST : 0U); + err = getnameinfo(ss2sa(&ss), sa_socklen(ss2sa(&ss)), namebuf, + sizeof(namebuf), 0, 0, + no_resolve ? NI_NUMERICHOST : 0U); if (err) { printf(_("unprintable address (type %d, error %d %s)"), a->addrtype, - err, gai_strerror (err)); + err, gai_strerror(err)); return; } - printf ("%s", namebuf); + printf("%s", namebuf); } -void -fillit(f, num, c) - FILE *f; - unsigned int num; - int c; +static void +fillit(FILE *f, unsigned int num, int c) { unsigned int i; - for (i=0; i<num; i++) + for (i = 0; i < num; i++) fputc(c, f); } diff --git a/src/clients/kpasswd/Makefile.in b/src/clients/kpasswd/Makefile.in index bd4a08cc1daf..294851802af6 100644 --- a/src/clients/kpasswd/Makefile.in +++ b/src/clients/kpasswd/Makefile.in @@ -1,16 +1,12 @@ mydir=clients$(S)kpasswd BUILDTOP=$(REL)..$(S).. -SRCS=kpasswd.c ksetpwd.c +SRCS=kpasswd.c kpasswd: kpasswd.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o kpasswd kpasswd.o $(KRB5_BASE_LIBS) -ksetpwd: ksetpwd.o $(KRB5_BASE_DEPLIBS) - $(CC_LINK) -o ksetpwd ksetpwd.o $(KRB5_BASE_LIBS) - kpasswd.o: $(srcdir)/kpasswd.c -ksetpwd.o: $(srcdir)/ksetpwd.c ##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc ##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY @@ -22,10 +18,10 @@ ksetpwd.o: $(srcdir)/ksetpwd.c ##WIN32##$(EXERES): $(VERSIONRC) ##WIN32## $(RC) $(RCFLAGS) -DKPASSWD_APP -fo $@ -r $** -all-unix: kpasswd ksetpwd +all-unix: kpasswd clean-unix:: - $(RM) kpasswd.o kpasswd ksetpwd.o ksetpwd + $(RM) kpasswd.o kpasswd install-all install-kdc install-server install-client install-unix: $(INSTALL_PROGRAM) kpasswd $(DESTDIR)$(CLIENT_BINDIR)/`echo kpasswd|sed '$(transform)'` diff --git a/src/clients/kpasswd/deps b/src/clients/kpasswd/deps index 0c01c30cc12e..360b6d73fc62 100644 --- a/src/clients/kpasswd/deps +++ b/src/clients/kpasswd/deps @@ -5,7 +5,3 @@ $(OUTPRE)kpasswd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ kpasswd.c -$(OUTPRE)ksetpwd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ - $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ - ksetpwd.c diff --git a/src/clients/kpasswd/kpasswd.c b/src/clients/kpasswd/kpasswd.c index efc596edf7ce..8dbe611c4fa3 100644 --- a/src/clients/kpasswd/kpasswd.c +++ b/src/clients/kpasswd/kpasswd.c @@ -1,4 +1,5 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ + #include "k5-platform.h" #include <locale.h> #include <sys/types.h> @@ -15,18 +16,18 @@ #ifdef HAVE_PWD_H #include <pwd.h> -static -void get_name_from_passwd_file(program_name, kcontext, me) - char * program_name; - krb5_context kcontext; - krb5_principal * me; +static void +get_name_from_passwd_file(char *program_name, krb5_context context, + krb5_principal *me) { struct passwd *pw; - krb5_error_code code; - if ((pw = getpwuid(getuid()))) { - if ((code = krb5_parse_name(kcontext, pw->pw_name, me))) { - com_err(program_name, code, _("when parsing name %s"), - pw->pw_name); + krb5_error_code ret; + + pw = getpwuid(getuid()); + if (pw != NULL) { + ret = krb5_parse_name(context, pw->pw_name, me); + if (ret) { + com_err(program_name, ret, _("when parsing name %s"), pw->pw_name); exit(1); } } else { @@ -35,9 +36,8 @@ void get_name_from_passwd_file(program_name, kcontext, me) } } #else /* HAVE_PWD_H */ -void get_name_from_passwd_file(kcontext, me) - krb5_context kcontext; - krb5_principal * me; +static void +get_name_from_passwd_file(krb5_context context, krb5_principal *me) { fprintf(stderr, _("Unable to identify user\n")); exit(1); @@ -49,13 +49,11 @@ int main(int argc, char *argv[]) krb5_error_code ret; krb5_context context; krb5_principal princ = NULL; - char *pname; + char *pname, *message; + char pw[1024]; krb5_ccache ccache; krb5_get_init_creds_opt *opts = NULL; krb5_creds creds; - char *message; - - char pw[1024]; unsigned int pwlen; int result_code; krb5_data result_code_string, result_string; @@ -73,48 +71,48 @@ int main(int argc, char *argv[]) com_err(argv[0], ret, _("initializing kerberos library")); exit(1); } - if ((ret = krb5_get_init_creds_opt_alloc(context, &opts))) { + ret = krb5_get_init_creds_opt_alloc(context, &opts); + if (ret) { com_err(argv[0], ret, _("allocating krb5_get_init_creds_opt")); exit(1); } - /* in order, use the first of: - - a name specified on the command line - - the principal name from an existing ccache - - the name corresponding to the ruid of the process - - otherwise, it's an error. - We always attempt to open the default ccache in order to use FAST if - possible. - */ + /* + * In order, use the first of: + * - A name specified on the command line + * - The principal name from an existing ccache + * - The name corresponding to the ruid of the process + * + * Otherwise, it's an error. + * We always attempt to open the default ccache in order to use FAST if + * possible. + */ ret = krb5_cc_default(context, &ccache); - if (ret != 0) { + if (ret) { com_err(argv[0], ret, _("opening default ccache")); exit(1); } ret = krb5_cc_get_principal(context, ccache, &princ); - if (ret != 0 && ret != KRB5_CC_NOTFOUND && ret != KRB5_FCC_NOFILE) { + if (ret && ret != KRB5_CC_NOTFOUND && ret != KRB5_FCC_NOFILE) { com_err(argv[0], ret, _("getting principal from ccache")); exit(1); - } else { - if (princ != NULL) { - ret = krb5_get_init_creds_opt_set_fast_ccache(context, opts, - ccache); - if (ret) { - com_err(argv[0], ret, _("while setting FAST ccache")); - exit(1); - } + } else if (princ != NULL) { + ret = krb5_get_init_creds_opt_set_fast_ccache(context, opts, ccache); + if (ret) { + com_err(argv[0], ret, _("while setting FAST ccache")); + exit(1); } } ret = krb5_cc_close(context, ccache); - if (ret != 0) { + if (ret) { com_err(argv[0], ret, _("closing ccache")); exit(1); } - if (pname) { + if (pname != NULL) { krb5_free_principal(context, princ); princ = NULL; - if ((ret = krb5_parse_name(context, pname, &princ))) { + ret = krb5_parse_name(context, pname, &princ); + if (ret) { com_err(argv[0], ret, _("parsing client name")); exit(1); } @@ -122,33 +120,37 @@ int main(int argc, char *argv[]) if (princ == NULL) get_name_from_passwd_file(argv[0], context, &princ); - krb5_get_init_creds_opt_set_tkt_life(opts, 5*60); + krb5_get_init_creds_opt_set_tkt_life(opts, 5 * 60); krb5_get_init_creds_opt_set_renew_life(opts, 0); krb5_get_init_creds_opt_set_forwardable(opts, 0); krb5_get_init_creds_opt_set_proxiable(opts, 0); - if ((ret = krb5_get_init_creds_password(context, &creds, princ, NULL, - krb5_prompter_posix, NULL, - 0, "kadmin/changepw", opts))) { - if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) + ret = krb5_get_init_creds_password(context, &creds, princ, NULL, + krb5_prompter_posix, NULL, 0, + "kadmin/changepw", opts); + if (ret) { + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { com_err(argv[0], 0, _("Password incorrect while getting initial ticket")); - else + } else { com_err(argv[0], ret, _("getting initial ticket")); + } + krb5_get_init_creds_opt_free(context, opts); exit(1); } pwlen = sizeof(pw); - if ((ret = krb5_read_password(context, P1, P2, pw, &pwlen))) { + ret = krb5_read_password(context, P1, P2, pw, &pwlen); + if (ret) { com_err(argv[0], ret, _("while reading password")); krb5_get_init_creds_opt_free(context, opts); exit(1); } - if ((ret = krb5_change_password(context, &creds, pw, - &result_code, &result_code_string, - &result_string))) { + ret = krb5_change_password(context, &creds, pw, &result_code, + &result_code_string, &result_string); + if (ret) { com_err(argv[0], ret, _("changing password")); krb5_get_init_creds_opt_free(context, opts); exit(1); @@ -158,17 +160,15 @@ int main(int argc, char *argv[]) if (krb5_chpw_message(context, &result_string, &message) != 0) message = NULL; printf("%.*s%s%s\n", - (int) result_code_string.length, result_code_string.data, + (int)result_code_string.length, result_code_string.data, message ? ": " : "", message ? message : NULL); krb5_free_string(context, message); krb5_get_init_creds_opt_free(context, opts); exit(2); } - if (result_string.data != NULL) - free(result_string.data); - if (result_code_string.data != NULL) - free(result_code_string.data); + free(result_string.data); + free(result_code_string.data); krb5_get_init_creds_opt_free(context, opts); printf(_("Password changed.\n")); diff --git a/src/clients/kpasswd/ksetpwd.c b/src/clients/kpasswd/ksetpwd.c deleted file mode 100644 index 2aafb6cedeb0..000000000000 --- a/src/clients/kpasswd/ksetpwd.c +++ /dev/null @@ -1,309 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -#include <k5-platform.h> -#include <krb5.h> -#include <unistd.h> -#include <time.h> - -#define TKTTIMELEFT 60*10 /* ten minutes */ - -static int verify_creds() -{ - krb5_context kcontext; - krb5_ccache ccache; - krb5_error_code kres; - - kres = krb5_init_context(&kcontext); - if( kres == 0 ) - { - kres = krb5_cc_default( kcontext, &ccache ); - if( kres == 0 ) - { - krb5_principal user_princ; - - kres = krb5_cc_get_principal( kcontext, ccache, &user_princ ); - if( kres == 0 ) - krb5_free_principal( kcontext, user_princ ); - krb5_cc_close( kcontext, ccache ); - } - krb5_free_context(kcontext); - } - return kres; -} - -static void get_init_creds_opt_init( krb5_get_init_creds_opt *outOptions ) -{ - krb5_preauthtype preauth[] = { KRB5_PADATA_ENC_TIMESTAMP }; - krb5_enctype etypes[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_CRC}; - krb5_get_init_creds_opt_set_address_list(outOptions, NULL); - krb5_get_init_creds_opt_set_etype_list( outOptions, etypes, sizeof(etypes)/sizeof(krb5_enctype) ); - krb5_get_init_creds_opt_set_preauth_list(outOptions, preauth, sizeof(preauth)/sizeof(krb5_preauthtype) ); -} - -typedef void * kbrccache_t; -#define CCACHE_PREFIX_DEFAULT "MEMORY:C_" - -static kbrccache_t userinitcontext( - const char * user, const char * domain, const char * passwd, const char * cachename, int initialize, - int * outError ) -{ - krb5_context kcontext = 0; - krb5_ccache kcache = 0; - krb5_creds kcreds; - krb5_principal kme = 0; - krb5_error_code kres; - char * pPass = strdup( passwd ); - char * pName = NULL; - char * pCacheName = NULL; - int numCreds = 0; - - memset( &kcreds, 0, sizeof(kcreds) ); - kres = krb5_init_context( &kcontext ); - if( kres ) - goto return_error; - if( domain ) - kres = krb5_build_principal( kcontext, &kme, strlen(domain), domain, user, (char *) 0 ); - else - kres = krb5_parse_name( kcontext, user, &kme ); - if( kres ) - goto fail; - krb5_unparse_name( kcontext, kme, &pName ); - if( cachename ) - { - if (asprintf(&pCacheName, "%s%s", cachename, pName) < 0) - { - kres = KRB5_CC_NOMEM; - goto fail; - } - kres = krb5_cc_resolve( kcontext, pCacheName, &kcache ); - if( kres ) - { - kres = krb5_cc_resolve( kcontext, CCACHE_PREFIX_DEFAULT, &kcache ); - if( kres == 0 ) - pCacheName = strdup(CCACHE_PREFIX_DEFAULT); - } - } - else - { - kres = krb5_cc_default( kcontext, &kcache ); - pCacheName = strdup( krb5_cc_get_name( kcontext, kcache ) ); - } - if( kres ) - { - krb5_free_context(kcontext); - goto return_error; - } - if( initialize ) - krb5_cc_initialize( kcontext, kcache, kme ); - if( kres == 0 && user && passwd ) - { - long timeneeded = time(0L) +TKTTIMELEFT; - int have_credentials = 0; - krb5_cc_cursor cc_curs = NULL; - numCreds = 0; - if( (kres=krb5_cc_start_seq_get(kcontext, kcache, &cc_curs)) >= 0 ) - { - while( (kres=krb5_cc_next_cred(kcontext, kcache, &cc_curs, &kcreds))== 0) - { - numCreds++; - if( krb5_principal_compare( kcontext, kme, kcreds.client ) ) - { - if( kcreds.ticket_flags & TKT_FLG_INITIAL && kcreds.times.endtime>timeneeded ) - have_credentials = 1; - } - krb5_free_cred_contents( kcontext, &kcreds ); - if( have_credentials ) - break; - } - krb5_cc_end_seq_get( kcontext, kcache, &cc_curs ); - } - else - { - const char * errmsg = error_message(kres); - fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg ); - } - if( kres != 0 || have_credentials == 0 ) - { - krb5_get_init_creds_opt *options = NULL; - kres = krb5_get_init_creds_opt_alloc(kcontext, &options); - if ( kres == 0 ) - { - get_init_creds_opt_init(options); -/* -** no valid credentials - get new ones -*/ - kres = krb5_get_init_creds_password( kcontext, &kcreds, kme, pPass, - NULL /*prompter*/, - NULL /*data*/, - 0 /*starttime*/, - 0 /*in_tkt_service*/, - options /*options*/ ); - } - if( kres == 0 ) - { - if( numCreds <= 0 ) - kres = krb5_cc_initialize( kcontext, kcache, kme ); - if( kres == 0 ) - kres = krb5_cc_store_cred( kcontext, kcache, &kcreds ); - if( kres == 0 ) - have_credentials = 1; - } - krb5_get_init_creds_opt_free(kcontext, options); - } -#ifdef NOTUSED - if( have_credentials ) - { - int mstat; - kres = gss_krb5_ccache_name( &mstat, pCacheName, NULL ); - if( getenv( ENV_DEBUG_LDAPKERB ) ) - fprintf( stderr, "gss credentials cache set to %s(%d)\n", pCacheName, kres ); - } -#endif - krb5_cc_close( kcontext, kcache ); - } -fail: - if( kres ) - { - const char * errmsg = error_message(kres); - fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg ); - } - krb5_free_principal( kcontext, kme ); - krb5_free_cred_contents( kcontext, &kcreds ); - if( pName ) - free( pName ); - free(pPass); - krb5_free_context(kcontext); - -return_error: - if( kres ) - { - if( pCacheName ) - { - free(pCacheName); - pCacheName = NULL; - } - } - if( outError ) - *outError = kres; - return pCacheName; -} - -static int init_creds() -{ - char user[512]; - char * password = NULL; - int result; - - user[0] = 0; - result = -1; - - for(;;) - { - while( user[0] == 0 ) - { - int userlen; - printf( "Username: "); - fflush(stdout); - if( fgets( user, sizeof(user), stdin ) == NULL ) - return -1; - userlen = strlen( user); - if( userlen < 2 ) - continue; - user[userlen-1] = 0; /* get rid of the newline */ - break; - } - { - kbrccache_t usercontext; - password = getpass( "Password: "); - if( ! password ) - return -1; - result = 0; - usercontext = userinitcontext( user, NULL, password, NULL, 1, &result ); - if( usercontext ) - break; - } - } - return result; -} - -int main( int argc, char ** argv ) -{ - char * new_password; - char * new_password2; - krb5_context kcontext; - krb5_error_code kerr; - krb5_principal target_principal; - - - if( argc < 2 ) - { - fprintf( stderr, "Usage: setpass user@REALM\n"); - exit(1); - } - -/* -** verify credentials - -*/ - if( verify_creds() ) - init_creds(); - if( verify_creds() ) - { - fprintf( stderr, "No user credentials available\n"); - exit(1); - } -/* -** check the principal name - -*/ - krb5_init_context(&kcontext); - kerr = krb5_parse_name( kcontext, argv[1], &target_principal ); - - { - char * pname = NULL; - kerr = krb5_unparse_name( kcontext, target_principal, &pname ); - printf( "Changing password for %s:\n", pname); - fflush( stdout ); - free( pname ); - } -/* -** get the new password - -*/ - for (;;) - { - new_password = getpass("Enter new password: "); - new_password2 = getpass("Verify new password: "); - if( strcmp( new_password, new_password2 ) == 0) - break; - printf("Passwords do not match\n"); - free( new_password ); - free( new_password2 ); - } -/* -** change the password - -*/ - { - int pw_result; - krb5_ccache ccache; - krb5_data pw_res_string, res_string; - - kerr = krb5_cc_default( kcontext, &ccache ); - if( kerr == 0 ) - { - kerr = krb5_set_password_using_ccache(kcontext, ccache, new_password, target_principal, - &pw_result, &pw_res_string, &res_string ); - if( kerr ) - fprintf( stderr, "Failed: %s\n", error_message(kerr) ); - else - { - if( pw_result ) - { - fprintf( stderr, "Failed(%d)", pw_result ); - if( pw_res_string.length > 0 ) - fprintf( stderr, ": %s", pw_res_string.data); - if( res_string.length > 0 ) - fprintf( stderr, " %s", res_string.data); - fprintf( stderr, "\n"); - } - } - } - } - return(0); -} diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c index a0736f2daad7..2a99521d4b2b 100644 --- a/src/clients/ksu/ccache.c +++ b/src/clients/ksu/ccache.c @@ -278,11 +278,11 @@ krb5_error_code krb5_check_exp(context, tkt_time) context->clockskew); fprintf(stderr,"krb5_check_exp: currenttime - endtime %d \n", - (currenttime - tkt_time.endtime )); + ts_delta(currenttime, tkt_time.endtime)); } - if (currenttime - tkt_time.endtime > context->clockskew){ + if (ts_after(currenttime, ts_incr(tkt_time.endtime, context->clockskew))) { retval = KRB5KRB_AP_ERR_TKT_EXPIRED ; return retval; } @@ -323,21 +323,11 @@ char *flags_string(cred) return(buf); } -void printtime(tv) - time_t tv; +void printtime(krb5_timestamp ts) { - char fmtbuf[18]; - char fill; - krb5_timestamp tstamp; - - /* XXXX ASSUMES sizeof(krb5_timestamp) >= sizeof(time_t) */ - (void) localtime((time_t *)&tv); - tstamp = tv; - fill = ' '; - if (!krb5_timestamp_to_sfstring(tstamp, - fmtbuf, - sizeof(fmtbuf), - &fill)) + char fmtbuf[18], fill = ' '; + + if (!krb5_timestamp_to_sfstring(ts, fmtbuf, sizeof(fmtbuf), &fill)) printf("%s", fmtbuf); } diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h index ee8e9d6a0f79..3bf0bd438449 100644 --- a/src/clients/ksu/ksu.h +++ b/src/clients/ksu/ksu.h @@ -150,7 +150,7 @@ extern krb5_boolean krb5_find_princ_in_cred_list extern krb5_error_code krb5_find_princ_in_cache (krb5_context, krb5_ccache, krb5_principal, krb5_boolean *); -extern void printtime (time_t); +extern void printtime (krb5_timestamp); /* authorization.c */ extern krb5_boolean fowner (FILE *, uid_t); diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c index 28342c2d7736..7ff676ca728b 100644 --- a/src/clients/ksu/main.c +++ b/src/clients/ksu/main.c @@ -932,7 +932,7 @@ int standard_shell(sh) static char * ontty() { - char *p, *ttyname(); + char *p; static char buf[MAXPATHLEN + 5]; int result; diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c index 80bee59e2337..77a128d5db82 100644 --- a/src/clients/kvno/kvno.c +++ b/src/clients/kvno/kvno.c @@ -36,8 +36,10 @@ extern int optind; extern char *optarg; static char *prog; +static int quiet = 0; -static void xusage() +static void +xusage() { fprintf(stderr, _("usage: %s [-C] [-u] [-c ccache] [-e etype]\n"), prog); fprintf(stderr, _("\t[-k keytab] [-S sname] [-U for_user [-P]]\n")); @@ -45,18 +47,16 @@ static void xusage() exit(1); } -int quiet = 0; - -static void do_v5_kvno (int argc, char *argv[], - char *ccachestr, char *etypestr, char *keytab_name, - char *sname, int canon, int unknown, - char *for_user, int proxy); +static void do_v5_kvno(int argc, char *argv[], char *ccachestr, char *etypestr, + char *keytab_name, char *sname, int canon, int unknown, + char *for_user, int proxy); #include <com_err.h> -static void extended_com_err_fn (const char *, errcode_t, const char *, - va_list); +static void extended_com_err_fn(const char *myprog, errcode_t code, + const char *fmt, va_list args); -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { int option; char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL; @@ -64,7 +64,7 @@ int main(int argc, char *argv[]) int canon = 0, unknown = 0, proxy = 0; setlocale(LC_ALL, ""); - set_com_err_hook (extended_com_err_fn); + set_com_err_hook(extended_com_err_fn); prog = strrchr(argv[0], '/'); prog = prog ? (prog + 1) : argv[0]; @@ -94,7 +94,7 @@ int main(int argc, char *argv[]) break; case 'S': sname = optarg; - if (unknown == 1){ + if (unknown == 1) { fprintf(stderr, _("Options -u and -S are mutually exclusive\n")); xusage(); @@ -102,7 +102,7 @@ int main(int argc, char *argv[]) break; case 'u': unknown = 1; - if (sname){ + if (sname != NULL) { fprintf(stderr, _("Options -u and -S are mutually exclusive\n")); xusage(); @@ -129,39 +129,150 @@ int main(int argc, char *argv[]) } } - if ((argc - optind) < 1) + if (argc - optind < 1) xusage(); - do_v5_kvno(argc - optind, argv + optind, - ccachestr, etypestr, keytab_name, sname, - canon, unknown, for_user, proxy); + do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr, keytab_name, + sname, canon, unknown, for_user, proxy); return 0; } #include <k5-int.h> static krb5_context context; -static void extended_com_err_fn (const char *myprog, errcode_t code, - const char *fmt, va_list args) +static void extended_com_err_fn(const char *myprog, errcode_t code, + const char *fmt, va_list args) { const char *emsg; - emsg = krb5_get_error_message (context, code); - fprintf (stderr, "%s: %s ", myprog, emsg); - krb5_free_error_message (context, emsg); - vfprintf (stderr, fmt, args); - fprintf (stderr, "\n"); + + emsg = krb5_get_error_message(context, code); + fprintf(stderr, "%s: %s ", myprog, emsg); + krb5_free_error_message(context, emsg); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + +/* Request a single service ticket and display its status (unless quiet is + * set). On failure, display an error message and return non-zero. */ +static krb5_error_code +kvno(const char *name, krb5_ccache ccache, krb5_principal me, + krb5_enctype etype, krb5_keytab keytab, const char *sname, + krb5_flags options, int unknown, krb5_principal for_user_princ, int proxy) +{ + krb5_error_code ret; + krb5_principal server = NULL; + krb5_ticket *ticket = NULL; + krb5_creds in_creds, *out_creds = NULL; + char *princ = NULL; + + memset(&in_creds, 0, sizeof(in_creds)); + + if (sname != NULL) { + ret = krb5_sname_to_principal(context, name, sname, KRB5_NT_SRV_HST, + &server); + } else { + ret = krb5_parse_name(context, name, &server); + } + if (ret) { + if (!quiet) + com_err(prog, ret, _("while parsing principal name %s"), name); + goto cleanup; + } + if (unknown) + krb5_princ_type(context, server) = KRB5_NT_UNKNOWN; + + ret = krb5_unparse_name(context, server, &princ); + if (ret) { + com_err(prog, ret, _("while formatting parsed principal name for " + "'%s'"), name); + goto cleanup; + } + + in_creds.keyblock.enctype = etype; + + if (for_user_princ != NULL) { + if (!proxy && !krb5_principal_compare(context, me, server)) { + ret = EINVAL; + com_err(prog, ret, + _("client and server principal names must match")); + goto cleanup; + } + + in_creds.client = for_user_princ; + in_creds.server = me; + ret = krb5_get_credentials_for_user(context, options, ccache, + &in_creds, NULL, &out_creds); + } else { + in_creds.client = me; + in_creds.server = server; + ret = krb5_get_credentials(context, options, ccache, &in_creds, + &out_creds); + } + + if (ret) { + com_err(prog, ret, _("while getting credentials for %s"), princ); + goto cleanup; + } + + /* We need a native ticket. */ + ret = krb5_decode_ticket(&out_creds->ticket, &ticket); + if (ret) { + com_err(prog, ret, _("while decoding ticket for %s"), princ); + goto cleanup; + } + + if (keytab != NULL) { + ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket); + if (ret) { + if (!quiet) { + fprintf(stderr, "%s: kvno = %d, keytab entry invalid\n", princ, + ticket->enc_part.kvno); + } + com_err(prog, ret, _("while decrypting ticket for %s"), princ); + goto cleanup; + } + if (!quiet) { + printf(_("%s: kvno = %d, keytab entry valid\n"), princ, + ticket->enc_part.kvno); + } + if (proxy) { + krb5_free_creds(context, out_creds); + out_creds = NULL; + + in_creds.client = ticket->enc_part2->client; + in_creds.server = server; + + ret = krb5_get_credentials_for_proxy(context, KRB5_GC_CANONICALIZE, + ccache, &in_creds, ticket, + &out_creds); + if (ret) { + com_err(prog, ret, _("%s: constrained delegation failed"), + princ); + goto cleanup; + } + } + } else { + if (!quiet) + printf(_("%s: kvno = %d\n"), princ, ticket->enc_part.kvno); + } + +cleanup: + krb5_free_principal(context, server); + krb5_free_ticket(context, ticket); + krb5_free_creds(context, out_creds); + krb5_free_unparsed_name(context, princ); + return ret; } -static void do_v5_kvno (int count, char *names[], - char * ccachestr, char *etypestr, char *keytab_name, - char *sname, int canon, int unknown, char *for_user, - int proxy) +static void +do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr, + char *keytab_name, char *sname, int canon, int unknown, + char *for_user, int proxy) { krb5_error_code ret; int i, errors; krb5_enctype etype; krb5_ccache ccache; krb5_principal me; - krb5_creds in_creds; krb5_keytab keytab = NULL; krb5_principal for_user_princ = NULL; krb5_flags options; @@ -191,7 +302,7 @@ static void do_v5_kvno (int count, char *names[], exit(1); } - if (keytab_name) { + if (keytab_name != NULL) { ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) { com_err(prog, ret, _("resolving keytab %s"), keytab_name); @@ -215,132 +326,16 @@ static void do_v5_kvno (int count, char *names[], exit(1); } - errors = 0; - - options = 0; - if (canon) - options |= KRB5_GC_CANONICALIZE; + options = canon ? KRB5_GC_CANONICALIZE : 0; + errors = 0; for (i = 0; i < count; i++) { - krb5_principal server = NULL; - krb5_ticket *ticket = NULL; - krb5_creds *out_creds = NULL; - char *princ = NULL; - - memset(&in_creds, 0, sizeof(in_creds)); - - if (sname != NULL) { - ret = krb5_sname_to_principal(context, names[i], - sname, KRB5_NT_SRV_HST, - &server); - } else { - ret = krb5_parse_name(context, names[i], &server); - } - if (ret) { - if (!quiet) { - com_err(prog, ret, _("while parsing principal name %s"), - names[i]); - } - goto error; - } - if (unknown == 1) { - krb5_princ_type(context, server) = KRB5_NT_UNKNOWN; - } - - ret = krb5_unparse_name(context, server, &princ); - if (ret) { - com_err(prog, ret, _("while formatting parsed principal name for " - "'%s'"), names[i]); - goto error; - } - - in_creds.keyblock.enctype = etype; - - if (for_user) { - if (!proxy && - !krb5_principal_compare(context, me, server)) { - com_err(prog, EINVAL, - _("client and server principal names must match")); - goto error; - } - - in_creds.client = for_user_princ; - in_creds.server = me; - - ret = krb5_get_credentials_for_user(context, options, ccache, - &in_creds, NULL, &out_creds); - } else { - in_creds.client = me; - in_creds.server = server; - ret = krb5_get_credentials(context, options, ccache, - &in_creds, &out_creds); - } - - if (ret) { - com_err(prog, ret, _("while getting credentials for %s"), princ); - goto error; - } - - /* we need a native ticket */ - ret = krb5_decode_ticket(&out_creds->ticket, &ticket); - if (ret) { - com_err(prog, ret, _("while decoding ticket for %s"), princ); - goto error; - } - - if (keytab) { - ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket); - if (ret) { - if (!quiet) { - fprintf(stderr, "%s: kvno = %d, keytab entry invalid\n", - princ, ticket->enc_part.kvno); - } - com_err(prog, ret, _("while decrypting ticket for %s"), princ); - goto error; - } - if (!quiet) { - printf(_("%s: kvno = %d, keytab entry valid\n"), - princ, ticket->enc_part.kvno); - } - if (proxy) { - krb5_free_creds(context, out_creds); - out_creds = NULL; - - in_creds.client = ticket->enc_part2->client; - in_creds.server = server; - - ret = krb5_get_credentials_for_proxy(context, - KRB5_GC_CANONICALIZE, - ccache, - &in_creds, - ticket, - &out_creds); - if (ret) { - com_err(prog, ret, - _("%s: constrained delegation failed"), princ); - goto error; - } - } - } else { - if (!quiet) - printf(_("%s: kvno = %d\n"), princ, ticket->enc_part.kvno); - } - - continue; - - error: - if (server != NULL) - krb5_free_principal(context, server); - if (ticket != NULL) - krb5_free_ticket(context, ticket); - if (out_creds != NULL) - krb5_free_creds(context, out_creds); - if (princ != NULL) - krb5_free_unparsed_name(context, princ); - errors++; + if (kvno(names[i], ccache, me, etype, keytab, sname, options, unknown, + for_user_princ, proxy) != 0) + errors++; } - if (keytab) + if (keytab != NULL) krb5_kt_close(context, keytab); krb5_free_principal(context, me); krb5_free_principal(context, for_user_princ); diff --git a/src/config/ac-archive/README b/src/config/ac-archive/README index 7bc626eb56c3..409d4b3c8f3d 100644 --- a/src/config/ac-archive/README +++ b/src/config/ac-archive/README @@ -1,51 +1,9 @@ -*- text -*- These macros are taken from the autoconf archive at -ac-archive.sourceforge.net. Unless otherwise noted, they are under -this modified version of the GNU General Public License version 2 -(also copied from ac-archive.sourceforge.net): +https://www.gnu.org/software/autoconf-archive/ . They are licensed +under a modified version of the GNU General Public License as noted in +the comments near the top of each file. - Every Autoconf macro presented on this web site is free software; - you can redistribute it and/or modify it under the terms of the - GNU General Public License as published by the Free Software - Foundation; either version 2, or (at your option) any later - version. - - They are distributed in the hope that they will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. (You should have received - a copy of the GNU General Public License along with this program; - if not, write to the Free Software Foundation, Inc., 59 Temple - Place -- Suite 330, Boston, MA 02111-1307, USA.) - - As a special exception, the Free Software Foundation gives - unlimited permission to copy, distribute and modify the configure - scripts that are the output of Autoconf. You need not follow the - terms of the GNU General Public License when using or distributing - such scripts, even though portions of the text of Autoconf appear - in them. The GNU General Public License (GPL) does govern all - other use of the material that constitutes the Autoconf program. - - Certain portions of the Autoconf source text are designed to be - copied (in certain cases, depending on the input) into the output - of Autoconf. We call these the "data" portions. The rest of the - Autoconf source text consists of comments plus executable code - that decides which of the data portions to output in any given - case. We call these comments and executable code the "non-data" - portions. Autoconf never copies any of the non-data portions into - its output. - - This special exception to the GPL applies to versions of Autoconf - released by the Free Software Foundation. When you make and - distribute a modified version of Autoconf, you may extend this - special exception to the GPL to apply to your modified version as - well, *unless* your modified version has the potential to copy - into its output some of the text that was the non-data portion of - the version that you started with. (In other words, unless your - change moves or copies text from the non-data portions to the data - portions.) If your modification has such potential, you must - delete any notice of this special exception to the GPL from your - modified version. - -acx_pthread.m4 version 1.5 2004/03/01 +ax_pthread.m4 serial 24 2017-02-06 +ax_recursive_eval.m4 serial 1 2017-01-05 diff --git a/src/config/ac-archive/acx_pthread.m4 b/src/config/ac-archive/acx_pthread.m4 deleted file mode 100644 index 6a1537d474fa..000000000000 --- a/src/config/ac-archive/acx_pthread.m4 +++ /dev/null @@ -1,239 +0,0 @@ -dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -dnl -dnl This macro figures out how to build C programs using POSIX -dnl threads. It sets the PTHREAD_LIBS output variable to the threads -dnl library and linker flags, and the PTHREAD_CFLAGS output variable -dnl to any special C compiler flags that are needed. (The user can also -dnl force certain compiler flags/libs to be tested by setting these -dnl environment variables.) -dnl -dnl Also sets PTHREAD_CC to any special C compiler that is needed for -dnl multi-threaded programs (defaults to the value of CC otherwise). -dnl (This is necessary on AIX to use the special cc_r compiler alias.) -dnl -dnl NOTE: You are assumed to not only compile your program with these -dnl flags, but also link it with them as well. e.g. you should link -dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS -dnl -dnl If you are only building threads programs, you may wish to -dnl use these variables in your default LIBS, CFLAGS, and CC: -dnl -dnl LIBS="$PTHREAD_LIBS $LIBS" -dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -dnl CC="$PTHREAD_CC" -dnl -dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute -dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE -dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). -dnl -dnl ACTION-IF-FOUND is a list of shell commands to run if a threads -dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands -dnl to run it if it is not found. If ACTION-IF-FOUND is not specified, -dnl the default action will define HAVE_PTHREAD. -dnl -dnl Please let the authors know if this macro fails on any platform, -dnl or if you have any other suggestions or comments. This macro was -dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org) -dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread -dnl macros posted by AFC to the autoconf macro repository. We are also -dnl grateful for the helpful feedback of numerous users. -dnl -dnl @version $Id: acx_pthread.m4,v 1.5 2004/03/01 19:28:29 guidod Exp $ -dnl @author Steven G. Johnson <stevenj@alum.mit.edu> and Alejandro Forero Cuervo <bachue@bachue.com> - -AC_DEFUN([ACX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_LANG_SAVE -AC_LANG_C -acx_pthread_ok=no - -# We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). -# It gets checked for in the link test anyway. - -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) - AC_MSG_RESULT($acx_pthread_ok) - if test x"$acx_pthread_ok" = xno; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" -fi - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all, and "pthread-config" -# which is a program returning the flags for the Pth emulation library. - -acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# pthread: Linux, etcetera -# --thread-safe: KAI C++ -# pthread-config: use pthread-config program (for GNU Pth library) - -case "${host_cpu}-${host_os}" in - *solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthread or - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: - - acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" - ;; -esac - -if test x"$acx_pthread_ok" = xno; then -for flag in $acx_pthread_flags; do - - case $flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" - ;; - - pthread-config) - AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) - if test x"$acx_pthread_config" = xno; then continue; fi - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - AC_TRY_LINK([#include <pthread.h>], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [acx_pthread_ok=yes]) - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - AC_MSG_RESULT($acx_pthread_ok) - if test "x$acx_pthread_ok" = xyes; then - break; - fi - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" -done -fi - -# Various other checks: -if test "x$acx_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Detect AIX lossage: threads are created detached by default - # and the JOINABLE attribute has a nonstandard name (UNDETACHED). - AC_MSG_CHECKING([for joinable pthread attribute]) - AC_TRY_LINK([#include <pthread.h>], - [int attr=PTHREAD_CREATE_JOINABLE;], - ok=PTHREAD_CREATE_JOINABLE, ok=unknown) - if test x"$ok" = xunknown; then - AC_TRY_LINK([#include <pthread.h>], - [int attr=PTHREAD_CREATE_UNDETACHED;], - ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) - fi - if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then - AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, - [Define to the necessary symbol if this constant - uses a non-standard name on your system.]) - fi - AC_MSG_RESULT(${ok}) - if test x"$ok" = xunknown; then - AC_MSG_WARN([we do not know how to create joinable pthreads]) - fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case "${host_cpu}-${host_os}" in - *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; - *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; - esac - AC_MSG_RESULT(${flag}) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - # More AIX lossage: must compile with cc_r - AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) -else - PTHREAD_CC="$CC" -fi - -AC_SUBST(PTHREAD_LIBS) -AC_SUBST(PTHREAD_CFLAGS) -AC_SUBST(PTHREAD_CC) - -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$acx_pthread_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) - : -else - acx_pthread_ok=no - $2 -fi -AC_LANG_RESTORE -])dnl ACX_PTHREAD diff --git a/src/config/ac-archive/ax_pthread.m4 b/src/config/ac-archive/ax_pthread.m4 new file mode 100644 index 000000000000..5fbf9fe0d686 --- /dev/null +++ b/src/config/ac-archive/ax_pthread.m4 @@ -0,0 +1,485 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also to link with them as well. For example, you might link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threaded programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu> +# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG> +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <https://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 24 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h> +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/src/config/ac-archive/ax_recursive_eval.m4 b/src/config/ac-archive/ax_recursive_eval.m4 new file mode 100644 index 000000000000..0625aca2255d --- /dev/null +++ b/src/config/ac-archive/ax_recursive_eval.m4 @@ -0,0 +1,56 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_recursive_eval.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_RECURSIVE_EVAL(VALUE, RESULT) +# +# DESCRIPTION +# +# Interpolate the VALUE in loop until it doesn't change, and set the +# result to $RESULT. WARNING: It's easy to get an infinite loop with some +# unsane input. +# +# LICENSE +# +# Copyright (c) 2008 Alexandre Duret-Lutz <adl@gnu.org> +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <https://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 1 + +AC_DEFUN([AX_RECURSIVE_EVAL], +[_lcl_receval="$1" +$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" + test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" + _lcl_receval_old='' + while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do + _lcl_receval_old="[$]_lcl_receval" + eval _lcl_receval="\"[$]_lcl_receval\"" + done + echo "[$]_lcl_receval")`]) diff --git a/src/config/ac-archive/relpaths.m4 b/src/config/ac-archive/relpaths.m4 deleted file mode 100644 index 15f24b3347e2..000000000000 --- a/src/config/ac-archive/relpaths.m4 +++ /dev/null @@ -1,155 +0,0 @@ -dnl @synopsis adl_COMPUTE_RELATIVE_PATHS(PATH_LIST) -dnl -dnl PATH_LIST is a space-separated list of colon-separated triplets of -dnl the form 'FROM:TO:RESULT'. This function iterates over these -dnl triplets and set $RESULT to the relative path from $FROM to $TO. -dnl Note that $FROM and $TO needs to be absolute filenames for this -dnl macro to success. -dnl -dnl For instance, -dnl -dnl first=/usr/local/bin -dnl second=/usr/local/share -dnl adl_COMPUTE_RELATIVE_PATHS([first:second:fs second:first:sf]) -dnl # $fs is set to ../share -dnl # $sf is set to ../bin -dnl -dnl $FROM and $TO are both eval'ed recursively and normalized, this -dnl means that you can call this macro with autoconf's dirnames like -dnl `prefix' or `datadir'. For example: -dnl -dnl adl_COMPUTE_RELATIVE_PATHS([bindir:datadir:bin_to_data]) -dnl -dnl adl_COMPUTE_RELATIVE_PATHS should also works with DOS filenames. -dnl -dnl You may want to use this macro in order to make your package -dnl relocatable. Instead of hardcoding $datadir into your programs just -dnl encode $bin_to_data and try to determine $bindir at run-time. -dnl -dnl This macro requires adl_NORMALIZE_PATH. -dnl -dnl @category Misc -dnl @author Alexandre Duret-Lutz <duret_g@epita.fr> -dnl @version 2001-05-25 -dnl @license GPLWithACException - -AC_DEFUN([adl_COMPUTE_RELATIVE_PATHS], -[for _lcl_i in $1; do - _lcl_from=\[$]`echo "[$]_lcl_i" | sed 's,:.*$,,'` - _lcl_to=\[$]`echo "[$]_lcl_i" | sed 's,^[[^:]]*:,,' | sed 's,:[[^:]]*$,,'` - _lcl_result_var=`echo "[$]_lcl_i" | sed 's,^.*:,,'` - adl_RECURSIVE_EVAL([[$]_lcl_from], [_lcl_from]) - adl_RECURSIVE_EVAL([[$]_lcl_to], [_lcl_to]) - _lcl_notation="$_lcl_from$_lcl_to" - adl_NORMALIZE_PATH([_lcl_from],['/']) - adl_NORMALIZE_PATH([_lcl_to],['/']) - adl_COMPUTE_RELATIVE_PATH([_lcl_from], [_lcl_to], [_lcl_result_tmp]) - adl_NORMALIZE_PATH([_lcl_result_tmp],["[$]_lcl_notation"]) - eval $_lcl_result_var='[$]_lcl_result_tmp' -done]) - -## Note: -## ***** -## The following helper macros are too fragile to be used out -## of adl_COMPUTE_RELATIVE_PATHS (mainly because they assume that -## paths are normalized), that's why I'm keeping them in the same file. -## Still, some of them maybe worth to reuse. - -dnl adl_COMPUTE_RELATIVE_PATH(FROM, TO, RESULT) -dnl =========================================== -dnl Compute the relative path to go from $FROM to $TO and set the value -dnl of $RESULT to that value. This function work on raw filenames -dnl (for instead it will considerate /usr//local and /usr/local as -dnl two distinct paths), you should really use adl_COMPUTE_REALTIVE_PATHS -dnl instead to have the paths sanitized automatically. -dnl -dnl For instance: -dnl first_dir=/somewhere/on/my/disk/bin -dnl second_dir=/somewhere/on/another/disk/share -dnl adl_COMPUTE_RELATIVE_PATH(first_dir, second_dir, first_to_second) -dnl will set $first_to_second to '../../../another/disk/share'. -AC_DEFUN([adl_COMPUTE_RELATIVE_PATH], -[adl_COMPUTE_COMMON_PATH([$1], [$2], [_lcl_common_prefix]) -adl_COMPUTE_BACK_PATH([$1], [_lcl_common_prefix], [_lcl_first_rel]) -adl_COMPUTE_SUFFIX_PATH([$2], [_lcl_common_prefix], [_lcl_second_suffix]) -$3="[$]_lcl_first_rel[$]_lcl_second_suffix"]) - -dnl adl_COMPUTE_COMMON_PATH(LEFT, RIGHT, RESULT) -dnl ============================================ -dnl Compute the common path to $LEFT and $RIGHT and set the result to $RESULT. -dnl -dnl For instance: -dnl first_path=/somewhere/on/my/disk/bin -dnl second_path=/somewhere/on/another/disk/share -dnl adl_COMPUTE_COMMON_PATH(first_path, second_path, common_path) -dnl will set $common_path to '/somewhere/on'. -AC_DEFUN([adl_COMPUTE_COMMON_PATH], -[$3='' -_lcl_second_prefix_match='' -while test "[$]_lcl_second_prefix_match" != 0; do - _lcl_first_prefix=`expr "x[$]$1" : "x\([$]$3/*[[^/]]*\)"` - _lcl_second_prefix_match=`expr "x[$]$2" : "x[$]_lcl_first_prefix"` - if test "[$]_lcl_second_prefix_match" != 0; then - if test "[$]_lcl_first_prefix" != "[$]$3"; then - $3="[$]_lcl_first_prefix" - else - _lcl_second_prefix_match=0 - fi - fi -done]) - -dnl adl_COMPUTE_SUFFIX_PATH(PATH, SUBPATH, RESULT) -dnl ============================================== -dnl Substrack $SUBPATH from $PATH, and set the resulting suffix -dnl (or the empty string if $SUBPATH is not a subpath of $PATH) -dnl to $RESULT. -dnl -dnl For instace: -dnl first_path=/somewhere/on/my/disk/bin -dnl second_path=/somewhere/on -dnl adl_COMPUTE_SUFFIX_PATH(first_path, second_path, common_path) -dnl will set $common_path to '/my/disk/bin'. -AC_DEFUN([adl_COMPUTE_SUFFIX_PATH], -[$3=`expr "x[$]$1" : "x[$]$2/*\(.*\)"`]) - -dnl adl_COMPUTE_BACK_PATH(PATH, SUBPATH, RESULT) -dnl ============================================ -dnl Compute the relative path to go from $PATH to $SUBPATH, knowing that -dnl $SUBPATH is a subpath of $PATH (any other words, only repeated '../' -dnl should be needed to move from $PATH to $SUBPATH) and set the value -dnl of $RESULT to that value. If $SUBPATH is not a subpath of PATH, -dnl set $RESULT to the empty string. -dnl -dnl For instance: -dnl first_path=/somewhere/on/my/disk/bin -dnl second_path=/somewhere/on -dnl adl_COMPUTE_BACK_PATH(first_path, second_path, back_path) -dnl will set $back_path to '../../../'. -AC_DEFUN([adl_COMPUTE_BACK_PATH], -[adl_COMPUTE_SUFFIX_PATH([$1], [$2], [_lcl_first_suffix]) -$3='' -_lcl_tmp='xxx' -while test "[$]_lcl_tmp" != ''; do - _lcl_tmp=`expr "x[$]_lcl_first_suffix" : "x[[^/]]*/*\(.*\)"` - if test "[$]_lcl_first_suffix" != ''; then - _lcl_first_suffix="[$]_lcl_tmp" - $3="../[$]$3" - fi -done]) - - -dnl adl_RECURSIVE_EVAL(VALUE, RESULT) -dnl ================================= -dnl Interpolate the VALUE in loop until it doesn't change, -dnl and set the result to $RESULT. -dnl WARNING: It's easy to get an infinite loop with some unsane input. -AC_DEFUN([adl_RECURSIVE_EVAL], -[_lcl_receval="$1" -$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" - test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" - _lcl_receval_old='' - while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do - _lcl_receval_old="[$]_lcl_receval" - eval _lcl_receval="\"[$]_lcl_receval\"" - done - echo "[$]_lcl_receval")`]) diff --git a/src/config/config.guess b/src/config/config.guess index c4bd827a7bed..31e01efec3e3 100755 --- a/src/config/config.guess +++ b/src/config/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2017 Free Software Foundation, Inc. -timestamp='2016-05-15' +timestamp='2017-11-07' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2016-05-15' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. +# along with this program; if not, see <https://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -27,7 +27,7 @@ timestamp='2016-05-15' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to <config-patches@gnu.org>. @@ -39,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -244,6 +244,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} exit ;; + *:MidnightBSD:*:*) + echo ${UNAME_MACHINE}-unknown-midnightbsd${UNAME_RELEASE} + exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; @@ -259,6 +262,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix exit ;; + *:Redox:*:*) + echo ${UNAME_MACHINE}-unknown-redox + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -315,15 +321,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; @@ -485,13 +482,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); @@ -614,7 +611,7 @@ EOF *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and @@ -635,8 +632,8 @@ EOF 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` @@ -749,7 +746,7 @@ EOF { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -758,7 +755,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -837,10 +834,11 @@ EOF UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin @@ -854,10 +852,6 @@ EOF *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; @@ -873,27 +867,12 @@ EOF echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; @@ -1000,6 +979,9 @@ EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; + mips64el:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; @@ -1032,6 +1014,9 @@ EOF ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; @@ -1090,7 +1075,7 @@ EOF i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + i*86:*:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} @@ -1297,14 +1282,21 @@ EOF if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub @@ -1328,15 +1320,18 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) + NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; - NSR-?:NONSTOP_KERNEL:*:*) + NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk${UNAME_RELEASE} + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; @@ -1408,16 +1403,28 @@ EOF exit ;; esac +echo "$0: unable to guess system type" >&2 + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <<EOF + +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. +EOF + ;; +esac + cat >&2 <<EOF -$0: unable to guess system type This script (version $timestamp), has failed to recognize the -operating system you are using. If your script is old, overwrite -config.guess and config.sub with the latest versions from: +operating system you are using. If your script is old, overwrite *all* +copies of config.guess and config.sub with the latest versions from: - http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess + https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess and - http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub If $0 has already been updated, send the following data and any information you think might be pertinent to config-patches@gnu.org to @@ -1449,7 +1456,7 @@ EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/src/config/config.sub b/src/config/config.sub index a1f8229449d2..00f68b8e5f3d 100755 --- a/src/config/config.sub +++ b/src/config/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2017 Free Software Foundation, Inc. -timestamp='2016-08-25' +timestamp='2017-11-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2016-08-25' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. +# along with this program; if not, see <https://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -33,7 +33,7 @@ timestamp='2016-08-25' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -117,7 +117,7 @@ case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` @@ -229,9 +229,6 @@ case $os in -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; -psos*) os=-psos ;; @@ -263,7 +260,7 @@ case $basic_machine in | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ @@ -301,6 +298,7 @@ case $basic_machine in | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ @@ -314,7 +312,7 @@ case $basic_machine in | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ - | we32k \ + | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -387,7 +385,7 @@ case $basic_machine in | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ @@ -428,6 +426,7 @@ case $basic_machine in | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ @@ -444,6 +443,7 @@ case $basic_machine in | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -639,7 +639,7 @@ case $basic_machine in basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; @@ -901,7 +901,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -946,6 +946,9 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -1241,6 +1244,9 @@ case $basic_machine in basic_machine=a29k-wrs os=-vxworks ;; + wasm32) + basic_machine=wasm32-unknown + ;; w65*) basic_machine=w65-wdc os=-none @@ -1249,6 +1255,9 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1356,8 +1365,8 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1377,9 +1386,9 @@ case $os in -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ @@ -1395,7 +1404,7 @@ case $os in | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ @@ -1407,7 +1416,7 @@ case $os in | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos* | -phoenix*) + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1482,7 +1491,7 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1537,6 +1546,19 @@ case $os in -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; -ios) @@ -1636,6 +1658,9 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; @@ -1681,7 +1706,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1816,7 +1841,7 @@ echo $basic_machine$os exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/src/config/post.in b/src/config/post.in index 77a9bffdf3ed..3643abad1ce0 100644 --- a/src/config/post.in +++ b/src/config/post.in @@ -156,7 +156,7 @@ clean: clean-$(WHAT) clean-unix:: $(RM) $(OBJS) $(DEPTARGETS_CLEAN) $(EXTRA_FILES) - $(RM) et-[ch]-*.et et-[ch]-*.[ch] testlog + $(RM) et-[ch]-*.et et-[ch]-*.[ch] testlog testtrace -$(RM) -r testdir clean-windows:: @@ -185,7 +185,7 @@ $(top_srcdir)/configure: @MAINT@ \ $(top_srcdir)/patchlevel.h \ $(top_srcdir)/aclocal.m4 (cd $(top_srcdir) && \ - $(AUTOCONF) --include=$(CONFIG_RELTOPDIR) $(AUTOCONFFLAGS)) + $(AUTOCONF) -f --include=$(CONFIG_RELTOPDIR) $(AUTOCONFFLAGS)) RECURSE_TARGETS=all-recurse clean-recurse distclean-recurse install-recurse \ generate-files-mac-recurse \ diff --git a/src/config/pre.in b/src/config/pre.in index e0626320c6e7..3f267eb1fec6 100644 --- a/src/config/pre.in +++ b/src/config/pre.in @@ -7,7 +7,7 @@ # srcdir=@srcdir@ # top_srcdir=@top_srcdir@ # but these are only set by autoconf 2.53, and thus not useful to us on -# Mac OS X yet (as of 10.2): +# macOS yet (as of 10.2): # abs_srcdir=@abs_srcdir@ # abs_top_srcdir=@abs_top_srcdir@ # builddir=@builddir@ @@ -402,10 +402,10 @@ HESIOD_LIBS = @HESIOD_LIBS@ KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB) KDB5_LIBS = $(KDB5_LIB) $(GSSRPC_LIBS) GSS_LIBS = $(GSS_KRB5_LIB) -# needs fixing if ever used on Mac OS X! +# needs fixing if ever used on macOS! GSSRPC_LIBS = -lgssrpc $(GSS_LIBS) KADM_COMM_LIBS = $(GSSRPC_LIBS) -# need fixing if ever used on Mac OS X! +# need fixing if ever used on macOS! KADMSRV_LIBS = -lkadm5srv_mit $(HESIOD_LIBS) $(KDB5_LIBS) $(KADM_COMM_LIBS) KADMCLNT_LIBS = -lkadm5clnt_mit $(KADM_COMM_LIBS) @@ -435,11 +435,6 @@ TCL_INCLUDES = @TCL_INCLUDES@ CRYPTO_IMPL = @CRYPTO_IMPL@ PRNG_ALG = @PRNG_ALG@ -# Crypto back-end selection and flags for PKINIT -PKINIT_CRYPTO_IMPL = @PKINIT_CRYPTO_IMPL@ -PKINIT_CRYPTO_IMPL_CFLAGS = @PKINIT_CRYPTO_IMPL_CFLAGS@ -PKINIT_CRYPTO_IMPL_LIBS = @PKINIT_CRYPTO_IMPL_LIBS@ - # TLS implementation selection TLS_IMPL = @TLS_IMPL@ TLS_IMPL_CFLAGS = @TLS_IMPL_CFLAGS@ @@ -451,6 +446,8 @@ HAVE_SASL = @HAVE_SASL@ # Whether we have libresolv 1.1.5 for URI discovery tests HAVE_RESOLV_WRAPPER = @HAVE_RESOLV_WRAPPER@ +SIZEOF_TIME_T = @SIZEOF_TIME_T@ + # error table rules # ### /* these are invoked as $(...) foo.et, which works, but could be better */ diff --git a/src/configure b/src/configure index 347016811691..dcb7bd72f350 100755 --- a/src/configure +++ b/src/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for Kerberos 5 1.15.1. +# Generated by GNU Autoconf 2.69 for Kerberos 5 1.16. # # Report bugs to <krb5-bugs@mit.edu>. # @@ -584,8 +584,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Kerberos 5' PACKAGE_TARNAME='krb5' -PACKAGE_VERSION='1.15.1' -PACKAGE_STRING='Kerberos 5 1.15.1' +PACKAGE_VERSION='1.16' +PACKAGE_STRING='Kerberos 5 1.16' PACKAGE_BUGREPORT='krb5-bugs@mit.edu' PACKAGE_URL='' @@ -681,6 +681,7 @@ SH5 SH DO_TCL KRB5_RCTMPDIR +SIZEOF_TIME_T SETENVOBJ KSU_LIBS EXTRA_SUPPORT_SYMS @@ -701,9 +702,6 @@ YASM TLS_IMPL_LIBS TLS_IMPL_CFLAGS TLS_IMPL -PKINIT_CRYPTO_IMPL_LIBS -PKINIT_CRYPTO_IMPL_CFLAGS -PKINIT_CRYPTO_IMPL PRNG_ALG CRYPTO_IMPL_LIBS CRYPTO_IMPL_CFLAGS @@ -774,14 +772,15 @@ TCL_LIBPATH TCL_LIBS TCL_INCLUDES KRB5_VERSION -EGREP -GREP DL_LIB THREAD_SUPPORT PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC -acx_pthread_config +ax_pthread_config +EGREP +GREP +SED krb5_cv_host host_os host_vendor @@ -886,11 +885,11 @@ enable_rpath enable_profiled with_tcl enable_athena +enable_nls with_vague_errors enable_audit_plugin with_crypto_impl with_prng_alg -with_pkinit_crypto_impl with_tls_impl enable_aesni enable_kdc_lookaside_cache @@ -1462,7 +1461,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Kerberos 5 1.15.1 to adapt to many kinds of systems. +\`configure' configures Kerberos 5 1.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1532,7 +1531,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Kerberos 5 1.15.1:";; + short | recursive ) echo "Configuration of Kerberos 5 1.16:";; esac cat <<\_ACEOF @@ -1551,6 +1550,7 @@ Optional Features: --disable-rpath suppress run path flags in link lines --enable-athena build with MIT Project Athena configuration + --disable-nls disable native language support --enable-audit-plugin=IMPL use audit plugin [ do not use audit ] --disable-aesni Do not build with AES-NI support @@ -1575,8 +1575,6 @@ Optional Packages: --with-vague-errors Do not [do] send helpful errors to client --with-crypto-impl=IMPL use specified crypto implementation [builtin] --with-prng-alg=ALG use specified PRNG algorithm. [fortuna] - --with-pkinit-crypto-impl=IMPL - use specified pkinit crypto implementation [openssl] --with-tls-impl=IMPL use specified TLS implementation [auto] --without-libedit do not compile with libedit --with-readline compile with GNU Readline @@ -1674,7 +1672,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Kerberos 5 configure 1.15.1 +Kerberos 5 configure 1.16 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2238,11 +2236,194 @@ $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include <stdio.h> +#include <stdlib.h> +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 <conftest.val; ac_retval=0 +else + ac_retval=1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f conftest.val + + fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_compute_int cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Kerberos 5 $as_me 1.15.1, which was +It was created by Kerberos 5 $as_me 1.16, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3704,6 +3885,63 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu + cflags_warning_test_flags= + cachevar=`echo "krb5_cv_cc_flag_-Werror=unknown-warning-option" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -Werror=unknown-warning-option" >&5 +$as_echo_n "checking if C compiler supports -Werror=unknown-warning-option... " >&6; } +if eval \${$cachevar+:} false; then : + $as_echo_n "(cached) " >&6 +else + # first try without, then with + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Werror=unknown-warning-option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval $cachevar=yes +else + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$old_cflags" +else + as_fn_error $? "compiling simple test program with $CFLAGS failed" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$cachevar + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS -Werror=unknown-warning-option" + fi + eval flag_supported='${'$cachevar'}' + + if test $flag_supported = yes; then + cflags_warning_test_flags=-Werror=unknown-warning-option + fi + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3923,6 +4161,75 @@ IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : @@ -4289,7 +4596,7 @@ main () _ACEOF if ac_fn_c_try_compile "$LINENO"; then : old_cflags="$CFLAGS" - CFLAGS="$CFLAGS -Wno-format-zero-length" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Wno-format-zero-length" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4323,7 +4630,7 @@ $as_echo "$ac_res" >&6; } # Other flags here may not be supported on some versions of # gcc that people want to use. - for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof error=uninitialized error=pointer-arith error=int-conversion error=incompatible-pointer-types error=discarded-qualifiers ; do + for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof error=uninitialized no-maybe-uninitialized error=pointer-arith error=int-conversion error=incompatible-pointer-types error=discarded-qualifiers error=implicit-int ; do cachevar=`echo "krb5_cv_cc_flag_-W$flag" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` { $as_echo "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -W$flag" >&5 $as_echo_n "checking if C compiler supports -W$flag... " >&6; } @@ -4344,7 +4651,7 @@ main () _ACEOF if ac_fn_c_try_compile "$LINENO"; then : old_cflags="$CFLAGS" - CFLAGS="$CFLAGS -W$flag" + CFLAGS="$CFLAGS $cflags_warning_test_flags -W$flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4411,7 +4718,7 @@ main () _ACEOF if ac_fn_c_try_compile "$LINENO"; then : old_cflags="$CFLAGS" - CFLAGS="$CFLAGS -Werror=$flag" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Werror=$flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4464,7 +4771,7 @@ main () _ACEOF if ac_fn_c_try_compile "$LINENO"; then : old_cflags="$CFLAGS" - CFLAGS="$CFLAGS -W$flag" + CFLAGS="$CFLAGS $cflags_warning_test_flags -W$flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4525,7 +4832,7 @@ main () _ACEOF if ac_fn_c_try_compile "$LINENO"; then : old_cflags="$CFLAGS" - CFLAGS="$CFLAGS -Werror-implicit-function-declaration" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Werror-implicit-function-declaration" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4578,7 +4885,7 @@ main () _ACEOF if ac_fn_c_try_compile "$LINENO"; then : old_cflags="$CFLAGS" - CFLAGS="$CFLAGS -Werror=implicit-function-declaration" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Werror=implicit-function-declaration" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4668,8 +4975,18 @@ $as_echo "$as_me: adding -O for inline thread-support function elimination" >&6; # works, but it also means that declaration-in-code warnings won't # be issued. # -v -fd -errwarn=E_DECLARATION_IN_CODE ... - WARN_CFLAGS="-errtags=yes -errwarn=E_BAD_PTR_INT_COMBINATION,E_BAD_PTR_INT_COMB_ARG,E_PTR_TO_VOID_IN_ARITHMETIC,E_NO_IMPLICIT_DECL_ALLOWED,E_ATTRIBUTE_PARAM_UNDEFINED" - WARN_CXXFLAGS="-errtags=yes +w +w2 -xport64" + if test "x$krb5_ac_warn_cflags_set" = xset ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: not adding extra warning flags because WARN_CFLAGS was set" >&5 +$as_echo "$as_me: not adding extra warning flags because WARN_CFLAGS was set" >&6;} + else + WARN_CFLAGS="-errtags=yes -errwarn=E_BAD_PTR_INT_COMBINATION,E_BAD_PTR_INT_COMB_ARG,E_PTR_TO_VOID_IN_ARITHMETIC,E_NO_IMPLICIT_DECL_ALLOWED,E_ATTRIBUTE_PARAM_UNDEFINED" + fi + if test "x$krb5_ac_warn_cxxflags_set" = xset ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: not adding extra warning flags because WARN_CXXFLAGS was set" >&5 +$as_echo "$as_me: not adding extra warning flags because WARN_CXXFLAGS was set" >&6;} + else + WARN_CXXFLAGS="-errtags=yes +w +w2 -xport64" + fi fi fi @@ -5808,28 +6125,33 @@ if test "$enable_thread_support" = yes; then + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -acx_pthread_ok=no +ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). +# requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x"; then : + CC="$PTHREAD_CC" +fi CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 -$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -5849,18 +6171,19 @@ return pthread_join (); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - acx_pthread_ok=yes + ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 -$as_echo "$acx_pthread_ok" >&6; } - if test x"$acx_pthread_ok" = xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -5873,7 +6196,7 @@ fi # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. -acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: @@ -5882,58 +6205,269 @@ acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -m # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) -case "${host_cpu}-${host_os}" in - *solaris*) +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} +fi +rm -f conftest* + + ;; + + solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthread or - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). - acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ;; esac -if test x"$acx_pthread_ok" = xno; then -for flag in $acx_pthread_flags; do +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +if test "x$GCC" = "xyes"; then : + ax_pthread_flags="-pthread -pthreads $ax_pthread_flags" +fi - case $flag in +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--"; then : + ax_pthread_check_cond=0 +else + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" +fi + +# Are we compiling with Clang? + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +$as_echo_n "checking whether $CC is Clang... " >&6; } +if ${ax_cv_PTHREAD_CLANG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then : + ax_cv_PTHREAD_CLANG=yes +fi +rm -f conftest* + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown"; then : + break +fi + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x"; then : + ax_pthread_try=no +fi + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; + -mt,pthread) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5 +$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; } + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + -*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 -$as_echo_n "checking whether pthreads work with $flag... " >&6; } - PTHREAD_CFLAGS="$flag" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; - pthread-config) - # Extract the first word of "pthread-config", so it can be a program name with args. + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_acx_pthread_config+:} false; then : +if ${ac_cv_prog_ax_pthread_config+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$acx_pthread_config"; then - ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test. + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -5942,7 +6476,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_acx_pthread_config="yes" + ac_cv_prog_ax_pthread_config="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5950,35 +6484,37 @@ done done IFS=$as_save_IFS - test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" fi fi -acx_pthread_config=$ac_cv_prog_acx_pthread_config -if test -n "$acx_pthread_config"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5 -$as_echo "$acx_pthread_config" >&6; } +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +$as_echo "$ax_pthread_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - if test x"$acx_pthread_config" = xno; then continue; fi - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; + if test "x$ax_pthread_config" = "xno"; then : + continue +fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 -$as_echo_n "checking for the pthreads library -l$flag... " >&6; } - PTHREAD_LIBS="-l$flag" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we @@ -5989,33 +6525,42 @@ $as_echo_n "checking for the pthreads library -l$flag... " >&6; } # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <pthread.h> +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; } int main () { -pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - acx_pthread_ok=yes + ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 -$as_echo "$acx_pthread_ok" >&6; } - if test "x$acx_pthread_ok" = xyes; then - break; - fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xyes"; then : + break +fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" @@ -6023,85 +6568,130 @@ done fi # Various other checks: -if test "x$acx_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" - # Detect AIX lossage: threads are created detached by default - # and the JOINABLE attribute has a nonstandard name (UNDETACHED). + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <pthread.h> int main () { -int attr=PTHREAD_CREATE_JOINABLE; +int attr = $ax_pthread_attr; return attr /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ok=PTHREAD_CREATE_JOINABLE -else - ok=unknown + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test x"$ok" = xunknown; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"; then : + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR +_ACEOF + + ax_pthread_joinable_attr_defined=yes + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +$as_echo_n "checking whether more special flags are required for pthreads... " >&6; } +if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"; then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <pthread.h> int main () { -int attr=PTHREAD_CREATE_UNDETACHED; +int i = PTHREAD_PRIO_INHERIT; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ok=PTHREAD_CREATE_UNDETACHED + ax_cv_PTHREAD_PRIO_INHERIT=yes else - ok=unknown + ax_cv_PTHREAD_PRIO_INHERIT=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - fi - if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then -$as_echo "#define PTHREAD_CREATE_JOINABLE \$ok" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"; then : - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ok}" >&5 -$as_echo "${ok}" >&6; } - if test x"$ok" = xunknown; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: we do not know how to create joinable pthreads" >&5 -$as_echo "$as_me: WARNING: we do not know how to create joinable pthreads" >&2;} - fi +$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 -$as_echo_n "checking if more special flags are required for pthreads... " >&6; } - flag=no - case "${host_cpu}-${host_os}" in - *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; - *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 -$as_echo "${flag}" >&6; } - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi + ax_pthread_prio_inherit_defined=yes - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" +fi + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" - # More AIX lossage: must compile with cc_r - # Extract the first word of "cc_r", so it can be a program name with args. -set dummy cc_r; ac_word=$2 + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + case "x/$CC" in #( + x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : + #handle absolute path differently from PATH based program lookup + case "x$CC" in #( + x/*) : + if as_fn_executable_p ${CC}_r; then : + PTHREAD_CC="${CC}_r" +fi ;; #( + *) : + for ac_prog in ${CC}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PTHREAD_CC+:} false; then : @@ -6117,7 +6707,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_PTHREAD_CC="cc_r" + ac_cv_prog_PTHREAD_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -6125,7 +6715,6 @@ done done IFS=$as_save_IFS - test -z "$ac_cv_prog_PTHREAD_CC" && ac_cv_prog_PTHREAD_CC="${CC}" fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC @@ -6138,22 +6727,33 @@ $as_echo "no" >&6; } fi -else - PTHREAD_CC="$CC" + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + ;; +esac ;; #( + *) : + ;; +esac + ;; + esac + fi fi +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$acx_pthread_ok" = xyes; then +if test "x$ax_pthread_ok" = "xyes"; then $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h : else - acx_pthread_ok=no + ax_pthread_ok=no as_fn_error $? "cannot determine options for enabling thread support; try --disable-thread-support" "$LINENO" 5 fi ac_ext=c @@ -6463,7 +7063,7 @@ done -KRB5_VERSION=1.15.1 +KRB5_VERSION=1.16 @@ -7755,20 +8355,12 @@ res1=`echo "$res1" | tr -d '*' | sed -e 's/ *$//'` res2=`echo "$res2" | tr -d '*' | sed -e 's/ *$//'` cat >>confdefs.h <<_ACEOF -#define GETSOCKNAME_ARG2_TYPE $res1 -_ACEOF - - -cat >>confdefs.h <<_ACEOF #define GETSOCKNAME_ARG3_TYPE $res2 _ACEOF -$as_echo "#define GETPEERNAME_ARG2_TYPE GETSOCKNAME_ARG2_TYPE" >>confdefs.h - - $as_echo "#define GETPEERNAME_ARG3_TYPE GETSOCKNAME_ARG3_TYPE" >>confdefs.h @@ -7813,10 +8405,20 @@ fi -ac_fn_c_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" +# Determine if NLS is desired and supported. +po= +# Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; +else + enable_nls=check +fi + +if test "$enable_nls" != no; then + ac_fn_c_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" if test "x$ac_cv_header_libintl_h" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dgettext" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dgettext" >&5 $as_echo_n "checking for library containing dgettext... " >&6; } if ${ac_cv_search_dgettext+:} false; then : $as_echo_n "(cached) " >&6 @@ -7873,13 +8475,14 @@ if test "$ac_res" != no; then : $as_echo "#define ENABLE_NLS 1" >>confdefs.h + nls_enabled=yes fi fi -# Extract the first word of "msgfmt", so it can be a program name with args. + # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } @@ -7916,9 +8519,16 @@ $as_echo "no" >&6; } fi -po= -if test x"$MSGFMT" != x; then - po=po + if test x"$MSGFMT" != x; then + po=po + fi + + # Error out if --enable-nls was explicitly requested but can't be enabled. + if test "$enable_nls" = yes; then + if test "$nls_enabled" != yes -o "x$po" = x; then + as_fn_error $? "NLS support requested but cannot be built" "$LINENO" 5 + fi + fi fi @@ -8543,147 +9153,6 @@ $as_echo "#define FORTUNA 1" >>confdefs.h fi -# WITH_PKINIT_CRYPTO_IMPL - -PKINIT_CRYPTO_IMPL="$CRYPTO_IMPL" - -# Check whether --with-pkinit-crypto-impl was given. -if test "${with_pkinit_crypto_impl+set}" = set; then : - withval=$with_pkinit_crypto_impl; PKINIT_CRYPTO_IMPL=$withval -{ $as_echo "$as_me:${as_lineno-$LINENO}: pkinit will use '$withval'" >&5 -$as_echo "$as_me: pkinit will use '$withval'" >&6;} - -else - withval=$PKINIT_CRYPTO_IMPL -fi - -case "$withval" in -builtin|openssl) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PKCS7_get_signer_info in -lcrypto" >&5 -$as_echo_n "checking for PKCS7_get_signer_info in -lcrypto... " >&6; } -if ${ac_cv_lib_crypto_PKCS7_get_signer_info+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcrypto $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char PKCS7_get_signer_info (); -int -main () -{ -return PKCS7_get_signer_info (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_crypto_PKCS7_get_signer_info=yes -else - ac_cv_lib_crypto_PKCS7_get_signer_info=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_PKCS7_get_signer_info" >&5 -$as_echo "$ac_cv_lib_crypto_PKCS7_get_signer_info" >&6; } -if test "x$ac_cv_lib_crypto_PKCS7_get_signer_info" = xyes; then : - PKINIT_CRYPTO_IMPL_LIBS=-lcrypto -fi - - PKINIT_CRYPTO_IMPL=openssl - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CMS_get0_content in -lcrypto" >&5 -$as_echo_n "checking for CMS_get0_content in -lcrypto... " >&6; } -if ${ac_cv_lib_crypto_CMS_get0_content+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcrypto $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char CMS_get0_content (); -int -main () -{ -return CMS_get0_content (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_crypto_CMS_get0_content=yes -else - ac_cv_lib_crypto_CMS_get0_content=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_CMS_get0_content" >&5 -$as_echo "$ac_cv_lib_crypto_CMS_get0_content" >&6; } -if test "x$ac_cv_lib_crypto_CMS_get0_content" = xyes; then : - -$as_echo "#define HAVE_OPENSSL_CMS 1" >>confdefs.h - -fi - - ;; -nss) - if test "${PKINIT_CRYPTO_IMPL_CFLAGS+set}" != set; then - PKINIT_CRYPTO_IMPL_CFLAGS=`pkg-config --cflags nss` - fi - if test "${PKINIT_CRYPTO_IMPL_LIBS+set}" != set; then - PKINIT_CRYPTO_IMPL_LIBS=`pkg-config --libs nss` - fi - -$as_echo "#define PKINIT_CRYPTO_IMPL_NSS 1" >>confdefs.h - - save_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $PKINIT_CRYPTO_IMPL_CFLAGS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include <nss.h> -#if NSS_VMAJOR < 3 || (NSS_VMAJOR == 3 && NSS_VMINOR < 12) -#error -#elif NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH < 11 -#error -#endif - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - as_fn_error $? "NSS version 3.12.11 or later required." "$LINENO" 5 -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$save_CFLAGS - ;; -*) - as_fn_error $? "Unknown crypto implementation $withval" "$LINENO" 5 - ;; -esac -ac_config_commands="$ac_config_commands PKINIT_CRYPTO_IMPL" - - - - - # WITH_TLS_IMPL @@ -10801,6 +11270,41 @@ _ACEOF fi +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 +$as_echo_n "checking size of time_t... " >&6; } +if ${ac_cv_sizeof_time_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_time_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (time_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_time_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 +$as_echo "$ac_cv_sizeof_time_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_TIME_T $ac_cv_sizeof_time_t +_ACEOF + + +SIZEOF_TIME_T=$ac_cv_sizeof_time_t + # Determine where to put the replay cache. @@ -12174,6 +12678,48 @@ if test "$k5_cv_openssl_version_okay" = yes && (test "$enable_pkinit" = yes || t PKINIT=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CMS_get0_content in -lcrypto" >&5 +$as_echo_n "checking for CMS_get0_content in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_CMS_get0_content+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char CMS_get0_content (); +int +main () +{ +return CMS_get0_content (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypto_CMS_get0_content=yes +else + ac_cv_lib_crypto_CMS_get0_content=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_CMS_get0_content" >&5 +$as_echo "$ac_cv_lib_crypto_CMS_get0_content" >&6; } +if test "x$ac_cv_lib_crypto_CMS_get0_content" = xyes; then : + +$as_echo "#define HAVE_OPENSSL_CMS 1" >>confdefs.h + +fi + elif test "$k5_cv_openssl_version_okay" = no && test "$enable_pkinit" = yes; then as_fn_error $? "Version of OpenSSL is too old; cannot enable PKINIT." "$LINENO" 5 else @@ -12319,6 +12865,9 @@ fi if test "$HAVE_CMOCKA_LIB" = yes && test "$HAVE_CMOCKA_H" = yes; then HAVE_CMOCKA=yes CMOCKA_LIBS='-lcmocka' + +$as_echo "#define HAVE_CMOCKA 1" >>confdefs.h + fi @@ -12437,9 +12986,9 @@ fi done - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_init in -lldap" >&5 -$as_echo_n "checking for ldap_init in -lldap... " >&6; } -if ${ac_cv_lib_ldap_ldap_init+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_str2dn in -lldap" >&5 +$as_echo_n "checking for ldap_str2dn in -lldap... " >&6; } +if ${ac_cv_lib_ldap_ldap_str2dn+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -12453,47 +13002,32 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char ldap_init (); +char ldap_str2dn (); int main () { -return ldap_init (); +return ldap_str2dn (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_ldap_ldap_init=yes + ac_cv_lib_ldap_ldap_str2dn=yes else - ac_cv_lib_ldap_ldap_init=no + ac_cv_lib_ldap_ldap_str2dn=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_init" >&5 -$as_echo "$ac_cv_lib_ldap_ldap_init" >&6; } -if test "x$ac_cv_lib_ldap_ldap_init" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_str2dn" >&5 +$as_echo "$ac_cv_lib_ldap_ldap_str2dn" >&6; } +if test "x$ac_cv_lib_ldap_ldap_str2dn" = xyes; then : : else - as_fn_error $? "libldap not found or missing ldap_init" "$LINENO" 5 + as_fn_error $? "libldap not found or missing ldap_str2dn" "$LINENO" 5 fi - old_LIBS="$LIBS" - LIBS="$LIBS -lldap" - for ac_func in ldap_initialize ldap_url_parse_nodn ldap_unbind_ext_s ldap_str2dn ldap_explode_dn -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - LIBS="$old_LIBS" BER_OKAY=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ber_init in -lldap" >&5 @@ -12911,7 +13445,7 @@ if test "${localedir+set}" != set; then fi -# For KCM lib/krb5/ccache to build KCM Mach RPC support for OS X only. +# For KCM lib/krb5/ccache to build KCM Mach RPC support for macOS only. case $host in *-*-darwin* | *-*-rhapsody*) OSX=osx ;; *) OSX=no ;; @@ -12948,10 +13482,10 @@ fi if test "${DEFCCNAME+set}" != set; then case $host in *-*-darwin[0-9].* | *-*-darwin10.*) - # Use the normal default for OS X 10.6 (Darwin 10) and prior. + # Use the normal default for macOS 10.6 (Darwin 10) and prior. ;; *-*-darwin*) - # For OS X 10.7 (Darwin 11) and later, the native ccache uses + # For macOS 10.7 (Darwin 11) and later, the native ccache uses # the KCM daemon. DEFCCNAME=KCM: ;; @@ -13052,9 +13586,11 @@ ac_config_files="$ac_config_files build-tools/kadm-server.pc build-tools/kadm-cl ac_config_files="$ac_config_files man/Makefile:$srcdir/./config/pre.in:man/Makefile.in:man/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files doc/Makefile:$srcdir/./config/pre.in:doc/Makefile.in:doc/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files include/Makefile:$srcdir/./config/pre.in:include/Makefile.in:include/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/certauth/test/Makefile:$srcdir/./config/pre.in:plugins/certauth/test/Makefile.in:plugins/certauth/test/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/hostrealm/test/Makefile:$srcdir/./config/pre.in:plugins/hostrealm/test/Makefile.in:plugins/hostrealm/test/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/localauth/test/Makefile:$srcdir/./config/pre.in:plugins/localauth/test/Makefile.in:plugins/localauth/test/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/kadm5_hook/test/Makefile:$srcdir/./config/pre.in:plugins/kadm5_hook/test/Makefile.in:plugins/kadm5_hook/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kadm5_auth/test/Makefile:$srcdir/./config/pre.in:plugins/kadm5_auth/test/Makefile.in:plugins/kadm5_auth/test/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/pwqual/test/Makefile:$srcdir/./config/pre.in:plugins/pwqual/test/Makefile.in:plugins/pwqual/test/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/audit/Makefile:$srcdir/./config/pre.in:plugins/audit/Makefile.in:plugins/audit/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/audit/test/Makefile:$srcdir/./config/pre.in:plugins/audit/test/Makefile.in:plugins/audit/test/deps:$srcdir/./config/post.in" @@ -13067,6 +13603,7 @@ ac_config_files="$ac_config_files build-tools/kadm-server.pc build-tools/kadm-cl ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/recno/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/recno/Makefile.in:plugins/kdb/db2/libdb2/recno/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/test/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/test/Makefile.in:plugins/kdb/db2/libdb2/test/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/kdb/test/Makefile:$srcdir/./config/pre.in:plugins/kdb/test/Makefile.in:plugins/kdb/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdcpolicy/test/Makefile:$srcdir/./config/pre.in:plugins/kdcpolicy/test/Makefile.in:plugins/kdcpolicy/test/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/preauth/otp/Makefile:$srcdir/./config/pre.in:plugins/preauth/otp/Makefile.in:plugins/preauth/otp/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/preauth/test/Makefile:$srcdir/./config/pre.in:plugins/preauth/test/Makefile.in:plugins/preauth/test/deps:$srcdir/./config/post.in" ac_config_files="$ac_config_files plugins/authdata/greet_client/Makefile:$srcdir/./config/pre.in:plugins/authdata/greet_client/Makefile.in:plugins/authdata/greet_client/deps:$srcdir/./config/post.in" @@ -13617,7 +14154,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Kerberos 5 $as_me 1.15.1, which was +This file was extended by Kerberos 5 $as_me 1.16, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13683,7 +14220,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Kerberos 5 config.status 1.15.1 +Kerberos 5 config.status 1.16 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -13803,7 +14340,6 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # CRYPTO_IMPL=$CRYPTO_IMPL PRNG_ALG=$PRNG_ALG -PKINIT_CRYPTO_IMPL=$PKINIT_CRYPTO_IMPL _ACEOF @@ -13816,7 +14352,6 @@ do "plugins/audit/simple/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/audit/simple/Makefile:$srcdir/./config/pre.in:plugins/audit/simple/Makefile.in:plugins/audit/simple/deps:$srcdir/./config/post.in" ;; "CRYPTO_IMPL") CONFIG_COMMANDS="$CONFIG_COMMANDS CRYPTO_IMPL" ;; "PRNG_ALG") CONFIG_COMMANDS="$CONFIG_COMMANDS PRNG_ALG" ;; - "PKINIT_CRYPTO_IMPL") CONFIG_COMMANDS="$CONFIG_COMMANDS PKINIT_CRYPTO_IMPL" ;; "include/autoconf.h") CONFIG_HEADERS="$CONFIG_HEADERS include/autoconf.h" ;; "kadmin/testing/scripts/env-setup.sh") CONFIG_FILES="$CONFIG_FILES kadmin/testing/scripts/env-setup.sh:kadmin/testing/scripts/env-setup.shin" ;; "include/gssrpc/types.h") CONFIG_FILES="$CONFIG_FILES include/gssrpc/types.h:include/gssrpc/types.hin" ;; @@ -13886,9 +14421,11 @@ do "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile:$srcdir/./config/pre.in:man/Makefile.in:man/deps:$srcdir/./config/post.in" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile:$srcdir/./config/pre.in:doc/Makefile.in:doc/deps:$srcdir/./config/post.in" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile:$srcdir/./config/pre.in:include/Makefile.in:include/deps:$srcdir/./config/post.in" ;; + "plugins/certauth/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/certauth/test/Makefile:$srcdir/./config/pre.in:plugins/certauth/test/Makefile.in:plugins/certauth/test/deps:$srcdir/./config/post.in" ;; "plugins/hostrealm/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/hostrealm/test/Makefile:$srcdir/./config/pre.in:plugins/hostrealm/test/Makefile.in:plugins/hostrealm/test/deps:$srcdir/./config/post.in" ;; "plugins/localauth/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/localauth/test/Makefile:$srcdir/./config/pre.in:plugins/localauth/test/Makefile.in:plugins/localauth/test/deps:$srcdir/./config/post.in" ;; "plugins/kadm5_hook/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kadm5_hook/test/Makefile:$srcdir/./config/pre.in:plugins/kadm5_hook/test/Makefile.in:plugins/kadm5_hook/test/deps:$srcdir/./config/post.in" ;; + "plugins/kadm5_auth/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kadm5_auth/test/Makefile:$srcdir/./config/pre.in:plugins/kadm5_auth/test/Makefile.in:plugins/kadm5_auth/test/deps:$srcdir/./config/post.in" ;; "plugins/pwqual/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/pwqual/test/Makefile:$srcdir/./config/pre.in:plugins/pwqual/test/Makefile.in:plugins/pwqual/test/deps:$srcdir/./config/post.in" ;; "plugins/audit/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/audit/Makefile:$srcdir/./config/pre.in:plugins/audit/Makefile.in:plugins/audit/deps:$srcdir/./config/post.in" ;; "plugins/audit/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/audit/test/Makefile:$srcdir/./config/pre.in:plugins/audit/test/Makefile.in:plugins/audit/test/deps:$srcdir/./config/post.in" ;; @@ -13901,6 +14438,7 @@ do "plugins/kdb/db2/libdb2/recno/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/recno/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/recno/Makefile.in:plugins/kdb/db2/libdb2/recno/deps:$srcdir/./config/post.in" ;; "plugins/kdb/db2/libdb2/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/test/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/test/Makefile.in:plugins/kdb/db2/libdb2/test/deps:$srcdir/./config/post.in" ;; "plugins/kdb/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/test/Makefile:$srcdir/./config/pre.in:plugins/kdb/test/Makefile.in:plugins/kdb/test/deps:$srcdir/./config/post.in" ;; + "plugins/kdcpolicy/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdcpolicy/test/Makefile:$srcdir/./config/pre.in:plugins/kdcpolicy/test/Makefile.in:plugins/kdcpolicy/test/deps:$srcdir/./config/post.in" ;; "plugins/preauth/otp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/preauth/otp/Makefile:$srcdir/./config/pre.in:plugins/preauth/otp/Makefile.in:plugins/preauth/otp/deps:$srcdir/./config/post.in" ;; "plugins/preauth/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/preauth/test/Makefile:$srcdir/./config/pre.in:plugins/preauth/test/Makefile.in:plugins/preauth/test/deps:$srcdir/./config/post.in" ;; "plugins/authdata/greet_client/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/authdata/greet_client/Makefile:$srcdir/./config/pre.in:plugins/authdata/greet_client/Makefile.in:plugins/authdata/greet_client/deps:$srcdir/./config/post.in" ;; diff --git a/src/configure.in b/src/configure.in index 037c9f316149..10f45eb12e16 100644 --- a/src/configure.in +++ b/src/configure.in @@ -118,15 +118,29 @@ LIBUTIL=-lutil ]) AC_SUBST(LIBUTIL) -AC_CHECK_HEADER(libintl.h, [ - AC_SEARCH_LIBS(dgettext, intl, [ - AC_DEFINE(ENABLE_NLS, 1, - [Define if translation functions should be used.])])]) - -AC_CHECK_PROG(MSGFMT,msgfmt,msgfmt) +# Determine if NLS is desired and supported. po= -if test x"$MSGFMT" != x; then - po=po +AC_ARG_ENABLE([nls], +AC_HELP_STRING([--disable-nls], [disable native language support]), + [], [enable_nls=check]) +if test "$enable_nls" != no; then + AC_CHECK_HEADER(libintl.h, [ + AC_SEARCH_LIBS(dgettext, intl, [ + AC_DEFINE(ENABLE_NLS, 1, + [Define if translation functions should be used.]) + nls_enabled=yes])]) + + AC_CHECK_PROG(MSGFMT,msgfmt,msgfmt) + if test x"$MSGFMT" != x; then + po=po + fi + + # Error out if --enable-nls was explicitly requested but can't be enabled. + if test "$enable_nls" = yes; then + if test "$nls_enabled" != yes -o "x$po" = x; then + AC_MSG_ERROR([NLS support requested but cannot be built]) + fi + fi fi AC_SUBST(po) @@ -264,51 +278,6 @@ if test "$PRNG_ALG" = fortuna; then AC_DEFINE(FORTUNA,1,[Define if Fortuna PRNG is selected]) fi -# WITH_PKINIT_CRYPTO_IMPL - -PKINIT_CRYPTO_IMPL="$CRYPTO_IMPL" -AC_ARG_WITH([pkinit-crypto-impl], -AC_HELP_STRING([--with-pkinit-crypto-impl=IMPL], [use specified pkinit crypto implementation @<:@openssl@:>@]), -[PKINIT_CRYPTO_IMPL=$withval -AC_MSG_NOTICE(pkinit will use '$withval') -], withval=$PKINIT_CRYPTO_IMPL) -case "$withval" in -builtin|openssl) - AC_CHECK_LIB(crypto, PKCS7_get_signer_info, PKINIT_CRYPTO_IMPL_LIBS=-lcrypto) - PKINIT_CRYPTO_IMPL=openssl - AC_CHECK_LIB(crypto, CMS_get0_content, - [AC_DEFINE([HAVE_OPENSSL_CMS], 1, - [Define if OpenSSL supports cms.])]) - ;; -nss) - if test "${PKINIT_CRYPTO_IMPL_CFLAGS+set}" != set; then - PKINIT_CRYPTO_IMPL_CFLAGS=`pkg-config --cflags nss` - fi - if test "${PKINIT_CRYPTO_IMPL_LIBS+set}" != set; then - PKINIT_CRYPTO_IMPL_LIBS=`pkg-config --libs nss` - fi - AC_DEFINE(PKINIT_CRYPTO_IMPL_NSS,1,[Define if pkinit crypto implementation is NSS]) - save_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $PKINIT_CRYPTO_IMPL_CFLAGS" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ -#include <nss.h> -#if NSS_VMAJOR < 3 || (NSS_VMAJOR == 3 && NSS_VMINOR < 12) -#error -#elif NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH < 11 -#error -#endif - ])], [], [AC_MSG_ERROR([NSS version 3.12.11 or later required.])]) - CFLAGS=$save_CFLAGS - ;; -*) - AC_MSG_ERROR([Unknown crypto implementation $withval]) - ;; -esac -AC_CONFIG_COMMANDS(PKINIT_CRYPTO_IMPL,,PKINIT_CRYPTO_IMPL=$PKINIT_CRYPTO_IMPL) -AC_SUBST(PKINIT_CRYPTO_IMPL) -AC_SUBST(PKINIT_CRYPTO_IMPL_CFLAGS) -AC_SUBST(PKINIT_CRYPTO_IMPL_LIBS) - # WITH_TLS_IMPL AC_ARG_WITH([tls-impl], @@ -744,6 +713,9 @@ fi AC_HEADER_TIME AC_CHECK_TYPE(time_t, long) +AC_CHECK_SIZEOF(time_t) +SIZEOF_TIME_T=$ac_cv_sizeof_time_t +AC_SUBST(SIZEOF_TIME_T) # Determine where to put the replay cache. @@ -1085,6 +1057,7 @@ fi if test "$k5_cv_openssl_version_okay" = yes && (test "$enable_pkinit" = yes || test "$enable_pkinit" = try); then K5_GEN_MAKEFILE(plugins/preauth/pkinit) PKINIT=yes + AC_CHECK_LIB(crypto, CMS_get0_content, [AC_DEFINE([HAVE_OPENSSL_CMS], 1, [Define if OpenSSL supports cms.])]) elif test "$k5_cv_openssl_version_okay" = no && test "$enable_pkinit" = yes; then AC_MSG_ERROR([Version of OpenSSL is too old; cannot enable PKINIT.]) else @@ -1131,6 +1104,7 @@ AC_CHECK_LIB(cmocka, _cmocka_run_group_tests, [HAVE_CMOCKA_LIB=yes]) if test "$HAVE_CMOCKA_LIB" = yes && test "$HAVE_CMOCKA_H" = yes; then HAVE_CMOCKA=yes CMOCKA_LIBS='-lcmocka' + AC_DEFINE([HAVE_CMOCKA],1,[Define if cmocka library is available.]) fi AC_SUBST(HAVE_CMOCKA) AC_SUBST(CMOCKA_LIBS) @@ -1213,11 +1187,7 @@ ldap_plugin_dir="" ldap_lib="" if test -n "$OPENLDAP_PLUGIN"; then AC_CHECK_HEADERS(ldap.h lber.h, :, [AC_MSG_ERROR($ac_header not found)]) - AC_CHECK_LIB(ldap, ldap_init, :, [AC_MSG_ERROR(libldap not found or missing ldap_init)]) - old_LIBS="$LIBS" - LIBS="$LIBS -lldap" - AC_CHECK_FUNCS(ldap_initialize ldap_url_parse_nodn ldap_unbind_ext_s ldap_str2dn ldap_explode_dn) - LIBS="$old_LIBS" + AC_CHECK_LIB(ldap, ldap_str2dn, :, [AC_MSG_ERROR(libldap not found or missing ldap_str2dn)]) BER_OKAY=0 AC_CHECK_LIB(ldap, ber_init, [BER_OKAY=1]) @@ -1342,7 +1312,7 @@ if test "${localedir+set}" != set; then fi AC_SUBST(localedir) -# For KCM lib/krb5/ccache to build KCM Mach RPC support for OS X only. +# For KCM lib/krb5/ccache to build KCM Mach RPC support for macOS only. case $host in *-*-darwin* | *-*-rhapsody*) OSX=osx ;; *) OSX=no ;; @@ -1376,10 +1346,10 @@ dnl brackets in the glob patterns. if test "${DEFCCNAME+set}" != set; then [case $host in *-*-darwin[0-9].* | *-*-darwin10.*) - # Use the normal default for OS X 10.6 (Darwin 10) and prior. + # Use the normal default for macOS 10.6 (Darwin 10) and prior. ;; *-*-darwin*) - # For OS X 10.7 (Darwin 11) and later, the native ccache uses + # For macOS 10.7 (Darwin 11) and later, the native ccache uses # the KCM daemon. DEFCCNAME=KCM: ;; @@ -1392,7 +1362,7 @@ if test "${DEFKTNAME+set}" != set; then DEFKTNAME=FILE:/etc/krb5.keytab fi if test "${DEFCKTNAME+set}" != set; then - adl_RECURSIVE_EVAL($localstatedir, exp_localstatedir) + AX_RECURSIVE_EVAL($localstatedir, exp_localstatedir) DEFCKTNAME=FILE:$exp_localstatedir/krb5/user/%{euid}/client.keytab fi AC_MSG_NOTICE([Default ccache name: $DEFCCNAME]) @@ -1447,9 +1417,11 @@ dnl ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test kdc slave config-files build-tools man doc include + plugins/certauth/test plugins/hostrealm/test plugins/localauth/test plugins/kadm5_hook/test + plugins/kadm5_auth/test plugins/pwqual/test plugins/audit plugins/audit/test @@ -1462,6 +1434,7 @@ dnl ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test plugins/kdb/db2/libdb2/recno plugins/kdb/db2/libdb2/test plugins/kdb/test + plugins/kdcpolicy/test plugins/preauth/otp plugins/preauth/test plugins/authdata/greet_client diff --git a/src/include/Makefile.in b/src/include/Makefile.in index f5b921833071..cfa5794b72bf 100644 --- a/src/include/Makefile.in +++ b/src/include/Makefile.in @@ -140,15 +140,18 @@ install-headers-unix install: krb5/krb5.h profile.h $(INSTALL_DATA) $(srcdir)/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5.h $(INSTALL_DATA) $(srcdir)/kdb.h $(DESTDIR)$(KRB5_INCDIR)$(S)kdb.h $(INSTALL_DATA) krb5/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)krb5.h + $(INSTALL_DATA) $(srcdir)/krb5/certauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)certauth_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/ccselect_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)ccselect_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/clpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)clpreauth_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/hostrealm_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)hostrealm_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/kdcpolicy_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpolicy_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/kdcpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpreauth_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/localauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)localauth_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/locate_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)locate_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)plugin.h $(INSTALL_DATA) $(srcdir)/krb5/preauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)preauth_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/pwqual_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)pwqual_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/kadm5_auth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kadm5_auth_plugin.h $(INSTALL_DATA) $(srcdir)/krb5/kadm5_hook_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kadm5_hook_plugin.h $(INSTALL_DATA) profile.h $(DESTDIR)$(KRB5_INCDIR)$(S)profile.h $(INSTALL_DATA) $(srcdir)/gssapi.h $(DESTDIR)$(KRB5_INCDIR)$(S)gssapi.h diff --git a/src/include/autoconf.h.in b/src/include/autoconf.h.in index b33c5222325e..3dfc128e67bd 100644 --- a/src/include/autoconf.h.in +++ b/src/include/autoconf.h.in @@ -62,9 +62,6 @@ #undef GETHOSTBYNAME_R_RETURNS_INT /* Type of getpeername second argument. */ -#undef GETPEERNAME_ARG2_TYPE - -/* Type of getpeername second argument. */ #undef GETPEERNAME_ARG3_TYPE /* Define if getpwnam_r exists but takes only 4 arguments (e.g., POSIX draft 6 @@ -81,9 +78,6 @@ /* Define if getservbyname_r returns int rather than struct servent * */ #undef GETSERVBYNAME_R_RETURNS_INT -/* Type of pointer target for argument 2 to getsockname */ -#undef GETSOCKNAME_ARG2_TYPE - /* Type of pointer target for argument 3 to getsockname */ #undef GETSOCKNAME_ARG3_TYPE @@ -124,6 +118,9 @@ /* Define to 1 if you have the `chmod' function. */ #undef HAVE_CHMOD +/* Define if cmocka library is available. */ +#undef HAVE_CMOCKA + /* Define to 1 if you have the `compile' function. */ #undef HAVE_COMPILE @@ -240,24 +237,9 @@ /* Define to 1 if you have the <lber.h> header file. */ #undef HAVE_LBER_H -/* Define to 1 if you have the `ldap_explode_dn' function. */ -#undef HAVE_LDAP_EXPLODE_DN - /* Define to 1 if you have the <ldap.h> header file. */ #undef HAVE_LDAP_H -/* Define to 1 if you have the `ldap_initialize' function. */ -#undef HAVE_LDAP_INITIALIZE - -/* Define to 1 if you have the `ldap_str2dn' function. */ -#undef HAVE_LDAP_STR2DN - -/* Define to 1 if you have the `ldap_unbind_ext_s' function. */ -#undef HAVE_LDAP_UNBIND_EXT_S - -/* Define to 1 if you have the `ldap_url_parse_nodn' function. */ -#undef HAVE_LDAP_URL_PARSE_NODN - /* Define to 1 if you have the `crypto' library (-lcrypto). */ #undef HAVE_LIBCRYPTO @@ -333,6 +315,9 @@ /* Define to 1 if you have the `pthread_once' function. */ #undef HAVE_PTHREAD_ONCE +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + /* Define to 1 if you have the `pthread_rwlock_init' function. */ #undef HAVE_PTHREAD_RWLOCK_INIT @@ -657,9 +642,6 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* Define if pkinit crypto implementation is NSS */ -#undef PKINIT_CRYPTO_IMPL_NSS - /* Define if setjmp indicates POSIX interface */ #undef POSIX_SETJMP @@ -672,7 +654,7 @@ /* Define if termios.h exists and tcsetattr exists */ #undef POSIX_TERMIOS -/* Define to the necessary symbol if this constant uses a non-standard name on +/* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE @@ -682,6 +664,9 @@ /* Define as return type of setrpcent */ #undef SETRPCENT_TYPE +/* The size of `time_t', as computed by sizeof. */ +#undef SIZEOF_TIME_T + /* Define for static plugin linkage */ #undef STATIC_PLUGINS diff --git a/src/include/fake-addrinfo.h b/src/include/fake-addrinfo.h index 03666a0aaaa7..80ca9f8dfd23 100644 --- a/src/include/fake-addrinfo.h +++ b/src/include/fake-addrinfo.h @@ -52,7 +52,7 @@ the data structures and flag values locally. - On Mac OS X, getaddrinfo results aren't cached (though + On macOS, getaddrinfo results aren't cached (though gethostbyname results are), so we need to build a cache here. Now things are getting really messy. Because the cache is in use, we use getservbyname, and throw away thread safety. (Not that the diff --git a/src/include/k5-cmocka.h b/src/include/k5-cmocka.h new file mode 100644 index 000000000000..c35b10be0736 --- /dev/null +++ b/src/include/k5-cmocka.h @@ -0,0 +1,16 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-cmocka.h - indirect header file for cmocka test programs */ + +/* + * This header conditionally includes cmocka.h, so that "make depend" can work + * on cmocka test programs when cmocka isn't available. It also includes the + * three system headers required for cmocka.h. + */ + +#include "autoconf.h" +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#ifdef HAVE_CMOCKA +#include <cmocka.h> +#endif diff --git a/src/include/k5-input.h b/src/include/k5-input.h index d42ebce8f271..9f47fa7ab903 100644 --- a/src/include/k5-input.h +++ b/src/include/k5-input.h @@ -33,7 +33,7 @@ #ifndef K5_INPUT_H #define K5_INPUT_H -#include "k5-int.h" +#include "k5-platform.h" /* * The k5input module defines helpers for safely consuming a fixed-sized block @@ -45,7 +45,7 @@ struct k5input { const unsigned char *ptr; size_t len; - krb5_error_code status; + int32_t status; }; static inline void @@ -59,7 +59,7 @@ k5_input_init(struct k5input *in, const void *ptr, size_t len) /* Only set the status value of in if it hasn't already been set, so status * reflects the first thing to go wrong. */ static inline void -k5_input_set_status(struct k5input *in, krb5_error_code status) +k5_input_set_status(struct k5input *in, int32_t status) { if (!in->status) in->status = status; diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 64991738a3e2..e1b1cb040d5e 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -212,6 +212,7 @@ typedef unsigned char u_char; #define KRB5_CONF_DNS_URI_LOOKUP "dns_uri_lookup" #define KRB5_CONF_DOMAIN_REALM "domain_realm" #define KRB5_CONF_ENABLE_ONLY "enable_only" +#define KRB5_CONF_ENCRYPTED_CHALLENGE_INDICATOR "encrypted_challenge_indicator" #define KRB5_CONF_ERR_FMT "err_fmt" #define KRB5_CONF_EXTRA_ADDRESSES "extra_addresses" #define KRB5_CONF_FORWARDABLE "forwardable" @@ -720,7 +721,7 @@ krb5_error_code krb5int_c_copy_keyblock_contents(krb5_context context, const krb5_keyblock *from, krb5_keyblock *to); -krb5_error_code krb5_crypto_us_timeofday(krb5_int32 *, krb5_int32 *); +krb5_error_code krb5_crypto_us_timeofday(krb5_timestamp *, krb5_int32 *); /* * End "los-proto.h" @@ -1155,7 +1156,10 @@ struct plugin_interface { #define PLUGIN_INTERFACE_AUDIT 7 #define PLUGIN_INTERFACE_TLS 8 #define PLUGIN_INTERFACE_KDCAUTHDATA 9 -#define PLUGIN_NUM_INTERFACES 10 +#define PLUGIN_INTERFACE_CERTAUTH 10 +#define PLUGIN_INTERFACE_KADM5_AUTH 11 +#define PLUGIN_INTERFACE_KDCPOLICY 12 +#define PLUGIN_NUM_INTERFACES 13 /* Retrieve the plugin module of type interface_id and name modname, * storing the result into module. */ @@ -1194,7 +1198,7 @@ k5_plugin_free_context(krb5_context context); struct _kdb5_dal_handle; /* private, in kdb5.h */ typedef struct _kdb5_dal_handle kdb5_dal_handle; struct _kdb_log_context; -typedef struct krb5_preauth_context_st krb5_preauth_context; +typedef struct krb5_preauth_context_st *krb5_preauth_context; struct ccselect_module_handle; struct localauth_module_handle; struct hostrealm_module_handle; @@ -1231,7 +1235,7 @@ struct _krb5_context { struct plugin_dir_handle libkrb5_plugins; /* preauth module stuff */ - krb5_preauth_context *preauth_context; + krb5_preauth_context preauth_context; /* cache module stuff */ struct ccselect_module_handle **ccselect_handles; @@ -2112,6 +2116,7 @@ krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **); krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype); krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype); +krb5_error_code k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out); krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *, krb5_const_pointer, krb5_kdc_rep *); @@ -2350,6 +2355,44 @@ k5memdup0(const void *in, size_t len, krb5_error_code *code) return ptr; } +/* Convert a krb5_timestamp to a time_t value, treating the negative range of + * krb5_timestamp as times between 2038 and 2106 (if time_t is 64-bit). */ +static inline time_t +ts2tt(krb5_timestamp timestamp) +{ + return (time_t)(uint32_t)timestamp; +} + +/* Return the delta between two timestamps (a - b) as a signed 32-bit value, + * without relying on undefined behavior. */ +static inline krb5_deltat +ts_delta(krb5_timestamp a, krb5_timestamp b) +{ + return (krb5_deltat)((uint32_t)a - (uint32_t)b); +} + +/* Increment a timestamp by a signed 32-bit interval, without relying on + * undefined behavior. */ +static inline krb5_timestamp +ts_incr(krb5_timestamp ts, krb5_deltat delta) +{ + return (krb5_timestamp)((uint32_t)ts + (uint32_t)delta); +} + +/* Return true if a comes after b. */ +static inline krb5_boolean +ts_after(krb5_timestamp a, krb5_timestamp b) +{ + return (uint32_t)a > (uint32_t)b; +} + +/* Return true if a and b are within d seconds. */ +static inline krb5_boolean +ts_within(krb5_timestamp a, krb5_timestamp b, krb5_deltat d) +{ + return !ts_after(a, ts_incr(b, d)) && !ts_after(b, ts_incr(a, d)); +} + krb5_error_code KRB5_CALLCONV krb5_get_credentials_for_user(krb5_context context, krb5_flags options, krb5_ccache ccache, diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h index 994f46323cb0..548c0486d567 100644 --- a/src/include/k5-platform.h +++ b/src/include/k5-platform.h @@ -71,6 +71,13 @@ #define CAN_COPY_VA_LIST #endif +/* This attribute prevents unused function warnings in gcc and clang. */ +#ifdef __GNUC__ +#define UNUSED __attribute__((__unused__)) +#else +#define UNUSED +#endif + #if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) #include <TargetConditionals.h> #endif @@ -354,19 +361,7 @@ typedef struct { int error; unsigned char did_run; } k5_init_t; -#if !defined(SHARED) && !defined(_WIN32) - -/* - * In this case, we just don't care about finalization. - * - * The code will still define the function, but we won't do anything - * with it. Annoying: This may generate unused-function warnings. - */ - -# define MAKE_FINI_FUNCTION(NAME) \ - static void NAME(void) - -#elif defined(USE_LINKER_FINI_OPTION) || defined(_WIN32) +#if defined(USE_LINKER_FINI_OPTION) || defined(_WIN32) /* If we're told the linker option will be used, it doesn't really matter what compiler we're using. Do it the same way regardless. */ @@ -400,6 +395,15 @@ typedef struct { int error; unsigned char did_run; } k5_init_t; # endif +#elif !defined(SHARED) + +/* + * In this case, we just don't care about finalization. The code will still + * define the function, but we won't do anything with it. + */ +# define MAKE_FINI_FUNCTION(NAME) \ + static void NAME(void) UNUSED + #elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS) /* If we're using gcc, if the C++ support works, the compiler should build executables and shared libraries that support the use of @@ -508,7 +512,7 @@ typedef struct { int error; unsigned char did_run; } k5_init_t; Linux: byteswap.h, bswap_16 etc. Solaris 10: none - Mac OS X: machine/endian.h or byte_order.h, NXSwap{Short,Int,LongLong} + macOS: machine/endian.h or byte_order.h, NXSwap{Short,Int,LongLong} NetBSD: sys/bswap.h, bswap16 etc. */ #if defined(HAVE_BYTESWAP_H) && defined(HAVE_BSWAP_16) diff --git a/src/include/k5-thread.h b/src/include/k5-thread.h index 3e3901d6e8fb..a3101239d8a5 100644 --- a/src/include/k5-thread.h +++ b/src/include/k5-thread.h @@ -134,6 +134,10 @@ More to be added, perhaps. */ #include <assert.h> +#ifndef NDEBUG +#include <stdio.h> +#include <string.h> +#endif /* The mutex structure we use, k5_mutex_t, is defined to some OS-specific bits. The use of multiple layers of typedefs are an @@ -363,12 +367,24 @@ static inline int k5_mutex_finish_init(k5_mutex_t *m) static inline void k5_mutex_lock(k5_mutex_t *m) { int r = k5_os_mutex_lock(m); +#ifndef NDEBUG + if (r != 0) { + fprintf(stderr, "k5_mutex_lock: Received error %d (%s)\n", + r, strerror(r)); + } +#endif assert(r == 0); } static inline void k5_mutex_unlock(k5_mutex_t *m) { int r = k5_os_mutex_unlock(m); +#ifndef NDEBUG + if (r != 0) { + fprintf(stderr, "k5_mutex_unlock: Received error %d (%s)\n", + r, strerror(r)); + } +#endif assert(r == 0); } diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h index c75e264e04f2..390a8b7d6fc7 100644 --- a/src/include/k5-trace.h +++ b/src/include/k5-trace.h @@ -155,6 +155,20 @@ void krb5int_trace(krb5_context context, const char *fmt, ...); TRACE(c, "ccselect choosing default cache {ccache} for server " \ "principal {princ}", cache, server) +#define TRACE_DNS_SRV_ANS(c, host, port, prio, weight) \ + TRACE(c, "SRV answer: {int} {int} {int} \"{str}\"", prio, weight, \ + port, host) +#define TRACE_DNS_SRV_NOTFOUND(c) \ + TRACE(c, "No SRV records found") +#define TRACE_DNS_SRV_SEND(c, domain) \ + TRACE(c, "Sending DNS SRV query for {str}", domain) +#define TRACE_DNS_URI_ANS(c, uri, prio, weight) \ + TRACE(c, "URI answer: {int} {int} \"{str}\"", prio, weight, uri) +#define TRACE_DNS_URI_NOTFOUND(c) \ + TRACE(c, "No URI records found") +#define TRACE_DNS_URI_SEND(c, domain) \ + TRACE(c, "Sending DNS URI query for {str}", domain) + #define TRACE_FAST_ARMOR_CCACHE(c, ccache_name) \ TRACE(c, "FAST armor ccache: {str}", ccache_name) #define TRACE_FAST_ARMOR_CCACHE_KEY(c, keyblock) \ @@ -213,8 +227,19 @@ void krb5int_trace(krb5_context context, const char *fmt, ...); TRACE(c, "Looked up etypes in keytab: {etypes}", etypes) #define TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(c, code) \ TRACE(c, "Couldn't lookup etypes in keytab: {kerr}", code) +#define TRACE_INIT_CREDS_PREAUTH(c) \ + TRACE(c, "Preauthenticating using KDC method data") #define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code) \ TRACE(c, "Decrypt with preauth AS key failed: {kerr}", code) +#define TRACE_INIT_CREDS_PREAUTH_MORE(c, patype) \ + TRACE(c, "Continuing preauth mech {int}", (int)patype) +#define TRACE_INIT_CREDS_PREAUTH_NONE(c) \ + TRACE(c, "Sending unauthenticated request") +#define TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(c) \ + TRACE(c, "Attempting optimistic preauth") +#define TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(c, patype, code) \ + TRACE(c, "Recovering from KDC error {int} using preauth mech {int}", \ + (int)patype, (int)code) #define TRACE_INIT_CREDS_RESTART_FAST(c) \ TRACE(c, "Restarting to upgrade to FAST") #define TRACE_INIT_CREDS_RESTART_PREAUTH_FAILED(c) \ @@ -228,6 +253,13 @@ void krb5int_trace(krb5_context context, const char *fmt, ...); #define TRACE_INIT_CREDS_SERVICE(c, service) \ TRACE(c, "Setting initial creds service to {str}", service) +#define TRACE_KADM5_AUTH_VTINIT_FAIL(c, ret) \ + TRACE(c, "kadm5_auth module failed to init vtable: {kerr}", ret) +#define TRACE_KADM5_AUTH_INIT_FAIL(c, name, ret) \ + TRACE(c, "kadm5_auth module {str} failed to init: {kerr}", ret) +#define TRACE_KADM5_AUTH_INIT_SKIP(c, name) \ + TRACE(c, "kadm5_auth module {str} declined to initialize", name) + #define TRACE_KT_GET_ENTRY(c, keytab, princ, vno, enctype, err) \ TRACE(c, "Retrieving {princ} from {keytab} (vno {int}, enctype {etype}) " \ "with result: {kerr}", princ, keytab, (int) vno, enctype, err) @@ -287,10 +319,16 @@ void krb5int_trace(krb5_context context, const char *fmt, ...); #define TRACE_PREAUTH_SKIP(c, name, patype) \ TRACE(c, "Skipping previously used preauth module {str} ({int})", \ name, (int) patype) -#define TRACE_PREAUTH_TRYAGAIN_INPUT(c, padata) \ - TRACE(c, "Preauth tryagain input types: {patypes}", padata) +#define TRACE_PREAUTH_TRYAGAIN_INPUT(c, patype, padata) \ + TRACE(c, "Preauth tryagain input types ({int}): {patypes}", patype, padata) +#define TRACE_PREAUTH_TRYAGAIN(c, name, patype, code) \ + TRACE(c, "Preauth module {str} ({int}) tryagain returned: {kerr}", \ + name, (int)patype, code) #define TRACE_PREAUTH_TRYAGAIN_OUTPUT(c, padata) \ TRACE(c, "Followup preauth for next request: {patypes}", padata) +#define TRACE_PREAUTH_WRONG_CONTEXT(c) \ + TRACE(c, "Wrong context passed to krb5_init_creds_free(); leaking " \ + "modreq objects") #define TRACE_PROFILE_ERR(c,subsection, section, retval) \ TRACE(c, "Bad value of {str} from [{str}] in conf file: {kerr}", \ @@ -454,4 +492,9 @@ void krb5int_trace(krb5_context context, const char *fmt, ...); #define TRACE_GET_CRED_VIA_TKT_EXT_RETURN(c, ret) \ TRACE(c, "Got cred; {kerr}", ret) +#define TRACE_KDCPOLICY_VTINIT_FAIL(c, ret) \ + TRACE(c, "KDC policy module failed to init vtable: {kerr}", ret) +#define TRACE_KDCPOLICY_INIT_SKIP(c, name) \ + TRACE(c, "kadm5_auth module {str} declined to initialize", name) + #endif /* K5_TRACE_H */ diff --git a/src/include/k5-utf8.h b/src/include/k5-utf8.h index 22f433c8e981..e2f20d45028f 100644 --- a/src/include/k5-utf8.h +++ b/src/include/k5-utf8.h @@ -73,57 +73,28 @@ typedef uint16_t krb5_ucs2; typedef uint32_t krb5_ucs4; -#define KRB5_MAX_UTF8_LEN (sizeof(krb5_ucs2) * 3/2) - int krb5int_utf8_to_ucs2(const char *p, krb5_ucs2 *out); size_t krb5int_ucs2_to_utf8(krb5_ucs2 c, char *buf); int krb5int_utf8_to_ucs4(const char *p, krb5_ucs4 *out); size_t krb5int_ucs4_to_utf8(krb5_ucs4 c, char *buf); -int -krb5int_ucs2s_to_utf8s(const krb5_ucs2 *ucs2s, - char **utf8s, - size_t *utf8slen); - -int -krb5int_ucs2cs_to_utf8s(const krb5_ucs2 *ucs2s, - size_t ucs2slen, - char **utf8s, - size_t *utf8slen); - -int -krb5int_ucs2les_to_utf8s(const unsigned char *ucs2les, - char **utf8s, - size_t *utf8slen); - -int -krb5int_ucs2lecs_to_utf8s(const unsigned char *ucs2les, - size_t ucs2leslen, - char **utf8s, - size_t *utf8slen); - -int -krb5int_utf8s_to_ucs2s(const char *utf8s, - krb5_ucs2 **ucs2s, - size_t *ucs2chars); - -int -krb5int_utf8cs_to_ucs2s(const char *utf8s, - size_t utf8slen, - krb5_ucs2 **ucs2s, - size_t *ucs2chars); - -int -krb5int_utf8s_to_ucs2les(const char *utf8s, - unsigned char **ucs2les, - size_t *ucs2leslen); - -int -krb5int_utf8cs_to_ucs2les(const char *utf8s, - size_t utf8slen, - unsigned char **ucs2les, - size_t *ucs2leslen); +/* + * Convert a little-endian UTF-16 string to an allocated null-terminated UTF-8 + * string. nbytes is the length of ucs2bytes in bytes, and must be an even + * number. Return EINVAL on invalid input, ENOMEM on out of memory, or 0 on + * success. + */ +int k5_utf16le_to_utf8(const uint8_t *utf16bytes, size_t nbytes, + char **utf8_out); + +/* + * Convert a UTF-8 string to an allocated little-endian UTF-16 string. The + * resulting length is in bytes and will always be even. Return EINVAL on + * invalid input, ENOMEM on out of memory, or 0 on success. + */ +int k5_utf8_to_utf16le(const char *utf8, uint8_t **utf16_out, + size_t *nbytes_out); /* returns the number of bytes in the UTF-8 string */ size_t krb5int_utf8_bytes(const char *); diff --git a/src/include/kdb.h b/src/include/kdb.h index da04724fcedb..5615329c0bb3 100644 --- a/src/include/kdb.h +++ b/src/include/kdb.h @@ -69,7 +69,7 @@ /* This version will be incremented when incompatible changes are made to the * KDB API, and will be kept in sync with the libkdb major version. */ -#define KRB5_KDB_API_VERSION 8 +#define KRB5_KDB_API_VERSION 9 /* Salt types */ #define KRB5_KDB_SALTTYPE_NORMAL 0 @@ -695,6 +695,8 @@ krb5_error_code krb5_db_check_policy_tgs(krb5_context kcontext, krb5_pa_data ***e_data); void krb5_db_audit_as_req(krb5_context kcontext, krb5_kdc_req *request, + const krb5_address *local_addr, + const krb5_address *remote_addr, krb5_db_entry *client, krb5_db_entry *server, krb5_timestamp authtime, krb5_error_code error_code); @@ -865,7 +867,7 @@ krb5_error_code krb5_db_register_keytab(krb5_context context); * This number indicates the date of the last incompatible change to the DAL. * The maj_ver field of the module's vtable structure must match this version. */ -#define KRB5_KDB_DAL_MAJOR_VERSION 6 +#define KRB5_KDB_DAL_MAJOR_VERSION 7 /* * A krb5_context can hold one database object. Modules should use @@ -1356,6 +1358,8 @@ typedef struct _kdb_vftabl { * AS request. */ void (*audit_as_req)(krb5_context kcontext, krb5_kdc_req *request, + const krb5_address *local_addr, + const krb5_address *remote_addr, krb5_db_entry *client, krb5_db_entry *server, krb5_timestamp authtime, krb5_error_code error_code); diff --git a/src/include/kdb_log.h b/src/include/kdb_log.h index 25b823674a9f..4239575659a3 100644 --- a/src/include/kdb_log.h +++ b/src/include/kdb_log.h @@ -21,9 +21,8 @@ extern "C" { /* * DB macros */ -#define INDEX(ulog, i) (kdb_ent_header_t *)((char *)(ulog) + \ - sizeof(kdb_hlog_t) + \ - (i) * ulog->kdb_block) +#define INDEX(ulog, i) (kdb_ent_header_t *)(void *) \ + ((char *)(ulog) + sizeof(kdb_hlog_t) + (i) * ulog->kdb_block) /* * Current DB version # diff --git a/src/include/krb5/certauth_plugin.h b/src/include/krb5/certauth_plugin.h new file mode 100644 index 000000000000..3074790f8745 --- /dev/null +++ b/src/include/krb5/certauth_plugin.h @@ -0,0 +1,128 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/krb5/certauth_plugin.h - certauth plugin header. */ +/* + * Copyright (C) 2017 by Red Hat, Inc. + * 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. + */ + +/* + * Declarations for certauth plugin module implementors. + * + * The certauth pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 1. + * + * certauth plugin modules should define a function named + * certauth_<modulename>_initvt, matching the signature: + * + * krb5_error_code + * certauth_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_certauth_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_CERTAUTH_PLUGIN_H +#define KRB5_CERTAUTH_PLUGIN_H + +#include <krb5/krb5.h> +#include <krb5/plugin.h> + +/* Abstract module data type. */ +typedef struct krb5_certauth_moddata_st *krb5_certauth_moddata; + +/* A module can optionally include <kdb.h> to inspect the client principal + * entry when authorizing a request. */ +struct _krb5_db_entry_new; + +/* + * Optional: Initialize module data. + */ +typedef krb5_error_code +(*krb5_certauth_init_fn)(krb5_context context, + krb5_certauth_moddata *moddata_out); + +/* + * Optional: Clean up the module data. + */ +typedef void +(*krb5_certauth_fini_fn)(krb5_context context, krb5_certauth_moddata moddata); + +/* + * Mandatory: + * Return 0 if the DER-encoded cert is authorized for PKINIT authentication by + * princ; otherwise return one of the following error codes: + * - KRB5KDC_ERR_CLIENT_NAME_MISMATCH - incorrect SAN value + * - KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE - incorrect EKU + * - KRB5KDC_ERR_CERTIFICATE_MISMATCH - other extension error + * - KRB5_PLUGIN_NO_HANDLE - the module has no opinion about cert + * + * - opts is used by built-in modules to receive internal data, and must be + * ignored by other modules. + * - db_entry receives the client principal database entry, and can be ignored + * by modules that do not link with libkdb5. + * - *authinds_out optionally returns a null-terminated list of authentication + * indicator strings upon KRB5_PLUGIN_NO_HANDLE or accepted authorization. + */ +typedef krb5_error_code +(*krb5_certauth_authorize_fn)(krb5_context context, + krb5_certauth_moddata moddata, + const uint8_t *cert, size_t cert_len, + krb5_const_principal princ, const void *opts, + const struct _krb5_db_entry_new *db_entry, + char ***authinds_out); + +/* + * Free indicators allocated by a module. Mandatory if authorize returns + * authentication indicators. + */ +typedef void +(*krb5_certauth_free_indicator_fn)(krb5_context context, + krb5_certauth_moddata moddata, + char **authinds); + +typedef struct krb5_certauth_vtable_st { + const char *name; + krb5_certauth_init_fn init; + krb5_certauth_fini_fn fini; + krb5_certauth_authorize_fn authorize; + krb5_certauth_free_indicator_fn free_ind; +} *krb5_certauth_vtable; + +#endif /* KRB5_CERTAUTH_PLUGIN_H */ diff --git a/src/include/krb5/kadm5_auth_plugin.h b/src/include/krb5/kadm5_auth_plugin.h new file mode 100644 index 000000000000..d514e99beb93 --- /dev/null +++ b/src/include/krb5/kadm5_auth_plugin.h @@ -0,0 +1,306 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2017 by the Massachusetts Institute of Technology. + * 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. + */ + +/* + * Declarations for kadm5_auth plugin module implementors. + * + * The kadm5_auth pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 1. + * + * kadm5_auth plugin modules should define a function named + * kadm5_auth_<modulename>_initvt, matching the signature: + * + * krb5_error_code + * kadm5_auth_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_kadm5_auth_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_KADM5_AUTH_PLUGIN_H +#define KRB5_KADM5_AUTH_PLUGIN_H + +#include <krb5/krb5.h> +#include <krb5/plugin.h> + +/* An abstract type for kadm5_auth module data. */ +typedef struct kadm5_auth_moddata_st *kadm5_auth_moddata; + +/* + * A module can optionally include <kadm5/admin.h> to inspect principal or + * policy records from requests that add or modify principals or policies. + * Note that fields of principal and policy structures are only valid if the + * corresponding bit is set in the accompanying mask parameter. + */ +struct _kadm5_principal_ent_t; +struct _kadm5_policy_ent_t; + +/* + * A module can optionally generate restrictions when checking permissions for + * adding or modifying a principal entry. Restriction fields will only be + * honored if the corresponding mask bit is set. The operable mask bits are + * defined in <kadmin/admin.h> and are: + * + * - KADM5_ATTRIBUTES for require_attrs, forbid_attrs + * - KADM5_POLICY for policy + * - KADM5_POLICY_CLR to require that policy be unset + * - KADM5_PRINC_EXPIRE_TIME for princ_lifetime + * - KADM5_PW_EXPIRATION for pw_lifetime + * - KADM5_MAX_LIFE for max_life + * - KADM5_MAX_RLIFE for max_renewable_life + */ +struct kadm5_auth_restrictions { + long mask; + krb5_flags require_attrs; + krb5_flags forbid_attrs; + krb5_deltat princ_lifetime; + krb5_deltat pw_lifetime; + krb5_deltat max_life; + krb5_deltat max_renewable_life; + char *policy; +}; + +/*** Method type declarations ***/ + +/* + * Optional: Initialize module data. acl_file is the realm's configured ACL + * file, or NULL if none was configured. Return 0 on success, + * KRB5_PLUGIN_NO_HANDLE if the module is inoperable (due to configuration, for + * example), and any other error code to abort kadmind startup. Optionally set + * *data_out to a module data object to be passed to future calls. + */ +typedef krb5_error_code +(*kadm5_auth_init_fn)(krb5_context context, const char *acl_file, + kadm5_auth_moddata *data_out); + +/* Optional: Release resources used by module data. */ +typedef void +(*kadm5_auth_fini_fn)(krb5_context context, kadm5_auth_moddata data); + +/* + * Each check method below should return 0 to explicitly authorize the request, + * KRB5_PLUGIN_NO_HANDLE to neither authorize nor deny the request, and any + * other error code (such as EPERM) to explicitly deny the request. If a check + * method is not defined, the module will neither authorize nor deny the + * request. A request succeeds if at least one kadm5_auth module explicitly + * authorizes the request and none of the modules explicitly deny it. + */ + +/* Optional: authorize an add-principal operation, and optionally generate + * restrictions. */ +typedef krb5_error_code +(*kadm5_auth_addprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out); + +/* Optional: authorize a modify-principal operation, and optionally generate + * restrictions. */ +typedef krb5_error_code +(*kadm5_auth_modprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out); + +/* Optional: authorize a set-string operation. */ +typedef krb5_error_code +(*kadm5_auth_setstr_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target, + const char *key, const char *value); + +/* Optional: authorize a change-password operation. */ +typedef krb5_error_code +(*kadm5_auth_cpw_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target); + +/* Optional: authorize a randomize-keys operation. */ +typedef krb5_error_code +(*kadm5_auth_chrand_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a set-key operation. */ +typedef krb5_error_code +(*kadm5_auth_setkey_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a purgekeys operation. */ +typedef krb5_error_code +(*kadm5_auth_purgekeys_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a delete-principal operation. */ +typedef krb5_error_code +(*kadm5_auth_delprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a rename-principal operation. */ +typedef krb5_error_code +(*kadm5_auth_renprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal src, + krb5_const_principal dest); + +/* Optional: authorize a get-principal operation. */ +typedef krb5_error_code +(*kadm5_auth_getprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a get-strings operation. */ +typedef krb5_error_code +(*kadm5_auth_getstrs_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize an extract-keys operation. */ +typedef krb5_error_code +(*kadm5_auth_extract_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a list-principals operation. */ +typedef krb5_error_code +(*kadm5_auth_listprincs_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client); + +/* Optional: authorize an add-policy operation. */ +typedef krb5_error_code +(*kadm5_auth_addpol_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask); + +/* Optional: authorize a modify-policy operation. */ +typedef krb5_error_code +(*kadm5_auth_modpol_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask); + +/* Optional: authorize a delete-policy operation. */ +typedef krb5_error_code +(*kadm5_auth_delpol_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy); + +/* Optional: authorize a get-policy operation. client_policy is the client + * principal's policy name, or NULL if it does not have one. */ +typedef krb5_error_code +(*kadm5_auth_getpol_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const char *client_policy); + +/* Optional: authorize a list-policies operation. */ +typedef krb5_error_code +(*kadm5_auth_listpols_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client); + +/* Optional: authorize an iprop operation. */ +typedef krb5_error_code +(*kadm5_auth_iprop_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client); + +/* + * Optional: receive a notification that the most recent authorized operation + * has ended. If a kadm5_auth module is also a KDB module, it can assume that + * all KDB methods invoked between a kadm5_auth authorization method invocation + * and a kadm5_auth end invocation are performed as part of the authorized + * operation. + * + * The end method may be invoked without a preceding authorization method in + * some cases; the module must be prepared to ignore such calls. + */ +typedef void +(*kadm5_auth_end_fn)(krb5_context context, kadm5_auth_moddata data); + +/* + * Optional: free a restrictions object. This method does not need to be + * defined if the module does not generate restrictions objects, or if it + * returns aliases to restrictions objects contained from within the module + * data. + */ +typedef void +(*kadm5_auth_free_restrictions_fn)(krb5_context context, + kadm5_auth_moddata data, + struct kadm5_auth_restrictions *rs); + +/* kadm5_auth vtable for major version 1. */ +typedef struct kadm5_auth_vtable_st { + const char *name; /* Mandatory: name of module. */ + kadm5_auth_init_fn init; + kadm5_auth_fini_fn fini; + + kadm5_auth_addprinc_fn addprinc; + kadm5_auth_modprinc_fn modprinc; + kadm5_auth_setstr_fn setstr; + kadm5_auth_cpw_fn cpw; + kadm5_auth_chrand_fn chrand; + kadm5_auth_setkey_fn setkey; + kadm5_auth_purgekeys_fn purgekeys; + kadm5_auth_delprinc_fn delprinc; + kadm5_auth_renprinc_fn renprinc; + + kadm5_auth_getprinc_fn getprinc; + kadm5_auth_getstrs_fn getstrs; + kadm5_auth_extract_fn extract; + kadm5_auth_listprincs_fn listprincs; + + kadm5_auth_addpol_fn addpol; + kadm5_auth_modpol_fn modpol; + kadm5_auth_delpol_fn delpol; + kadm5_auth_getpol_fn getpol; + kadm5_auth_listpols_fn listpols; + + kadm5_auth_iprop_fn iprop; + + kadm5_auth_end_fn end; + + kadm5_auth_free_restrictions_fn free_restrictions; + /* Minor version 1 ends here. */ +} *kadm5_auth_vtable; + +#endif /* KRB5_KADM5_AUTH_PLUGIN_H */ diff --git a/src/include/krb5/kdcpolicy_plugin.h b/src/include/krb5/kdcpolicy_plugin.h new file mode 100644 index 000000000000..c7592c5dba78 --- /dev/null +++ b/src/include/krb5/kdcpolicy_plugin.h @@ -0,0 +1,128 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/krb5/kdcpolicy_plugin.h - KDC policy plugin interface */ +/* + * Copyright (C) 2017 by Red Hat, Inc. + * 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. + */ + +/* + * Declarations for kdcpolicy plugin module implementors. + * + * The kdcpolicy pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 1. + * + * kdcpolicy plugin modules should define a function named + * kdcpolicy_<modulename>_initvt, matching the signature: + * + * krb5_error_code + * kdcpolicy_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_kdcpolicy_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_POLICY_PLUGIN_H +#define KRB5_POLICY_PLUGIN_H + +#include <krb5/krb5.h> + +/* Abstract module datatype. */ +typedef struct krb5_kdcpolicy_moddata_st *krb5_kdcpolicy_moddata; + +/* A module can optionally include kdb.h to inspect principal entries when + * authorizing requests. */ +struct _krb5_db_entry_new; + +/* + * Optional: Initialize module data. Return 0 on success, + * KRB5_PLUGIN_NO_HANDLE if the module is inoperable (due to configuration, for + * example), and any other error code to abort KDC startup. Optionally set + * *data_out to a module data object to be passed to future calls. + */ +typedef krb5_error_code +(*krb5_kdcpolicy_init_fn)(krb5_context context, + krb5_kdcpolicy_moddata *data_out); + +/* Optional: Clean up module data. */ +typedef krb5_error_code +(*krb5_kdcpolicy_fini_fn)(krb5_context context, + krb5_kdcpolicy_moddata moddata); + +/* + * Optional: return an error code and set status to an appropriate string + * literal to deny an AS request; otherwise return 0. lifetime_out, if set, + * restricts the ticket lifetime. renew_lifetime_out, if set, restricts the + * ticket renewable lifetime. + */ +typedef krb5_error_code +(*krb5_kdcpolicy_check_as_fn)(krb5_context context, + krb5_kdcpolicy_moddata moddata, + const krb5_kdc_req *request, + const struct _krb5_db_entry_new *client, + const struct _krb5_db_entry_new *server, + const char *const *auth_indicators, + const char **status, krb5_deltat *lifetime_out, + krb5_deltat *renew_lifetime_out); + +/* + * Optional: return an error code and set status to an appropriate string + * literal to deny a TGS request; otherwise return 0. lifetime_out, if set, + * restricts the ticket lifetime. renew_lifetime_out, if set, restricts the + * ticket renewable lifetime. + */ +typedef krb5_error_code +(*krb5_kdcpolicy_check_tgs_fn)(krb5_context context, + krb5_kdcpolicy_moddata moddata, + const krb5_kdc_req *request, + const struct _krb5_db_entry_new *server, + const krb5_ticket *ticket, + const char *const *auth_indicators, + const char **status, krb5_deltat *lifetime_out, + krb5_deltat *renew_lifetime_out); + +typedef struct krb5_kdcpolicy_vtable_st { + const char *name; + krb5_kdcpolicy_init_fn init; + krb5_kdcpolicy_fini_fn fini; + krb5_kdcpolicy_check_as_fn check_as; + krb5_kdcpolicy_check_tgs_fn check_tgs; +} *krb5_kdcpolicy_vtable; + +#endif /* KRB5_POLICY_PLUGIN_H */ diff --git a/src/include/krb5/kdcpreauth_plugin.h b/src/include/krb5/kdcpreauth_plugin.h index f455effaecdb..f388200999ef 100644 --- a/src/include/krb5/kdcpreauth_plugin.h +++ b/src/include/krb5/kdcpreauth_plugin.h @@ -34,7 +34,7 @@ * Declarations for kdcpreauth plugin module implementors. * * The kdcpreauth interface has a single supported major version, which is 1. - * Major version 1 has a current minor version of 3. kdcpreauth modules should + * Major version 1 has a current minor version of 2. kdcpreauth modules should * define a function named kdcpreauth_<modulename>_initvt, matching the * signature: * @@ -221,6 +221,25 @@ typedef struct krb5_kdcpreauth_callbacks_st { /* End of version 3 kdcpreauth callbacks. */ + /* + * Return true if princ matches the principal named in the request or the + * client principal (possibly canonicalized). If princ does not match, + * attempt a database lookup of princ with aliases allowed and compare the + * result to the client principal, returning true if it matches. + * Otherwise, return false. + */ + krb5_boolean (*match_client)(krb5_context context, + krb5_kdcpreauth_rock rock, + krb5_principal princ); + + /* + * Get an alias to the client DB entry principal (possibly canonicalized). + */ + krb5_principal (*client_name)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* End of version 4 kdcpreauth callbacks. */ + } *krb5_kdcpreauth_callbacks; /* Optional: preauth plugin initialization function. */ diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index ac22f4c55098..c86e78274484 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -181,7 +181,16 @@ typedef krb5_int32 krb5_cryptotype; typedef krb5_int32 krb5_preauthtype; /* This may change, later on */ typedef krb5_int32 krb5_flags; + +/** + * Represents a timestamp in seconds since the POSIX epoch. This legacy type + * is used frequently in the ABI, but cannot represent timestamps after 2038 as + * a positive number. Code which uses this type should cast values of it to + * uint32_t so that negative values are treated as timestamps between 2038 and + * 2106 on platforms with 64-bit time_t. + */ typedef krb5_int32 krb5_timestamp; + typedef krb5_int32 krb5_deltat; /** @@ -3221,8 +3230,9 @@ krb5_get_credentials_renew(krb5_context context, krb5_flags options, */ krb5_error_code KRB5_CALLCONV krb5_mk_req(krb5_context context, krb5_auth_context *auth_context, - krb5_flags ap_req_options, char *service, char *hostname, - krb5_data *in_data, krb5_ccache ccache, krb5_data *outbuf); + krb5_flags ap_req_options, const char *service, + const char *hostname, krb5_data *in_data, krb5_ccache ccache, + krb5_data *outbuf); /** * Create a @c KRB_AP_REQ message using supplied credentials. @@ -5615,8 +5625,9 @@ krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, */ krb5_error_code KRB5_CALLCONV krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, - char *rhost, krb5_principal client, krb5_principal server, - krb5_ccache cc, int forwardable, krb5_data *outbuf); + const char *rhost, krb5_principal client, + krb5_principal server, krb5_ccache cc, int forwardable, + krb5_data *outbuf); /** * Create and initialize an authentication context. @@ -6000,15 +6011,19 @@ krb5_error_code KRB5_CALLCONV krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber); -#if KRB5_DEPRECATED -/** @deprecated Not replaced. +/** + * Cause an auth context to use cipher state. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context * - * RFC 4120 doesn't have anything like the initvector concept; - * only really old protocols may need this API. + * Prepare @a auth_context to use cipher state when krb5_mk_priv() or + * krb5_rd_priv() encrypt or decrypt data. + * + * @retval 0 Success; otherwise - Kerberos error codes */ -KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV +krb5_error_code KRB5_CALLCONV krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context); -#endif /** * Set the replay cache in an auth context. @@ -7306,6 +7321,9 @@ typedef struct _krb5_init_creds_context *krb5_init_creds_context; * * @param [in] context Library context * @param [in] ctx Initial credentials context + * + * @a context must be the same as the one passed to krb5_init_creds_init() for + * this initial credentials context. */ void KRB5_CALLCONV krb5_init_creds_free(krb5_context context, krb5_init_creds_context ctx); @@ -7320,6 +7338,9 @@ krb5_init_creds_free(krb5_context context, krb5_init_creds_context ctx); * krb5_init_creds_init(). On successful return, the credentials can be * retrieved with krb5_init_creds_get_creds(). * + * @a context must be the same as the one passed to krb5_init_creds_init() for + * this initial credentials context. + * * @retval 0 Success; otherwise - Kerberos error codes */ krb5_error_code KRB5_CALLCONV @@ -7370,6 +7391,10 @@ krb5_init_creds_get_error(krb5_context context, krb5_init_creds_context ctx, * This function creates a new context for acquiring initial credentials. Use * krb5_init_creds_free() to free @a ctx when it is no longer needed. * + * Any subsequent calls to krb5_init_creds_step(), krb5_init_creds_get(), or + * krb5_init_creds_free() for this initial credentials context must use the + * same @a context argument as the one passed to this function. + * * @retval 0 Success; otherwise - Kerberos error codes */ krb5_error_code KRB5_CALLCONV @@ -7419,6 +7444,9 @@ krb5_init_creds_set_keytab(krb5_context context, krb5_init_creds_context ctx, * transmit the next request using TCP rather than UDP. If this function * returns any other error, the initial credential exchange has failed. * + * @a context must be the same as the one passed to krb5_init_creds_init() for + * this initial credentials context. + * * @retval 0 Success; otherwise - Kerberos error codes */ krb5_error_code KRB5_CALLCONV @@ -8229,9 +8257,9 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, * If successful, @a pac is marked as verified. * * @note A checksum mismatch can occur if the PAC was copied from a cross-realm - * TGT by an ignorant KDC; also Apple Mac OS X Server Open Directory (as of - * 10.6) generates PACs with no server checksum at all. One should consider - * not failing the whole authentication because of this reason, but, instead, + * TGT by an ignorant KDC; also macOS Server Open Directory (as of 10.6) + * generates PACs with no server checksum at all. One should consider not + * failing the whole authentication because of this reason, but, instead, * treating the ticket as if it did not contain a PAC or marking the PAC * information as non-verified. * diff --git a/src/include/net-server.h b/src/include/net-server.h index 37721e7f17a0..e5edcc49d5a1 100644 --- a/src/include/net-server.h +++ b/src/include/net-server.h @@ -86,7 +86,7 @@ void loop_free(verto_ctx *ctx); */ typedef void (*loop_respond_fn)(void *arg, krb5_error_code code, krb5_data *response); -void dispatch(void *handle, struct sockaddr *local_addr, +void dispatch(void *handle, const krb5_fulladdr *local_addr, const krb5_fulladdr *remote_addr, krb5_data *request, int is_tcp, verto_ctx *vctx, loop_respond_fn respond, void *arg); krb5_error_code make_toolong_error (void *handle, krb5_data **); diff --git a/src/include/socket-utils.h b/src/include/socket-utils.h index 156663683047..e1f33aa31763 100644 --- a/src/include/socket-utils.h +++ b/src/include/socket-utils.h @@ -119,6 +119,17 @@ sa_is_inet(struct sockaddr *sa) return sa->sa_family == AF_INET || sa->sa_family == AF_INET6; } +/* Return true if sa is an IPv4 or IPv6 wildcard address. */ +static inline int +sa_is_wildcard(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET6) + return IN6_IS_ADDR_UNSPECIFIED(&sa2sin6(sa)->sin6_addr); + else if (sa->sa_family == AF_INET) + return sa2sin(sa)->sin_addr.s_addr == INADDR_ANY; + return 0; +} + /* Return the length of an IPv4 or IPv6 socket structure; abort if it is * neither. */ static inline socklen_t diff --git a/src/include/win-mac.h b/src/include/win-mac.h index 1994388b71d3..c3744ed14ee6 100644 --- a/src/include/win-mac.h +++ b/src/include/win-mac.h @@ -225,9 +225,7 @@ typedef _W64 int ssize_t; HINSTANCE get_lib_instance(void); -#define GETSOCKNAME_ARG2_TYPE struct sockaddr #define GETSOCKNAME_ARG3_TYPE size_t -#define GETPEERNAME_ARG2_TYPE GETSOCKNAME_ARG2_TYPE #define GETPEERNAME_ARG3_TYPE GETSOCKNAME_ARG3_TYPE #endif /* !RES_ONLY */ diff --git a/src/kadmin/cli/deps b/src/kadmin/cli/deps index a9c997b395ab..a5873fc79443 100644 --- a/src/kadmin/cli/deps +++ b/src/kadmin/cli/deps @@ -5,14 +5,21 @@ $(OUTPRE)kadmin.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ - $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \ - $(top_srcdir)/include/krb5.h kadmin.c kadmin.h + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kadmin.c kadmin.h $(OUTPRE)kadmin_ct.$(OBJEXT): $(COM_ERR_DEPS) $(SS_DEPS) \ kadmin_ct.c $(OUTPRE)ss_wrapper.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ diff --git a/src/kadmin/cli/getdate.y b/src/kadmin/cli/getdate.y index 4f0c56f7eb20..059f112da13a 100644 --- a/src/kadmin/cli/getdate.y +++ b/src/kadmin/cli/getdate.y @@ -6,7 +6,7 @@ ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990; ** send any email to Rich. ** -** This grammar has nine shift/reduce conflicts. +** This grammar has four shift/reduce conflicts. ** ** This code is in the public domain and has no copyright. */ @@ -118,7 +118,7 @@ static int getdate_yyerror (char *); #define EPOCH 1970 -#define EPOCH_END 2038 /* assumes 32 bits */ +#define EPOCH_END 2106 /* assumes unsigned 32-bit range */ #define HOUR(x) ((time_t)(x) * 60) #define SECSPERDAY (24L * 60L * 60L) @@ -176,6 +176,9 @@ static time_t yyRelSeconds; %} +/* Mute shift/reduce warning as per header comment. */ +%expect 4 + %union { time_t Number; enum _MERIDIAN Meridian; diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c index c53c677a82d0..aee5c83b9546 100644 --- a/src/kadmin/cli/kadmin.c +++ b/src/kadmin/cli/kadmin.c @@ -31,8 +31,7 @@ * library */ /* for "_" macro */ -#include "k5-platform.h" -#include <krb5.h> +#include "k5-int.h" #include <kadm5/admin.h> #include <adm_proto.h> #include <errno.h> @@ -144,8 +143,8 @@ strdate(krb5_timestamp when) { struct tm *tm; static char out[40]; + time_t lcltim = ts2tt(when); - time_t lcltim = when; tm = localtime(&lcltim); strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm); return out; diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c index f7889bd234f5..aca136f0b62f 100644 --- a/src/kadmin/dbutil/dump.c +++ b/src/kadmin/dbutil/dump.c @@ -370,11 +370,12 @@ k5beta7_common(krb5_context context, krb5_db_entry *entry, fprintf(fp, "princ\t%d\t%lu\t%d\t%d\t%d\t%s\t", (int)entry->len, (unsigned long)strlen(name), counter, (int)entry->n_key_data, (int)entry->e_length, name); - fprintf(fp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d", entry->attributes, - entry->max_life, entry->max_renewable_life, entry->expiration, - entry->pw_expiration, - omit_nra ? 0 : entry->last_success, - omit_nra ? 0 : entry->last_failed, + fprintf(fp, "%d\t%d\t%d\t%u\t%u\t%u\t%u\t%d", entry->attributes, + entry->max_life, entry->max_renewable_life, + (unsigned int)entry->expiration, + (unsigned int)entry->pw_expiration, + (unsigned int)(omit_nra ? 0 : entry->last_success), + (unsigned int)(omit_nra ? 0 : entry->last_failed), omit_nra ? 0 : entry->fail_auth_count); /* Write out tagged data. */ @@ -688,6 +689,10 @@ process_tl_data(const char *fname, FILE *filep, int lineno, _("cannot read tagged data type and length")); return EINVAL; } + if (i1 < INT16_MIN || i1 > INT16_MAX || u1 > UINT16_MAX) { + load_err(fname, lineno, _("data type or length overflowed")); + return EINVAL; + } tl->tl_data_type = i1; tl->tl_data_length = u1; if (read_octets_or_minus1(filep, tl->tl_data_length, @@ -708,7 +713,7 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep, { int retval, nread, i, j; krb5_db_entry *dbentry; - int t1, t2, t3, t4, t5, t6, t7; + int t1, t2, t3, t4; unsigned int u1, u2, u3, u4, u5; char *name = NULL; krb5_key_data *kp = NULL, *kd; @@ -735,6 +740,10 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep, goto fail; /* Get memory for and form tagged data linked list */ + if (u3 > UINT16_MAX) { + load_err(fname, *linenop, _("cannot allocate tl_data (too large)")); + goto fail; + } if (alloc_tl_data(u3, &dbentry->tl_data)) goto fail; dbentry->n_tl_data = u3; @@ -764,8 +773,8 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep, } /* Get the fixed principal attributes */ - nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t", - &t1, &t2, &t3, &t4, &t5, &t6, &t7, &u1); + nread = fscanf(filep, "%d\t%d\t%d\t%u\t%u\t%d\t%d\t%d\t", + &t1, &t2, &t3, &u1, &u2, &u3, &u4, &u5); if (nread != 8) { load_err(fname, *linenop, _("cannot read principal attributes")); goto fail; @@ -773,11 +782,11 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep, dbentry->attributes = t1; dbentry->max_life = t2; dbentry->max_renewable_life = t3; - dbentry->expiration = t4; - dbentry->pw_expiration = t5; - dbentry->last_success = t6; - dbentry->last_failed = t7; - dbentry->fail_auth_count = u1; + dbentry->expiration = u1; + dbentry->pw_expiration = u2; + dbentry->last_success = u3; + dbentry->last_failed = u4; + dbentry->fail_auth_count = u5; dbentry->mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS | @@ -823,13 +832,17 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep, load_err(fname, *linenop, _("cannot read key size and version")); goto fail; } + if (t1 > KRB5_KDB_V1_KEY_DATA_ARRAY) { + load_err(fname, *linenop, _("unsupported key_data_ver version")); + goto fail; + } kd->key_data_ver = t1; kd->key_data_kvno = t2; for (j = 0; j < t1; j++) { nread = fscanf(filep, "%d\t%d\t", &t3, &t4); - if (nread != 2) { + if (nread != 2 || t4 < 0) { load_err(fname, *linenop, _("cannot read key type and length")); goto fail; diff --git a/src/kadmin/dbutil/kdb5_mkey.c b/src/kadmin/dbutil/kdb5_mkey.c index 7df8cbc83f21..2efe3176e81b 100644 --- a/src/kadmin/dbutil/kdb5_mkey.c +++ b/src/kadmin/dbutil/kdb5_mkey.c @@ -44,8 +44,8 @@ static char *strdate(krb5_timestamp when) { struct tm *tm; static char out[40]; + time_t lcltim = ts2tt(when); - time_t lcltim = when; tm = localtime(&lcltim); strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm); return out; @@ -481,7 +481,7 @@ kdb5_use_mkey(int argc, char *argv[]) cur_actkvno != NULL; prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) { - if (new_actkvno->act_time < cur_actkvno->act_time) { + if (ts_after(cur_actkvno->act_time, new_actkvno->act_time)) { if (prev_actkvno) { prev_actkvno->next = new_actkvno; new_actkvno->next = cur_actkvno; @@ -499,7 +499,7 @@ kdb5_use_mkey(int argc, char *argv[]) } } - if (actkvno_list->act_time > now) { + if (ts_after(actkvno_list->act_time, now)) { com_err(progname, EINVAL, _("there must be one master key currently active")); exit_status++; diff --git a/src/kadmin/dbutil/tabdump.c b/src/kadmin/dbutil/tabdump.c index 69a3482ec935..fb36b060ac96 100644 --- a/src/kadmin/dbutil/tabdump.c +++ b/src/kadmin/dbutil/tabdump.c @@ -148,7 +148,7 @@ write_date_iso(struct rec_args *args, krb5_timestamp when) struct tm *tm = NULL; struct rechandle *h = args->rh; - t = when; + t = ts2tt(when); tm = gmtime(&t); if (tm == NULL) { errno = EINVAL; diff --git a/src/kadmin/ktutil/ktutil.c b/src/kadmin/ktutil/ktutil.c index ef16d37a5693..6a8586da8207 100644 --- a/src/kadmin/ktutil/ktutil.c +++ b/src/kadmin/ktutil/ktutil.c @@ -140,7 +140,8 @@ void ktutil_add_entry(argc, argv) char *princ = NULL; char *enctype = NULL; krb5_kvno kvno = 0; - int use_pass = 0, use_key = 0, i; + int use_pass = 0, use_key = 0, use_kvno = 0, i; + char *salt = NULL; for (i = 1; i < argc; i++) { if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-p", 2)) { @@ -149,6 +150,7 @@ void ktutil_add_entry(argc, argv) } if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-k", 2)) { kvno = (krb5_kvno) atoi(argv[++i]); + use_kvno++; continue; } if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-e", 2)) { @@ -163,15 +165,22 @@ void ktutil_add_entry(argc, argv) use_key++; continue; } + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-s", 2)) { + salt = argv[++i]; + continue; + } } - if (argc != 8 || !(princ && kvno && enctype) || (use_pass+use_key != 1)) { + if (!((argc == 8 && princ && use_kvno && enctype) || + (argc == 10 && princ && use_kvno && enctype && salt)) || + use_pass + use_key != 1) { fprintf(stderr, _("usage: %s (-key | -password) -p principal " - "-k kvno -e enctype\n"), argv[0]); + "-k kvno -e enctype [-s salt]\n"), argv[0]); return; } - retval = ktutil_add(kcontext, &ktlist, princ, kvno, enctype, use_pass); + retval = ktutil_add(kcontext, &ktlist, princ, kvno, enctype, use_pass, + salt); if (retval) com_err(argv[0], retval, _("while adding new entry")); } diff --git a/src/kadmin/ktutil/ktutil.h b/src/kadmin/ktutil/ktutil.h index c4839ff12aa8..8bf491525095 100644 --- a/src/kadmin/ktutil/ktutil.h +++ b/src/kadmin/ktutil/ktutil.h @@ -38,7 +38,8 @@ krb5_error_code ktutil_add (krb5_context, char *, krb5_kvno, char *, - int); + int, + char *); krb5_error_code ktutil_read_keytab (krb5_context, char *, diff --git a/src/kadmin/ktutil/ktutil_funcs.c b/src/kadmin/ktutil/ktutil_funcs.c index 20a348c80582..7a3aa0dcad59 100644 --- a/src/kadmin/ktutil/ktutil_funcs.c +++ b/src/kadmin/ktutil/ktutil_funcs.c @@ -87,13 +87,14 @@ krb5_error_code ktutil_delete(context, list, idx) * one first. */ krb5_error_code ktutil_add(context, list, princ_str, kvno, - enctype_str, use_pass) + enctype_str, use_pass, salt_str) krb5_context context; krb5_kt_list *list; char *princ_str; krb5_kvno kvno; char *enctype_str; int use_pass; + char *salt_str; { krb5_keytab_entry *entry; krb5_kt_list lp = NULL, prev = NULL; @@ -101,7 +102,7 @@ krb5_error_code ktutil_add(context, list, princ_str, kvno, krb5_enctype enctype; krb5_timestamp now; krb5_error_code retval; - krb5_data password, salt; + krb5_data password, salt, defsalt = empty_data(); krb5_keyblock key; char buf[BUFSIZ]; char promptstr[1024]; @@ -165,9 +166,14 @@ krb5_error_code ktutil_add(context, list, princ_str, kvno, &password.length); if (retval) goto cleanup; - retval = krb5_principal2salt(context, princ, &salt); - if (retval) - goto cleanup; + if (salt_str != NULL) { + salt = string2data(salt_str); + } else { + retval = krb5_principal2salt(context, princ, &defsalt); + if (retval) + goto cleanup; + salt = defsalt; + } retval = krb5_c_string_to_key(context, enctype, &password, &salt, &key); if (retval) @@ -225,6 +231,7 @@ cleanup: if (prev) prev->next = NULL; ktutil_free_kt_list(context, lp); + krb5_free_data_contents(context, &defsalt); return retval; } diff --git a/src/kadmin/server/Makefile.in b/src/kadmin/server/Makefile.in index 3a013a4d4e15..16d5cc54aa4c 100644 --- a/src/kadmin/server/Makefile.in +++ b/src/kadmin/server/Makefile.in @@ -7,8 +7,10 @@ LOCALINCLUDES = -I$(top_srcdir)/lib/gssapi/generic \ -I$(BUILDTOP)/lib/gssapi/krb5 -I$(top_srcdir)/lib/kadm5/srv PROG = kadmind -OBJS = kadm_rpc_svc.o server_stubs.o ovsec_kadmd.o schpw.o misc.o ipropd_svc.o -SRCS = kadm_rpc_svc.c server_stubs.c ovsec_kadmd.c schpw.c misc.c ipropd_svc.c +OBJS = auth.o auth_acl.o auth_self.o kadm_rpc_svc.o server_stubs.o \ + ovsec_kadmd.o schpw.o misc.o ipropd_svc.o +SRCS = auth.o auth_acl.c auth_self.c kadm_rpc_svc.c server_stubs.c \ + ovsec_kadmd.c schpw.c misc.c ipropd_svc.c all: $(PROG) diff --git a/src/kadmin/server/auth.c b/src/kadmin/server/auth.c new file mode 100644 index 000000000000..081b20a8b678 --- /dev/null +++ b/src/kadmin/server/auth.c @@ -0,0 +1,314 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/server/auth.c - kadm5_auth pluggable interface consumer */ +/* + * Copyright (C) 2017 by the Massachusetts Institute of Technology. + * 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. + */ + +#include "k5-int.h" +#include <kadm5/admin.h> +#include <krb5/kadm5_auth_plugin.h> +#include "auth.h" + +typedef struct { + struct kadm5_auth_vtable_st vt; + kadm5_auth_moddata data; +} *auth_handle; + +static auth_handle *handles; + +void +auth_fini(krb5_context context) +{ + auth_handle *hp, h; + + if (handles == NULL) + return; + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.fini != NULL) + h->vt.fini(context, h->data); + free(h); + } + free(handles); + handles = NULL; +} + +krb5_error_code +auth_init(krb5_context context, const char *acl_file) +{ + krb5_error_code ret; + krb5_plugin_initvt_fn *modules = NULL, *mod; + size_t count; + auth_handle h = NULL; + const int intf = PLUGIN_INTERFACE_KADM5_AUTH; + + ret = k5_plugin_register(context, intf, "acl", kadm5_auth_acl_initvt); + if (ret) + goto cleanup; + ret = k5_plugin_register(context, intf, "self", kadm5_auth_self_initvt); + if (ret) + goto cleanup; + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KADM5_AUTH, &modules); + if (ret) + goto cleanup; + + /* Allocate a large enough list of handles. */ + for (count = 0; modules[count] != NULL; count++); + handles = k5calloc(count + 1, sizeof(*handles), &ret); + if (handles == NULL) + goto cleanup; + + /* For each module, allocate a handle, initialize its vtable, and + * initialize its module data. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + h = k5alloc(sizeof(*h), &ret); + if (h == NULL) + goto cleanup; + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt); + if (ret) { /* Failed vtable init is non-fatal. */ + TRACE_KADM5_AUTH_VTINIT_FAIL(context, ret); + free(h); + h = NULL; + continue; + } + h->data = NULL; + if (h->vt.init != NULL) { + ret = h->vt.init(context, acl_file, &h->data); + if (ret == KRB5_PLUGIN_NO_HANDLE) { + TRACE_KADM5_AUTH_INIT_SKIP(context, h->vt.name); + free(h); + h = NULL; + continue; + } + if (ret) { + TRACE_KADM5_AUTH_INIT_FAIL(context, h->vt.name, ret); + goto cleanup; + } + } + handles[count++] = h; + handles[count] = NULL; + h = NULL; + } + + ret = 0; + +cleanup: + if (ret) + auth_fini(context); + free(h); + k5_plugin_free_modules(context, modules); + return ret; +} + +/* Invoke the appropriate method from h->vt for opcode, passing client and the + * correct subset of p1, p2, s1, s2, polent, and mask for the method. */ +static krb5_error_code +call_module(krb5_context context, auth_handle h, int opcode, + krb5_const_principal client, krb5_const_principal p1, + krb5_const_principal p2, const char *s1, const char *s2, + const kadm5_policy_ent_rec *polent, long mask) +{ + /* addprinc and modprinc are handled through auth_restrict(). */ + assert(opcode != OP_ADDPRINC && opcode != OP_MODPRINC); + + if (opcode == OP_SETSTR && h->vt.setstr != NULL) + return h->vt.setstr(context, h->data, client, p1, s1, s2); + else if (opcode == OP_CPW && h->vt.cpw != NULL) + return h->vt.cpw(context, h->data, client, p1); + else if (opcode == OP_CHRAND && h->vt.chrand != NULL) + return h->vt.chrand(context, h->data, client, p1); + else if (opcode == OP_SETKEY && h->vt.setkey != NULL) + return h->vt.setkey(context, h->data, client, p1); + else if (opcode == OP_PURGEKEYS && h->vt.purgekeys != NULL) + return h->vt.purgekeys(context, h->data, client, p1); + else if (opcode == OP_DELPRINC && h->vt.delprinc != NULL) + return h->vt.delprinc(context, h->data, client, p1); + else if (opcode == OP_RENPRINC && h->vt.renprinc != NULL) + return h->vt.renprinc(context, h->data, client, p1, p2); + else if (opcode == OP_GETPRINC && h->vt.getprinc != NULL) + return h->vt.getprinc(context, h->data, client, p1); + else if (opcode == OP_GETSTRS && h->vt.getstrs != NULL) + return h->vt.getstrs(context, h->data, client, p1); + else if (opcode == OP_EXTRACT && h->vt.extract != NULL) + return h->vt.extract(context, h->data, client, p1); + else if (opcode == OP_LISTPRINCS && h->vt.listprincs != NULL) + return h->vt.listprincs(context, h->data, client); + else if (opcode == OP_ADDPOL && h->vt.addpol != NULL) + return h->vt.addpol(context, h->data, client, s1, polent, mask); + else if (opcode == OP_MODPOL && h->vt.modpol != NULL) + return h->vt.modpol(context, h->data, client, s1, polent, mask); + else if (opcode == OP_DELPOL && h->vt.delpol != NULL) + return h->vt.delpol(context, h->data, client, s1); + else if (opcode == OP_GETPOL && h->vt.getpol != NULL) + return h->vt.getpol(context, h->data, client, s1, s2); + else if (opcode == OP_LISTPOLS && h->vt.listpols != NULL) + return h->vt.listpols(context, h->data, client); + else if (opcode == OP_IPROP && h->vt.iprop != NULL) + return h->vt.iprop(context, h->data, client); + + return KRB5_PLUGIN_NO_HANDLE; +} + +krb5_boolean +auth(krb5_context context, int opcode, krb5_const_principal client, + krb5_const_principal p1, krb5_const_principal p2, const char *s1, + const char *s2, const kadm5_policy_ent_rec *polent, long mask) +{ + krb5_error_code ret; + krb5_boolean authorized = FALSE; + auth_handle *hp, h; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + + ret = call_module(context, h, opcode, client, p1, p2, s1, s2, + polent, mask); + if (!ret) + authorized = TRUE; + else if (ret != KRB5_PLUGIN_NO_HANDLE) + return FALSE; + } + + return authorized; +} + +/* Impose restrictions, modifying *ent and *mask. */ +static krb5_error_code +impose_restrictions(krb5_context context, + const struct kadm5_auth_restrictions *rs, + kadm5_principal_ent_t ent, long *mask) +{ + krb5_error_code ret; + krb5_timestamp now; + + if (rs == NULL) + return 0; + if (rs->mask & (KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION)) { + ret = krb5_timeofday(context, &now); + if (ret) + return ret; + } + + if (rs->mask & KADM5_ATTRIBUTES) { + ent->attributes |= rs->require_attrs; + ent->attributes &= rs->forbid_attrs; + *mask |= KADM5_ATTRIBUTES; + } + if (rs->mask & KADM5_POLICY_CLR) { + *mask &= ~KADM5_POLICY; + *mask |= KADM5_POLICY_CLR; + } else if (rs->mask & KADM5_POLICY) { + if (ent->policy != NULL && strcmp(ent->policy, rs->policy) != 0) { + free(ent->policy); + ent->policy = NULL; + } + if (ent->policy == NULL) { + ent->policy = strdup(rs->policy); + if (ent->policy == NULL) + return ENOMEM; + } + *mask |= KADM5_POLICY; + } + if (rs->mask & KADM5_PRINC_EXPIRE_TIME) { + if (!(*mask & KADM5_PRINC_EXPIRE_TIME) || + ts_after(ent->princ_expire_time, ts_incr(now, rs->princ_lifetime))) + ent->princ_expire_time = now + rs->princ_lifetime; + *mask |= KADM5_PRINC_EXPIRE_TIME; + } + if (rs->mask & KADM5_PW_EXPIRATION) { + if (!(*mask & KADM5_PW_EXPIRATION) || + ts_after(ent->pw_expiration, ts_incr(now, rs->pw_lifetime))) + ent->pw_expiration = now + rs->pw_lifetime; + *mask |= KADM5_PW_EXPIRATION; + } + if (rs->mask & KADM5_MAX_LIFE) { + if (!(*mask & KADM5_MAX_LIFE) || ent->max_life > rs->max_life) + ent->max_life = rs->max_life; + *mask |= KADM5_MAX_LIFE; + } + if (rs->mask & KADM5_MAX_RLIFE) { + if (!(*mask & KADM5_MAX_RLIFE) || + ent->max_renewable_life > rs->max_renewable_life) + ent->max_renewable_life = rs->max_renewable_life; + *mask |= KADM5_MAX_RLIFE; + } + return 0; +} + +krb5_boolean +auth_restrict(krb5_context context, int opcode, krb5_const_principal client, + kadm5_principal_ent_t ent, long *mask) +{ + auth_handle *hp, h; + krb5_boolean authorized = FALSE; + krb5_error_code ret, rs_ret; + krb5_const_principal target = ent->principal; + struct kadm5_auth_restrictions *rs; + + assert(opcode == OP_ADDPRINC || opcode == OP_MODPRINC); + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + + ret = KRB5_PLUGIN_NO_HANDLE; + rs = NULL; + if (opcode == OP_ADDPRINC && h->vt.addprinc != NULL) { + ret = h->vt.addprinc(context, h->data, client, target, ent, *mask, + &rs); + } else if (opcode == OP_MODPRINC && h->vt.modprinc != NULL) { + ret = h->vt.modprinc(context, h->data, client, target, ent, *mask, + &rs); + } + if (rs != NULL) { + rs_ret = impose_restrictions(context, rs, ent, mask); + if (h->vt.free_restrictions != NULL) + h->vt.free_restrictions(context, h->data, rs); + if (rs_ret) + return FALSE; + } + if (!ret) + authorized = TRUE; + else if (ret != KRB5_PLUGIN_NO_HANDLE) + return FALSE; + } + + return authorized; +} + +void +auth_end(krb5_context context) +{ + auth_handle *hp, h; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.end != NULL) + h->vt.end(context, h->data); + } +} diff --git a/src/kadmin/server/auth.h b/src/kadmin/server/auth.h new file mode 100644 index 000000000000..4d265add7c0d --- /dev/null +++ b/src/kadmin/server/auth.h @@ -0,0 +1,85 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/server/auth.h - kadmin authorization declarations */ +/* + * Copyright (C) 2017 by the Massachusetts Institute of Technology. + * 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. + */ + +#ifndef AUTH_H +#define AUTH_H + +#define OP_ADDPRINC 1 +#define OP_MODPRINC 2 +#define OP_SETSTR 3 +#define OP_CPW 4 +#define OP_CHRAND 5 +#define OP_SETKEY 6 +#define OP_PURGEKEYS 7 +#define OP_DELPRINC 8 +#define OP_RENPRINC 9 +#define OP_GETPRINC 10 +#define OP_GETSTRS 11 +#define OP_EXTRACT 12 +#define OP_LISTPRINCS 13 +#define OP_ADDPOL 14 +#define OP_MODPOL 15 +#define OP_DELPOL 16 +#define OP_GETPOL 17 +#define OP_LISTPOLS 18 +#define OP_IPROP 19 + +/* Initialize all authorization modules. */ +krb5_error_code auth_init(krb5_context context, const char *acl_file); + +/* Release authorization module state. */ +void auth_fini(krb5_context context); + +/* Authorize the operation given by opcode, using the appropriate subset of p1, + * p2, s1, s2, polent, and mask. */ +krb5_boolean auth(krb5_context context, int opcode, + krb5_const_principal client, krb5_const_principal p1, + krb5_const_principal p2, const char *s1, const char *s2, + const kadm5_policy_ent_rec *polent, long mask); + +/* Authorize an add-principal or modify-principal operation, and apply + * restrictions to ent and mask if any modules supply them. */ +krb5_boolean auth_restrict(krb5_context context, int opcode, + krb5_const_principal client, + kadm5_principal_ent_t ent, long *mask); + +/* Notify modules that the most recent authorized operation has ended. */ +void auth_end(krb5_context context); + +/* initvt declarations for built-in modules */ + +krb5_error_code kadm5_auth_acl_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); +krb5_error_code kadm5_auth_self_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +#endif /* AUTH_H */ diff --git a/src/kadmin/server/auth_acl.c b/src/kadmin/server/auth_acl.c new file mode 100644 index 000000000000..efe9c6961bbb --- /dev/null +++ b/src/kadmin/server/auth_acl.c @@ -0,0 +1,755 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/server/auth_acl.c - ACL kadm5_auth module */ +/* + * Copyright 1995-2004, 2007, 2008, 2017 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include <syslog.h> +#include <kadm5/admin.h> +#include <krb5/kadm5_auth_plugin.h> +#include "adm_proto.h" +#include <ctype.h> +#include "auth.h" + +/* + * Access control bits. + */ +#define ACL_ADD 1 +#define ACL_DELETE 2 +#define ACL_MODIFY 4 +#define ACL_CHANGEPW 8 +/* #define ACL_CHANGE_OWN_PW 16 */ +#define ACL_INQUIRE 32 +#define ACL_EXTRACT 64 +#define ACL_LIST 128 +#define ACL_SETKEY 256 +#define ACL_IPROP 512 + +#define ACL_ALL_MASK (ACL_ADD | \ + ACL_DELETE | \ + ACL_MODIFY | \ + ACL_CHANGEPW | \ + ACL_INQUIRE | \ + ACL_LIST | \ + ACL_IPROP | \ + ACL_SETKEY) + +struct acl_op_table { + char op; + uint32_t mask; +}; + +struct acl_entry { + struct acl_entry *next; + krb5_principal client; + uint32_t op_allowed; + krb5_principal target; + struct kadm5_auth_restrictions *rs; +}; + +static const struct acl_op_table acl_op_table[] = { + { 'a', ACL_ADD }, + { 'd', ACL_DELETE }, + { 'm', ACL_MODIFY }, + { 'c', ACL_CHANGEPW }, + { 'i', ACL_INQUIRE }, + { 'l', ACL_LIST }, + { 'p', ACL_IPROP }, + { 's', ACL_SETKEY }, + { 'x', ACL_ALL_MASK }, + { '*', ACL_ALL_MASK }, + { 'e', ACL_EXTRACT }, + { '\0', 0 } +}; + +struct wildstate { + int nwild; + const krb5_data *backref[9]; +}; + +struct acl_state { + struct acl_entry *list; +}; + +/* + * Get a line from the ACL file. Lines ending with \ are continued on the next + * line. The caller should set *lineno to 1 and *incr to 0 before the first + * call. On successful return, *lineno will be the line number of the line + * read. Return a pointer to the line on success, or NULL on end of file or + * read failure. + */ +static char * +get_line(FILE *fp, const char *fname, int *lineno, int *incr) +{ + const int chunksize = 128; + struct k5buf buf; + size_t old_len; + char *p; + + /* Increment *lineno by the number of newlines from the last line. */ + *lineno += *incr; + *incr = 0; + + k5_buf_init_dynamic(&buf); + for (;;) { + /* Read at least part of a line into the buffer. */ + old_len = buf.len; + p = k5_buf_get_space(&buf, chunksize); + if (p == NULL) + return NULL; + + if (fgets(p, chunksize, fp) == NULL) { + /* We reached the end. Return a final unterminated line, if there + * is one and it's not a comment. */ + k5_buf_truncate(&buf, old_len); + if (buf.len > 0 && *(char *)buf.data != '#') + return buf.data; + k5_buf_free(&buf); + return NULL; + } + + /* Set the buffer length based on the actual amount read. */ + k5_buf_truncate(&buf, old_len + strlen(p)); + + p = buf.data; + if (buf.len > 0 && p[buf.len - 1] == '\n') { + /* We have a complete raw line in the buffer. */ + (*incr)++; + k5_buf_truncate(&buf, buf.len - 1); + if (buf.len > 0 && p[buf.len - 1] == '\\') { + /* This line has a continuation marker; keep reading. */ + k5_buf_truncate(&buf, buf.len - 1); + } else if (buf.len == 0 || *p == '#') { + /* This line is empty or a comment. Start over. */ + *lineno += *incr; + *incr = 0; + k5_buf_truncate(&buf, 0); + } else { + return buf.data; + } + } + } +} + +/* + * Parse a restrictions field. Return NULL on failure. + * + * Allowed restrictions are: + * [+-]flagname (recognized by krb5_flagspec_to_mask) + * flag is forced to indicated value + * -clearpolicy policy is forced clear + * -policy pol policy is forced to be "pol" + * -{expire,pwexpire,maxlife,maxrenewlife} deltat + * associated value will be forced to + * MIN(deltat, requested value) + */ +static struct kadm5_auth_restrictions * +parse_restrictions(const char *str, const char *fname) +{ + char *copy = NULL, *token, *arg, *save; + const char *delims = "\t\n\f\v\r ,"; + krb5_deltat delta; + struct kadm5_auth_restrictions *rs; + + copy = strdup(str); + if (copy == NULL) + return NULL; + + rs = calloc(1, sizeof(*rs)); + if (rs == NULL) { + free(copy); + return NULL; + } + + rs->forbid_attrs = ~(krb5_flags)0; + for (token = strtok_r(copy, delims, &save); token != NULL; + token = strtok_r(NULL, delims, &save)) { + + if (krb5_flagspec_to_mask(token, &rs->require_attrs, + &rs->forbid_attrs) == 0) { + rs->mask |= KADM5_ATTRIBUTES; + continue; + } + + if (strcmp(token, "-clearpolicy") == 0) { + rs->mask |= KADM5_POLICY_CLR; + continue; + } + + /* Everything else needs an argument. */ + arg = strtok_r(NULL, delims, &save); + if (arg == NULL) + goto error; + + if (strcmp(token, "-policy") == 0) { + if (rs->policy != NULL) + goto error; + rs->policy = strdup(arg); + if (rs->policy == NULL) + goto error; + rs->mask |= KADM5_POLICY; + continue; + } + + /* All other arguments must be a deltat. */ + if (krb5_string_to_deltat(arg, &delta) != 0) + goto error; + + if (strcmp(token, "-expire") == 0) { + rs->princ_lifetime = delta; + rs->mask |= KADM5_PRINC_EXPIRE_TIME; + } else if (strcmp(token, "-pwexpire") == 0) { + rs->pw_lifetime = delta; + rs->mask |= KADM5_PW_EXPIRATION; + } else if (strcmp(token, "-maxlife") == 0) { + rs->max_life = delta; + rs->mask |= KADM5_MAX_LIFE; + } else if (strcmp(token, "-maxrenewlife") == 0) { + rs->max_renewable_life = delta; + rs->mask |= KADM5_MAX_RLIFE; + } else { + goto error; + } + } + + free(copy); + return rs; + +error: + krb5_klog_syslog(LOG_ERR, _("%s: invalid restrictions: %s"), fname, str); + free(copy); + free(rs->policy); + free(rs); + return NULL; +} + +static void +free_acl_entry(struct acl_entry *entry) +{ + krb5_free_principal(NULL, entry->client); + krb5_free_principal(NULL, entry->target); + if (entry->rs != NULL) { + free(entry->rs->policy); + free(entry->rs); + } + free(entry); +} + +/* Parse the four fields of an ACL entry and return a structure representing + * it. Log a message and return NULL on error. */ +static struct acl_entry * +parse_entry(krb5_context context, const char *client, const char *ops, + const char *target, const char *rs, const char *line, + const char *fname) +{ + struct acl_entry *entry; + const char *op; + char rop; + int t; + + entry = calloc(1, sizeof(*entry)); + if (entry == NULL) + return NULL; + + for (op = ops; *op; op++) { + rop = isupper((unsigned char)*op) ? tolower((unsigned char)*op) : *op; + for (t = 0; acl_op_table[t].op; t++) { + if (rop == acl_op_table[t].op) { + if (rop == *op) + entry->op_allowed |= acl_op_table[t].mask; + else + entry->op_allowed &= ~acl_op_table[t].mask; + break; + } + } + if (!acl_op_table[t].op) { + krb5_klog_syslog(LOG_ERR, + _("Unrecognized ACL operation '%c' in %s"), + *op, line); + goto error; + } + } + + if (strcmp(client, "*") != 0) { + if (krb5_parse_name(context, client, &entry->client) != 0) { + krb5_klog_syslog(LOG_ERR, _("Cannot parse client principal '%s'"), + client); + goto error; + } + } + + if (target != NULL && strcmp(target, "*") != 0) { + if (krb5_parse_name(context, target, &entry->target) != 0) { + krb5_klog_syslog(LOG_ERR, _("Cannot parse target principal '%s'"), + target); + goto error; + } + } + + if (rs != NULL) { + entry->rs = parse_restrictions(rs, fname); + if (entry->rs == NULL) + goto error; + } + + return entry; + +error: + free_acl_entry(entry); + return NULL; +} + +/* Parse the contents of an ACL line. */ +static struct acl_entry * +parse_line(krb5_context context, const char *line, const char *fname) +{ + struct acl_entry *entry = NULL; + char *copy; + char *client, *client_end, *ops, *ops_end, *target, *target_end, *rs, *end; + const char *ws = "\t\n\f\v\r ,"; + + /* + * Format: + * entry ::= [<whitespace>] <principal> <whitespace> <opstring> + * [<whitespace> <target> [<whitespace> <restrictions> + * [<whitespace>]]] + */ + + /* Make a copy and remove any trailing whitespace. */ + copy = strdup(line); + if (copy == NULL) + return NULL; + end = copy + strlen(copy); + while (end > copy && isspace(end[-1])) + *--end = '\0'; + + /* Find the beginning and end of each field. The end of restrictions is + * the end of copy. */ + client = copy + strspn(copy, ws); + client_end = client + strcspn(client, ws); + ops = client_end + strspn(client_end, ws); + ops_end = ops + strcspn(ops, ws); + target = ops_end + strspn(ops_end, ws); + target_end = target + strcspn(target, ws); + rs = target_end + strspn(target_end, ws); + + /* Terminate the first three fields. */ + *client_end = *ops_end = *target_end = '\0'; + + /* The last two fields are optional; represent them as NULL if not present. + * The first two fields are required. */ + if (*target == '\0') + target = NULL; + if (*rs == '\0') + rs = NULL; + if (*client != '\0' && *ops != '\0') + entry = parse_entry(context, client, ops, target, rs, line, fname); + free(copy); + return entry; +} + +/* Free all ACL entries. */ +static void +free_acl_entries(struct acl_state *state) +{ + struct acl_entry *entry, *next; + + for (entry = state->list; entry != NULL; entry = next) { + next = entry->next; + free_acl_entry(entry); + } + state->list = NULL; +} + +/* Open and parse the ACL file. */ +static krb5_error_code +load_acl_file(krb5_context context, const char *fname, struct acl_state *state) +{ + krb5_error_code ret; + FILE *fp; + char *line; + struct acl_entry **entry_slot; + int lineno, incr; + + state->list = NULL; + + /* Open the ACL file for reading. */ + fp = fopen(fname, "r"); + if (fp == NULL) { + krb5_klog_syslog(LOG_ERR, _("%s while opening ACL file %s"), + error_message(errno), fname); + ret = errno; + k5_setmsg(context, errno, _("Cannot open %s: %s"), fname, + error_message(ret)); + return ret; + } + + set_cloexec_file(fp); + lineno = 1; + incr = 0; + entry_slot = &state->list; + + /* Get a non-comment line. */ + while ((line = get_line(fp, fname, &lineno, &incr)) != NULL) { + /* Parse it. Fail out on syntax error. */ + *entry_slot = parse_line(context, line, fname); + if (*entry_slot == NULL) { + krb5_klog_syslog(LOG_ERR, + _("%s: syntax error at line %d <%.10s...>"), + fname, lineno, line); + k5_setmsg(context, EINVAL, + _("%s: syntax error at line %d <%.10s...>"), + fname, lineno, line); + free_acl_entries(state); + free(line); + fclose(fp); + return EINVAL; + } + entry_slot = &(*entry_slot)->next; + free(line); + } + + fclose(fp); + return 0; +} + +/* + * See if two data entries match. If e1 is a wildcard (matching a whole + * component only) and targetflag is false, save an alias to e2 into + * ws->backref. If e1 is a back-reference and targetflag is true, compare the + * appropriate entry in ws->backref to e2. If ws is NULL, do not store or + * match back-references. + */ +static krb5_boolean +match_data(const krb5_data *e1, const krb5_data *e2, krb5_boolean targetflag, + struct wildstate *ws) +{ + int n; + + if (data_eq_string(*e1, "*")) { + if (ws != NULL && !targetflag) { + if (ws->nwild < 9) + ws->backref[ws->nwild++] = e2; + } + return TRUE; + } + + if (ws != NULL && targetflag && e1->length == 2 && e1->data[0] == '*' && + e1->data[1] >= '1' && e1->data[1] <= '9') { + n = e1->data[1] - '1'; + if (n >= ws->nwild) + return FALSE; + return data_eq(*e2, *ws->backref[n]); + } else { + return data_eq(*e2, *e1); + } +} + +/* Return true if p1 matches p2. p1 may contain wildcards if targetflag is + * false, or backreferences if it is true. */ +static krb5_boolean +match_princ(krb5_const_principal p1, krb5_const_principal p2, + krb5_boolean targetflag, struct wildstate *ws) +{ + int i; + + /* The principals must be of the same length. */ + if (p1->length != p2->length) + return FALSE; + + /* The realm must match, and does not interact with wildcard state. */ + if (!match_data(&p1->realm, &p2->realm, targetflag, NULL)) + return FALSE; + + /* All components of the principals must match. */ + for (i = 0; i < p1->length; i++) { + if (!match_data(&p1->data[i], &p2->data[i], targetflag, ws)) + return FALSE; + } + + return TRUE; +} + +/* Find an ACL entry matching principal and target_principal. Return NULL if + * none is found. */ +static struct acl_entry * +find_entry(struct acl_state *state, krb5_const_principal client, + krb5_const_principal target) +{ + struct acl_entry *entry; + struct wildstate ws; + + for (entry = state->list; entry != NULL; entry = entry->next) { + memset(&ws, 0, sizeof(ws)); + if (entry->client != NULL) { + if (!match_princ(entry->client, client, FALSE, &ws)) + continue; + } + + if (entry->target != NULL) { + if (target == NULL) + continue; + if (!match_princ(entry->target, target, TRUE, &ws)) + continue; + } + + return entry; + } + + return NULL; +} + +/* Return true if op is permitted for this principal. Set *rs_out (if not + * NULL) according to any restrictions in the ACL entry. */ +static krb5_error_code +acl_check(kadm5_auth_moddata data, uint32_t op, krb5_const_principal client, + krb5_const_principal target, struct kadm5_auth_restrictions **rs_out) +{ + struct acl_entry *entry; + + if (rs_out != NULL) + *rs_out = NULL; + + entry = find_entry((struct acl_state *)data, client, target); + if (entry == NULL) + return KRB5_PLUGIN_NO_HANDLE; + if (!(entry->op_allowed & op)) + return KRB5_PLUGIN_NO_HANDLE; + + if (rs_out != NULL && entry->rs != NULL && entry->rs->mask) + *rs_out = entry->rs; + + return 0; +} + +static krb5_error_code +acl_init(krb5_context context, const char *acl_file, + kadm5_auth_moddata *data_out) +{ + krb5_error_code ret; + struct acl_state *state; + + *data_out = NULL; + if (acl_file == NULL) + return KRB5_PLUGIN_NO_HANDLE; + state = malloc(sizeof(*state)); + state->list = NULL; + ret = load_acl_file(context, acl_file, state); + if (ret) { + free(state); + return ret; + } + *data_out = (kadm5_auth_moddata)state; + return 0; +} + +static void +acl_fini(krb5_context context, kadm5_auth_moddata data) +{ + if (data == NULL) + return; + free_acl_entries((struct acl_state *)data); + free(data); +} + +static krb5_error_code +acl_addprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out) +{ + return acl_check(data, ACL_ADD, client, target, rs_out); +} + +static krb5_error_code +acl_modprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out) +{ + return acl_check(data, ACL_MODIFY, client, target, rs_out); +} + +static krb5_error_code +acl_setstr(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const char *key, const char *value) +{ + return acl_check(data, ACL_MODIFY, client, target, NULL); +} + +static krb5_error_code +acl_cpw(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_CHANGEPW, client, target, NULL); +} + +static krb5_error_code +acl_chrand(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_CHANGEPW, client, target, NULL); +} + +static krb5_error_code +acl_setkey(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_SETKEY, client, target, NULL); +} + +static krb5_error_code +acl_purgekeys(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_MODIFY, client, target, NULL); +} + +static krb5_error_code +acl_delprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_DELETE, client, target, NULL); +} + +static krb5_error_code +acl_renprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal src, + krb5_const_principal dest) +{ + struct kadm5_auth_restrictions *rs; + + if (acl_check(data, ACL_DELETE, client, src, NULL) == 0 && + acl_check(data, ACL_ADD, client, dest, &rs) == 0 && rs == NULL) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +static krb5_error_code +acl_getprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_INQUIRE, client, target, NULL); +} + +static krb5_error_code +acl_getstrs(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_INQUIRE, client, target, NULL); +} + +static krb5_error_code +acl_extract(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_EXTRACT, client, target, NULL); +} + +static krb5_error_code +acl_listprincs(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client) +{ + return acl_check(data, ACL_LIST, client, NULL, NULL); +} + +static krb5_error_code +acl_addpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask) +{ + return acl_check(data, ACL_ADD, client, NULL, NULL); +} + +static krb5_error_code +acl_modpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask) +{ + return acl_check(data, ACL_MODIFY, client, NULL, NULL); +} + +static krb5_error_code +acl_delpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy) +{ + return acl_check(data, ACL_DELETE, client, NULL, NULL); +} + +static krb5_error_code +acl_getpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const char *client_policy) +{ + return acl_check(data, ACL_INQUIRE, client, NULL, NULL); +} + +static krb5_error_code +acl_listpols(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client) +{ + return acl_check(data, ACL_LIST, client, NULL, NULL); +} + +static krb5_error_code +acl_iprop(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client) +{ + return acl_check(data, ACL_IPROP, client, NULL, NULL); +} + +krb5_error_code +kadm5_auth_acl_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + kadm5_auth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (kadm5_auth_vtable)vtable; + vt->name = "acl"; + vt->init = acl_init; + vt->fini = acl_fini; + vt->addprinc = acl_addprinc; + vt->modprinc = acl_modprinc; + vt->setstr = acl_setstr; + vt->cpw = acl_cpw; + vt->chrand = acl_chrand; + vt->setkey = acl_setkey; + vt->purgekeys = acl_purgekeys; + vt->delprinc = acl_delprinc; + vt->renprinc = acl_renprinc; + vt->getprinc = acl_getprinc; + vt->getstrs = acl_getstrs; + vt->extract = acl_extract; + vt->listprincs = acl_listprincs; + vt->addpol = acl_addpol; + vt->modpol = acl_modpol; + vt->delpol = acl_delpol; + vt->getpol = acl_getpol; + vt->listpols = acl_listpols; + vt->iprop = acl_iprop; + return 0; +} diff --git a/src/kadmin/server/auth_self.c b/src/kadmin/server/auth_self.c new file mode 100644 index 000000000000..253d4bc596ae --- /dev/null +++ b/src/kadmin/server/auth_self.c @@ -0,0 +1,77 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/server/auth_self.c - self-service kadm5_auth module */ +/* + * Copyright (C) 2017 by the Massachusetts Institute of Technology. + * 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. + */ + +#include "k5-int.h" +#include <kadm5/admin.h> +#include <krb5/kadm5_auth_plugin.h> +#include "auth.h" + +/* Authorize a principal to operate on itself. Applies to cpw, chrand, + * purgekeys, getprinc, and getstrs. */ +static krb5_error_code +self_compare(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + if (krb5_principal_compare(context, client, target)) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* Authorize a principal to get the policy record for its own policy. */ +static krb5_error_code +self_getpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const char *client_policy) +{ + if (client_policy != NULL && strcmp(policy, client_policy) == 0) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +krb5_error_code +kadm5_auth_self_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + kadm5_auth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (kadm5_auth_vtable)vtable; + vt->name = "self"; + vt->cpw = self_compare; + vt->chrand = self_compare; + vt->purgekeys = self_compare; + vt->getprinc = self_compare; + vt->getstrs = self_compare; + vt->getpol = self_getpol; + return 0; +} diff --git a/src/kadmin/server/deps b/src/kadmin/server/deps index 44311af19af7..99aef7500e00 100644 --- a/src/kadmin/server/deps +++ b/src/kadmin/server/deps @@ -1,6 +1,44 @@ # # Generated makefile dependencies follow. # +$(OUTPRE)auth_acl.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kadm5_auth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth.h auth_acl.c +$(OUTPRE)auth_self.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kadm5_auth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth.h auth_self.c $(OUTPRE)kadm_rpc_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \ @@ -29,28 +67,27 @@ $(OUTPRE)server_stubs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \ $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ - $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_acl.h \ - $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ - $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/adm_proto.h \ - $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ - $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ - $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ - $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ - $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ - $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ - $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ - $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ - $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ - misc.h server_stubs.c + $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth.h misc.h \ + server_stubs.c $(OUTPRE)ovsec_kadmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssrpc/types.h \ $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ - $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_acl.h \ - $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ - $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ - $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.h \ + $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.h \ $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.h $(COM_ERR_DEPS) \ $(VERTO_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_gssapi.h \ @@ -71,7 +108,7 @@ $(OUTPRE)ovsec_kadmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/lib/gssapi/generic/gssapiP_generic.h \ $(top_srcdir)/lib/gssapi/generic/gssapi_ext.h $(top_srcdir)/lib/gssapi/generic/gssapi_generic.h \ $(top_srcdir)/lib/gssapi/krb5/gssapiP_krb5.h $(top_srcdir)/lib/gssapi/krb5/gssapi_krb5.h \ - misc.h ovsec_kadmd.c + auth.h misc.h ovsec_kadmd.c $(OUTPRE)schpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ @@ -97,23 +134,23 @@ $(OUTPRE)misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ - $(BUILDTOP)/include/kadm5/server_acl.h $(BUILDTOP)/include/kadm5/server_internal.h \ - $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ - $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ - $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ - $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ - $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ - $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ - $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ - $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ - $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ - $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ - $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ - $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ - $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ - $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ - misc.c misc.h + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth.h misc.c \ + misc.h $(OUTPRE)ipropd_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ @@ -131,5 +168,5 @@ $(OUTPRE)ipropd_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \ $(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ - $(top_srcdir)/lib/gssapi/krb5/gssapi_krb5.h $(top_srcdir)/lib/kadm5/srv/server_acl.h \ + $(top_srcdir)/lib/gssapi/krb5/gssapi_krb5.h auth.h \ ipropd_svc.c misc.h diff --git a/src/kadmin/server/ipropd_svc.c b/src/kadmin/server/ipropd_svc.c index bce668f4221a..e6e190136f88 100644 --- a/src/kadmin/server/ipropd_svc.c +++ b/src/kadmin/server/ipropd_svc.c @@ -16,7 +16,6 @@ #include <kadm5/admin.h> #include <kadm5/kadm_rpc.h> #include <kadm5/server_internal.h> -#include <server_acl.h> #include <adm_proto.h> #include <string.h> #include <gssapi_krb5.h> @@ -25,6 +24,7 @@ #include <arpa/inet.h> #include <netdb.h> #include <kdb_log.h> +#include "auth.h" #include "misc.h" #include "osconf.h" @@ -129,6 +129,20 @@ buf_to_string(gss_buffer_desc *b) return s; } +static krb5_boolean +iprop_acl_check(krb5_context context, const char *client_name) +{ + krb5_principal client_princ; + krb5_boolean result; + + if (krb5_parse_name(context, client_name, &client_princ) != 0) + return FALSE; + result = auth(context, OP_IPROP, client_princ, + NULL, NULL, NULL, NULL, NULL, 0); + krb5_free_principal(context, client_princ); + return result; +} + kdb_incr_result_t * iprop_get_updates_1_svc(kdb_last_t *arg, struct svc_req *rqstp) { @@ -174,11 +188,7 @@ iprop_get_updates_1_svc(kdb_last_t *arg, struct svc_req *rqstp) DPRINT("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n", whoami, client_name, service_name); - if (!kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_IPROP, - NULL, - NULL)) { + if (!iprop_acl_check(handle->context, client_name)) { ret.ret = UPDATE_PERM_DENIED; DPRINT("%s: PERMISSION DENIED: clprinc=`%s'\n\tsvcprinc=`%s'\n", @@ -301,11 +311,7 @@ ipropx_resync(uint32_t vers, struct svc_req *rqstp) DPRINT("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n", whoami, client_name, service_name); - if (!kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_IPROP, - NULL, - NULL)) { + if (!iprop_acl_check(handle->context, client_name)) { ret.ret = UPDATE_PERM_DENIED; DPRINT("%s: Permission denied\n", whoami); @@ -532,9 +538,9 @@ krb5_iprop_prog_1(struct svc_req *rqstp, union { kdb_last_t iprop_get_updates_1_arg; } argument; - char *result; + void *result; bool_t (*_xdr_argument)(), (*_xdr_result)(); - char *(*local)(/* union XXX *, struct svc_req * */); + void *(*local)(/* union XXX *, struct svc_req * */); char *whoami = "krb5_iprop_prog_1"; if (!check_iprop_rpcsec_auth(rqstp)) { @@ -555,19 +561,19 @@ krb5_iprop_prog_1(struct svc_req *rqstp, case IPROP_GET_UPDATES: _xdr_argument = xdr_kdb_last_t; _xdr_result = xdr_kdb_incr_result_t; - local = (char *(*)()) iprop_get_updates_1_svc; + local = (void *(*)()) iprop_get_updates_1_svc; break; case IPROP_FULL_RESYNC: _xdr_argument = xdr_void; _xdr_result = xdr_kdb_fullresync_result_t; - local = (char *(*)()) iprop_full_resync_1_svc; + local = (void *(*)()) iprop_full_resync_1_svc; break; case IPROP_FULL_RESYNC_EXT: _xdr_argument = xdr_u_int32; _xdr_result = xdr_kdb_fullresync_result_t; - local = (char *(*)()) iprop_full_resync_ext_1_svc; + local = (void *(*)()) iprop_full_resync_ext_1_svc; break; default: diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c index 27a6376af6b1..6b258a6a056e 100644 --- a/src/kadmin/server/misc.c +++ b/src/kadmin/server/misc.c @@ -7,96 +7,9 @@ #include <k5-int.h> #include <kdb.h> #include <kadm5/server_internal.h> -#include <kadm5/server_acl.h> #include "misc.h" +#include "auth.h" #include "net-server.h" - -/* - * Function: chpass_principal_wrapper_3 - * - * Purpose: wrapper to kadm5_chpass_principal that checks to see if - * pw_min_life has been reached. if not it returns an error. - * otherwise it calls kadm5_chpass_principal - * - * Arguments: - * principal (input) krb5_principals whose password we are - * changing - * keepold (input) whether to preserve old keys - * n_ks_tuple (input) the number of key-salt tuples in ks_tuple - * ks_tuple (input) array of tuples indicating the caller's - * requested enctypes/salttypes - * password (input) password we are going to change to. - * <return value> 0 on success error code on failure. - * - * Requires: - * kadm5_init to have been run. - * - * Effects: - * calls kadm5_chpass_principal which changes the kdb and the - * the admin db. - * - */ -kadm5_ret_t -chpass_principal_wrapper_3(void *server_handle, - krb5_principal principal, - krb5_boolean keepold, - int n_ks_tuple, - krb5_key_salt_tuple *ks_tuple, - char *password) -{ - kadm5_ret_t ret; - - ret = check_min_life(server_handle, principal, NULL, 0); - if (ret) - return ret; - - return kadm5_chpass_principal_3(server_handle, principal, - keepold, n_ks_tuple, ks_tuple, - password); -} - - -/* - * Function: randkey_principal_wrapper_3 - * - * Purpose: wrapper to kadm5_randkey_principal which checks the - * password's min. life. - * - * Arguments: - * principal (input) krb5_principal whose password we are - * changing - * keepold (input) whether to preserve old keys - * n_ks_tuple (input) the number of key-salt tuples in ks_tuple - * ks_tuple (input) array of tuples indicating the caller's - * requested enctypes/salttypes - * key (output) new random key - * <return value> 0, error code on error. - * - * Requires: - * kadm5_init needs to be run - * - * Effects: - * calls kadm5_randkey_principal - * - */ -kadm5_ret_t -randkey_principal_wrapper_3(void *server_handle, - krb5_principal principal, - krb5_boolean keepold, - int n_ks_tuple, - krb5_key_salt_tuple *ks_tuple, - krb5_keyblock **keys, int *n_keys) -{ - kadm5_ret_t ret; - - ret = check_min_life(server_handle, principal, NULL, 0); - if (ret) - return ret; - return kadm5_randkey_principal_3(server_handle, principal, - keepold, n_ks_tuple, ks_tuple, - keys, n_keys); -} - kadm5_ret_t schpw_util_wrapper(void *server_handle, krb5_principal client, @@ -107,8 +20,6 @@ schpw_util_wrapper(void *server_handle, { kadm5_ret_t ret; kadm5_server_handle_t handle = server_handle; - krb5_boolean access_granted; - krb5_boolean self; /* * If no target is explicitly provided, then the target principal @@ -117,32 +28,22 @@ schpw_util_wrapper(void *server_handle, if (target == NULL) target = client; - /* - * A principal can always change its own password, as long as it - * has an initial ticket and meets the minimum password lifetime - * requirement. - */ - self = krb5_principal_compare(handle->context, client, target); - if (self) { + /* If the client is changing its own password, require it to use an initial + * ticket, and enforce the policy min_life. */ + if (krb5_principal_compare(handle->context, client, target)) { + if (!initial_flag) { + strlcpy(msg_ret, "Ticket must be derived from a password", + msg_len); + return KADM5_AUTH_INITIAL; + } + ret = check_min_life(server_handle, target, msg_ret, msg_len); if (ret != 0) return ret; - - access_granted = initial_flag; - } else - access_granted = FALSE; - - if (!access_granted && - kadm5int_acl_check_krb(handle->context, client, - ACL_CHANGEPW, target, NULL)) { - /* - * Otherwise, principals with appropriate privileges can change - * any password - */ - access_granted = TRUE; } - if (access_granted) { + if (auth(handle->context, OP_CPW, client, target, + NULL, NULL, NULL, NULL, 0)) { ret = kadm5_chpass_principal_util(server_handle, target, new_pw, ret_pw, @@ -159,7 +60,7 @@ kadm5_ret_t check_min_life(void *server_handle, krb5_principal principal, char *msg_ret, unsigned int msg_len) { - krb5_int32 now; + krb5_timestamp now; kadm5_ret_t ret; kadm5_policy_ent_rec pol; kadm5_principal_ent_rec princ; @@ -184,7 +85,7 @@ check_min_life(void *server_handle, krb5_principal principal, (void) kadm5_free_principal_ent(handle->lhandle, &princ); return (ret == KADM5_UNK_POLICY) ? 0 : ret; } - if((now - princ.last_pwd_change) < pol.pw_min_life && + if(ts_delta(now, princ.last_pwd_change) < pol.pw_min_life && !(princ.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) { if (msg_ret != NULL) { time_t until; diff --git a/src/kadmin/server/misc.h b/src/kadmin/server/misc.h index ea0fc7d2217a..3a112a0b7b2e 100644 --- a/src/kadmin/server/misc.h +++ b/src/kadmin/server/misc.h @@ -13,23 +13,6 @@ int setup_gss_names(struct svc_req *, gss_buffer_desc *, gss_buffer_desc *); - -kadm5_ret_t -chpass_principal_wrapper_3(void *server_handle, - krb5_principal principal, - krb5_boolean keepold, - int n_ks_tuple, - krb5_key_salt_tuple *ks_tuple, - char *password); - -kadm5_ret_t -randkey_principal_wrapper_3(void *server_handle, - krb5_principal principal, - krb5_boolean keepold, - int n_ks_tuple, - krb5_key_salt_tuple *ks_tuple, - krb5_keyblock **keys, int *n_keys); - kadm5_ret_t schpw_util_wrapper(void *server_handle, krb5_principal client, krb5_principal target, krb5_boolean initial_flag, diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c index a3edd3b00169..6c875901a976 100644 --- a/src/kadmin/server/ovsec_kadmd.c +++ b/src/kadmin/server/ovsec_kadmd.c @@ -51,7 +51,6 @@ #include <gssrpc/auth_gssapi.h> #include <kadm5/admin.h> #include <kadm5/kadm_rpc.h> -#include <kadm5/server_acl.h> #include <adm_proto.h> #include "kdb_kt.h" /* for krb5_ktkdb_set_context */ #include <string.h> @@ -59,6 +58,7 @@ #include <kdb_log.h> #include "misc.h" +#include "auth.h" #if defined(NEED_DAEMON_PROTO) int daemon(int, int); @@ -356,6 +356,7 @@ main(int argc, char *argv[]) verto_ctx *vctx; const char *pid_file = NULL; char **db_args = NULL, **tmpargs; + const char *acl_file; int ret, i, db_args_size = 0, strong_random = 1, proponly = 0; setlocale(LC_ALL, ""); @@ -505,7 +506,8 @@ main(int argc, char *argv[]) if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE) fail_to_start(0, _("Cannot initialize GSSAPI service name")); - ret = kadm5int_acl_init(context, 0, params.acl_file); + acl_file = (*params.acl_file != '\0') ? params.acl_file : NULL; + ret = auth_init(context, acl_file); if (ret) fail_to_start(ret, _("initializing ACL file")); @@ -550,7 +552,7 @@ main(int argc, char *argv[]) svcauth_gssapi_unset_names(); kadm5_destroy(global_server_handle); loop_free(vctx); - kadm5int_acl_finish(context, 0); + auth_fini(context); (void)gss_release_name(&minor_status, &gss_changepw_name); (void)gss_release_name(&minor_status, &gss_oldchangepw_name); for (i = 0; i < 4; i++) diff --git a/src/kadmin/server/schpw.c b/src/kadmin/server/schpw.c index 900adf7a0997..491cba91aa1a 100644 --- a/src/kadmin/server/schpw.c +++ b/src/kadmin/server/schpw.c @@ -18,8 +18,8 @@ static krb5_error_code process_chpw_request(krb5_context context, void *server_handle, char *realm, - krb5_keytab keytab, const krb5_fulladdr *local_faddr, - const krb5_fulladdr *remote_faddr, krb5_data *req, + krb5_keytab keytab, const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_data *req, krb5_data *rep) { krb5_error_code ret; @@ -42,7 +42,7 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm, struct sockaddr_storage ss; socklen_t salen; char addrbuf[100]; - krb5_address *addr = remote_faddr->address; + krb5_address *addr = remote_addr->address; *rep = empty_data(); @@ -205,15 +205,6 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm, goto chpwfail; } - /* for cpw, verify that this is an AS_REQ ticket */ - if (vno == 1 && - (ticket->enc_part2->flags & TKT_FLG_INITIAL) == 0) { - numresult = KRB5_KPASSWD_INITIAL_FLAG_NEEDED; - strlcpy(strresult, "Ticket must be derived from a password", - sizeof(strresult)); - goto chpwfail; - } - /* change the password */ ptr = k5memdup0(clear.data, clear.length, &ret); @@ -237,7 +228,7 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm, sin->sin_family = AF_INET; memcpy(&sin->sin_addr, addr->contents, addr->length); - sin->sin_port = htons(remote_faddr->port); + sin->sin_port = htons(remote_addr->port); salen = sizeof(*sin); break; } @@ -246,7 +237,7 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm, sin6->sin6_family = AF_INET6; memcpy(&sin6->sin6_addr, addr->contents, addr->length); - sin6->sin6_port = htons(remote_faddr->port); + sin6->sin6_port = htons(remote_addr->port); salen = sizeof(*sin6); break; } @@ -292,6 +283,9 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm, case KADM5_AUTH_CHANGEPW: numresult = KRB5_KPASSWD_ACCESSDENIED; break; + case KADM5_AUTH_INITIAL: + numresult = KRB5_KPASSWD_INITIAL_FLAG_NEEDED; + break; case KADM5_PASS_Q_TOOSHORT: case KADM5_PASS_REUSE: case KADM5_PASS_Q_CLASS: @@ -326,7 +320,7 @@ chpwfail: if (ap_rep.length) { ret = krb5_auth_con_setaddrs(context, auth_context, - local_faddr->address, NULL); + local_addr->address, NULL); if (ret) { numresult = KRB5_KPASSWD_HARDERROR; strlcpy(strresult, @@ -366,7 +360,7 @@ chpwfail: to mk_error do. */ krberror.error = ret; krberror.error -= ERROR_TABLE_BASE_krb5; - if (krberror.error < 0 || krberror.error > KRB_ERR_MAX) + if (krberror.error > KRB_ERR_MAX) krberror.error = KRB_ERR_GENERIC; krberror.client = NULL; @@ -436,29 +430,15 @@ bailout: /* Dispatch routine for set/change password */ void -dispatch(void *handle, struct sockaddr *local_saddr, - const krb5_fulladdr *remote_faddr, krb5_data *request, int is_tcp, +dispatch(void *handle, const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_data *request, int is_tcp, verto_ctx *vctx, loop_respond_fn respond, void *arg) { krb5_error_code ret; krb5_keytab kt = NULL; kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle; - krb5_fulladdr local_faddr; - krb5_address **local_kaddrs = NULL, local_kaddr_buf; krb5_data *response = NULL; - if (local_saddr == NULL) { - ret = krb5_os_localaddr(server_handle->context, &local_kaddrs); - if (ret != 0) - goto egress; - - local_faddr.address = local_kaddrs[0]; - local_faddr.port = 0; - } else { - local_faddr.address = &local_kaddr_buf; - init_addr(&local_faddr, local_saddr); - } - ret = krb5_kt_resolve(server_handle->context, "KDB:", &kt); if (ret != 0) { krb5_klog_syslog(LOG_ERR, _("chpw: Couldn't open admin keytab %s"), @@ -474,14 +454,13 @@ dispatch(void *handle, struct sockaddr *local_saddr, handle, server_handle->params.realm, kt, - &local_faddr, - remote_faddr, + local_addr, + remote_addr, request, response); egress: if (ret) krb5_free_data(server_handle->context, response); - krb5_free_addresses(server_handle->context, local_kaddrs); krb5_kt_close(server_handle->context, kt); (*respond)(arg, ret, ret == 0 ? response : NULL); } diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c index 86c162590e4b..cfef97fec147 100644 --- a/src/kadmin/server/server_stubs.c +++ b/src/kadmin/server/server_stubs.c @@ -12,10 +12,10 @@ #include <kadm5/admin.h> #include <kadm5/kadm_rpc.h> #include <kadm5/server_internal.h> -#include <kadm5/server_acl.h> #include <syslog.h> #include <adm_proto.h> /* krb5_klog_syslog */ #include "misc.h" +#include "auth.h" extern gss_name_t gss_changepw_name; extern gss_name_t gss_oldchangepw_name; @@ -216,19 +216,6 @@ static gss_name_t acceptor_name(gss_ctx_id_t context) return name; } -static int cmp_gss_krb5_name(kadm5_server_handle_t handle, - gss_name_t gss_name, krb5_principal princ) -{ - krb5_principal princ2; - int status; - - if (! gss_to_krb5_name(handle, gss_name, &princ2)) - return 0; - status = krb5_principal_compare(handle->context, princ, princ2); - krb5_free_principal(handle->context, princ2); - return status; -} - static int gss_to_krb5_name(kadm5_server_handle_t handle, gss_name_t gss_name, krb5_principal *princ) { @@ -314,12 +301,76 @@ stub_cleanup(kadm5_server_handle_t handle, char *princ_str, { OM_uint32 minor_stat; + auth_end(handle->context); free_server_handle(handle); free(princ_str); gss_release_buffer(&minor_stat, client_name); gss_release_buffer(&minor_stat, service_name); } +static krb5_boolean +stub_auth(kadm5_server_handle_t handle, int opcode, krb5_const_principal p1, + krb5_const_principal p2, const char *s1, const char *s2) +{ + return auth(handle->context, opcode, handle->current_caller, p1, p2, + s1, s2, NULL, 0); +} + +static krb5_boolean +stub_auth_pol(kadm5_server_handle_t handle, int opcode, const char *policy, + const kadm5_policy_ent_rec *polent, long mask) +{ + return auth(handle->context, opcode, handle->current_caller, NULL, NULL, + policy, NULL, polent, mask); +} + +static krb5_boolean +stub_auth_restrict(kadm5_server_handle_t handle, int opcode, + kadm5_principal_ent_t ent, long *mask) +{ + return auth_restrict(handle->context, opcode, handle->current_caller, + ent, mask); +} + +/* Return true if the client authenticated to kadmin/changepw and princ is not + * the client principal. */ +static krb5_boolean +changepw_not_self(kadm5_server_handle_t handle, struct svc_req *rqstp, + krb5_const_principal princ) +{ + return CHANGEPW_SERVICE(rqstp) && + !krb5_principal_compare(handle->context, handle->current_caller, + princ); +} + +static krb5_boolean +ticket_is_initial(struct svc_req *rqstp) +{ + OM_uint32 status, minor_stat; + krb5_flags flags; + + status = gss_krb5_get_tkt_flags(&minor_stat, rqstp->rq_svccred, &flags); + if (status != GSS_S_COMPLETE) + return 0; + return (flags & TKT_FLG_INITIAL) != 0; +} + +/* If a key change request is for the client's own principal, verify that the + * client used an initial ticket and enforce the policy min_life. */ +static kadm5_ret_t +check_self_keychange(kadm5_server_handle_t handle, struct svc_req *rqstp, + krb5_principal princ) +{ + if (!krb5_principal_compare(handle->context, handle->current_caller, + princ)) + return 0; + + if (!ticket_is_initial(rqstp)) + return KADM5_AUTH_INITIAL; + + return check_min_life(handle, princ, NULL, 0); +} + static int log_unauth( char *op, @@ -387,7 +438,6 @@ create_principal_2_svc(cprinc_arg *arg, generic_ret *ret, gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; kadm5_server_handle_t handle; - restriction_t *rp; const char *errmsg = NULL; ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, @@ -396,11 +446,8 @@ create_principal_2_svc(cprinc_arg *arg, generic_ret *ret, if (ret->code) goto exit_func; - if (CHANGEPW_SERVICE(rqstp) - || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_ADD, - arg->rec.principal, &rp) - || kadm5int_acl_impose_restrictions(handle->context, - &arg->rec, &arg->mask, rp)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_restrict(handle, OP_ADDPRINC, &arg->rec, &arg->mask)) { ret->code = KADM5_AUTH_ADD; log_unauth("kadm5_create_principal", prime_arg, &client_name, &service_name, rqstp); @@ -431,7 +478,6 @@ create_principal3_2_svc(cprinc3_arg *arg, generic_ret *ret, gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; kadm5_server_handle_t handle; - restriction_t *rp; const char *errmsg = NULL; ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, @@ -440,11 +486,8 @@ create_principal3_2_svc(cprinc3_arg *arg, generic_ret *ret, if (ret->code) goto exit_func; - if (CHANGEPW_SERVICE(rqstp) - || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_ADD, - arg->rec.principal, &rp) - || kadm5int_acl_impose_restrictions(handle->context, - &arg->rec, &arg->mask, rp)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_restrict(handle, OP_ADDPRINC, &arg->rec, &arg->mask)) { ret->code = KADM5_AUTH_ADD; log_unauth("kadm5_create_principal", prime_arg, &client_name, &service_name, rqstp); @@ -498,9 +541,8 @@ delete_principal_2_svc(dprinc_arg *arg, generic_ret *ret, if (ret->code) goto exit_func; - if (CHANGEPW_SERVICE(rqstp) - || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_DELETE, - arg->princ, NULL)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_DELPRINC, arg->princ, NULL, NULL, NULL)) { ret->code = KADM5_AUTH_DELETE; log_unauth("kadm5_delete_principal", prime_arg, &client_name, &service_name, rqstp); @@ -540,7 +582,6 @@ modify_principal_2_svc(mprinc_arg *arg, generic_ret *ret, gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; kadm5_server_handle_t handle; - restriction_t *rp; const char *errmsg = NULL; ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, @@ -549,11 +590,8 @@ modify_principal_2_svc(mprinc_arg *arg, generic_ret *ret, if (ret->code) goto exit_func; - if (CHANGEPW_SERVICE(rqstp) - || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_MODIFY, - arg->rec.principal, &rp) - || kadm5int_acl_impose_restrictions(handle->context, - &arg->rec, &arg->mask, rp)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_restrict(handle, OP_MODPRINC, &arg->rec, &arg->mask)) { ret->code = KADM5_AUTH_MODIFY; log_unauth("kadm5_modify_principal", prime_arg, &client_name, &service_name, rqstp); @@ -592,7 +630,6 @@ rename_principal_2_svc(rprinc_arg *arg, generic_ret *ret, gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; kadm5_server_handle_t handle; - restriction_t *rp; const char *errmsg = NULL; size_t tlen1, tlen2, clen, slen; char *tdots1, *tdots2, *cdots, *sdots; @@ -617,29 +654,19 @@ rename_principal_2_svc(rprinc_arg *arg, generic_ret *ret, slen = service_name.length; trunc_name(&slen, &sdots); - ret->code = KADM5_OK; - if (! CHANGEPW_SERVICE(rqstp)) { - if (!kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_DELETE, arg->src, NULL)) + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_RENPRINC, arg->src, arg->dest, NULL, NULL)) { + ret->code = KADM5_AUTH_INSUFFICIENT; + log_unauth("kadm5_rename_principal", prime_arg1, &client_name, + &service_name, rqstp); + } else { + ret->code = check_lockdown_keys(handle, arg->src); + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_rename_principal", prime_arg1, &client_name, + &service_name, rqstp); ret->code = KADM5_AUTH_DELETE; - /* any restrictions at all on the ADD kills the RENAME */ - if (!kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_ADD, arg->dest, &rp) || rp) { - if (ret->code == KADM5_AUTH_DELETE) - ret->code = KADM5_AUTH_INSUFFICIENT; - else - ret->code = KADM5_AUTH_ADD; - } - if (ret->code == KADM5_OK) { - ret->code = check_lockdown_keys(handle, arg->src); - if (ret->code == KADM5_PROTECT_KEYS) { - log_unauth("kadm5_rename_principal", prime_arg1, &client_name, - &service_name, rqstp); - ret->code = KADM5_AUTH_DELETE; - } } - } else - ret->code = KADM5_AUTH_INSUFFICIENT; + } if (ret->code != KADM5_OK) { /* okay to cast lengths to int because trunc_name limits max value */ krb5_klog_syslog(LOG_NOTICE, @@ -696,12 +723,8 @@ get_principal_2_svc(gprinc_arg *arg, gprinc_ret *ret, struct svc_req *rqstp) funcname = "kadm5_get_principal"; - if (! cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) && - (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_INQUIRE, - arg->princ, - NULL))) { + if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_GETPRINC, arg->princ, NULL, NULL, NULL)) { ret->code = KADM5_AUTH_GET; log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); @@ -743,11 +766,8 @@ get_princs_2_svc(gprincs_arg *arg, gprincs_ret *ret, struct svc_req *rqstp) if (prime_arg == NULL) prime_arg = "*"; - if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_LIST, - NULL, - NULL)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_LISTPRINCS, NULL, NULL, NULL, NULL)) { ret->code = KADM5_AUTH_LIST; log_unauth("kadm5_get_principals", prime_arg, &client_name, &service_name, rqstp); @@ -793,17 +813,15 @@ chpass_principal_2_svc(chpass_arg *arg, generic_ret *ret, &service_name, rqstp); ret->code = KADM5_AUTH_CHANGEPW; } - } else if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) { - ret->code = chpass_principal_wrapper_3(handle, arg->princ, FALSE, 0, - NULL, arg->pass); - } else if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_CHANGEPW, arg->princ, NULL)) { - ret->code = kadm5_chpass_principal(handle, arg->princ, arg->pass); - } else { + } else if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_CPW, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_CHANGEPW; log_unauth("kadm5_chpass_principal", prime_arg, &client_name, &service_name, rqstp); - ret->code = KADM5_AUTH_CHANGEPW; + } else { + ret->code = check_self_keychange(handle, rqstp, arg->princ); + if (!ret->code) + ret->code = kadm5_chpass_principal(handle, arg->princ, arg->pass); } if (ret->code != KADM5_AUTH_CHANGEPW) { @@ -845,20 +863,18 @@ chpass_principal3_2_svc(chpass3_arg *arg, generic_ret *ret, &service_name, rqstp); ret->code = KADM5_AUTH_CHANGEPW; } - } else if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) { - ret->code = chpass_principal_wrapper_3(handle, arg->princ, - arg->keepold, arg->n_ks_tuple, - arg->ks_tuple, arg->pass); - } else if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_CHANGEPW, arg->princ, NULL)) { - ret->code = kadm5_chpass_principal_3(handle, arg->princ, arg->keepold, - arg->n_ks_tuple, arg->ks_tuple, - arg->pass); - } else { + } else if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_CPW, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_CHANGEPW; log_unauth("kadm5_chpass_principal", prime_arg, &client_name, &service_name, rqstp); - ret->code = KADM5_AUTH_CHANGEPW; + } else { + ret->code = check_self_keychange(handle, rqstp, arg->princ); + if (!ret->code) { + ret->code = kadm5_chpass_principal_3(handle, arg->princ, + arg->keepold, arg->n_ks_tuple, + arg->ks_tuple, arg->pass); + } } if (ret->code != KADM5_AUTH_CHANGEPW) { @@ -901,8 +917,7 @@ setv4key_principal_2_svc(setv4key_arg *arg, generic_ret *ret, ret->code = KADM5_AUTH_SETKEY; } } else if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_SETKEY, arg->princ, NULL)) { + stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) { ret->code = kadm5_setv4key_principal(handle, arg->princ, arg->keyblock); } else { @@ -952,8 +967,7 @@ setkey_principal_2_svc(setkey_arg *arg, generic_ret *ret, ret->code = KADM5_AUTH_SETKEY; } } else if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_SETKEY, arg->princ, NULL)) { + stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) { ret->code = kadm5_setkey_principal(handle, arg->princ, arg->keyblocks, arg->n_keys); } else { @@ -1002,8 +1016,7 @@ setkey_principal3_2_svc(setkey3_arg *arg, generic_ret *ret, ret->code = KADM5_AUTH_SETKEY; } } else if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_SETKEY, arg->princ, NULL)) { + stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) { ret->code = kadm5_setkey_principal_3(handle, arg->princ, arg->keepold, arg->n_ks_tuple, arg->ks_tuple, arg->keyblocks, arg->n_keys); @@ -1053,8 +1066,7 @@ setkey_principal4_2_svc(setkey4_arg *arg, generic_ret *ret, ret->code = KADM5_AUTH_SETKEY; } } else if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_SETKEY, arg->princ, NULL)) { + stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) { ret->code = kadm5_setkey_principal_4(handle, arg->princ, arg->keepold, arg->key_data, arg->n_key_data); } else { @@ -1079,8 +1091,8 @@ exit_func: return TRUE; } -/* Empty out *keys/*nkeys if princ is protected with the lockdown attribute, or - * if we fail to check. */ +/* Empty out *keys / *nkeys if princ is protected with the lockdown + * attribute, or if we fail to check. */ static kadm5_ret_t chrand_check_lockdown(kadm5_server_handle_t handle, krb5_principal princ, krb5_keyblock **keys, int *nkeys) @@ -1119,17 +1131,17 @@ chrand_principal_2_svc(chrand_arg *arg, chrand_ret *ret, struct svc_req *rqstp) funcname = "kadm5_randkey_principal"; - if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) { - ret->code = randkey_principal_wrapper_3(handle, arg->princ, FALSE, 0, - NULL, &k, &nkeys); - } else if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_CHANGEPW, arg->princ, NULL)) { - ret->code = kadm5_randkey_principal(handle, arg->princ, &k, &nkeys); - } else { + if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_CHRAND, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_CHANGEPW; log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); - ret->code = KADM5_AUTH_CHANGEPW; + } else { + ret->code = check_self_keychange(handle, rqstp, arg->princ); + if (!ret->code) { + ret->code = kadm5_randkey_principal(handle, arg->princ, + &k, &nkeys); + } } if (ret->code == KADM5_OK) { @@ -1176,20 +1188,19 @@ chrand_principal3_2_svc(chrand3_arg *arg, chrand_ret *ret, funcname = "kadm5_randkey_principal"; - if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) { - ret->code = randkey_principal_wrapper_3(handle, arg->princ, - arg->keepold, arg->n_ks_tuple, - arg->ks_tuple, &k, &nkeys); - } else if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_CHANGEPW, arg->princ, NULL)) { - ret->code = kadm5_randkey_principal_3(handle, arg->princ, arg->keepold, - arg->n_ks_tuple, arg->ks_tuple, - &k, &nkeys); - } else { + if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_CHRAND, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_CHANGEPW; log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); - ret->code = KADM5_AUTH_CHANGEPW; + } else { + ret->code = check_self_keychange(handle, rqstp, arg->princ); + if (!ret->code) { + ret->code = kadm5_randkey_principal_3(handle, arg->princ, + arg->keepold, + arg->n_ks_tuple, + arg->ks_tuple, &k, &nkeys); + } } if (ret->code == KADM5_OK) { @@ -1233,9 +1244,9 @@ create_policy_2_svc(cpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) prime_arg = arg->rec.policy; - if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_ADD, NULL, NULL)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_pol(handle, OP_ADDPOL, arg->rec.policy, + &arg->rec, arg->mask)) { ret->code = KADM5_AUTH_ADD; log_unauth("kadm5_create_policy", prime_arg, &client_name, &service_name, rqstp); @@ -1275,9 +1286,8 @@ delete_policy_2_svc(dpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) prime_arg = arg->name; - if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_DELETE, NULL, NULL)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_DELPOL, NULL, NULL, arg->name, NULL)) { log_unauth("kadm5_delete_policy", prime_arg, &client_name, &service_name, rqstp); ret->code = KADM5_AUTH_DELETE; @@ -1316,9 +1326,9 @@ modify_policy_2_svc(mpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) prime_arg = arg->rec.policy; - if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_MODIFY, NULL, NULL)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_pol(handle, OP_MODPOL, arg->rec.policy, + &arg->rec, arg->mask)) { log_unauth("kadm5_modify_policy", prime_arg, &client_name, &service_name, rqstp); ret->code = KADM5_AUTH_MODIFY; @@ -1349,7 +1359,9 @@ get_policy_2_svc(gpol_arg *arg, gpol_ret *ret, struct svc_req *rqstp) kadm5_ret_t ret2; kadm5_principal_ent_rec caller_ent; kadm5_server_handle_t handle; - const char *errmsg = NULL; + const char *errmsg = NULL, *cpolicy = NULL; + + memset(&caller_ent, 0, sizeof(caller_ent)); ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, &ret->api_version, &client_name, &service_name, @@ -1361,31 +1373,20 @@ get_policy_2_svc(gpol_arg *arg, gpol_ret *ret, struct svc_req *rqstp) prime_arg = arg->name; - ret->code = KADM5_AUTH_GET; - if (!CHANGEPW_SERVICE(rqstp) && kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_INQUIRE, NULL, NULL)) - ret->code = KADM5_OK; - else { - ret->code = kadm5_get_principal(handle->lhandle, - handle->current_caller, &caller_ent, - KADM5_PRINCIPAL_NORMAL_MASK); - if (ret->code == KADM5_OK) { - if (caller_ent.aux_attributes & KADM5_POLICY && - strcmp(caller_ent.policy, arg->name) == 0) { - ret->code = KADM5_OK; - } else { - ret->code = KADM5_AUTH_GET; - } - ret2 = kadm5_free_principal_ent(handle->lhandle, - &caller_ent); - ret->code = ret->code ? ret->code : ret2; - } - } + /* Look up the client principal's policy value. */ + ret2 = kadm5_get_principal(handle->lhandle, handle->current_caller, + &caller_ent, KADM5_PRINCIPAL_NORMAL_MASK); + if (ret2 == KADM5_OK && (caller_ent.aux_attributes & KADM5_POLICY)) + cpolicy = caller_ent.policy; - if (ret->code == KADM5_OK) { + ret->code = KADM5_AUTH_GET; + if ((CHANGEPW_SERVICE(rqstp) && + (cpolicy == NULL || strcmp(cpolicy, arg->name) != 0)) || + !stub_auth(handle, OP_GETPOL, NULL, NULL, arg->name, cpolicy)) { + ret->code = KADM5_AUTH_GET; + log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); + } else { ret->code = kadm5_get_policy(handle, arg->name, &ret->rec); - if (ret->code != 0) errmsg = krb5_get_error_message(handle->context, ret->code); @@ -1394,13 +1395,10 @@ get_policy_2_svc(gpol_arg *arg, gpol_ret *ret, struct svc_req *rqstp) &client_name, &service_name, rqstp); if (errmsg != NULL) krb5_free_error_message(handle->context, errmsg); - - } else { - log_unauth(funcname, prime_arg, - &client_name, &service_name, rqstp); } exit_func: + (void)kadm5_free_principal_ent(handle->lhandle, &caller_ent); stub_cleanup(handle, NULL, &client_name, &service_name); return TRUE; } @@ -1424,9 +1422,8 @@ get_pols_2_svc(gpols_arg *arg, gpols_ret *ret, struct svc_req *rqstp) if (prime_arg == NULL) prime_arg = "*"; - if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_LIST, NULL, NULL)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_LISTPOLS, NULL, NULL, NULL, NULL)) { ret->code = KADM5_AUTH_LIST; log_unauth("kadm5_get_policies", prime_arg, &client_name, &service_name, rqstp); @@ -1494,10 +1491,8 @@ purgekeys_2_svc(purgekeys_arg *arg, generic_ret *ret, struct svc_req *rqstp) funcname = "kadm5_purgekeys"; - if (!cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) && - (CHANGEPW_SERVICE(rqstp) - || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_MODIFY, - arg->princ, NULL))) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_PURGEKEYS, arg->princ, NULL, NULL, NULL)) { ret->code = KADM5_AUTH_MODIFY; log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); } else { @@ -1532,12 +1527,8 @@ get_strings_2_svc(gstrings_arg *arg, gstrings_ret *ret, struct svc_req *rqstp) if (ret->code) goto exit_func; - if (! cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) && - (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, - rqst2name(rqstp), - ACL_INQUIRE, - arg->princ, - NULL))) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_GETSTRS, arg->princ, NULL, NULL, NULL)) { ret->code = KADM5_AUTH_GET; log_unauth("kadm5_get_strings", prime_arg, &client_name, &service_name, rqstp); @@ -1574,9 +1565,9 @@ set_string_2_svc(sstring_arg *arg, generic_ret *ret, struct svc_req *rqstp) if (ret->code) goto exit_func; - if (CHANGEPW_SERVICE(rqstp) - || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_MODIFY, - arg->princ, NULL)) { + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_SETSTR, arg->princ, NULL, + arg->key, arg->value)) { ret->code = KADM5_AUTH_MODIFY; log_unauth("kadm5_mod_strings", prime_arg, &client_name, &service_name, rqstp); @@ -1665,8 +1656,7 @@ get_principal_keys_2_svc(getpkeys_arg *arg, getpkeys_ret *ret, goto exit_func; if (!(CHANGEPW_SERVICE(rqstp)) && - kadm5int_acl_check(handle->context, rqst2name(rqstp), - ACL_EXTRACT, arg->princ, NULL)) { + stub_auth(handle, OP_EXTRACT, arg->princ, NULL, NULL, NULL)) { ret->code = kadm5_get_principal_keys(handle, arg->princ, arg->kvno, &ret->key_data, &ret->n_key_data); } else { diff --git a/src/kadmin/testing/util/tcl_kadm5.c b/src/kadmin/testing/util/tcl_kadm5.c index a4997c60ca04..9dde579ef397 100644 --- a/src/kadmin/testing/util/tcl_kadm5.c +++ b/src/kadmin/testing/util/tcl_kadm5.c @@ -697,13 +697,13 @@ static Tcl_DString *unparse_principal_ent(kadm5_principal_ent_t princ, } else Tcl_DStringAppendElement(str, "null"); - sprintf(buf, "%d", princ->princ_expire_time); + sprintf(buf, "%u", (unsigned int)princ->princ_expire_time); Tcl_DStringAppendElement(str, buf); - sprintf(buf, "%d", princ->last_pwd_change); + sprintf(buf, "%u", (unsigned int)princ->last_pwd_change); Tcl_DStringAppendElement(str, buf); - sprintf(buf, "%d", princ->pw_expiration); + sprintf(buf, "%u", (unsigned int)princ->pw_expiration); Tcl_DStringAppendElement(str, buf); sprintf(buf, "%d", princ->max_life); @@ -722,7 +722,7 @@ static Tcl_DString *unparse_principal_ent(kadm5_principal_ent_t princ, } else Tcl_DStringAppendElement(str, "null"); - sprintf(buf, "%d", princ->mod_date); + sprintf(buf, "%u", (unsigned int)princ->mod_date); Tcl_DStringAppendElement(str, buf); if (mask & KADM5_ATTRIBUTES) { @@ -758,10 +758,10 @@ static Tcl_DString *unparse_principal_ent(kadm5_principal_ent_t princ, sprintf(buf, "%d", princ->max_renewable_life); Tcl_DStringAppendElement(str, buf); - sprintf(buf, "%d", princ->last_success); + sprintf(buf, "%u", (unsigned int)princ->last_success); Tcl_DStringAppendElement(str, buf); - sprintf(buf, "%d", princ->last_failed); + sprintf(buf, "%u", (unsigned int)princ->last_failed); Tcl_DStringAppendElement(str, buf); sprintf(buf, "%d", princ->fail_auth_count); diff --git a/src/kdc/deps b/src/kdc/deps index b5257c715f88..6bc00f7a938c 100644 --- a/src/kdc/deps +++ b/src/kdc/deps @@ -171,20 +171,22 @@ $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ $(top_srcdir)/include/socket-utils.h extern.h kdc5_err.h \ - kdc_audit.h kdc_util.h main.c realm_data.h reqstate.h + kdc_audit.h kdc_util.h main.c policy.h realm_data.h \ + reqstate.h $(OUTPRE)policy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ - $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ - $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ - $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ - $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ - $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpolicy_plugin.h \ $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ $(top_srcdir)/include/socket-utils.h extern.h kdc_util.h \ - policy.c realm_data.h reqstate.h + policy.c policy.h realm_data.h reqstate.h $(OUTPRE)extern.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ @@ -279,14 +281,14 @@ $(OUTPRE)kdc_log.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(OUTPRE)t_replay.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ - $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ - $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ - $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-queue.h \ - $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ - $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ - $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ - $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ - $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ - extern.h kdc_util.h realm_data.h replay.c reqstate.h \ - t_replay.c + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-cmocka.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-queue.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h extern.h kdc_util.h \ + realm_data.h replay.c reqstate.h t_replay.c diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c index 3a169ebc7f40..3867ff952e49 100644 --- a/src/kdc/dispatch.c +++ b/src/kdc/dispatch.c @@ -94,8 +94,8 @@ static void reseed_random(krb5_context kdc_err_context) { krb5_error_code retval; - krb5_int32 now, now_usec; - krb5_int32 usec_difference; + krb5_timestamp now; + krb5_int32 now_usec, usec_difference; krb5_data data; retval = krb5_crypto_us_timeofday(&now, &now_usec); @@ -104,7 +104,7 @@ reseed_random(krb5_context kdc_err_context) if (last_os_random == 0) last_os_random = now; /* Grab random data from OS every hour*/ - if (now-last_os_random >= 60 * 60) { + if (ts_delta(now, last_os_random) >= 60 * 60) { krb5_c_random_os_entropy(kdc_err_context, 0, NULL); last_os_random = now; } @@ -119,8 +119,8 @@ reseed_random(krb5_context kdc_err_context) } void -dispatch(void *cb, struct sockaddr *local_saddr, - const krb5_fulladdr *from, krb5_data *pkt, int is_tcp, +dispatch(void *cb, const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_data *pkt, int is_tcp, verto_ctx *vctx, loop_respond_fn respond, void *arg) { krb5_error_code retval; @@ -150,8 +150,8 @@ dispatch(void *cb, struct sockaddr *local_saddr, const char *name = 0; char buf[46]; - name = inet_ntop (ADDRTYPE2FAMILY (from->address->addrtype), - from->address->contents, buf, sizeof (buf)); + name = inet_ntop(ADDRTYPE2FAMILY(remote_addr->address->addrtype), + remote_addr->address->contents, buf, sizeof(buf)); if (name == 0) name = "[unknown address type]"; if (response) @@ -177,7 +177,7 @@ dispatch(void *cb, struct sockaddr *local_saddr, /* try TGS_REQ first; they are more common! */ if (krb5_is_tgs_req(pkt)) { - retval = process_tgs_req(handle, pkt, from, &response); + retval = process_tgs_req(handle, pkt, remote_addr, &response); } else if (krb5_is_as_req(pkt)) { if (!(retval = decode_krb5_as_req(pkt, &as_req))) { /* @@ -187,7 +187,8 @@ dispatch(void *cb, struct sockaddr *local_saddr, */ state->active_realm = setup_server_realm(handle, as_req->server); if (state->active_realm != NULL) { - process_as_req(as_req, pkt, from, state->active_realm, vctx, + process_as_req(as_req, pkt, local_addr, remote_addr, + state->active_realm, vctx, finish_dispatch_cache, state); return; } else { diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 712ccb794680..7c8da63e1861 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -87,7 +87,7 @@ get_key_exp(krb5_db_entry *entry) return entry->pw_expiration; if (entry->pw_expiration == 0) return entry->expiration; - return min(entry->expiration, entry->pw_expiration); + return ts_min(entry->expiration, entry->pw_expiration); } /* @@ -160,7 +160,8 @@ struct as_req_state { struct kdc_request_state *rstate; char *sname, *cname; void *pa_context; - const krb5_fulladdr *from; + const krb5_fulladdr *local_addr; + const krb5_fulladdr *remote_addr; krb5_data **auth_indicators; krb5_error_code preauth_err; @@ -207,6 +208,13 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) state->ticket_reply.enc_part2 = &state->enc_tkt_reply; + errcode = check_kdcpolicy_as(kdc_context, state->request, state->client, + state->server, state->auth_indicators, + state->kdc_time, &state->enc_tkt_reply.times, + &state->status); + if (errcode) + goto egress; + /* * Find the server key */ @@ -239,10 +247,8 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) state->reply.ticket = &state->ticket_reply; state->reply_encpart.session = &state->session_key; if ((errcode = fetch_last_req_info(state->client, - &state->reply_encpart.last_req))) { - state->status = "FETCH_LAST_REQ"; + &state->reply_encpart.last_req))) goto egress; - } state->reply_encpart.nonce = state->request->nonce; state->reply_encpart.key_exp = get_key_exp(state->client); state->reply_encpart.flags = state->enc_tkt_reply.flags; @@ -300,27 +306,21 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) errcode = krb5_encrypt_tkt_part(kdc_context, &state->server_keyblock, &state->ticket_reply); - if (errcode) { - state->status = "ENCRYPT_TICKET"; + if (errcode) goto egress; - } errcode = kau_make_tkt_id(kdc_context, &state->ticket_reply, &au_state->tkt_out_id); - if (errcode) { - state->status = "GENERATE_TICKET_ID"; + if (errcode) goto egress; - } state->ticket_reply.enc_part.kvno = server_key->key_data_kvno; errcode = kdc_fast_response_handle_padata(state->rstate, state->request, &state->reply, state->client_keyblock.enctype); - if (errcode) { - state->status = "MAKE_FAST_RESPONSE"; + if (errcode) goto egress; - } /* now encode/encrypt the response */ @@ -328,10 +328,8 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) errcode = kdc_fast_handle_reply_key(state->rstate, &state->client_keyblock, &as_encrypting_key); - if (errcode) { - state->status = "MAKE_FAST_REPLY_KEY"; + if (errcode) goto egress; - } errcode = return_enc_padata(kdc_context, state->req_pkt, state->request, as_encrypting_key, state->server, &state->reply_encpart, FALSE); @@ -348,10 +346,8 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) &state->reply, &response); if (state->client_key != NULL) state->reply.enc_part.kvno = state->client_key->key_data_kvno; - if (errcode) { - state->status = "ENCODE_KDC_REP"; + if (errcode) goto egress; - } /* these parts are left on as a courtesy from krb5_encode_kdc_rep so we can use them in raw form if needed. But, we don't... */ @@ -359,14 +355,14 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) state->reply.enc_part.ciphertext.length); free(state->reply.enc_part.ciphertext.data); - log_as_req(kdc_context, state->from, state->request, &state->reply, - state->client, state->cname, state->server, - state->sname, state->authtime, 0, 0, 0); + log_as_req(kdc_context, state->local_addr, state->remote_addr, + state->request, &state->reply, state->client, state->cname, + state->server, state->sname, state->authtime, 0, 0, 0); did_log = 1; egress: - if (errcode != 0) - assert (state->status != 0); + if (errcode != 0 && state->status == NULL) + state->status = "UNKNOWN_REASON"; au_state->status = state->status; au_state->reply = &state->reply; @@ -381,8 +377,8 @@ egress: emsg = krb5_get_error_message(kdc_context, errcode); if (state->status) { - log_as_req(kdc_context, - state->from, state->request, &state->reply, state->client, + log_as_req(kdc_context, state->local_addr, state->remote_addr, + state->request, &state->reply, state->client, state->cname, state->server, state->sname, state->authtime, state->status, errcode, emsg); did_log = 1; @@ -492,7 +488,8 @@ finish_preauth(void *arg, krb5_error_code code) /*ARGSUSED*/ void process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, - const krb5_fulladdr *from, kdc_realm_t *kdc_active_realm, + const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, kdc_realm_t *kdc_active_realm, verto_ctx *vctx, loop_respond_fn respond, void *arg) { krb5_error_code errcode; @@ -511,7 +508,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, state->arg = arg; state->request = request; state->req_pkt = req_pkt; - state->from = from; + state->local_addr = local_addr; + state->remote_addr = remote_addr; state->active_realm = kdc_active_realm; errcode = kdc_make_rstate(kdc_active_realm, &state->rstate); @@ -522,7 +520,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, } /* Initialize audit state. */ - errcode = kau_init_kdc_req(kdc_context, state->request, from, &au_state); + errcode = kau_init_kdc_req(kdc_context, state->request, remote_addr, + &au_state); if (errcode) { (*respond)(arg, errcode, NULL); kdc_free_rstate(state->rstate); @@ -543,7 +542,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, if (fetch_asn1_field((unsigned char *) req_pkt->data, 1, 4, &encoded_req_body) != 0) { errcode = ASN1_BAD_ID; - state->status = "FETCH_REQ_BODY"; goto errout; } errcode = kdc_find_fast(&state->request, &encoded_req_body, NULL, NULL, @@ -556,10 +554,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, /* Not a FAST request; copy the encoded request body. */ errcode = krb5_copy_data(kdc_context, &encoded_req_body, &state->inner_body); - if (errcode) { - state->status = "COPY_REQ_BODY"; + if (errcode) goto errout; - } } au_state->request = state->request; state->rock.request = state->request; @@ -574,10 +570,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, } if ((errcode = krb5_unparse_name(kdc_context, state->request->client, - &state->cname))) { - state->status = "UNPARSE_CLIENT"; + &state->cname))) goto errout; - } limit_string(state->cname); if (!state->request->server) { @@ -587,10 +581,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, } if ((errcode = krb5_unparse_name(kdc_context, state->request->server, - &state->sname))) { - state->status = "UNPARSE_SERVER"; + &state->sname))) goto errout; - } limit_string(state->sname); /* @@ -670,18 +662,14 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, au_state->stage = VALIDATE_POL; - if ((errcode = krb5_timeofday(kdc_context, &state->kdc_time))) { - state->status = "TIMEOFDAY"; + if ((errcode = krb5_timeofday(kdc_context, &state->kdc_time))) goto errout; - } state->authtime = state->kdc_time; /* for audit_as_request() */ if ((errcode = validate_as_request(kdc_active_realm, state->request, *state->client, *state->server, state->kdc_time, &state->status, &state->e_data))) { - if (!state->status) - state->status = "UNKNOWN_REASON"; errcode += ERROR_TABLE_BASE_krb5; goto errout; } @@ -701,10 +689,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, } if ((errcode = krb5_c_make_random_key(kdc_context, useenctype, - &state->session_key))) { - state->status = "MAKE_RANDOM_KEY"; + &state->session_key))) goto errout; - } /* * Canonicalization is only effective if we are issuing a TGT @@ -785,10 +771,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, state->request->client = NULL; errcode = krb5_copy_principal(kdc_context, krb5_anonymous_principal(), &state->request->client); - if (errcode) { - state->status = "COPY_ANONYMOUS_PRINCIPAL"; + if (errcode) goto errout; - } state->enc_tkt_reply.client = state->request->client; setflag(state->client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH); } @@ -841,6 +825,8 @@ prepare_error_as(struct kdc_request_state *rstate, krb5_kdc_req *request, kdc_realm_t *kdc_active_realm = rstate->realm_data; size_t count; + errpkt.magic = KV5M_ERROR; + if (e_data_in != NULL) { /* Add a PA-FX-COOKIE to e_data_in. e_data is a shallow copy * containing aliases. */ @@ -854,7 +840,7 @@ prepare_error_as(struct kdc_request_state *rstate, krb5_kdc_req *request, e_data[count] = cookie; } - errpkt.ctime = request->nonce; + errpkt.ctime = 0; errpkt.cusec = 0; retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec); diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 547a41441767..cc5a6923629a 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -195,15 +195,12 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, if (!header_ticket) { errcode = KRB5_NO_TKT_SUPPLIED; /* XXX? */ - status="UNEXPECTED NULL in header_ticket"; goto cleanup; } errcode = kau_make_tkt_id(kdc_context, header_ticket, &au_state->tkt_in_id); - if (errcode) { - status = "GENERATE_TICKET_ID"; + if (errcode) goto cleanup; - } scratch.length = pa_tgs_req->length; scratch.data = (char *) pa_tgs_req->contents; @@ -264,16 +261,12 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, au_state->stage = VALIDATE_POL; - if ((errcode = krb5_timeofday(kdc_context, &kdc_time))) { - status = "TIME_OF_DAY"; + if ((errcode = krb5_timeofday(kdc_context, &kdc_time))) goto cleanup; - } if ((retval = validate_tgs_request(kdc_active_realm, request, *server, header_ticket, kdc_time, &status, &e_data))) { - if (!status) - status = "UNKNOWN_REASON"; if (retval == KDC_ERR_POLICY || retval == KDC_ERR_BADOPTION) au_state->violation = PROT_CONSTRAINT; errcode = retval + ERROR_TABLE_BASE_krb5; @@ -340,7 +333,6 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, retval = kau_make_tkt_id(kdc_context, request->second_ticket[st_idx], &au_state->evid_tkt_id); if (retval) { - status = "GENERATE_TICKET_ID"; errcode = retval; goto cleanup; } @@ -500,12 +492,12 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, old_starttime = enc_tkt_reply.times.starttime ? enc_tkt_reply.times.starttime : enc_tkt_reply.times.authtime; - old_life = enc_tkt_reply.times.endtime - old_starttime; + old_life = ts_delta(enc_tkt_reply.times.endtime, old_starttime); enc_tkt_reply.times.starttime = kdc_time; enc_tkt_reply.times.endtime = - min(header_ticket->enc_part2->times.renew_till, - kdc_time + old_life); + ts_min(header_ticket->enc_part2->times.renew_till, + ts_incr(kdc_time, old_life)); } else { /* not a renew request */ enc_tkt_reply.times.starttime = kdc_time; @@ -518,6 +510,12 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, kdc_get_ticket_renewtime(kdc_active_realm, request, header_enc_tkt, client, server, &enc_tkt_reply); + errcode = check_kdcpolicy_tgs(kdc_context, request, server, header_ticket, + auth_indicators, kdc_time, + &enc_tkt_reply.times, &status); + if (errcode) + goto cleanup; + /* * Set authtime to be the same as header or evidence ticket's */ @@ -723,10 +721,8 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, &ticket_reply); if (!isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) krb5_free_keyblock_contents(kdc_context, &encrypting_key); - if (errcode) { - status = "ENCRYPT_TICKET"; + if (errcode) goto cleanup; - } ticket_reply.enc_part.kvno = ticket_kvno; /* Start assembling the response */ au_state->stage = ENCR_REP; @@ -740,10 +736,8 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, s4u_x509_user, &reply, &reply_encpart); - if (errcode) { - status = "MAKE_S4U2SELF_PADATA"; + if (errcode) au_state->status = status; - } kau_s4u2self(kdc_context, errcode ? FALSE : TRUE, au_state); if (errcode) goto cleanup; @@ -775,16 +769,12 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, header_ticket->enc_part2->session->enctype; errcode = kdc_fast_response_handle_padata(state, request, &reply, subkey ? subkey->enctype : header_ticket->enc_part2->session->enctype); - if (errcode !=0 ) { - status = "MAKE_FAST_RESPONSE"; + if (errcode) goto cleanup; - } errcode =kdc_fast_handle_reply_key(state, subkey?subkey:header_ticket->enc_part2->session, &reply_key); - if (errcode) { - status = "MAKE_FAST_REPLY_KEY"; + if (errcode) goto cleanup; - } errcode = return_enc_padata(kdc_context, pkt, request, reply_key, server, &reply_encpart, is_referral && @@ -796,10 +786,8 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, } errcode = kau_make_tkt_id(kdc_context, &ticket_reply, &au_state->tkt_out_id); - if (errcode) { - status = "GENERATE_TICKET_ID"; + if (errcode) goto cleanup; - } if (kdc_fast_hide_client(state)) reply.client = (krb5_principal)krb5_anonymous_principal(); @@ -807,11 +795,8 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, subkey ? 1 : 0, reply_key, &reply, response); - if (errcode) { - status = "ENCODE_KDC_REP"; - } else { + if (!errcode) status = "ISSUE"; - } memset(ticket_reply.enc_part.ciphertext.data, 0, ticket_reply.enc_part.ciphertext.length); @@ -823,7 +808,8 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, free(reply.enc_part.ciphertext.data); cleanup: - assert(status != NULL); + if (status == NULL) + status = "UNKNOWN_REASON"; if (reply_key) krb5_free_keyblock(kdc_context, reply_key); if (errcode) @@ -909,7 +895,8 @@ prepare_error_tgs (struct kdc_request_state *state, krb5_data *scratch, *e_data_asn1 = NULL, *fast_edata = NULL; kdc_realm_t *kdc_active_realm = state->realm_data; - errpkt.ctime = request->nonce; + errpkt.magic = KV5M_ERROR; + errpkt.ctime = 0; errpkt.cusec = 0; if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime, @@ -1052,7 +1039,7 @@ gen_session_key(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req, retval = get_2ndtkt_enctype(kdc_active_realm, req, &useenctype, status); if (retval != 0) - goto cleanup; + return retval; } if (useenctype == 0) { useenctype = select_session_keytype(kdc_active_realm, server, @@ -1062,17 +1049,10 @@ gen_session_key(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req, if (useenctype == 0) { /* unsupported ktype */ *status = "BAD_ENCRYPTION_TYPE"; - retval = KRB5KDC_ERR_ETYPE_NOSUPP; - goto cleanup; - } - retval = krb5_c_make_random_key(kdc_context, useenctype, skey); - if (retval != 0) { - /* random key failed */ - *status = "MAKE_RANDOM_KEY"; - goto cleanup; + return KRB5KDC_ERR_ETYPE_NOSUPP; } -cleanup: - return retval; + + return krb5_c_make_random_key(kdc_context, useenctype, skey); } /* diff --git a/src/kdc/extern.c b/src/kdc/extern.c index fe627494b8d3..84b5c6ad5d1c 100644 --- a/src/kdc/extern.c +++ b/src/kdc/extern.c @@ -37,6 +37,8 @@ kdc_realm_t **kdc_realmlist = (kdc_realm_t **) NULL; int kdc_numrealms = 0; krb5_data empty_string = {0, 0, ""}; -krb5_timestamp kdc_infinity = KRB5_INT32_MAX; /* XXX */ krb5_keyblock psr_key; krb5_int32 max_dgram_reply_size = MAX_DGRAM_SIZE; + +/* With ts_after(), this is the largest timestamp value. */ +krb5_timestamp kdc_infinity = -1; diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c index 9df940219cd8..e05107ef328d 100644 --- a/src/kdc/fast_util.c +++ b/src/kdc/fast_util.c @@ -607,7 +607,7 @@ kdc_fast_read_cookie(krb5_context context, struct kdc_request_state *state, ret = krb5_timeofday(context, &now); if (ret) goto cleanup; - if (now - COOKIE_LIFETIME > cookie->time) { + if (ts2tt(now) > cookie->time + COOKIE_LIFETIME) { /* Don't accept the cookie contents. Only return an error if the * cookie is relevant to the request. */ if (is_relevant(cookie->data, req->padata)) @@ -700,7 +700,7 @@ kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state, ret = krb5_timeofday(context, &now); if (ret) goto cleanup; - cookie.time = now; + cookie.time = ts2tt(now); cookie.data = contents; ret = encode_krb5_secure_cookie(&cookie, &der_cookie); if (ret) diff --git a/src/kdc/kdc_log.c b/src/kdc/kdc_log.c index 94a2a1c87c91..7e8733980a41 100644 --- a/src/kdc/kdc_log.c +++ b/src/kdc/kdc_log.c @@ -54,7 +54,9 @@ /* Someday, pass local address/port as well. */ /* Currently no info about name canonicalization is logged. */ void -log_as_req(krb5_context context, const krb5_fulladdr *from, +log_as_req(krb5_context context, + const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_db_entry *client, const char *cname, krb5_db_entry *server, const char *sname, @@ -67,8 +69,8 @@ log_as_req(krb5_context context, const krb5_fulladdr *from, const char *cname2 = cname ? cname : "<unknown client>"; const char *sname2 = sname ? sname : "<unknown server>"; - fromstring = inet_ntop(ADDRTYPE2FAMILY (from->address->addrtype), - from->address->contents, + fromstring = inet_ntop(ADDRTYPE2FAMILY(remote_addr->address->addrtype), + remote_addr->address->contents, fromstringbuf, sizeof(fromstringbuf)); if (!fromstring) fromstring = "<unknown>"; @@ -79,9 +81,9 @@ log_as_req(krb5_context context, const krb5_fulladdr *from, /* success */ char rep_etypestr[128]; rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); - krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %d, %s, " + krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %u, %s, " "%s for %s"), - ktypestr, fromstring, authtime, + ktypestr, fromstring, (unsigned int)authtime, rep_etypestr, cname2, sname2); } else { /* fail */ @@ -89,14 +91,15 @@ log_as_req(krb5_context context, const krb5_fulladdr *from, ktypestr, fromstring, status, cname2, sname2, emsg ? ", " : "", emsg ? emsg : ""); } - krb5_db_audit_as_req(context, request, client, server, authtime, - errcode); + krb5_db_audit_as_req(context, request, + local_addr->address, remote_addr->address, + client, server, authtime, errcode); #if 0 /* Sun (OpenSolaris) version would probably something like this. The client and server names passed can be null, unlike in the logging routines used above. Note that a struct in_addr is used, but the real address could be an IPv6 address. */ - audit_krb5kdc_as_req(some in_addr *, (in_port_t)from->port, 0, + audit_krb5kdc_as_req(some in_addr *, (in_port_t)remote_addr->port, 0, cname, sname, errcode); #endif } @@ -156,10 +159,10 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, name (useful), and doesn't log ktypestr (probably not important). */ if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) { - krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %d, %s%s " + krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %u, %s%s " "%s for %s%s%s"), - ktypestr, fromstring, status, authtime, rep_etypestr, - !errcode ? "," : "", logcname, logsname, + ktypestr, fromstring, status, (unsigned int)authtime, + rep_etypestr, !errcode ? "," : "", logcname, logsname, errcode ? ", " : "", errcode ? emsg : ""); if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) krb5_klog_syslog(LOG_INFO, @@ -171,9 +174,9 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, logaltcname); } else - krb5_klog_syslog(LOG_INFO, _("TGS_REQ %s: %s: authtime %d, %s for %s, " + krb5_klog_syslog(LOG_INFO, _("TGS_REQ %s: %s: authtime %u, %s for %s, " "2nd tkt client %s"), - fromstring, status, authtime, + fromstring, status, (unsigned int)authtime, logcname, logsname, logaltcname); /* OpenSolaris: audit_krb5kdc_tgs_req(...) or diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index 605fcb7addc6..81d0b8cffd39 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -568,8 +568,37 @@ set_cookie(krb5_context context, krb5_kdcpreauth_rock rock, return kdc_fast_set_cookie(rock->rstate, pa_type, data); } +static krb5_boolean +match_client(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_principal princ) +{ + krb5_db_entry *ent; + krb5_boolean match = FALSE; + krb5_principal req_client = rock->request->client; + krb5_principal client = rock->client->princ; + + /* Check for a direct match against the request principal or + * the post-canon client principal. */ + if (krb5_principal_compare_flags(context, princ, req_client, + KRB5_PRINCIPAL_COMPARE_ENTERPRISE) || + krb5_principal_compare(context, princ, client)) + return TRUE; + + if (krb5_db_get_principal(context, princ, KRB5_KDB_FLAG_ALIAS_OK, &ent)) + return FALSE; + match = krb5_principal_compare(context, ent->princ, client); + krb5_db_free_principal(context, ent); + return match; +} + +static krb5_principal +client_name(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return rock->client->princ; +} + static struct krb5_kdcpreauth_callbacks_st callbacks = { - 3, + 4, max_time_skew, client_keys, free_keys, @@ -583,7 +612,9 @@ static struct krb5_kdcpreauth_callbacks_st callbacks = { client_keyblock, add_auth_indicator, get_cookie, - set_cookie + set_cookie, + match_client, + client_name }; static krb5_error_code diff --git a/src/kdc/kdc_preauth_ec.c b/src/kdc/kdc_preauth_ec.c index feef3683141c..7e636b3f9fed 100644 --- a/src/kdc/kdc_preauth_ec.c +++ b/src/kdc/kdc_preauth_ec.c @@ -56,7 +56,6 @@ ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdcpreauth_verify_respond_fn respond, void *arg) { krb5_error_code retval = 0; - krb5_timestamp now; krb5_enc_data *enc = NULL; krb5_data scratch, plain; krb5_keyblock *armor_key = cb->fast_armor(context, rock); @@ -66,6 +65,8 @@ ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_keyblock *kdc_challenge_key; krb5_kdcpreauth_modreq modreq = NULL; int i = 0; + char *ai = NULL, *realmstr = NULL; + krb5_data realm = request->server->realm; plain.data = NULL; @@ -84,6 +85,15 @@ ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, if (plain.data == NULL) retval = ENOMEM; } + + /* Check for a configured FAST ec auth indicator. */ + realmstr = k5memdup0(realm.data, realm.length, &retval); + if (realmstr != NULL) + retval = profile_get_string(context->profile, KRB5_CONF_REALMS, + realmstr, + KRB5_CONF_ENCRYPTED_CHALLENGE_INDICATOR, + NULL, &ai); + if (retval == 0) retval = cb->client_keys(context, rock, &client_keys); if (retval == 0) { @@ -113,21 +123,20 @@ ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, if (retval == 0) retval = decode_krb5_pa_enc_ts(&plain, &ts); if (retval == 0) - retval = krb5_timeofday(context, &now); + retval = krb5_check_clockskew(context, ts->patimestamp); if (retval == 0) { - if (labs(now-ts->patimestamp) < context->clockskew) { - enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; - /* - * If this fails, we won't generate a reply to the client. That - * may cause the client to fail, but at this point the KDC has - * considered this a success, so the return value is ignored. - */ - if (krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor", - &client_keys[i], "challengelongterm", - &kdc_challenge_key) == 0) - modreq = (krb5_kdcpreauth_modreq)kdc_challenge_key; - } else { /*skew*/ - retval = KRB5KRB_AP_ERR_SKEW; + enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; + /* + * If this fails, we won't generate a reply to the client. That may + * cause the client to fail, but at this point the KDC has considered + * this a success, so the return value is ignored. + */ + if (krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor", + &client_keys[i], "challengelongterm", + &kdc_challenge_key) == 0) { + modreq = (krb5_kdcpreauth_modreq)kdc_challenge_key; + if (ai != NULL) + cb->add_auth_indicator(context, rock, ai); } } cb->free_keys(context, rock, client_keys); @@ -137,6 +146,8 @@ ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_free_enc_data(context, enc); if (ts) krb5_free_pa_enc_ts(context, ts); + free(realmstr); + free(ai); (*respond)(arg, retval, modreq, NULL, NULL); } diff --git a/src/kdc/kdc_preauth_encts.c b/src/kdc/kdc_preauth_encts.c index e80dc12a8cf3..25fc784576ef 100644 --- a/src/kdc/kdc_preauth_encts.c +++ b/src/kdc/kdc_preauth_encts.c @@ -58,7 +58,6 @@ enc_ts_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_keyblock key; krb5_key_data * client_key; krb5_int32 start; - krb5_timestamp timenow; scratch.data = (char *)pa->contents; scratch.length = pa->length; @@ -95,14 +94,10 @@ enc_ts_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, if ((retval = decode_krb5_pa_enc_ts(&enc_ts_data, &pa_enc)) != 0) goto cleanup; - if ((retval = krb5_timeofday(context, &timenow)) != 0) + retval = krb5_check_clockskew(context, pa_enc->patimestamp); + if (retval) goto cleanup; - if (labs(timenow - pa_enc->patimestamp) > context->clockskew) { - retval = KRB5KRB_AP_ERR_SKEW; - goto cleanup; - } - setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH); retval = 0; diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 29f9dbbf07eb..754570c01310 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -642,7 +642,6 @@ validate_as_request(kdc_realm_t *kdc_active_realm, krb5_db_entry server, krb5_timestamp kdc_time, const char **status, krb5_pa_data ***e_data) { - int errcode; krb5_error_code ret; /* @@ -654,7 +653,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm, } /* The client must not be expired */ - if (client.expiration && client.expiration < kdc_time) { + if (client.expiration && ts_after(kdc_time, client.expiration)) { *status = "CLIENT EXPIRED"; if (vague_errors) return(KRB_ERR_GENERIC); @@ -664,7 +663,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm, /* The client's password must not be expired, unless the server is a KRB5_KDC_PWCHANGE_SERVICE. */ - if (client.pw_expiration && client.pw_expiration < kdc_time && + if (client.pw_expiration && ts_after(kdc_time, client.pw_expiration) && !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) { *status = "CLIENT KEY EXPIRED"; if (vague_errors) @@ -674,7 +673,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm, } /* The server must not be expired */ - if (server.expiration && server.expiration < kdc_time) { + if (server.expiration && ts_after(kdc_time, server.expiration)) { *status = "SERVICE EXPIRED"; return(KDC_ERR_SERVICE_EXP); } @@ -750,12 +749,6 @@ validate_as_request(kdc_realm_t *kdc_active_realm, if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP) return errcode_to_protocol(ret); - /* Check against local policy. */ - errcode = against_local_policy_as(request, client, server, - kdc_time, status, e_data); - if (errcode) - return errcode; - return 0; } @@ -1220,8 +1213,10 @@ kdc_process_for_user(kdc_realm_t *kdc_active_realm, req_data.data = (char *)pa_data->contents; code = decode_krb5_pa_for_user(&req_data, &for_user); - if (code) + if (code) { + *status = "DECODE_PA_FOR_USER"; return code; + } code = verify_for_user_checksum(kdc_context, tgs_session, for_user); if (code) { @@ -1320,8 +1315,10 @@ kdc_process_s4u_x509_user(krb5_context context, req_data.data = (char *)pa_data->contents; code = decode_krb5_pa_s4u_x509_user(&req_data, s4u_x509_user); - if (code) + if (code) { + *status = "DECODE_PA_S4U_X509_USER"; return code; + } code = verify_s4u_x509_user_checksum(context, tgs_subkey ? tgs_subkey : @@ -1624,6 +1621,7 @@ kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm, * that is validated previously in validate_tgs_request(). */ if (request->kdc_options & (NON_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY)) { + *status = "INVALID_S4U2PROXY_OPTIONS"; return KRB5KDC_ERR_BADOPTION; } @@ -1631,6 +1629,7 @@ kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm, if (!krb5_principal_compare(kdc_context, server->princ, /* after canon */ server_princ)) { + *status = "EVIDENCE_TICKET_MISMATCH"; return KRB5KDC_ERR_SERVER_NOMATCH; } @@ -1760,14 +1759,19 @@ kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm, krb5_db_entry *server, krb5_timestamp *out_endtime) { - krb5_timestamp until, life; + krb5_timestamp until; + krb5_deltat life; if (till == 0) till = kdc_infinity; - until = min(till, endtime); + until = ts_min(till, endtime); - life = until - starttime; + /* Determine the requested lifetime, capped at the maximum valid time + * interval. */ + life = ts_delta(until, starttime); + if (ts_after(until, starttime) && life < 0) + life = INT32_MAX; if (client != NULL && client->max_life != 0) life = min(life, client->max_life); @@ -1776,7 +1780,7 @@ kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm, if (kdc_active_realm->realm_maxlife != 0) life = min(life, kdc_active_realm->realm_maxlife); - *out_endtime = starttime + life; + *out_endtime = ts_incr(starttime, life); } /* @@ -1791,6 +1795,7 @@ kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request, { krb5_timestamp rtime, max_rlife; + clear(tkt->flags, TKT_FLG_RENEWABLE); tkt->times.renew_till = 0; /* Don't issue renewable tickets if the client or server don't allow it, @@ -1806,25 +1811,27 @@ kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request, if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) rtime = request->rtime ? request->rtime : kdc_infinity; else if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) && - tkt->times.endtime < request->till) + ts_after(request->till, tkt->times.endtime)) rtime = request->till; else return; /* Truncate it to the allowable renewable time. */ if (tgt != NULL) - rtime = min(rtime, tgt->times.renew_till); + rtime = ts_min(rtime, tgt->times.renew_till); max_rlife = min(server->max_renewable_life, realm->realm_maxrlife); if (client != NULL) max_rlife = min(max_rlife, client->max_renewable_life); - rtime = min(rtime, tkt->times.starttime + max_rlife); + rtime = ts_min(rtime, ts_incr(tkt->times.starttime, max_rlife)); - /* Make the ticket renewable if the truncated requested time is larger than - * the ticket end time. */ - if (rtime > tkt->times.endtime) { - setflag(tkt->flags, TKT_FLG_RENEWABLE); - tkt->times.renew_till = rtime; - } + /* If the client only specified renewable-ok, don't issue a renewable + * ticket unless the truncated renew time exceeds the ticket end time. */ + if (!isflagset(request->kdc_options, KDC_OPT_RENEWABLE) && + !ts_after(rtime, tkt->times.endtime)) + return; + + setflag(tkt->flags, TKT_FLG_RENEWABLE); + tkt->times.renew_till = rtime; } /** diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index bcf05fc2779f..f99efcf505d1 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -140,7 +140,7 @@ cammac_check_kdcver(krb5_context context, krb5_cammac *cammac, /* do_as_req.c */ void process_as_req (krb5_kdc_req *, krb5_data *, - const krb5_fulladdr *, kdc_realm_t *, + const krb5_fulladdr *, const krb5_fulladdr *, kdc_realm_t *, verto_ctx *, loop_respond_fn, void *); /* do_tgs_req.c */ @@ -151,7 +151,7 @@ process_tgs_req (struct server_handle *, krb5_data *, /* dispatch.c */ void dispatch (void *, - struct sockaddr *, + const krb5_fulladdr *, const krb5_fulladdr *, krb5_data *, int, @@ -166,17 +166,6 @@ kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...) #endif ; -/* policy.c */ -int -against_local_policy_as (krb5_kdc_req *, krb5_db_entry, - krb5_db_entry, krb5_timestamp, - const char **, krb5_pa_data ***); - -int -against_local_policy_tgs (krb5_kdc_req *, krb5_db_entry, - krb5_ticket *, const char **, - krb5_pa_data ***); - /* kdc_preauth.c */ krb5_boolean enctype_requires_etype_info_2(krb5_enctype enctype); @@ -346,7 +335,9 @@ kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request, krb5_db_entry *server, krb5_enc_tkt_part *tkt); void -log_as_req(krb5_context context, const krb5_fulladdr *from, +log_as_req(krb5_context context, + const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_db_entry *client, const char *cname, krb5_db_entry *server, const char *sname, @@ -452,6 +443,8 @@ struct krb5_kdcpreauth_rock_st { #define max(a, b) ((a) > (b) ? (a) : (b)) #endif +#define ts_min(a, b) (ts_after(a, b) ? (b) : (a)) + #define ADDRTYPE2FAMILY(X) \ ((X) == ADDRTYPE_INET6 ? AF_INET6 : (X) == ADDRTYPE_INET ? AF_INET : -1) diff --git a/src/kdc/main.c b/src/kdc/main.c index ebc852bba2e9..f2226da2597f 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -31,6 +31,7 @@ #include "kdc_util.h" #include "kdc_audit.h" #include "extern.h" +#include "policy.h" #include "kdc5_err.h" #include "kdb_kt.h" #include "net-server.h" @@ -986,6 +987,12 @@ int main(int argc, char **argv) load_preauth_plugins(&shandle, kcontext, ctx); load_authdata_plugins(kcontext); + retval = load_kdcpolicy_plugins(kcontext); + if (retval) { + kdc_err(kcontext, retval, _("while loading KDC policy plugin")); + finish_realms(); + return 1; + } retval = setup_sam(); if (retval) { @@ -1068,6 +1075,7 @@ int main(int argc, char **argv) krb5_klog_syslog(LOG_INFO, _("shutting down")); unload_preauth_plugins(kcontext); unload_authdata_plugins(kcontext); + unload_kdcpolicy_plugins(kcontext); unload_audit_modules(kcontext); krb5_klog_close(kcontext); finish_realms(); diff --git a/src/kdc/policy.c b/src/kdc/policy.c index 6cba4303f81d..26c16f97cb53 100644 --- a/src/kdc/policy.c +++ b/src/kdc/policy.c @@ -1,67 +1,246 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* kdc/policy.c - Policy decision routines for KDC */ /* - * Copyright 1990 by the Massachusetts Institute of Technology. + * Copyright (C) 2017 by Red Hat, Inc. + * All rights reserved. * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. + * * 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. */ #include "k5-int.h" #include "kdc_util.h" #include "extern.h" +#include "policy.h" +#include "adm_proto.h" +#include <krb5/kdcpolicy_plugin.h> +#include <syslog.h> + +typedef struct kdcpolicy_handle_st { + struct krb5_kdcpolicy_vtable_st vt; + krb5_kdcpolicy_moddata moddata; +} *kdcpolicy_handle; + +static kdcpolicy_handle *handles; + +static void +free_indicators(char **ais) +{ + size_t i; -int -against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client, - krb5_db_entry server, krb5_timestamp kdc_time, - const char **status, krb5_pa_data ***e_data) + if (ais == NULL) + return; + for (i = 0; ais[i] != NULL; i++) + free(ais[i]); + free(ais); +} + +/* Convert inds to a null-terminated list of C strings. */ +static krb5_error_code +authind_strings(krb5_data *const *inds, char ***strs_out) { -#if 0 - /* An AS request must include the addresses field */ - if (request->addresses == 0) { - *status = "NO ADDRESS"; - return KRB5KDC_ERR_POLICY; + krb5_error_code ret; + char **list = NULL; + size_t i, count; + + *strs_out = NULL; + + for (count = 0; inds != NULL && inds[count] != NULL; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + goto error; + + for (i = 0; i < count; i++) { + list[i] = k5memdup0(inds[i]->data, inds[i]->length, &ret); + if (list[i] == NULL) + goto error; } -#endif - return 0; /* not against policy */ + *strs_out = list; + return 0; + +error: + free_indicators(list); + return ret; +} + +/* Constrain times->endtime to life and times->renew_till to rlife, relative to + * now. */ +static void +update_ticket_times(krb5_ticket_times *times, krb5_timestamp now, + krb5_deltat life, krb5_deltat rlife) +{ + if (life) + times->endtime = ts_min(ts_incr(now, life), times->endtime); + if (rlife) + times->renew_till = ts_min(ts_incr(now, rlife), times->renew_till); +} + +/* Check an AS request against kdcpolicy modules, updating times with any + * module endtime constraints. Set an appropriate status string on error. */ +krb5_error_code +check_kdcpolicy_as(krb5_context context, const krb5_kdc_req *request, + const krb5_db_entry *client, const krb5_db_entry *server, + krb5_data *const *auth_indicators, krb5_timestamp kdc_time, + krb5_ticket_times *times, const char **status) +{ + krb5_deltat life, rlife; + krb5_error_code ret; + kdcpolicy_handle *hp, h; + char **ais = NULL; + + *status = NULL; + + ret = authind_strings(auth_indicators, &ais); + if (ret) + goto done; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.check_as == NULL) + continue; + + ret = h->vt.check_as(context, h->moddata, request, client, server, + (const char **)ais, status, &life, &rlife); + if (ret) + goto done; + + update_ticket_times(times, kdc_time, life, rlife); + } + +done: + free_indicators(ais); + return ret; } /* - * This is where local policy restrictions for the TGS should placed. + * Check the TGS request against the local TGS policy. Accepts an + * authentication indicator for the module policy decisions. Returns 0 and a + * NULL status string on success. */ krb5_error_code -against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server, - krb5_ticket *ticket, const char **status, - krb5_pa_data ***e_data) +check_kdcpolicy_tgs(krb5_context context, const krb5_kdc_req *request, + const krb5_db_entry *server, const krb5_ticket *ticket, + krb5_data *const *auth_indicators, krb5_timestamp kdc_time, + krb5_ticket_times *times, const char **status) { -#if 0 - /* - * For example, if your site wants to disallow ticket forwarding, - * you might do something like this: - */ - - if (isflagset(request->kdc_options, KDC_OPT_FORWARDED)) { - *status = "FORWARD POLICY"; - return KRB5KDC_ERR_POLICY; + krb5_deltat life, rlife; + krb5_error_code ret; + kdcpolicy_handle *hp, h; + char **ais = NULL; + + *status = NULL; + + ret = authind_strings(auth_indicators, &ais); + if (ret) + goto done; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.check_tgs == NULL) + continue; + + ret = h->vt.check_tgs(context, h->moddata, request, server, ticket, + (const char **)ais, status, &life, &rlife); + if (ret) + goto done; + + update_ticket_times(times, kdc_time, life, rlife); } -#endif - return 0; /* not against policy */ +done: + free_indicators(ais); + return ret; +} + +void +unload_kdcpolicy_plugins(krb5_context context) +{ + kdcpolicy_handle *hp, h; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.fini != NULL) + h->vt.fini(context, h->moddata); + free(h); + } + free(handles); + handles = NULL; +} + +krb5_error_code +load_kdcpolicy_plugins(krb5_context context) +{ + krb5_error_code ret; + krb5_plugin_initvt_fn *modules = NULL, *mod; + kdcpolicy_handle h; + size_t count; + + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KDCPOLICY, &modules); + if (ret) + goto cleanup; + + for (count = 0; modules[count] != NULL; count++); + handles = k5calloc(count + 1, sizeof(*handles), &ret); + if (handles == NULL) + goto cleanup; + + count = 0; + for (mod = modules; *mod != NULL; mod++) { + h = k5calloc(1, sizeof(*h), &ret); + if (h == NULL) + goto cleanup; + + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt); + if (ret) { /* Version mismatch. */ + TRACE_KDCPOLICY_VTINIT_FAIL(context, ret); + free(h); + continue; + } + if (h->vt.init != NULL) { + ret = h->vt.init(context, &h->moddata); + if (ret == KRB5_PLUGIN_NO_HANDLE) { + TRACE_KDCPOLICY_INIT_SKIP(context, h->vt.name); + free(h); + continue; + } + if (ret) { + kdc_err(context, ret, _("while loading policy module %s"), + h->vt.name); + free(h); + goto cleanup; + } + } + handles[count++] = h; + } + + ret = 0; + +cleanup: + if (ret) + unload_kdcpolicy_plugins(context); + k5_plugin_free_modules(context, modules); + return ret; } diff --git a/src/kdc/policy.h b/src/kdc/policy.h index 6b000dc90346..2a57b0a01683 100644 --- a/src/kdc/policy.h +++ b/src/kdc/policy.h @@ -26,11 +26,22 @@ #ifndef __KRB5_KDC_POLICY__ #define __KRB5_KDC_POLICY__ -extern int against_postdate_policy (krb5_timestamp); +krb5_error_code +load_kdcpolicy_plugins(krb5_context context); -extern int against_flag_policy_as (const krb5_kdc_req *); +void +unload_kdcpolicy_plugins(krb5_context context); -extern int against_flag_policy_tgs (const krb5_kdc_req *, - const krb5_ticket *); +krb5_error_code +check_kdcpolicy_as(krb5_context context, const krb5_kdc_req *request, + const krb5_db_entry *client, const krb5_db_entry *server, + krb5_data *const *auth_indicators, krb5_timestamp kdc_time, + krb5_ticket_times *times, const char **status); + +krb5_error_code +check_kdcpolicy_tgs(krb5_context context, const krb5_kdc_req *request, + const krb5_db_entry *server, const krb5_ticket *ticket, + krb5_data *const *auth_indicators, krb5_timestamp kdc_time, + krb5_ticket_times *times, const char **status); #endif /* __KRB5_KDC_POLICY__ */ diff --git a/src/kdc/replay.c b/src/kdc/replay.c index 8da7ac19aef3..caca783bf1ab 100644 --- a/src/kdc/replay.c +++ b/src/kdc/replay.c @@ -61,7 +61,7 @@ static size_t total_size = 0; static krb5_ui_4 seed; #define STALE_TIME (2*60) /* two minutes */ -#define STALE(ptr, now) (abs((ptr)->timein - (now)) >= STALE_TIME) +#define STALE(ptr, now) (ts_after(now, ts_incr((ptr)->timein, STALE_TIME))) /* Return x rotated to the left by r bits. */ static inline krb5_ui_4 diff --git a/src/kdc/t_emptytgt.py b/src/kdc/t_emptytgt.py index 8f7717a011c2..2d0432e338ac 100755 --- a/src/kdc/t_emptytgt.py +++ b/src/kdc/t_emptytgt.py @@ -2,7 +2,6 @@ from k5test import * realm = K5Realm(create_host=False) -output = realm.run([kvno, 'krbtgt/'], expected_code=1) -if 'not found in Kerberos database' not in output: - fail('TGT lookup for empty realm failed in unexpected way') +realm.run([kvno, 'krbtgt/'], expected_code=1, + expected_msg='not found in Kerberos database') success('Empty tgt lookup.') diff --git a/src/kdc/t_replay.c b/src/kdc/t_replay.c index 1442e0e8ceee..00bb39012680 100644 --- a/src/kdc/t_replay.c +++ b/src/kdc/t_replay.c @@ -36,10 +36,7 @@ #ifndef NOCACHE -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <cmocka.h> +#include "k5-cmocka.h" /* For wrapping functions */ #include "k5-int.h" @@ -623,6 +620,8 @@ test_kdc_check_lookaside_hit(void **state) assert_true(data_eq(rep, *result_data)); assert_int_equal(hits, 1); assert_int_equal(e->num_hits, 1); + + krb5_free_data(context, result_data); } static void @@ -700,6 +699,8 @@ test_kdc_check_lookaside_hit_multiple(void **state) assert_int_equal(e1->num_hits, 1); assert_int_equal(e2->num_hits, 0); + krb5_free_data(context, result_data); + /* Set result_data so we can verify that it is reset to NULL. */ result_data = &req1; result = kdc_check_lookaside(context, &req2, &result_data); @@ -733,6 +734,8 @@ test_kdc_check_lookaside_hit_hash_collision(void **state) assert_int_equal(e1->num_hits, 1); assert_int_equal(e2->num_hits, 0); + krb5_free_data(context, result_data); + /* Set result_data so we can verify that it is reset to NULL. */ result_data = &req1; result = kdc_check_lookaside(context, &req2, &result_data); @@ -903,7 +906,7 @@ test_kdc_insert_lookaside_cache_expire(void **state) assert_non_null(e); e->num_hits = 5; - time_return(STALE_TIME, 0); + time_return(STALE_TIME + 1, 0); kdc_insert_lookaside(context, &req2, NULL); assert_null(K5_LIST_FIRST(&hash_table[req_hash1])); diff --git a/src/kdc/tgs_policy.c b/src/kdc/tgs_policy.c index a30cacc665a1..33cfbcd8184f 100644 --- a/src/kdc/tgs_policy.c +++ b/src/kdc/tgs_policy.c @@ -186,7 +186,7 @@ static int check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry server, krb5_ticket *tkt, krb5_timestamp kdc_time, const char **status) { - if (server.expiration && server.expiration < kdc_time) { + if (server.expiration && ts_after(kdc_time, server.expiration)) { *status = "SERVICE EXPIRED"; return KDC_ERR_SERVICE_EXP; } @@ -222,7 +222,7 @@ check_tgs_times(krb5_kdc_req *req, krb5_ticket_times *times, KDC time. */ if (req->kdc_options & KDC_OPT_VALIDATE) { starttime = times->starttime ? times->starttime : times->authtime; - if (starttime > kdc_time) { + if (ts_after(starttime, kdc_time)) { *status = "NOT_YET_VALID"; return KRB_AP_ERR_TKT_NYV; } @@ -231,7 +231,8 @@ check_tgs_times(krb5_kdc_req *req, krb5_ticket_times *times, * Check the renew_till time. The endtime was already * been checked in the initial authentication check. */ - if ((req->kdc_options & KDC_OPT_RENEW) && times->renew_till < kdc_time) { + if ((req->kdc_options & KDC_OPT_RENEW) && + ts_after(kdc_time, times->renew_till)) { *status = "TKT_EXPIRED"; return KRB_AP_ERR_TKT_EXPIRED; } @@ -374,11 +375,5 @@ validate_tgs_request(kdc_realm_t *kdc_active_realm, if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP) return errcode_to_protocol(ret); - /* Check local policy. */ - errcode = against_local_policy_tgs(request, server, ticket, - status, e_data); - if (errcode) - return errcode; - return 0; } diff --git a/src/lib/apputils/net-server.c b/src/lib/apputils/net-server.c index 29ec84a15b22..a40da927ef16 100644 --- a/src/lib/apputils/net-server.c +++ b/src/lib/apputils/net-server.c @@ -105,17 +105,6 @@ paddr(struct sockaddr *sa) return buf; } -/* Return true if sa is an IPv4 or IPv6 wildcard address. */ -static int -is_wildcard(struct sockaddr *sa) -{ - if (sa->sa_family == AF_INET6) - return IN6_IS_ADDR_UNSPECIFIED(&sa2sin6(sa)->sin6_addr); - else if (sa->sa_family == AF_INET) - return sa2sin(sa)->sin_addr.s_addr == INADDR_ANY; - return 0; -} - /* KDC data. */ enum conn_type { @@ -142,8 +131,8 @@ struct connection { struct sockaddr_storage addr_s; socklen_t addrlen; char addrbuf[56]; - krb5_fulladdr faddr; - krb5_address kaddr; + krb5_address remote_addr_buf; + krb5_fulladdr remote_addr; /* Incoming data (TCP) */ size_t bufsiz; @@ -451,14 +440,6 @@ loop_add_rpc_service(int default_port, const char *addresses, u_long prognum, #define SOCKET_ERRNO errno #include "foreachaddr.h" -struct socksetup { - verto_ctx *ctx; - void *handle; - const char *prog; - krb5_error_code retval; - int listen_backlog; -}; - static void free_connection(struct connection *conn) { @@ -533,7 +514,7 @@ free_socket(verto_ctx *ctx, verto_ev *ev) static verto_ev * make_event(verto_ctx *ctx, verto_ev_flag flags, verto_callback callback, - int sock, struct connection *conn, int addevent) + int sock, struct connection *conn) { verto_ev *ev; void *tmp; @@ -544,45 +525,44 @@ make_event(verto_ctx *ctx, verto_ev_flag flags, verto_callback callback, return NULL; } - if (addevent) { - if (!ADD(events, ev, tmp)) { - com_err(conn->prog, ENOMEM, _("cannot save event")); - verto_del(ev); - return NULL; - } + if (!ADD(events, ev, tmp)) { + com_err(conn->prog, ENOMEM, _("cannot save event")); + verto_del(ev); + return NULL; } verto_set_private(ev, conn, free_socket); return ev; } -static verto_ev * -add_fd(struct socksetup *data, int sock, enum conn_type conntype, - verto_ev_flag flags, verto_callback callback, int addevent) +static krb5_error_code +add_fd(int sock, enum conn_type conntype, verto_ev_flag flags, void *handle, + const char *prog, verto_ctx *ctx, verto_callback callback, + verto_ev **ev_out) { struct connection *newconn; + *ev_out = NULL; + #ifndef _WIN32 if (sock >= FD_SETSIZE) { - data->retval = EMFILE; /* XXX */ - com_err(data->prog, 0, - _("file descriptor number %d too high"), sock); - return 0; + com_err(prog, 0, _("file descriptor number %d too high"), sock); + return EMFILE; } #endif newconn = malloc(sizeof(*newconn)); if (newconn == NULL) { - data->retval = ENOMEM; - com_err(data->prog, ENOMEM, + com_err(prog, ENOMEM, _("cannot allocate storage for connection info")); - return 0; + return ENOMEM; } memset(newconn, 0, sizeof(*newconn)); - newconn->handle = data->handle; - newconn->prog = data->prog; + newconn->handle = handle; + newconn->prog = prog; newconn->type = conntype; - return make_event(data->ctx, flags, callback, sock, newconn, addevent); + *ev_out = make_event(ctx, flags, callback, sock, newconn); + return 0; } static void process_packet(verto_ctx *ctx, verto_ev *ev); @@ -592,77 +572,62 @@ static void process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev); static void accept_rpc_connection(verto_ctx *ctx, verto_ev *ev); static void process_rpc_connection(verto_ctx *ctx, verto_ev *ev); -static verto_ev * -add_tcp_read_fd(struct socksetup *data, int sock) -{ - return add_fd(data, sock, CONN_TCP, - VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST, - process_tcp_connection_read, 1); -} - /* * Create a socket and bind it to addr. Ensure the socket will work with * select(). Set the socket cloexec, reuseaddr, and if applicable v6-only. - * Does not call listen(). Returns -1 on failure after logging an error. + * Does not call listen(). On failure, log an error and return an error code. */ -static int -create_server_socket(struct socksetup *data, struct sockaddr *addr, int type) +static krb5_error_code +create_server_socket(struct sockaddr *addr, int type, const char *prog, + int *fd_out) { - int sock; + int sock, e; + + *fd_out = -1; sock = socket(addr->sa_family, type, 0); if (sock == -1) { - data->retval = errno; - com_err(data->prog, errno, _("Cannot create TCP server socket on %s"), + e = errno; + com_err(prog, e, _("Cannot create TCP server socket on %s"), paddr(addr)); - return -1; + return e; } set_cloexec_fd(sock); #ifndef _WIN32 /* Windows FD_SETSIZE is a count. */ if (sock >= FD_SETSIZE) { close(sock); - com_err(data->prog, 0, _("TCP socket fd number %d (for %s) too high"), + com_err(prog, 0, _("TCP socket fd number %d (for %s) too high"), sock, paddr(addr)); - return -1; + return EMFILE; } #endif - if (setreuseaddr(sock, 1) < 0) { - com_err(data->prog, errno, - _("Cannot enable SO_REUSEADDR on fd %d"), sock); - } + if (setreuseaddr(sock, 1) < 0) + com_err(prog, errno, _("Cannot enable SO_REUSEADDR on fd %d"), sock); if (addr->sa_family == AF_INET6) { #ifdef IPV6_V6ONLY - if (setv6only(sock, 1)) - com_err(data->prog, errno, - _("setsockopt(%d,IPV6_V6ONLY,1) failed"), sock); - else - com_err(data->prog, 0, _("setsockopt(%d,IPV6_V6ONLY,1) worked"), + if (setv6only(sock, 1)) { + com_err(prog, errno, _("setsockopt(%d,IPV6_V6ONLY,1) failed"), sock); + } else { + com_err(prog, 0, _("setsockopt(%d,IPV6_V6ONLY,1) worked"), sock); + } #else krb5_klog_syslog(LOG_INFO, _("no IPV6_V6ONLY socket option support")); #endif /* IPV6_V6ONLY */ } if (bind(sock, addr, sa_socklen(addr)) == -1) { - data->retval = errno; - com_err(data->prog, errno, _("Cannot bind server socket on %s"), - paddr(addr)); + e = errno; + com_err(prog, e, _("Cannot bind server socket on %s"), paddr(addr)); close(sock); - return -1; + return e; } - return sock; -} - -static verto_ev * -add_rpc_data_fd(struct socksetup *data, int sock) -{ - return add_fd(data, sock, CONN_RPC, - VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST, - process_rpc_connection, 1); + *fd_out = sock; + return 0; } static const int one = 1; @@ -716,12 +681,13 @@ static const enum conn_type bind_conn_types[] = * The conn_type of this socket. */ static krb5_error_code -setup_socket(struct socksetup *data, struct bind_address *ba, - struct sockaddr *sock_address, verto_callback vcb, - enum conn_type ctype) +setup_socket(struct bind_address *ba, struct sockaddr *sock_address, + void *handle, const char *prog, verto_ctx *ctx, + int tcp_listen_backlog, verto_callback vcb, enum conn_type ctype) { krb5_error_code ret; struct connection *conn; + verto_ev_flag flags; verto_ev *ev = NULL; int sock = -1; @@ -729,18 +695,16 @@ setup_socket(struct socksetup *data, struct bind_address *ba, bind_type_names[ba->type], paddr(sock_address)); /* Create the socket. */ - sock = create_server_socket(data, sock_address, bind_socktypes[ba->type]); - if (sock == -1) { - ret = data->retval; + ret = create_server_socket(sock_address, bind_socktypes[ba->type], prog, + &sock); + if (ret) goto cleanup; - } /* Listen for backlogged connections on TCP sockets. (For RPC sockets this * will be done by svc_register().) */ - if (ba->type == TCP && listen(sock, data->listen_backlog) != 0) { + if (ba->type == TCP && listen(sock, tcp_listen_backlog) != 0) { ret = errno; - com_err(data->prog, errno, - _("Cannot listen on %s server socket on %s"), + com_err(prog, errno, _("Cannot listen on %s server socket on %s"), bind_type_names[ba->type], paddr(sock_address)); goto cleanup; } @@ -748,7 +712,7 @@ setup_socket(struct socksetup *data, struct bind_address *ba, /* Set non-blocking I/O for UDP and TCP listener sockets. */ if (ba->type != RPC && setnbio(sock) != 0) { ret = errno; - com_err(data->prog, errno, + com_err(prog, errno, _("cannot set listening %s socket on %s non-blocking"), bind_type_names[ba->type], paddr(sock_address)); goto cleanup; @@ -757,19 +721,18 @@ setup_socket(struct socksetup *data, struct bind_address *ba, /* Turn off the linger option for TCP sockets. */ if (ba->type == TCP && setnolinger(sock) != 0) { ret = errno; - com_err(data->prog, errno, - _("cannot set SO_LINGER on %s socket on %s"), + com_err(prog, errno, _("cannot set SO_LINGER on %s socket on %s"), bind_type_names[ba->type], paddr(sock_address)); goto cleanup; } /* Try to turn on pktinfo for UDP wildcard sockets. */ - if (ba->type == UDP && is_wildcard(sock_address)) { + if (ba->type == UDP && sa_is_wildcard(sock_address)) { krb5_klog_syslog(LOG_DEBUG, _("Setting pktinfo on socket %s"), paddr(sock_address)); ret = set_pktinfo(sock, sock_address->sa_family); if (ret) { - com_err(data->prog, ret, + com_err(prog, ret, _("Cannot request packet info for UDP socket address " "%s port %d"), paddr(sock_address), ba->port); krb5_klog_syslog(LOG_INFO, _("System does not support pktinfo yet " @@ -780,13 +743,11 @@ setup_socket(struct socksetup *data, struct bind_address *ba, } /* Add the socket to the event loop. */ - ev = add_fd(data, sock, ctype, - VERTO_EV_FLAG_IO_READ | - VERTO_EV_FLAG_PERSIST | - VERTO_EV_FLAG_REINITIABLE, vcb, 1); - if (ev == NULL) { + flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST | + VERTO_EV_FLAG_REINITIABLE; + ret = add_fd(sock, ctype, flags, handle, prog, ctx, vcb, &ev); + if (ret) { krb5_klog_syslog(LOG_ERR, _("Error attempting to add verto event")); - ret = data->retval; goto cleanup; } @@ -829,13 +790,10 @@ cleanup: * This function uses getaddrinfo to figure out all the addresses. This will * automatically figure out which socket families that should be used on the * host making it useful even for wildcard addresses. - * - * Arguments: - * - data - * A pointer to the socksetup data. */ static krb5_error_code -setup_addresses(struct socksetup *data) +setup_addresses(verto_ctx *ctx, void *handle, const char *prog, + int tcp_listen_backlog) { /* An bind_type enum map for the verto callback functions. */ static verto_callback *const verto_callbacks[] = { @@ -896,8 +854,8 @@ setup_addresses(struct socksetup *data) /* Set the real port number. */ sa_setport(ai->ai_addr, addr.port); - ret = setup_socket(data, &addr, ai->ai_addr, - verto_callbacks[addr.type], + ret = setup_socket(&addr, ai->ai_addr, handle, prog, ctx, + tcp_listen_backlog, verto_callbacks[addr.type], bind_conn_types[addr.type]); if (ret) { krb5_klog_syslog(LOG_ERR, @@ -929,9 +887,9 @@ krb5_error_code loop_setup_network(verto_ctx *ctx, void *handle, const char *prog, int tcp_listen_backlog) { - struct socksetup setup_data; + krb5_error_code ret; verto_ev *ev; - int i, ret; + int i; /* Check to make sure that at least one address was added to the loop. */ if (bind_addresses.n == 0) @@ -942,15 +900,9 @@ loop_setup_network(verto_ctx *ctx, void *handle, const char *prog, verto_del(ev); events.n = 0; - setup_data.ctx = ctx; - setup_data.handle = handle; - setup_data.prog = prog; - setup_data.retval = 0; - setup_data.listen_backlog = tcp_listen_backlog; - krb5_klog_syslog(LOG_INFO, _("setting up network...")); - ret = setup_addresses(&setup_data); - if (ret != 0) { + ret = setup_addresses(ctx, handle, prog, tcp_listen_backlog); + if (ret) { com_err(prog, ret, _("Error setting up network")); exit(1); } @@ -999,8 +951,10 @@ struct udp_dispatch_state { void *handle; const char *prog; int port_fd; - krb5_address addr; - krb5_fulladdr faddr; + krb5_address remote_addr_buf; + krb5_fulladdr remote_addr; + krb5_address local_addr_buf; + krb5_fulladdr local_addr; socklen_t saddr_len; socklen_t daddr_len; struct sockaddr_storage saddr; @@ -1132,10 +1086,15 @@ process_packet(verto_ctx *ctx, verto_ev *ev) state->request.length = cc; state->request.data = state->pktbuf; - state->faddr.address = &state->addr; - init_addr(&state->faddr, ss2sa(&state->saddr)); + + state->remote_addr.address = &state->remote_addr_buf; + init_addr(&state->remote_addr, ss2sa(&state->saddr)); + + state->local_addr.address = &state->local_addr_buf; + init_addr(&state->local_addr, ss2sa(&state->daddr)); + /* This address is in net order. */ - dispatch(state->handle, ss2sa(&state->daddr), &state->faddr, + dispatch(state->handle, &state->local_addr, &state->remote_addr, &state->request, 0, ctx, process_packet_response, state); } @@ -1186,9 +1145,9 @@ accept_tcp_connection(verto_ctx *ctx, verto_ev *ev) struct sockaddr_storage addr_s; struct sockaddr *addr = (struct sockaddr *)&addr_s; socklen_t addrlen = sizeof(addr_s); - struct socksetup sockdata; struct connection *newconn, *conn; char tmpbuf[10]; + verto_ev_flag flags; verto_ev *newev; conn = verto_get_private(ev); @@ -1204,13 +1163,9 @@ accept_tcp_connection(verto_ctx *ctx, verto_ev *ev) #endif setnbio(s), setnolinger(s), setkeepalive(s); - sockdata.ctx = ctx; - sockdata.handle = conn->handle; - sockdata.prog = conn->prog; - sockdata.retval = 0; - - newev = add_tcp_read_fd(&sockdata, s); - if (newev == NULL) { + flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST; + if (add_fd(s, CONN_TCP, flags, conn->handle, conn->prog, ctx, + process_tcp_connection_read, &newev) != 0) { close(s); return; } @@ -1253,14 +1208,16 @@ accept_tcp_connection(verto_ctx *ctx, verto_ev *ev) return; } newconn->offset = 0; - newconn->faddr.address = &newconn->kaddr; - init_addr(&newconn->faddr, ss2sa(&newconn->addr_s)); + newconn->remote_addr.address = &newconn->remote_addr_buf; + init_addr(&newconn->remote_addr, ss2sa(&newconn->addr_s)); SG_SET(&newconn->sgbuf[0], newconn->lenbuf, 4); SG_SET(&newconn->sgbuf[1], 0, 0); } struct tcp_dispatch_state { struct sockaddr_storage local_saddr; + krb5_address local_addr_buf; + krb5_fulladdr local_addr; struct connection *conn; krb5_data request; verto_ctx *ctx; @@ -1288,7 +1245,7 @@ process_tcp_response(void *arg, krb5_error_code code, krb5_data *response) state->conn->sgnum = 2; ev = make_event(state->ctx, VERTO_EV_FLAG_IO_WRITE | VERTO_EV_FLAG_PERSIST, - process_tcp_connection_write, state->sock, state->conn, 1); + process_tcp_connection_write, state->sock, state->conn); if (ev) { free(state); return; @@ -1381,7 +1338,6 @@ process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev) } else { /* msglen known. */ socklen_t local_saddrlen = sizeof(struct sockaddr_storage); - struct sockaddr *local_saddrp = NULL; len = conn->msglen - (conn->offset - 4); nread = SOCKET_READ(verto_get_fd(ev), @@ -1403,10 +1359,14 @@ process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev) state->request.data = conn->buffer + 4; if (getsockname(verto_get_fd(ev), ss2sa(&state->local_saddr), - &local_saddrlen) == 0) - local_saddrp = ss2sa(&state->local_saddr); - - dispatch(state->conn->handle, local_saddrp, &conn->faddr, + &local_saddrlen) < 0) { + krb5_klog_syslog(LOG_ERR, _("getsockname failed: %s"), + error_message(errno)); + goto kill_tcp_connection; + } + state->local_addr.address = &state->local_addr_buf; + init_addr(&state->local_addr, ss2sa(&state->local_saddr)); + dispatch(state->conn->handle, &state->local_addr, &conn->remote_addr, &state->request, 1, ctx, process_tcp_response, state); } @@ -1489,18 +1449,13 @@ have_event_for_fd(int fd) static void accept_rpc_connection(verto_ctx *ctx, verto_ev *ev) { - struct socksetup sockdata; + verto_ev_flag flags; struct connection *conn; fd_set fds; register int s; conn = verto_get_private(ev); - sockdata.ctx = ctx; - sockdata.handle = conn->handle; - sockdata.prog = conn->prog; - sockdata.retval = 0; - /* Service the woken RPC listener descriptor. */ FD_ZERO(&fds); FD_SET(verto_get_fd(ev), &fds); @@ -1519,8 +1474,9 @@ accept_rpc_connection(verto_ctx *ctx, verto_ev *ev) if (!FD_ISSET(s, &svc_fdset) || have_event_for_fd(s)) continue; - newev = add_rpc_data_fd(&sockdata, s); - if (newev == NULL) + flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST; + if (add_fd(s, CONN_RPC, flags, conn->handle, conn->prog, ctx, + process_rpc_connection, &newev) != 0) continue; newconn = verto_get_private(newev); @@ -1559,8 +1515,8 @@ accept_rpc_connection(verto_ctx *ctx, verto_ev *ev) if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections) kill_lru_tcp_or_rpc_connection(newconn->handle, newev); - newconn->faddr.address = &newconn->kaddr; - init_addr(&newconn->faddr, ss2sa(&newconn->addr_s)); + newconn->remote_addr.address = &newconn->remote_addr_buf; + init_addr(&newconn->remote_addr, ss2sa(&newconn->addr_s)); } } diff --git a/src/lib/apputils/udppktinfo.c b/src/lib/apputils/udppktinfo.c index bc7ad09b070c..c096c12b7e61 100644 --- a/src/lib/apputils/udppktinfo.c +++ b/src/lib/apputils/udppktinfo.c @@ -141,19 +141,17 @@ is_socket_bound_to_wildcard(int sock) { struct sockaddr_storage bound_addr; socklen_t bound_addr_len = sizeof(bound_addr); + struct sockaddr *sa = ss2sa(&bound_addr); - if (getsockname(sock, ss2sa(&bound_addr), &bound_addr_len) < 0) + if (getsockname(sock, sa, &bound_addr_len) < 0) return -1; - switch (ss2sa(&bound_addr)->sa_family) { - case AF_INET: - return ss2sin(&bound_addr)->sin_addr.s_addr == INADDR_ANY; - case AF_INET6: - return IN6_IS_ADDR_UNSPECIFIED(&ss2sin6(&bound_addr)->sin6_addr); - default: + if (!sa_is_inet(sa)) { errno = EINVAL; return -1; } + + return sa_is_wildcard(sa); } #ifdef HAVE_IP_PKTINFO @@ -402,7 +400,7 @@ set_msg_from_ipv6_pktinfo(struct msghdr *msg, struct cmsghdr *cmsgptr, /* * Because of the possibility of asymmetric routing, we * normally don't want to specify an interface. However, - * Mac OS X doesn't like sending from a link-local address + * macOS doesn't like sending from a link-local address * (which can come up in testing at least, if you wind up * with a "foo.local" name) unless we do specify the * interface. diff --git a/src/lib/apputils/udppktinfo.h b/src/lib/apputils/udppktinfo.h index b0c7ea36b7b9..ff5759ab7ad3 100644 --- a/src/lib/apputils/udppktinfo.h +++ b/src/lib/apputils/udppktinfo.h @@ -32,7 +32,7 @@ * This holds whatever additional information might be needed to * properly send back to the client from the correct local address. * - * In this case, we only need one datum so far: On Mac OS X, the + * In this case, we only need one datum so far: On macOS, the * kernel doesn't seem to like sending from link-local addresses * unless we specify the correct interface. */ diff --git a/src/lib/crypto/builtin/des/des_int.h b/src/lib/crypto/builtin/des/des_int.h index 0801cb5828c9..67e40a19ca32 100644 --- a/src/lib/crypto/builtin/des/des_int.h +++ b/src/lib/crypto/builtin/des/des_int.h @@ -74,7 +74,7 @@ #endif /* defined(__MACH__) && defined(__APPLE__) */ /* Macro to add deprecated attribute to DES types and functions */ -/* Currently only defined on Mac OS X 10.5 and later. */ +/* Currently only defined on macOS 10.5 and later. */ #ifndef KRB5INT_DES_DEPRECATED #define KRB5INT_DES_DEPRECATED #endif diff --git a/src/lib/crypto/builtin/des/destest.c b/src/lib/crypto/builtin/des/destest.c index 6eeb070d867f..dd2f68ec4032 100644 --- a/src/lib/crypto/builtin/des/destest.c +++ b/src/lib/crypto/builtin/des/destest.c @@ -52,6 +52,7 @@ /* Test a DES implementation against known inputs & outputs. */ #include "des_int.h" +#include <ctype.h> #include <stdio.h> void convert (char *, unsigned char []); @@ -160,7 +161,7 @@ convert(text, cblock) { register int i; for (i = 0; i < 8; i++) { - if (text[i*2] < 0 || text[i*2] >= 128) + if (!isascii((unsigned char)text[i * 2])) abort (); if (value[(int) text[i*2]] == -1 || value[(int) text[i*2+1]] == -1) { printf("Bad value byte %d in %s\n", i, text); diff --git a/src/lib/crypto/builtin/enc_provider/rc4.c b/src/lib/crypto/builtin/enc_provider/rc4.c index 3776f80715ab..df710489eaf0 100644 --- a/src/lib/crypto/builtin/enc_provider/rc4.c +++ b/src/lib/crypto/builtin/enc_provider/rc4.c @@ -113,7 +113,7 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, return KRB5_BAD_MSIZE; if (state != NULL) { - cipher_state = (ArcFourCipherState *)state->data; + cipher_state = (ArcFourCipherState *)(void *)state->data; arcfour_ctx = &cipher_state->ctx; if (cipher_state->initialized == 0) { ret = k5_arcfour_init(arcfour_ctx, key->keyblock.contents, diff --git a/src/lib/crypto/builtin/sha2/sha256.c b/src/lib/crypto/builtin/sha2/sha256.c index e34bed575c5f..2b5cbe480503 100644 --- a/src/lib/crypto/builtin/sha2/sha256.c +++ b/src/lib/crypto/builtin/sha2/sha256.c @@ -211,14 +211,14 @@ k5_sha256_update(SHA256_CTX *m, const void *v, size_t len) #if !defined(WORDS_BIGENDIAN) || defined(_CRAY) int i; uint32_t current[16]; - struct x32 *u = (struct x32*)m->save; + struct x32 *u = (struct x32*)(void*)m->save; for(i = 0; i < 8; i++){ current[2*i+0] = swap_uint32_t(u[i].a); current[2*i+1] = swap_uint32_t(u[i].b); } calc(m, current); #else - calc(m, (uint32_t*)m->save); + calc(m, (uint32_t*)(void*)m->save); #endif offset = 0; } diff --git a/src/lib/crypto/builtin/sha2/sha512.c b/src/lib/crypto/builtin/sha2/sha512.c index 8f0ce894033f..6130655576c9 100644 --- a/src/lib/crypto/builtin/sha2/sha512.c +++ b/src/lib/crypto/builtin/sha2/sha512.c @@ -217,14 +217,14 @@ k5_sha512_update (SHA512_CTX *m, const void *v, size_t len) #if !defined(WORDS_BIGENDIAN) || defined(_CRAY) int i; uint64_t current[16]; - struct x64 *us = (struct x64*)m->save; + struct x64 *us = (struct x64*)(void*)m->save; for(i = 0; i < 8; i++){ current[2*i+0] = swap_uint64_t(us[i].a); current[2*i+1] = swap_uint64_t(us[i].b); } calc(m, current); #else - calc(m, (uint64_t*)m->save); + calc(m, (uint64_t*)(void*)m->save); #endif offset = 0; } diff --git a/src/lib/crypto/krb/Makefile.in b/src/lib/crypto/krb/Makefile.in index c5660c5fe1fa..fc01a2ced4ae 100644 --- a/src/lib/crypto/krb/Makefile.in +++ b/src/lib/crypto/krb/Makefile.in @@ -212,7 +212,7 @@ depend: $(SRCS) check-unix: t_fortuna if [ $(PRNG_ALG) = fortuna ]; then \ - $(RUN_TEST) ./t_fortuna > t_fortuna.output; \ + $(RUN_TEST) ./t_fortuna > t_fortuna.output && \ cmp t_fortuna.output $(srcdir)/t_fortuna.expected; \ fi diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h index d75b49c693f0..e5099291e309 100644 --- a/src/lib/crypto/krb/crypto_int.h +++ b/src/lib/crypto/krb/crypto_int.h @@ -111,6 +111,7 @@ struct krb5_keytypes { prf_func prf; krb5_cksumtype required_ctype; krb5_flags flags; + unsigned int ssf; }; #define ETYPE_WEAK 1 diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c index 0ed74bd6ebde..b1b40e7ecd6e 100644 --- a/src/lib/crypto/krb/enctype_util.c +++ b/src/lib/crypto/krb/enctype_util.c @@ -131,3 +131,19 @@ krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest, return ENOMEM; return 0; } + +/* The security of a mechanism cannot be summarized with a simple integer + * value, but we provide a per-enctype value for Cyrus SASL's SSF. */ +krb5_error_code +k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out) +{ + const struct krb5_keytypes *ktp; + + *ssf_out = 0; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return EINVAL; + *ssf_out = ktp->ssf; + return 0; +} diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c index 0e5e977d418a..53d4a5c79b47 100644 --- a/src/lib/crypto/krb/etypes.c +++ b/src/lib/crypto/krb/etypes.c @@ -42,7 +42,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_des_string_to_key, k5_rand2key_des, krb5int_des_prf, CKSUMTYPE_RSA_MD5_DES, - ETYPE_WEAK }, + ETYPE_WEAK, 56 }, { ENCTYPE_DES_CBC_MD4, "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4", &krb5int_enc_des, &krb5int_hash_md4, @@ -51,7 +51,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_des_string_to_key, k5_rand2key_des, krb5int_des_prf, CKSUMTYPE_RSA_MD4_DES, - ETYPE_WEAK }, + ETYPE_WEAK, 56 }, { ENCTYPE_DES_CBC_MD5, "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5", &krb5int_enc_des, &krb5int_hash_md5, @@ -60,7 +60,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_des_string_to_key, k5_rand2key_des, krb5int_des_prf, CKSUMTYPE_RSA_MD5_DES, - ETYPE_WEAK }, + ETYPE_WEAK, 56 }, { ENCTYPE_DES_CBC_RAW, "des-cbc-raw", { 0 }, "DES cbc mode raw", &krb5int_enc_des, NULL, @@ -69,7 +69,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_des_string_to_key, k5_rand2key_des, krb5int_des_prf, 0, - ETYPE_WEAK }, + ETYPE_WEAK, 56 }, { ENCTYPE_DES3_CBC_RAW, "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw", &krb5int_enc_des3, NULL, @@ -78,7 +78,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_dk_string_to_key, k5_rand2key_des3, NULL, /*PRF*/ 0, - ETYPE_WEAK }, + ETYPE_WEAK, 112 }, { ENCTYPE_DES3_CBC_SHA1, "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" }, @@ -89,7 +89,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_dk_string_to_key, k5_rand2key_des3, krb5int_dk_prf, CKSUMTYPE_HMAC_SHA1_DES3, - 0 /*flags*/ }, + 0 /*flags*/, 112 }, { ENCTYPE_DES_HMAC_SHA1, "des-hmac-sha1", { 0 }, "DES with HMAC/sha1", @@ -99,7 +99,10 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_dk_string_to_key, k5_rand2key_des, NULL, /*PRF*/ 0, - ETYPE_WEAK }, + ETYPE_WEAK, 56 }, + + /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we + * consider its strength degraded and assign it an SSF value of 64. */ { ENCTYPE_ARCFOUR_HMAC, "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" }, "ArcFour with HMAC/md5", @@ -110,7 +113,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key, k5_rand2key_direct, krb5int_arcfour_prf, CKSUMTYPE_HMAC_MD5_ARCFOUR, - 0 /*flags*/ }, + 0 /*flags*/, 64 }, { ENCTYPE_ARCFOUR_HMAC_EXP, "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" }, "Exportable ArcFour with HMAC/md5", @@ -121,7 +124,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key, k5_rand2key_direct, krb5int_arcfour_prf, CKSUMTYPE_HMAC_MD5_ARCFOUR, - ETYPE_WEAK + ETYPE_WEAK, 40 }, { ENCTYPE_AES128_CTS_HMAC_SHA1_96, @@ -133,7 +136,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_aes_string_to_key, k5_rand2key_direct, krb5int_dk_prf, CKSUMTYPE_HMAC_SHA1_96_AES128, - 0 /*flags*/ }, + 0 /*flags*/, 128 }, { ENCTYPE_AES256_CTS_HMAC_SHA1_96, "aes256-cts-hmac-sha1-96", { "aes256-cts", "aes256-sha1" }, "AES-256 CTS mode with 96-bit SHA-1 HMAC", @@ -143,7 +146,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_aes_string_to_key, k5_rand2key_direct, krb5int_dk_prf, CKSUMTYPE_HMAC_SHA1_96_AES256, - 0 /*flags*/ }, + 0 /*flags*/, 256 }, { ENCTYPE_CAMELLIA128_CTS_CMAC, "camellia128-cts-cmac", { "camellia128-cts" }, @@ -155,7 +158,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_camellia_string_to_key, k5_rand2key_direct, krb5int_dk_cmac_prf, CKSUMTYPE_CMAC_CAMELLIA128, - 0 /*flags*/ }, + 0 /*flags*/, 128 }, { ENCTYPE_CAMELLIA256_CTS_CMAC, "camellia256-cts-cmac", { "camellia256-cts" }, "Camellia-256 CTS mode with CMAC", @@ -166,7 +169,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_camellia_string_to_key, k5_rand2key_direct, krb5int_dk_cmac_prf, CKSUMTYPE_CMAC_CAMELLIA256, - 0 /*flags */ }, + 0 /*flags */, 256 }, { ENCTYPE_AES128_CTS_HMAC_SHA256_128, "aes128-cts-hmac-sha256-128", { "aes128-sha2" }, @@ -177,7 +180,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_aes2_string_to_key, k5_rand2key_direct, krb5int_aes2_prf, CKSUMTYPE_HMAC_SHA256_128_AES128, - 0 /*flags*/ }, + 0 /*flags*/, 128 }, { ENCTYPE_AES256_CTS_HMAC_SHA384_192, "aes256-cts-hmac-sha384-192", { "aes256-sha2" }, "AES-256 CTS mode with 192-bit SHA-384 HMAC", @@ -187,7 +190,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { krb5int_aes2_string_to_key, k5_rand2key_direct, krb5int_aes2_prf, CKSUMTYPE_HMAC_SHA384_192_AES256, - 0 /*flags*/ }, + 0 /*flags*/, 256 }, }; const int krb5int_enctypes_length = diff --git a/src/lib/crypto/krb/s2k_des.c b/src/lib/crypto/krb/s2k_des.c index 31a613bebc61..d5c29befcb2e 100644 --- a/src/lib/crypto/krb/s2k_des.c +++ b/src/lib/crypto/krb/s2k_des.c @@ -509,7 +509,7 @@ des_s2k(const krb5_data *pw, const krb5_data *salt, unsigned char *key_out) #define FETCH4(VAR, IDX) VAR = temp.ui[IDX/4] #define PUT4(VAR, IDX) temp.ui[IDX/4] = VAR - copylen = pw->length + (salt ? salt->length : 0); + copylen = pw->length + salt->length; /* Don't need NUL termination, at this point we're treating it as a byte array, not a string. */ copy = malloc(copylen); @@ -517,7 +517,7 @@ des_s2k(const krb5_data *pw, const krb5_data *salt, unsigned char *key_out) return ENOMEM; if (pw->length > 0) memcpy(copy, pw->data, pw->length); - if (salt != NULL && salt->length > 0) + if (salt->length > 0) memcpy(copy + pw->length, salt->data, salt->length); memset(&temp, 0, sizeof(temp)); diff --git a/src/lib/crypto/krb/s2k_pbkdf2.c b/src/lib/crypto/krb/s2k_pbkdf2.c index ec5856c2be79..1fea03408c76 100644 --- a/src/lib/crypto/krb/s2k_pbkdf2.c +++ b/src/lib/crypto/krb/s2k_pbkdf2.c @@ -47,7 +47,7 @@ krb5int_dk_string_to_key(const struct krb5_keytypes *ktp, keybytes = ktp->enc->keybytes; keylength = ktp->enc->keylength; - concatlen = string->length + (salt ? salt->length : 0); + concatlen = string->length + salt->length; concat = k5alloc(concatlen, &ret); if (ret != 0) @@ -63,7 +63,7 @@ krb5int_dk_string_to_key(const struct krb5_keytypes *ktp, if (string->length > 0) memcpy(concat, string->data, string->length); - if (salt != NULL && salt->length > 0) + if (salt->length > 0) memcpy(concat + string->length, salt->data, salt->length); krb5int_nfold(concatlen*8, concat, keybytes*8, foldstring); diff --git a/src/lib/crypto/krb/s2k_rc4.c b/src/lib/crypto/krb/s2k_rc4.c index 49ad89d323b0..081a91217c69 100644 --- a/src/lib/crypto/krb/s2k_rc4.c +++ b/src/lib/crypto/krb/s2k_rc4.c @@ -10,6 +10,7 @@ krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp, krb5_error_code err = 0; krb5_crypto_iov iov; krb5_data hash_out; + char *utf8; unsigned char *copystr; size_t copystrlen; @@ -20,8 +21,11 @@ krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp, return (KRB5_BAD_MSIZE); /* We ignore salt per the Microsoft spec. */ - err = krb5int_utf8cs_to_ucs2les(string->data, string->length, ©str, - ©strlen); + utf8 = k5memdup0(string->data, string->length, &err); + if (utf8 == NULL) + return err; + err = k5_utf8_to_utf16le(utf8, ©str, ©strlen); + free(utf8); if (err) return err; diff --git a/src/lib/crypto/krb/string_to_key.c b/src/lib/crypto/krb/string_to_key.c index b55ee75d2f34..352a8e8dcce2 100644 --- a/src/lib/crypto/krb/string_to_key.c +++ b/src/lib/crypto/krb/string_to_key.c @@ -43,6 +43,7 @@ krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype, const krb5_data *params, krb5_keyblock *key) { krb5_error_code ret; + krb5_data empty = empty_data(); const struct krb5_keytypes *ktp; size_t keylength; @@ -51,8 +52,12 @@ krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype, return KRB5_BAD_ENCTYPE; keylength = ktp->enc->keylength; + /* For compatibility with past behavior, treat a null salt as empty. */ + if (salt == NULL) + salt = ∅ + /* Fail gracefully if someone is using the old AFS string-to-key hack. */ - if (salt != NULL && salt->length == SALT_TYPE_AFS_LENGTH) + if (salt->length == SALT_TYPE_AFS_LENGTH) return EINVAL; key->contents = malloc(keylength); diff --git a/src/lib/crypto/krb/t_fortuna.c b/src/lib/crypto/krb/t_fortuna.c index 4f25bee62cb5..508ffcf915c7 100644 --- a/src/lib/crypto/krb/t_fortuna.c +++ b/src/lib/crypto/krb/t_fortuna.c @@ -85,7 +85,7 @@ head_tail_test(struct fortuna_state *st) { static unsigned char buffer[1024 * 1024]; unsigned char c; - size_t i, len = sizeof(buffer); + int i, len = sizeof(buffer); int bit, bits[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; double res; diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports index 447e45644453..82eb5f30c031 100644 --- a/src/lib/crypto/libk5crypto.exports +++ b/src/lib/crypto/libk5crypto.exports @@ -108,3 +108,4 @@ krb5int_nfold k5_allow_weak_pbkdf2iter krb5_c_prfplus krb5_c_derive_prfplus +k5_enctype_to_ssf |