3 Commits

Author SHA1 Message Date
oysteikt 845fb73ad1 WIP 2026-02-02 08:53:06 +09:00
oysteikt d0b5821e9a Set up nix tooling 2026-02-01 03:45:20 +09:00
oysteikt 072c1f062f zed: set tab width 2026-02-01 03:45:18 +09:00
207 changed files with 29623 additions and 6067 deletions
-2
View File
@@ -3,7 +3,6 @@ name: Test Coverage
on:
push:
branches:
- 'master'
- 'coverage-*'
jobs:
@@ -37,7 +36,6 @@ jobs:
../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap --prefix=$HOME/inst CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS"
make -j4
- name: Test
timeout-minutes: 40
run: |
cd build
sudo sysctl kernel.core_pattern=core.%p || true
+2 -1
View File
@@ -49,7 +49,8 @@ jobs:
cd build
../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="-Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations"
ulimit -c unlimited
# We don't want to scan-build SQLite3 because ETOOSLOW
# We don't want to scan-build libedit nor SQLite3 because ETOOSLOW
(cd lib/libedit && make -j4)
(cd lib/sqlite && make -j4)
cov-build --dir cov-int make -j4
tar czvf ../heimdal.tgz cov-int
-1
View File
@@ -78,7 +78,6 @@ jobs:
../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="${{ matrix.cflags }} -Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations" --with-mitkrb5=$HOME/mitkrb5 --with-older-heimdal=$HOME/oh5l
make -j4
- name: Test
timeout-minutes: 20
env:
CC: ${{ matrix.compiler }}
MAKEVARS: ${{ matrix.makevars }}
+1 -98
View File
@@ -5,7 +5,6 @@ on:
branches:
- 'master'
- 'heimdal-7-1-branch'
- 'test-ILP32'
paths:
- '!docs/**'
- '!**.md'
@@ -64,7 +63,6 @@ jobs:
os: ubuntu-22.04
compiler: gcc
cflags: '-Wnonnull'
configureopts: '--with-readline=yes'
steps:
- name: Clone repository
uses: actions/checkout@v4
@@ -75,7 +73,7 @@ jobs:
sudo apt-get install -y bison comerr-dev flex doxygen
sudo apt-get install -y libcap-ng-dev libdb-dev libedit-dev libjson-perl
sudo apt-get install -y libldap2-dev libncurses5-dev libperl4-corelibs-perl
sudo apt-get install -y libsqlite3-dev libkeyutils-dev libreadline-dev pkg-config python3
sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python3
sudo apt-get install -y ss-dev texinfo unzip netbase keyutils ldap-utils
sudo apt-get install -y gdb apport curl libmicrohttpd-dev jq valgrind
# Temporary workaround for:
@@ -85,7 +83,6 @@ jobs:
env:
CC: ${{ matrix.compiler }}
MAKEVARS: ${{ matrix.makevars }}
CONFIGURE_OPTS: ${{ matrix.configureopts }}
run: |
/bin/sh ./autogen.sh
mkdir build
@@ -93,7 +90,6 @@ jobs:
../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="${{ matrix.cflags }} -Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations"
make -j4
- name: Test
timeout-minutes: 40
env:
CC: ${{ matrix.compiler }}
MAKEVARS: ${{ matrix.makevars }}
@@ -111,27 +107,6 @@ jobs:
make DESTDIR=/tmp/h5l install
cd /tmp/h5l
tar czf $HOME/heimdal-install-linux-${{ matrix.compiler }}.tgz .
- name: Interrupted/timed out test diagnostics
if: ${{ cancelled() || failure() }}
run: |
set -x
# Show any test-related processes still running
ps auxww | grep -E 'kdc|test_context|kinit|kadmin|check-' | grep -v grep || true
# Show who's on the test port
ss -tlnp sport = :49188 || true
# Show the newest .log file (the one likely interrupted)
newest=$(find build/tests -name '*.log' -newer build/tests/gss/Makefile -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)
if [ -n "$newest" ]; then
echo "=== Newest test log: $newest ==="
cat "$newest"
fi
# Also show KDC messages.log if any exist
for f in build/tests/gss/messages.log build/tests/kdc/messages.log; do
if [ -f "$f" ]; then
echo "=== $f ==="
tail -100 "$f"
fi
done
- name: Core dump stacks
if: ${{ always() }}
run: |
@@ -172,75 +147,3 @@ jobs:
with:
name: Test Logs (${{ matrix.name }})
path: '~/logs-linux-${{ matrix.compiler }}.tgz'
linux-i386:
name: linux-i386 (${{ matrix.name }})
# Run if no [only X] tag, or if [only linux] is present (check both push commits and PR titles)
if: >-
(!contains(github.event.head_commit.message, '[only ') &&
!contains(github.event.pull_request.title, '[only ')) ||
contains(github.event.head_commit.message, '[only linux]') ||
contains(github.event.pull_request.title, '[only linux]')
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
include:
- name: time32
image: i386/debian:bookworm
year2038_configure: ""
time_t_size: 4
- name: year2038
image: i386/debian:trixie
year2038_configure: --enable-year2038
time_t_size: 8
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Build and test on Debian i386
run: |
docker run --security-opt seccomp=unconfined --platform linux/386 --rm \
-v "$PWD:/src:ro" \
-e YEAR2038_CONFIGURE="${{ matrix.year2038_configure }}" \
-e EXPECT_TIME_T_SIZE="${{ matrix.time_t_size }}" \
${{ matrix.image }} \
/bin/bash -euxc '
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y --no-install-recommends \
autoconf automake bison build-essential ca-certificates \
comerr-dev curl doxygen flex gdb git iproute2 jq keyutils \
ldap-utils libcap-ng-dev libdb-dev libedit-dev libjson-perl \
libkeyutils-dev libldap2-dev liblmdb-dev libmicrohttpd-dev libncurses5-dev \
libperl4-corelibs-perl libreadline-dev libsqlite3-dev libssl-dev \
libtool make netbase pkg-config procps python3 ss-dev tar \
texinfo unzip valgrind xz-utils
cp -a /src /tmp/heimdal-src
git config --global --add safe.directory /tmp/heimdal-src
cd /tmp/heimdal-src
/bin/sh ./autogen.sh
mkdir build
cd build
../configure --srcdir=`dirname "$PWD"` \
--enable-maintainer-mode \
--enable-developer \
${YEAR2038_CONFIGURE} \
--with-ldap \
--with-readline=yes \
--with-db-type-preference=lmdb \
--prefix=/tmp/heimdal-i386-inst \
CFLAGS="-Wnonnull -Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations"
printf "%s\n" \
"#include \"include/config.h\"" \
"#include <stdio.h>" \
"#include <time.h>" \
"int main(void) { unsigned long s = sizeof(time_t); printf(\"sizeof(time_t)=%lu\n\", s); return s == EXPECT_TIME_T_SIZE ? 0 : 1; }" \
> check-time-t.c
cc -I. -I.. -DEXPECT_TIME_T_SIZE="$EXPECT_TIME_T_SIZE" -o check-time-t check-time-t.c
./check-time-t
make -j4
make -C lib/asn1 check
make -C lib/hx509 check TESTS=test_cert_binary
make DESTDIR=/tmp/heimdal-i386-root install
'
-24
View File
@@ -62,7 +62,6 @@ jobs:
- name: osx-clang
os: macos-latest
compiler: clang
configureopts: '--with-libedit=yes'
steps:
- name: Install packages
run: |
@@ -94,7 +93,6 @@ jobs:
# with:
# limit-access-to-actor: true
- name: Test
timeout-minutes: 25
shell: bash
env:
CC: ${{ matrix.compiler }}
@@ -107,27 +105,6 @@ jobs:
sudo lsof -nP -i:49188 || true
cd build
make check
- name: Interrupted/timed out test diagnostics
if: ${{ cancelled() || failure() }}
run: |
set -x
# Show any test-related processes still running
ps auxww | grep -E 'kdc|test_context|kinit|kadmin|check-' | grep -v grep || true
# Show who's on the test port
sudo lsof -nP -i:49188 || true
# Show the newest .log file (the one likely interrupted)
newest=$(find build/tests -name '*.log' -newer build/tests/gss/Makefile -print0 2>/dev/null | xargs -0 stat -f '%m %N' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)
if [ -n "$newest" ]; then
echo "=== Newest test log: $newest ==="
cat "$newest"
fi
# Also show KDC messages.log if any exist
for f in build/tests/gss/messages.log build/tests/kdc/messages.log; do
if [ -f "$f" ]; then
echo "=== $f ==="
tail -100 "$f"
fi
done
- name: Install
run: |
cd build || true
@@ -135,7 +112,6 @@ jobs:
cd /tmp/h5l
tar czf $HOME/heimdal-install-osx.tgz .
- name: Test logs
if: ${{ always() }}
run: |
find build -depth -name \*.trs|xargs grep -lw FAIL|sed -e 's/trs$/log/' | cpio -o > $HOME/logs-osx.cpio
find build -name \*.trs|xargs grep -lw FAIL|sed -e 's/trs$/log/'|xargs cat
+2 -2
View File
@@ -44,11 +44,11 @@ jobs:
cd build
../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="-Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations"
ulimit -c unlimited
# We don't want to scan-build SQLite3 because ETOOSLOW
# We don't want to scan-build libedit nor SQLite3 because ETOOSLOW
(cd lib/libedit && make -j4)
(cd lib/sqlite && make -j4)
scan-build --keep-going make -j4
- name: Test
timeout-minutes: 40
env:
CC: ${{ matrix.compiler }}
MAKEVARS: ${{ matrix.makevars }}
-1
View File
@@ -90,7 +90,6 @@ jobs:
../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --enable-dynamic --disable-static --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="${{ matrix.cflags }} -Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations" LDFLAGS="${{ matrix.ldflags }}"
make -j4
- name: Test
timeout-minutes: 80
env:
CC: ${{ matrix.compiler }}
MAKEVARS: ${{ matrix.makevars }}
-1
View File
@@ -46,7 +46,6 @@ jobs:
../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="-gdwarf-4 -g -ggdb3 -O0 -Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations"
make -j4
- name: Test
timeout-minutes: 120
env:
CC: ${{ matrix.compiler }}
MAKEVARS: ${{ matrix.makevars }}
-1
View File
@@ -119,7 +119,6 @@ jobs:
)
- name: Test
timeout-minutes: 20
shell: cmd
run: |
set "PATH=%PATH%;C:\msys64\usr\bin"
+26 -3
View File
@@ -64,6 +64,32 @@ asn1_*_asn1.c
/tmp.h
/ylwrap
/lib/libedit/aclocal.m4
/lib/libedit/autom4te.cache
/lib/libedit/compile
/lib/libedit/config.guess
/lib/libedit/config.h
/lib/libedit/config.log
/lib/libedit/config.status
/lib/libedit/config.sub
/lib/libedit/configure
/lib/libedit/depcomp
/lib/libedit/install-sh
/lib/libedit/libtool
/lib/libedit/ltmain.sh
/lib/libedit/missing
/lib/libedit/setupbuild.cmd
/lib/libedit/ylwrap
/lib/libedit/src/common.h
/lib/libedit/src/emacs.h
/lib/libedit/src/fcns.c
/lib/libedit/src/fcns.h
/lib/libedit/src/func.h
/lib/libedit/src/help.c
/lib/libedit/src/help.h
/lib/libedit/src/vi.h
/lib/libedit/stamp-h1
# Files in subdirectories.
/admin/ktutil
@@ -694,6 +720,3 @@ asn1_*_asn1.c
/tools/krb5-gssapi.pc
/tools/krb5.pc
/tools/krb5-config
result
result-*
-1
View File
@@ -7,7 +7,6 @@ Release Notes - Heimdal - Version Heimdal 8.0 (future)
- Errors found by the LLVM scan-build static analyzer.
- Errors found by the valgrind memory debugger.
- Fix out-of-tree SQLite3 ccache permissions / umask issues.
- Clamp far-future ASN.1 times on 32-bit time_t platforms instead of wrapping.
- iprop bugs, race conditions, and performance
- Many misc. bugs
-2
View File
@@ -1,7 +1,6 @@
[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/linux.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Alinux)
[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/osx.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Aosx)
[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/windows.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Awindows)
[![Coverage Status](https://coveralls.io/repos/github/heimdal/heimdal/badge.svg?branch=master)](https://coveralls.io/github/heimdal/heimdal?branch=master)
Heimdal
=======
@@ -34,4 +33,3 @@ Build Status
[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/linux.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Alinux)
[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/osx.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Aosx)
[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/windows.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Awindows)
[![Coverage Status](https://coveralls.io/repos/github/heimdal/heimdal/badge.svg?branch=master)](https://coveralls.io/github/heimdal/heimdal?branch=master)
+27 -50
View File
@@ -43,9 +43,6 @@ kt_rename(struct rename_options *opt, int argc, char **argv)
krb5_keytab keytab;
krb5_kt_cursor cursor;
krb5_principal from_princ, to_princ;
krb5_keytab_entry *entries = NULL;
size_t num_entries = 0;
size_t i;
ret = krb5_parse_name(context, argv[0], &from_princ);
if(ret != 0) {
@@ -66,14 +63,6 @@ kt_rename(struct rename_options *opt, int argc, char **argv)
return 1;
}
/*
* Collect matching entries first, then close the cursor before
* adding/removing. We must not call krb5_kt_add_entry() or
* krb5_kt_remove_entry() while holding the seq_get cursor because
* the cursor holds a shared file lock and the add/remove operations
* need an exclusive lock -- with per-fd locking (BSD flock, OFD locks)
* this self-deadlocks.
*/
ret = krb5_kt_start_seq_get(context, keytab, &cursor);
if(ret) {
krb5_kt_close(context, keytab);
@@ -81,52 +70,40 @@ kt_rename(struct rename_options *opt, int argc, char **argv)
krb5_free_principal(context, to_princ);
return 1;
}
while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
if(krb5_principal_compare(context, entry.principal, from_princ)) {
krb5_keytab_entry *tmp;
tmp = realloc(entries, (num_entries + 1) * sizeof(*entries));
if (tmp == NULL) {
krb5_kt_free_entry(context, &entry);
ret = krb5_enomem(context);
break;
}
entries = tmp;
krb5_free_principal(context, entry.principal);
entry.principal = NULL;
entries[num_entries++] = entry;
} else {
krb5_kt_free_entry(context, &entry);
}
}
if(ret == KRB5_CC_END || ret == KRB5_KT_END)
ret = 0;
else if(ret)
krb5_warn(context, ret, "getting entry from keytab");
krb5_kt_end_seq_get(context, keytab, &cursor);
for (i = 0; ret == 0 && i < num_entries; i++) {
entries[i].principal = to_princ;
ret = krb5_kt_add_entry(context, keytab, &entries[i]);
if(ret) {
krb5_warn(context, ret, "adding entry");
while(1) {
ret = krb5_kt_next_entry(context, keytab, &entry, &cursor);
if(ret != 0) {
if(ret != KRB5_CC_END && ret != KRB5_KT_END)
krb5_warn(context, ret, "getting entry from keytab");
else
ret = 0;
break;
}
if (opt->delete_flag) {
entries[i].principal = from_princ;
ret = krb5_kt_remove_entry(context, keytab, &entries[i]);
if(krb5_principal_compare(context, entry.principal, from_princ)) {
krb5_free_principal(context, entry.principal);
entry.principal = to_princ;
ret = krb5_kt_add_entry(context, keytab, &entry);
if(ret) {
krb5_warn(context, ret, "removing entry");
entry.principal = NULL;
krb5_kt_free_entry(context, &entry);
krb5_warn(context, ret, "adding entry");
break;
}
if (opt->delete_flag) {
entry.principal = from_princ;
ret = krb5_kt_remove_entry(context, keytab, &entry);
if(ret) {
entry.principal = NULL;
krb5_kt_free_entry(context, &entry);
krb5_warn(context, ret, "removing entry");
break;
}
}
entry.principal = NULL;
}
krb5_kt_free_entry(context, &entry);
}
for (i = 0; i < num_entries; i++) {
entries[i].principal = NULL;
krb5_kt_free_entry(context, &entries[i]);
}
free(entries);
krb5_kt_end_seq_get(context, keytab, &cursor);
krb5_free_principal(context, from_princ);
krb5_free_principal(context, to_princ);
+1 -1
View File
@@ -10,4 +10,4 @@ man_MANS = bsearch.1
EXTRA_DIST = NTMakefile $(man_MANS)
LDADD = $(LIB_vers) $(LIB_heimbase) $(LIB_roken)
LDADD = $(LIB_roken) $(LIB_vers) $(LIB_heimbase)
-3
View File
@@ -57,9 +57,6 @@ AS_IF([test "x$with_berkeley_db" != xno],
db.h \
])])
dnl detect if compat db_185.h is present
AC_CHECK_HEADERS([db_185.h])
dnl db_create is used by db3 and db4 and db5 and db6
AC_FIND_FUNC_NO_LIBS(db_create, [$dbheader] db-6 db-5 db4 db3 db, [
+11 -71
View File
@@ -9,80 +9,20 @@ AC_DEFUN([KRB_READLINE],[
dnl readline
readline_requested="${with_readline-unset}"
libedit_requested="${with_libedit-unset}"
have_readline=no
rk_TEST_PACKAGE(readline,
[#include <stdio.h>
#if defined(HAVE_READLINE_READLINE_H)
#include <readline/readline.h>
#elif defined(HAVE_READLINE_H)
#include <readline.h>
#endif
],-lreadline,[$LIB_tgetent],,[READLINE],, [readline.h readline/readline.h])
rk_TEST_PACKAGE(libedit,
[#include <stdio.h>
#if defined(HAVE_EDITLINE_READLINE_H)
#include <editline/readline.h>
#elif defined(HAVE_READLINE_READLINE_H)
#include <readline/readline.h>
#elif defined(HAVE_READLINE_H)
#include <readline.h>
#endif
],-ledit,[$LIB_tgetent],,[READLINE],,
[readline.h readline/readline.h editline/readline.h])
ac_foo=no
build_editline=no
if test "$with_readline" = yes; then
have_readline=yes
:
elif test "$with_libedit" = yes; then
INCLUDE_readline="${INCLUDE_libedit}"
LIB_readline="${LIB_libedit}"
have_readline=yes
elif test "$readline_requested" != no; then
rk_readline_header=no
AC_CHECK_HEADERS([readline/readline.h readline.h],
[rk_readline_header=yes])
if test "$rk_readline_header" = yes; then
AC_CHECK_LIB(readline, readline, [
LIB_readline="-lreadline"
if test "x$LIB_tgetent" != x; then
LIB_readline="$LIB_readline $LIB_tgetent"
fi
have_readline=yes
with_readline=yes
], [], [$LIB_tgetent])
fi
fi
if test "$have_readline" != yes && test "$libedit_requested" != no; then
rk_libedit_header=no
AC_CHECK_HEADERS([editline/readline.h readline/readline.h readline.h],
[rk_libedit_header=yes])
if test "$rk_libedit_header" = yes; then
AC_CHECK_LIB(edit, readline, [
LIB_readline="-ledit"
if test "x$LIB_tgetent" != x; then
LIB_readline="$LIB_readline $LIB_tgetent"
fi
have_readline=yes
with_libedit=yes
], [], [$LIB_tgetent])
fi
fi
if test "$have_readline" = yes; then
AC_DEFINE(HAVE_READLINE, 1,
[Define if you have a readline compatible library.])dnl
AC_DEFINE(READLINE, 1, [Define if you have the readline package.])dnl
LIB_readline="${LIB_libedit}"
elif test "$ac_cv_func_readline" = yes; then
:
else
INCLUDE_readline=
LIB_readline=
AC_MSG_NOTICE([readline/libedit not found; command line editing disabled])
build_libedit=yes
LIB_readline="\$(top_builddir)/lib/libedit/src/libheimedit.la \$(LIB_tgetent)"
fi
AC_SUBST(INCLUDE_readline)
AC_SUBST(LIB_readline)
AM_CONDITIONAL(LIBEDIT, test "$build_libedit" = yes)
AC_DEFINE(HAVE_READLINE, 1,
[Define if you have a readline compatible library.])dnl
])
-6
View File
@@ -19,10 +19,4 @@ if test "$enable_largefile" != no; then
[CPPFLAGS="$CPPFLAGS $ac_cv_sys_largefile_opts"])
fi
fi
if test "$enable_year2038" != no; then
if test -n "$ac_cv_sys_year2038_opts"; then
AS_CASE([$ac_cv_sys_year2038_opts],[-D_TIME_BITS=*|-D__MINGW_USE_VC2005_COMPAT],
[CPPFLAGS="$CPPFLAGS $ac_cv_sys_year2038_opts"])
fi
fi
])
+1 -2
View File
@@ -192,6 +192,7 @@ AC_CHECK_FUNCS([ \
mkdtemp \
mkostemp \
on_exit \
poll \
random \
secure_getenv \
setprogname \
@@ -359,8 +360,6 @@ AC_BROKEN([ \
mergesort \
mergesort_r \
mkstemp \
poll \
pread \
putenv \
rcmd \
readv \
+4 -4
View File
@@ -24,8 +24,8 @@ AC_ARG_WITH($1-config,
AS_HELP_STRING([--with-$1-config=path],[config program for $1]))
m4_ifval([$6],
[m4_define([rk_pkgname], [$6])],
[m4_define([rk_pkgname], [AS_TR_CPP($1)])])
m4_define([rk_pkgname], $6),
m4_define([rk_pkgname], AS_TR_CPP($1)))
AC_MSG_CHECKING(for $1)
@@ -91,7 +91,7 @@ if test "$with_$1" != no; then
if test "$[]$1_cflags" -a "$[]$1_libs"; then
CFLAGS="$[]$1_cflags $save_CFLAGS"
LIBS="$[]$1_libs $save_LIBS"
m4_ifval([$8],[AC_CHECK_HEADERS([$8])])
m4_ifval([$8],[AC_CHECK_HEADERS([[$8]])])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[$2]],[[]])],[
INCLUDE_$1="$[]$1_cflags"
LIB_$1="$[]$1_libs"
@@ -102,7 +102,7 @@ if test "$with_$1" != no; then
ires= lres=
for i in $header_dirs; do
CFLAGS="-I$i $save_CFLAGS"
m4_ifval([$8],[AC_CHECK_HEADERS([$8])])
m4_ifval([$8],[AC_CHECK_HEADERS([[$8]])])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]],[[]])],[ires=$i;break])
done
for i in $lib_dirs; do
+22
View File
@@ -382,6 +382,28 @@ AC_SUBST(ENABLE_AFS_STRING_TO_KEY)dnl
rk_CHECK_MAN
rk_TEST_PACKAGE(readline,
[#include <stdio.h>
#if defined(HAVE_READLINE_READLINE_H)
#include <readline/readline.h>
#elif defined(HAVE_READLINE_H)
#include <readline.h>
#endif
],-lreadline,,, READLINE,, [readline.h readline/readline.h])
rk_TEST_PACKAGE(libedit,
[#include <stdio.h>
#if defined(HAVE_READLINE_READLINE_H)
#include <readline/readline.h>
#elif defined(HAVE_READLINE_H)
#include <readline.h>
#elif defined(HAVE_EDITLINE_READLINE_H)
#include <editline/readline.h>
#endif
],-ledit,,, READLINE,, [readline.h readline/readline.h editline/readline.h])
AC_CONFIG_SUBDIRS([lib/libedit])
KRB_C_BIGENDIAN
AC_C_INLINE
+3
View File
@@ -13,6 +13,9 @@ The @code{popper} was also a Berkeley program initially.
Some of the functions in @file{libroken} also come from Berkeley by way
of NetBSD/FreeBSD.
@code{editline} was written by Simmule Turner and Rich Salz. Heimdal
contains a modifed copy.
The @code{getifaddrs} implementation for Linux was written by Hideaki
YOSHIFUJI for the Usagi project.
+42
View File
@@ -123,6 +123,48 @@ SUCH DAMAGE.
@end verbatim
@copynext
@heading The Regents of the University of California.
libedit
@verbatim
SPDX-License-Identifier: BSD-3-Clause
Copyright (c) 1992, 1993
The Regents of the University of California. All rights reserved.
This code is derived from software contributed to Berkeley by
Christos Zoulas of Cornell University.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
@end verbatim
@copynext
@copynext
@heading Doug Rabson
GSS-API mechglue layer.
Generated
+3 -3
View File
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1770380644,
"narHash": "sha256-P7dWMHRUWG5m4G+06jDyThXO7kwSk46C1kgjEWcybkE=",
"lastModified": 1742800061,
"narHash": "sha256-oDJGK1UMArK52vcW9S5S2apeec4rbfNELgc50LqiPNs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ae67888ff7ef9dff69b3cf0cc0fbfbcd3a722abe",
"rev": "1750f3c1c89488e2ffdd47cab9d05454dddfb734",
"type": "github"
},
"original": {
+4 -18
View File
@@ -22,27 +22,13 @@
default = pkgs.callPackage ./nix/shell.nix { };
});
packages = forAllSystems (system: pkgs: let
src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.difference ./. (lib.fileset.unions [
./.github
./.gitignore
./.zed
./flake.nix
./flake.lock
./nix
]);
};
in {
packages = forAllSystems (system: pkgs: with pkgs; {
default = self.packages.${system}.heimdal;
src = pkgs.runCommand "heimdal-src" {} "ln -s ${src} \"$out\"";
heimdal = pkgs.callPackage ./nix/heimdal/package.nix {
inherit src;
heimdal = pkgs.callPackage ./nix/heimdal {
src = lib.cleanSource ./.;
inherit (pkgs.darwin.apple_sdk.frameworks) CoreFoundation Security SystemConfiguration;
autoreconfHook = pkgs.buildPackages.autoreconfHook271;
autoreconfHook = pkgs.buildPackages.autoreconfHook269;
};
nixosTest = pkgs.testers.runNixOSTest (import ./nix/nixosTest.nix { inherit nixpkgs; });
+2 -3
View File
@@ -9,11 +9,9 @@ CHECK_LOCAL = no-check-local
AM_CPPFLAGS += -DHOST=\"$(CANONICAL_HOST)\"
include_HEADERS = heim_threads.h
nodist_include_HEADERS = krb5-types.h
noinst_HEADERS = heimqueue.h crypto-headers.h
noinst_HEADERS = heimqueue.h heim_threads.h crypto-headers.h
EXTRA_DIST = NTMakefile krb5-types.cross config.h.w32
@@ -50,6 +48,7 @@ CLEANFILES = \
der.h \
digest_asn1.h \
digest_template_asn1.h \
editline.h \
err.h \
getarg.h \
glob.h \
+1 -1
View File
@@ -54,7 +54,7 @@ kadmind_SOURCES = \
add_random_users_SOURCES = add-random-users.c
test_util_SOURCES = test_util.c util.c random_password.c
test_util_SOURCES = test_util.c util.c
TESTS = test_util
+17
View File
@@ -68,6 +68,12 @@ do_ext_keytab(krb5_principal principal, void *data)
if (ret)
goto out;
/* Debug: record which principal was fetched and some context */
krb5_warnx(context, "do_ext_keytab: fetched principal %s mask=0x%x n_key_data=%d",
unparsed ? unparsed : "<unparsed>",
mask,
(int)princ.n_key_data);
if (!e->random_key_flag) {
if (princ.n_key_data == 0) {
krb5_warnx(context, "principal has no keys, or user lacks "
@@ -111,6 +117,13 @@ do_ext_keytab(krb5_principal principal, void *data)
keys[i].keyblock.keyvalue.data = kd->key_data_contents[0];
keys[i].timestamp = time(NULL);
n_k++;
/* Debug: log each key extracted (kvno/enctype) for the principal */
krb5_warnx(context, "do_ext_keytab: principal=%s key_index=%zu kvno=%d enctype=%d",
unparsed ? unparsed : "<unparsed>",
i,
keys[i].vno,
keys[i].keyblock.keytype);
}
} else if (e->random_key_flag) {
ret = kadm5_randkey_principal_3(e->kadm_handle, principal, e->keep,
@@ -208,6 +221,10 @@ ext_keytab(struct ext_keytab_options *opt, int argc, char **argv)
return ret;
}
/* Debug: record ext_keytab invocation details */
krb5_warnx(context, "ext_keytab: invoking foreach_principal for %zu principals, enctypes=%s",
(size_t)argc, enctypes ? enctypes : "<none>");
for(i = 0; i < argc; i++) {
ret = foreach_principal(argv[i], do_ext_keytab, "ext", &data);
if (ret)
+69 -4
View File
@@ -488,12 +488,71 @@ do_get_entry(krb5_principal principal, void *data)
e->upto--;
memset(&princ, 0, sizeof(princ));
ret = kadm5_get_principal(e->kadm_handle, principal,
&princ,
e->mask | e->extra_mask);
/* Loud tracing: record which principal we are about to request from kadmind.
*
* Guard the unparse call: don't call into unparse with a NULL principal
* and only use the unparsed string if the call succeeds.
*/
{
char *want = NULL;
if (principal != NULL && krb5_unparse_name(context, principal, &want) == 0 && want != NULL) {
krb5_warnx(context, "kadmin:get: do_get_entry: requesting principal lookup for %s (mask=0x%x extra_mask=0x%x) (pid=%d)",
want, e->mask, e->extra_mask, (int)getpid());
} else {
krb5_warnx(context, "kadmin:get: do_get_entry: requesting principal lookup for <unparsed> (mask=0x%x extra_mask=0x%x) (pid=%d)",
e->mask, e->extra_mask, (int)getpid());
}
free(want);
}
/* Always request the principal field so we can safely unparse/format
* the returned entry. Some callers request only TL_DATA (eg aliases),
* and the kadm5 backend may return successful results without filling
* the principal pointer which leads to crashes when we try to use it.
*/
{
uint32_t want_mask = e->mask | e->extra_mask | KADM5_PRINCIPAL;
ret = kadm5_get_principal(e->kadm_handle, principal,
&princ,
want_mask);
}
if (ret == 0) {
/* Success: log the fact we received a principal record and some basic info */
{
char *got = NULL;
if (krb5_unparse_name(context, princ.principal, &got) == 0) {
krb5_warnx(context, "kadmin:get: do_get_entry: kadm5_get_principal succeeded: principal=%s kvno=%d n_key_data=%d (pid=%d)",
got ? got : "<unparsed>",
princ.kvno,
princ.n_key_data,
(int)getpid());
} else {
krb5_warnx(context, "kadmin:get: do_get_entry: kadm5_get_principal succeeded: <unparsed principal> kvno=%d n_key_data=%d (pid=%d)",
princ.kvno, princ.n_key_data, (int)getpid());
}
free(got);
}
(e->format)(e, &princ);
kadm5_free_principal_ent(e->kadm_handle, &princ);
} else {
/* Failure: log explicit error so we can trace failing lookups.
*
* Guard the unparse call similarly to above.
*/
{
char *want2 = NULL;
if (principal != NULL && krb5_unparse_name(context, principal, &want2) == 0 && want2 != NULL) {
krb5_warn(context, ret, "kadmin:get: do_get_entry: kadm5_get_principal(%s) failed (pid=%d)",
want2, (int)getpid());
} else {
krb5_warn(context, ret, "kadmin:get: do_get_entry: kadm5_get_principal(<unparsed>) failed (pid=%d)",
(int)getpid());
}
free(want2);
}
}
e->n++;
@@ -627,8 +686,14 @@ getit(struct get_options *opt, const char *name, int argc, char **argv)
return 0;
}
for(i = 0; i < argc; i++)
for(i = 0; i < argc; i++) {
/* Loud tracing: announce each foreach_principal invocation */
krb5_warnx(context, "kadmin:get: getit: invoking foreach_principal for arg[%d]=%s (call %d of %d) (pid=%d)",
i, argv[i] ? argv[i] : "<null>", i+1, argc, (int)getpid());
ret = foreach_principal(argv[i], do_get_entry, name, &data);
if (ret)
krb5_warn(context, ret, "kadmin:get: getit: foreach_principal(%s) returned error", argv[i] ? argv[i] : "<null>");
}
kadm5_destroy(data.kadm_handle);
+120 -19
View File
@@ -32,30 +32,131 @@
*/
#include "kadmin_locl.h"
#include <base64.h>
#define RANDOM_PASSWORD_BYTES 12
/* This file defines some a function that generates a random password,
that can be used when creating a large amount of principals (such
as for a batch of students). Since this is a political matter, you
should think about how secure generated passwords has to be.
Both methods defined here will give you at least 55 bits of
entropy.
*/
/* If you want OTP-style passwords, define OTP_STYLE */
#ifdef OTP_STYLE
#include <otp.h>
#else
static void generate_password(char **pw, int num_classes, ...);
#endif
void
random_password(char *pw, size_t len)
{
unsigned char random[RANDOM_PASSWORD_BYTES];
char *password = NULL;
size_t password_len;
#ifdef OTP_STYLE
{
OtpKey newkey;
if (len == 0)
return;
krb5_generate_random_block(random, sizeof(random));
if (rk_base64url_encode(random, sizeof(random), &password) < 0 ||
password == NULL) {
memset_s(random, sizeof(random), 0, sizeof(random));
krb5_abortx(NULL, "Failed to encode random password");
krb5_generate_random_block(&newkey, sizeof(newkey));
otp_print_stddict (newkey, pw, len);
strlwr(pw);
}
password_len = strlen(password);
strlcpy(pw, password, len);
memset_s(random, sizeof(random), 0, sizeof(random));
memset_s(password, password_len, 0, password_len);
free(password);
#else
char *pass;
generate_password(&pass, 3,
"abcdefghijklmnopqrstuvwxyz", 7,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2,
"@$%&*()-+=:,/<>1234567890", 1);
strlcpy(pw, pass, len);
len = strlen(pass);
memset_s(pass, len, 0, len);
free(pass);
#endif
}
/* some helper functions */
#ifndef OTP_STYLE
/* return a random value in range 0-127 */
static int
RND(unsigned char *key, int keylen, int *left)
{
if(*left == 0){
krb5_generate_random_block(key, keylen);
*left = keylen;
}
(*left)--;
return ((unsigned char*)key)[*left];
}
/* This a helper function that generates a random password with a
number of characters from a set of character classes.
If there are n classes, and the size of each class is Pi, and the
number of characters from each class is Ni, the number of possible
passwords are (given that the character classes are disjoint):
n n
----- / ---- \
| | Ni | \ |
| | Pi | \ Ni| !
| | ---- * | / |
| | Ni! | /___ |
i=1 \ i=1 /
Since it uses the RND function above, neither the size of each
class, nor the total length of the generated password should be
larger than 127 (without fixing RND).
*/
static void
generate_password(char **pw, int num_classes, ...)
{
struct {
const char *str;
int len;
int freq;
} *classes;
va_list ap;
int len, i;
unsigned char rbuf[8]; /* random buffer */
int rleft = 0;
*pw = NULL;
classes = malloc(num_classes * sizeof(*classes));
if(classes == NULL)
return;
va_start(ap, num_classes);
len = 0;
for(i = 0; i < num_classes; i++){
classes[i].str = va_arg(ap, const char*);
classes[i].len = strlen(classes[i].str);
classes[i].freq = va_arg(ap, int);
len += classes[i].freq;
}
va_end(ap);
*pw = malloc(len + 1);
if(*pw == NULL) {
free(classes);
return;
}
for(i = 0; i < len; i++) {
int j;
int x = RND(rbuf, sizeof(rbuf), &rleft) % (len - i);
int t = 0;
for(j = 0; j < num_classes; j++) {
if(x < t + classes[j].freq) {
(*pw)[i] = classes[j].str[RND(rbuf, sizeof(rbuf), &rleft)
% classes[j].len];
classes[j].freq--;
break;
}
t += classes[j].freq;
}
}
(*pw)[len] = '\0';
memset_s(rbuf, sizeof(rbuf), 0, sizeof(rbuf));
free(classes);
}
#endif
+24
View File
@@ -624,7 +624,31 @@ proc_get_principal(kadm5_server_context *contextp,
if(ret)
goto fail;
/* Loud tracing: log which client requested this GET and what principal is being looked up */
{
char *want = NULL;
(void) krb5_unparse_name(contextp->context, princ, &want);
krb5_warnx(contextp->context,
"proc_get_principal: received GET request for principal=%s mask=0x%x (pid=%d ppid=%d uid=%d)",
want ? want : "<unparsed>",
mask,
(int)getpid(),
(int)getppid(),
(int)getuid());
free(want);
}
ret = kadm5_get_principal(contextp, princ, &ent, mask);
if (ret) {
/* Extra log to make failures obvious at the call site */
char *want2 = NULL;
(void) krb5_unparse_name(contextp->context, princ, &want2);
krb5_warn(contextp->context, ret,
"proc_get_principal: kadm5_get_principal failed for principal=%s (pid=%d)",
want2 ? want2 : "<unparsed>",
(int)getpid());
free(want2);
}
fail:
krb5_warn(contextp->context, ret, "get principal principal");
+5
View File
@@ -226,6 +226,8 @@ kadmind_dispatch_int(void *kadm_handlep, krb5_boolean initial,
ret_sp = krb5_store_int32(rsp, KADM5_FAILURE);
goto fail;
}
/* Debug: record which client and numeric command we received */
krb5_warnx(contextp->context, "kadmind_dispatch: received request from client=%s cmd=%d", client, cmd);
switch(cmd){
case kadm_nop:{
@@ -268,6 +270,8 @@ kadmind_dispatch_int(void *kadm_handlep, krb5_boolean initial,
mask |= KADM5_PRINCIPAL;
krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
krb5_warnx(contextp->context, "%s: %s %s", client, op, name);
/* Debug: include mask/keys_ok context so we can correlate admin requests to keytab lookups */
krb5_warnx(contextp->context, "kadmind_dispatch: GET invoked by %s for %s (mask=0x%x, keys_ok=%d)", client, name, mask, keys_ok);
/* If the caller doesn't have KADM5_PRIV_GET, we're done. */
ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_GET, princ);
@@ -307,6 +311,7 @@ kadmind_dispatch_int(void *kadm_handlep, krb5_boolean initial,
}
}
krb5_warnx(contextp->context, "kadmind_dispatch: calling kadm5_get_principal for %s (mask=0x%x, keys_ok=%d)", name, mask, keys_ok);
ret = kadm5_get_principal(kadm_handlep, princ, &ent, mask);
ret_sp = krb5_store_int32(rsp, ret);
if (ret == 0) {
+1 -44
View File
@@ -68,49 +68,6 @@ test_time(void)
return errors;
}
static int
test_random_password(void)
{
static const char alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
char pw[128];
char small[5];
char zero[1] = { 'x' };
size_t i, j;
int errors = 0;
for (i = 0; i < 128; i++) {
random_password(pw, sizeof(pw));
if (strlen(pw) != 16) {
printf("wrong random password length: %lu\n",
(unsigned long)strlen(pw));
errors++;
}
for (j = 0; pw[j] != '\0'; j++) {
if (strchr(alphabet, pw[j]) == NULL) {
printf("random password contains invalid byte: 0x%02x\n",
(unsigned char)pw[j]);
errors++;
}
}
}
random_password(small, sizeof(small));
if (strlen(small) != sizeof(small) - 1) {
printf("wrong short random password length: %lu\n",
(unsigned long)strlen(small));
errors++;
}
random_password(zero, 0);
if (zero[0] != 'x') {
printf("zero-length random password buffer was modified\n");
errors++;
}
return errors;
}
int
main(int argc, char **argv)
@@ -125,9 +82,9 @@ main(int argc, char **argv)
ret = 0;
ret += test_time();
ret += test_random_password();
krb5_free_context(context);
return ret;
}
+4 -6
View File
@@ -460,7 +460,6 @@ fast_unwrap_request(astgs_request_t r,
char *armor_client_principal_name = NULL;
char *armor_server_principal_name = NULL;
PA_FX_FAST_REQUEST fxreq;
krb5_auth_context free_ac = NULL;
krb5_auth_context ac = NULL;
krb5_ticket *ticket = NULL;
krb5_flags ap_req_options;
@@ -582,7 +581,7 @@ fast_unwrap_request(astgs_request_t r,
goto out;
}
ret = krb5_verify_ap_req2(r->context, &free_ac,
ret = krb5_verify_ap_req2(r->context, &ac,
&ap_req,
armor_server_principal,
&r->armor_key->key,
@@ -594,8 +593,6 @@ fast_unwrap_request(astgs_request_t r,
if (ret)
goto out;
ac = free_ac;
ret = krb5_unparse_name(r->context, armor_server_principal,
&armor_server_principal_name);
if (ret)
@@ -624,6 +621,7 @@ fast_unwrap_request(astgs_request_t r,
"<out of memory>");
if (ac->remote_subkey == NULL) {
krb5_auth_con_free(r->context, ac);
kdc_log(r->context, r->config, 2,
"FAST AP-REQ remote subkey missing");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
@@ -749,8 +747,8 @@ fast_unwrap_request(astgs_request_t r,
kdc_log(r->context, r->config, 5, "Client selected FAST");
out:
if (free_ac)
krb5_auth_con_free(r->context, free_ac);
if (ac && ac != tgs_ac)
krb5_auth_con_free(r->context, ac);
krb5_free_principal(r->context, armor_server_principal);
krb5_xfree(armor_client_principal_name);
+1 -28
View File
@@ -51,7 +51,7 @@ static const char *kdc_plugin_deps[] = {
static struct heim_plugin_data kdc_plugin_data = {
"krb5",
"kdc",
KRB5_PLUGIN_KDC_VERSION_11,
KRB5_PLUGIN_KDC_VERSION_10,
kdc_plugin_deps,
kdc_get_instance
};
@@ -239,33 +239,6 @@ _kdc_referral_policy(astgs_request_t r)
return ret;
}
static krb5_error_code KRB5_LIB_CALL
hwauth_policy(krb5_context context, const void *plug, void *plugctx, void *userctx)
{
const krb5plugin_kdc_ftable *ft = plug;
if (ft->hwauth_policy == NULL) {
return KRB5_PLUGIN_NO_HANDLE;
}
return ft->hwauth_policy(rk_UNCONST(plug), userctx);
}
krb5_error_code
_kdc_hwauth_policy(astgs_request_t r)
{
krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
if (have_plugin) {
ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, hwauth_policy);
}
if (ret != KRB5_PLUGIN_NO_HANDLE) {
return ret;
}
return r->client->flags.require_hwauth ? KRB5KDC_ERR_POLICY : 0;
}
static krb5_error_code KRB5_LIB_CALL
finalize_reply(krb5_context context, const void *plug, void *plugctx, void *userctx)
{
+1 -12
View File
@@ -95,16 +95,6 @@ typedef krb5_error_code
typedef krb5_error_code
(KRB5_CALLCONV *krb5plugin_kdc_referral_policy)(void *, astgs_request_t);
/*
* A hardware authentication policy plugin can indicate what is to
* happen when a client authenticates using a method other than
* hardware authentication. It can return zero to allow the
* authentication, or an appropriate error code to deny it.
*/
typedef krb5_error_code
(KRB5_CALLCONV *krb5plugin_kdc_hwauth_policy)(void *, astgs_request_t);
/*
* Update the AS or TGS reply immediately prior to encoding.
*/
@@ -127,7 +117,7 @@ typedef krb5_error_code
* Plugins should carefully check API contract notes for changes
* between plugin API versions.
*/
#define KRB5_PLUGIN_KDC_VERSION_11 11
#define KRB5_PLUGIN_KDC_VERSION_10 10
typedef struct krb5plugin_kdc_ftable {
HEIM_PLUGIN_FTABLE_COMMON_ELEMENTS(krb5_context);
@@ -135,7 +125,6 @@ typedef struct krb5plugin_kdc_ftable {
krb5plugin_kdc_pac_verify pac_verify;
krb5plugin_kdc_client_access client_access;
krb5plugin_kdc_referral_policy referral_policy;
krb5plugin_kdc_hwauth_policy hwauth_policy;
krb5plugin_kdc_finalize_reply finalize_reply;
krb5plugin_kdc_audit audit;
} krb5plugin_kdc_ftable;
+1 -1
View File
@@ -228,5 +228,5 @@ There should be a way to specify protocol, port, and address triplets,
not just addresses and protocol, port tuples.
.Sh SEE ALSO
.Xr kinit 1 ,
.Xr krb5.conf 5 ,
.Xr krb5.conf 5,
.Xr getservbyname 3
+13 -19
View File
@@ -37,15 +37,16 @@
#if SIZEOF_TIME_T == 4
#define MAX_TIME ((time_t)INT32_MAX)
#elif SIZEOF_TIME_T == 8
#define MAX_TIME ((time_t)INT64_MAX)
#define MAX_TIME ((time_t)INT32_MAX)
#else
#error "Unexpected sizeof(time_t)"
#endif
#else
#if SIZEOF_TIME_T == 4
#define MAX_TIME ((time_t)UINT32_MAX)
#define MAX_TIME ((time_t)INT32_MAX)
#else
#define MAX_TIME ((time_t)UINT64_MAX)
#define MAX_TIME ((time_t)INT32_MAX)
#endif
#endif
@@ -535,11 +536,7 @@ pa_pkinit_validate(astgs_request_t r, const PA_DATA *pa)
ret = _kdc_pk_rd_padata(r, pa, &pkp);
if (ret || pkp == NULL) {
if (ret == KRB5_KDC_ERR_REVOKED_CERTIFICATE) {
ret = KRB5_KDC_ERR_CLIENT_NOT_TRUSTED;
} else {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
}
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
_kdc_r_log(r, 4, "Failed to decode PKINIT PA-DATA -- %s",
r->cname);
goto out;
@@ -938,9 +935,6 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
goto out;
}
free_EncryptedData(&enc_data);
if (ret) {
goto out;
}
ret = decode_PA_ENC_TS_ENC(ts_data.data,
ts_data.length,
&p,
@@ -952,7 +946,7 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
r->cname);
goto out;
}
if (krb5_time_abs(kdc_time, p.patimestamp) > r->context->max_skew) {
if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
char client_time[100];
krb5_format_time(r->context, p.patimestamp,
@@ -962,7 +956,7 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
_kdc_r_log(r, 4, "Too large time skew, "
"client time %s is out by %u > %u seconds -- %s",
client_time,
(unsigned)krb5_time_abs(kdc_time, p.patimestamp),
(unsigned)labs(kdc_time - p.patimestamp),
r->context->max_skew,
r->cname);
kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
@@ -2269,12 +2263,12 @@ _kdc_as_rep(astgs_request_t r)
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto out;
}
if (!(pat[n].flags & PA_HARDWARE_AUTH)) {
ret = _kdc_hwauth_policy(r);
if (ret) {
kdc_log(r->context, config, 4, "Hardware authentication required for %s", r->cname);
goto out;
}
if (r->client->flags.require_hwauth &&
!(pat[n].flags & PA_HARDWARE_AUTH)) {
kdc_log(r->context, config, 4, "Hardware authentication required for %s", r->cname);
ret = KRB5KDC_ERR_POLICY;
goto out;
}
kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
pat[n].name);
+19 -12
View File
@@ -399,6 +399,7 @@ mk_error_response(krb5_context context,
Kx509Response rep;
const char *msg;
char *freeme0 = NULL;
char *freeme1 = NULL;
va_list ap;
if (code != 0) {
@@ -416,6 +417,9 @@ mk_error_response(krb5_context context,
va_end(ap);
}
if (!reqctx->config->enable_kx509)
code = KRB5KDC_ERR_POLICY;
/* Make sure we only send RFC4120 and friends wire protocol error codes */
if (code) {
if (code == KX509_ERR_NONE) {
@@ -437,6 +441,12 @@ mk_error_response(krb5_context context,
msg = freeme0;
va_end(ap);
if (!reqctx->config->enable_kx509 &&
asprintf(&freeme1, "kx509 service is disabled (%s)", msg) > -1 &&
freeme1 != NULL) {
msg = freeme1;
}
rep.hash = NULL;
rep.certificate = NULL;
rep.error_code = code;
@@ -458,6 +468,7 @@ mk_error_response(krb5_context context,
free(rep.e_text);
free(rep.hash);
free(freeme0);
free(freeme1);
return ret;
}
@@ -889,15 +900,14 @@ _kdc_do_kx509(kx509_req_context r)
if (r->req.authenticator.length == 0) {
/*
* Unauthenticated kx509 service availability probe.
*
* mk_error_response() will check whether the service is enabled and
* possibly change the error code and message.
*/
is_probe = 1;
kdc_audit_addkv((kdc_request_t)r, 0, "probe", "unauthenticated");
if (!r->config->enable_kx509)
ret = mk_error_response(r->context, r, 4, KRB5KDC_ERR_POLICY,
"kx509 service is disabled");
else
ret = mk_error_response(r->context, r, 4, 0,
"kx509 service is available");
ret = mk_error_response(r->context, r, 4, 0,
"kx509 service is available");
goto out;
}
@@ -928,12 +938,6 @@ _kdc_do_kx509(kx509_req_context r)
* Provided we got the session key, errors past this point will be
* authenticated.
*/
if (ret == 0 && !r->config->enable_kx509) {
ret = mk_error_response(r->context, r, 4, KRB5KDC_ERR_POLICY,
"kx509 service is disabled");
goto out;
}
if (ret == 0)
ret = krb5_ticket_get_client(r->context, ticket, &cprincipal);
@@ -979,6 +983,9 @@ _kdc_do_kx509(kx509_req_context r)
if (r->req.pk_key.length == 0) {
/*
* The request is an authenticated kx509 service availability probe.
*
* mk_error_response() will check whether the service is enabled and
* possibly change the error code and message.
*/
is_probe = 1;
kdc_audit_addkv((kdc_request_t)r, 0, "probe", "authenticated");
+2 -4
View File
@@ -432,7 +432,7 @@ pk_check_pkauthenticator_win2k(krb5_context context,
krb5_timeofday (context, &now);
/* XXX cusec */
if (a->ctime == 0 || krb5_time_abs(a->ctime, now) > context->max_skew) {
if (a->ctime == 0 || labs(a->ctime - now) > context->max_skew) {
krb5_clear_error_message(context);
return KRB5KRB_AP_ERR_SKEW;
}
@@ -451,7 +451,7 @@ pk_check_pkauthenticator(krb5_context context,
krb5_timeofday (context, &now);
/* XXX cusec */
if (a->ctime == 0 || krb5_time_abs(a->ctime, now) > context->max_skew) {
if (a->ctime == 0 || labs(a->ctime - now) > context->max_skew) {
krb5_clear_error_message(context);
return KRB5KRB_AP_ERR_SKEW;
}
@@ -797,8 +797,6 @@ _kdc_pk_rd_padata(astgs_request_t priv,
hx509_verify_attach_anchors(cp->verify_ctx, trust_anchors);
hx509_certs_free(&trust_anchors);
hx509_verify_attach_revoke(cp->verify_ctx, kdc_identity->revokectx);
if (config->pkinit_allow_proxy_certs)
hx509_verify_set_proxy_certificate(cp->verify_ctx, 1);
+2 -4
View File
@@ -1104,8 +1104,7 @@ get_new_tickets(krb5_context context,
}
if (ticket_life != 0) {
if (krb5_time_abs(cred.times.endtime - cred.times.starttime,
ticket_life) > 30) {
if (labs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) {
char life[64];
unparse_time_approx(cred.times.endtime - cred.times.starttime,
life, sizeof(life));
@@ -1113,8 +1112,7 @@ get_new_tickets(krb5_context context,
}
}
if (renew_life) {
if (krb5_time_abs(cred.times.renew_till - cred.times.starttime,
renew) > 30) {
if (labs(cred.times.renew_till - cred.times.starttime - renew) > 30) {
char life[64];
unparse_time_approx(cred.times.renew_till - cred.times.starttime,
life, sizeof(life));
+4
View File
@@ -1,5 +1,8 @@
include $(top_srcdir)/Makefile.am.common
if LIBEDIT
dir_editline = libedit
endif
if DCE
dir_dce = kdfs
endif
@@ -18,6 +21,7 @@ SUBDIRS = \
vers \
$(dir_com_err) \
base \
$(dir_editline) \
sl \
wind \
asn1 \
+1 -3
View File
@@ -97,10 +97,8 @@ der_print_hex_heim_integer (const heim_integer *data, char **p)
if (data->negative) {
len = asprintf(&q, "-%s", *p);
free(*p);
if (len < 0) {
*p = NULL;
if (len < 0)
return ENOMEM;
}
*p = q;
}
return 0;
-3
View File
@@ -191,7 +191,6 @@ init_generate (const char *filename, const char *base)
fprintf (headerfile,
"#include <stddef.h>\n"
"#include <stdint.h>\n"
"#include <errno.h>\n"
"#include <time.h>\n\n");
fprintf (headerfile,
"#ifndef __asn1_common_definitions__\n"
@@ -600,8 +599,6 @@ generate_constant (const Symbol *s)
/* header file */
gen_upper = strdup(s->gen_name);
if (gen_upper == NULL)
errx(1, "malloc");
len = strlen(gen_upper);
for (i = 0; i < len; i++)
gen_upper[i] = toupper((unsigned char)s->gen_name[i]);
-6
View File
@@ -289,11 +289,7 @@ static struct tlist *
tlist_new(const char *name)
{
struct tlist *tl = calloc(1, sizeof(*tl));
if (tl == NULL)
errx(1, "malloc");
tl->name = strdup(name);
if (tl->name == NULL)
errx(1, "malloc");
HEIM_TAILQ_INIT(&tl->template);
return tl;
}
@@ -425,8 +421,6 @@ add_line(struct templatehead *t, const char *fmt, ...)
{
struct template *q = calloc(1, sizeof(*q));
va_list ap;
if (q == NULL)
errx(1, "malloc");
va_start(ap, fmt);
if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL)
errx(1, "malloc");
+14 -22
View File
@@ -38,26 +38,12 @@
#include <vis.h>
#include <vis-extras.h>
#include <heimbase.h>
#include <errno.h>
#ifndef ENOTSUP
/* Very old MSVC CRTs don't have ENOTSUP */
#define ENOTSUP EINVAL
#endif
static int
int32_ptr_equal(int32_t i, const void *ptr)
{
const intptr_t v = (intptr_t)ptr;
#if INTPTR_MAX > INT32_MAX || INTPTR_MIN < INT32_MIN
if (v > INT32_MAX || v < INT32_MIN)
return 0;
#endif
return i == (int32_t)v;
}
struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = {
#define el(name, type) { \
(asn1_type_encode)der_put_##name, \
@@ -1507,7 +1493,9 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
} else if (tdefval->tt & A1_DV_INTEGER32) {
const int32_t *i = el;
if (int32_ptr_equal(*i, tdefval->ptr))
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
*i == (int32_t)(intptr_t)tdefval->ptr)
break;
} else if (tdefval->tt & A1_DV_INTEGER) {
const struct heim_integer *i = el;
@@ -1579,7 +1567,9 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
} else if (tdefval->tt & A1_DV_INTEGER32) {
const int32_t *i = data;
if (int32_ptr_equal(*i, tdefval->ptr))
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
*i == (int32_t)(intptr_t)tdefval->ptr)
exclude = 1;
} else if (tdefval->tt & A1_DV_INTEGER) {
const struct heim_integer *i = data;
@@ -2082,7 +2072,9 @@ _asn1_length(const struct asn1_template *t, const void *data)
} else if (tdefval->tt & A1_DV_INTEGER32) {
const int32_t *i = el;
if (int32_ptr_equal(*i, tdefval->ptr))
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
*i == (int32_t)(intptr_t)tdefval->ptr)
break;
} else if (tdefval->tt & A1_DV_INTEGER) {
const struct heim_integer *i = el;
@@ -2139,7 +2131,9 @@ _asn1_length(const struct asn1_template *t, const void *data)
} else if (tdefval->tt & A1_DV_INTEGER32) {
const int32_t *i = data;
if (int32_ptr_equal(*i, tdefval->ptr))
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
*i == (int32_t)(intptr_t)tdefval->ptr)
exclude = 1;
} else if (tdefval->tt & A1_DV_INTEGER) {
const struct heim_integer *i = data;
@@ -2489,10 +2483,8 @@ _asn1_print_open_type(const struct asn1_template *t, /* object set template */
}
if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
size_t offset = t->offset + sizeof(*elementp);
offset += (sizeof(void *) - offset % sizeof(void *)) % sizeof(void *);
dp = DPOC(data, offset);
unsigned align = 8 - ((t->offset + sizeof(*elementp)) & 0x7);
dp = DPOC(data, t->offset + sizeof(*elementp) + align);
if (*dp) {
struct rk_strpool *r2 = NULL;
char *s = NULL;
+2 -17
View File
@@ -46,21 +46,6 @@ static const unsigned ndays[2][12] ={
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
static time_t
_clamp_time_t(uint64_t t)
{
#if SIZEOF_TIME_T < 8
#ifdef TIME_T_UNSIGNED
#define MAX_TIME ((UINT64_C(1) << (SIZEOF_TIME_T * 8)) - 1)
#else
#define MAX_TIME ((UINT64_C(1) << ((SIZEOF_TIME_T * 8) - 1)) - 1)
#endif
return t < MAX_TIME ? t : MAX_TIME;
#else
return t;
#endif
}
/*
* This is a simplifed version of timegm(3) that doesn't accept out of
* bound values that timegm(3) normally accepts but those are not
@@ -70,7 +55,7 @@ _clamp_time_t(uint64_t t)
time_t
_der_timegm (struct tm *tm)
{
uint64_t res = 0;
time_t res = 0;
int i;
/*
@@ -104,7 +89,7 @@ _der_timegm (struct tm *tm)
res += tm->tm_min;
res *= 60;
res += tm->tm_sec;
return _clamp_time_t(res);
return res;
}
struct tm *
+3 -23
View File
@@ -86,26 +86,6 @@ static heim_error_code parse_list(struct fileptr *f, unsigned *lineno,
heim_config_binding **parent,
const char **err_message);
static int
todash(int c)
{
if (c == '_')
return '-';
return c;
}
static int
strcmp_du(const char *s1, const char *s2)
{
while (todash((unsigned char)*s1) == todash((unsigned char)*s2)) {
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return todash((unsigned char)*s1) - todash((unsigned char)*s2);
}
heim_config_section *
heim_config_get_entry(heim_config_section **parent, const char *name, int type)
{
@@ -114,7 +94,7 @@ heim_config_get_entry(heim_config_section **parent, const char *name, int type)
for (q = parent; *q != NULL; q = &(*q)->next)
if (type == heim_config_list &&
(unsigned)type == (*q)->type &&
strcmp_du(name, (*q)->name) == 0)
strcmp(name, (*q)->name) == 0)
return *q;
*q = calloc(1, sizeof(**q));
if (*q == NULL)
@@ -808,7 +788,7 @@ vget_next(heim_context context,
const char *p = va_arg(args, const char *);
while (b != NULL) {
if (strcmp_du(b->name, name) == 0) {
if (strcmp(b->name, name) == 0) {
if (b->type == (unsigned)type && p == NULL) {
*pointer = b;
return b->u.generic;
@@ -846,7 +826,7 @@ heim_config_vget_next(heim_context context,
/* we were called again, so just look for more entries with the
same name and type */
for (b = (*pointer)->next; b != NULL; b = b->next) {
if(strcmp_du(b->name, (*pointer)->name) == 0 && b->type == (unsigned)type) {
if(strcmp(b->name, (*pointer)->name) == 0 && b->type == (unsigned)type) {
*pointer = b;
return b->u.generic;
}
+9 -28
View File
@@ -355,12 +355,11 @@ open_file(heim_context context, heim_log_facility *fac, int min, int max,
return ret;
}
static heim_error_code
addlog_dest(heim_context context, heim_log_facility *f,
const char *orig, int default_min, int default_max)
heim_error_code
heim_addlog_dest(heim_context context, heim_log_facility *f, const char *orig)
{
heim_error_code ret = 0;
int min = default_min, max = default_max, n;
int min = 0, max = 3, n;
char c;
const char *p = orig;
#ifdef _WIN32
@@ -394,6 +393,8 @@ addlog_dest(heim_context context, heim_log_facility *f,
return HEIM_ERR_LOG_PARSE;
}
p++;
} else {
max = 5;
}
if (strcmp(p, "STDERR") == 0) {
ret = open_file(context, f, min, max, NULL, "a", stderr,
@@ -444,12 +445,6 @@ addlog_dest(heim_context context, heim_log_facility *f,
return ret;
}
heim_error_code
heim_addlog_dest(heim_context context, heim_log_facility *f, const char *orig)
{
return addlog_dest(context, f, orig, 0, 5);
}
heim_error_code
heim_openlog(heim_context context,
const char *program,
@@ -653,9 +648,9 @@ heim_add_warn_dest(heim_context context, const char *program,
return 0;
}
static heim_error_code
add_debug_dest(heim_context context, const char *program,
const char *log_spec, int default_min, int default_max)
heim_error_code
heim_add_debug_dest(heim_context context, const char *program,
const char *log_spec)
{
heim_log_facility *fac;
heim_error_code ret;
@@ -667,26 +662,12 @@ add_debug_dest(heim_context context, const char *program,
heim_set_debug_dest(context, fac);
}
ret = addlog_dest(context, fac, log_spec, default_min, default_max);
ret = heim_addlog_dest(context, fac, log_spec);
if (ret)
return ret;
return 0;
}
heim_error_code
heim_add_debug_dest(heim_context context, const char *program,
const char *log_spec)
{
return add_debug_dest(context, program, log_spec, 0, 5);
}
heim_error_code
heim_add_trace_dest(heim_context context, const char *program,
const char *log_spec)
{
return add_debug_dest(context, program, log_spec, 0, -1);
}
struct heim_audit_kv_tuple {
heim_string_t key;
heim_object_t value;
-78
View File
@@ -142,83 +142,6 @@ test_rwlock(void)
return 0;
}
static int
file_contains(const char *filename, const char *needle)
{
char buf[1024];
FILE *f;
int found = 0;
f = fopen(filename, "r");
if (f == NULL)
return 0;
while (fgets(buf, sizeof(buf), f) != NULL) {
if (strstr(buf, needle) != NULL) {
found = 1;
break;
}
}
fclose(f);
return found;
}
static int
test_log_dest(void)
{
const char *normal = "test-log-dest.log";
const char *trace = "test-trace-dest.log";
const char *explicit = "test-trace-explicit-dest.log";
heim_log_facility *fac = NULL;
heim_context context;
int ret;
unlink(normal);
unlink(trace);
unlink(explicit);
context = heim_context_init();
heim_assert(context != NULL, "heim_context_init failed");
ret = heim_initlog(context, "test_base", &fac);
heim_assert(ret == 0, "heim_initlog failed");
ret = heim_addlog_dest(context, fac, normal);
heim_assert(ret == 0, "heim_addlog_dest failed");
heim_log(context, fac, 10, "normal level 10");
heim_log(context, fac, 5, "normal level 5");
heim_closelog(context, fac);
heim_assert(!file_contains(normal, "normal level 10"),
"normal log destination traced level 10 by default");
heim_assert(file_contains(normal, "normal level 5"),
"normal log destination did not log level 5 by default");
ret = heim_add_trace_dest(context, "test_base", trace);
heim_assert(ret == 0, "heim_add_trace_dest failed");
ret = heim_add_trace_dest(context, "test_base",
"5/FILE:test-trace-explicit-dest.log");
heim_assert(ret == 0, "heim_add_trace_dest with explicit level failed");
heim_debug(context, 10, "trace level 10");
heim_debug(context, 5, "trace level 5");
heim_assert(file_contains(trace, "trace level 10"),
"trace log destination did not trace level 10 by default");
heim_assert(!file_contains(explicit, "trace level 10"),
"explicit trace destination ignored its level filter");
heim_assert(file_contains(explicit, "trace level 5"),
"explicit trace destination did not log matching level");
heim_context_free(&context);
unlink(normal);
unlink(trace);
unlink(explicit);
return 0;
}
static int
test_dict(void)
{
@@ -1442,7 +1365,6 @@ main(int argc, char **argv)
res |= test_memory();
res |= test_mutex();
res |= test_rwlock();
res |= test_log_dest();
res |= test_dict();
res |= test_auto_release();
res |= test_string();
-1
View File
@@ -10,7 +10,6 @@ HEIMDAL_BASE_1.0 {
heim_abort;
heim_abortv;
heim_add_debug_dest;
heim_add_trace_dest;
heim_add_et_list;
heim_addlog_dest;
heim_addlog_func;
-6
View File
@@ -15,7 +15,6 @@
.Fl r
.Op Fl MNln
.Op Fl C Ar ccache
.Op Fl L Ar localuser
.Op Fl S Ar maxsize
.Op Fl c count
.Op Fl m mech
@@ -36,11 +35,6 @@ write an accepted delegated credential into
This only makes sense if
.Fl r
is specified.
.It Fl L Ar localuser
try to authorize as
.Ar localuser
with
.Fn gss_authorize_localname .
.It Fl D
delegate credentials.
This only makes sense as a client, that is when
+7 -37
View File
@@ -435,13 +435,11 @@ initiate_many(gss_name_t service, int delegate, int negotiate, int memcache,
}
static int
accept_one(gss_name_t service, const char *ccname, const char *localuser,
int negotiate)
accept_one(gss_name_t service, const char *ccname, int negotiate)
{
gss_cred_id_t cred = NULL;
gss_cred_id_t deleg_creds = NULL;
gss_name_t client = GSS_C_NO_NAME;
gss_name_t lname = GSS_C_NO_NAME;
gss_name_t client;
gss_OID mech_oid;
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
gss_buffer_desc in = GSS_C_EMPTY_BUFFER;
@@ -497,23 +495,8 @@ accept_one(gss_name_t service, const char *ccname, const char *localuser,
printf("Authenticated: %.*s\n", (int)dname.length,
(char *)dname.value);
(void) gss_release_buffer(&min, &dname);
if (localuser) {
gss_buffer_desc lnamebuf;
lnamebuf.length = strlen(localuser);
lnamebuf.value = rk_UNCONST(localuser);
maj = gss_import_name(&min, &lnamebuf,
GSS_C_NT_USER_NAME, &lname);
GBAIL("gss_import_name", maj, min);
maj = gss_authorize_localname(&min, client, lname);
GBAIL("gss_authorize_localname", maj, min);
if (!nflag)
printf("Authorized: %s\n", localuser);
}
(void) gss_release_name(&min, &client);
(void) gss_delete_sec_context(&min, &ctx, GSS_C_NO_BUFFER);
if (ccname) {
#ifdef HAVE_GSS_STORE_CRED_INTO
@@ -549,12 +532,6 @@ bail:
gss_release_cred(&min, &cred);
if (deleg_creds)
gss_release_cred(&min, &deleg_creds);
if (lname)
gss_release_name(&min, &lname);
if (client)
gss_release_name(&min, &client);
if (ctx != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&min, &ctx, GSS_C_NO_BUFFER);
free(in.value);
@@ -608,8 +585,8 @@ usage(int ecode)
{
FILE *f = ecode == 0 ? stdout : stderr;
fprintf(f, "Usage: gss-token [-DNn] [-c count] service@host\n");
fprintf(f, " gss-token -r [-Nln] [-C ccache] [-L localuser] "
"[-c count] [service@host]\n");
fprintf(f, " gss-token -r [-Nln] [-C ccache] [-c count] "
"[service@host]\n");
exit(ecode);
}
@@ -629,14 +606,12 @@ main(int argc, char **argv)
int ret = 0;
int optidx = 0;
char *ccname = NULL;
char *localuser = NULL;
char *mech = NULL;
struct getargs args[] = {
{ "help", 'h', arg_flag, &hflag, NULL, NULL },
{ "version", 0, arg_flag, &version_flag, NULL, NULL },
{ NULL, 'C', arg_string, &ccname, NULL, NULL },
{ NULL, 'D', arg_flag, &Dflag, NULL, NULL },
{ NULL, 'L', arg_string, &localuser, NULL, NULL },
{ NULL, 'M', arg_flag, &Mflag, NULL, NULL },
{ NULL, 'N', arg_flag, &Nflag, NULL, NULL },
{ NULL, 'S', arg_integer, &Sflag, NULL, NULL },
@@ -687,11 +662,6 @@ main(int argc, char **argv)
"make sense without -r.\n");
usage(1);
}
if (localuser) {
fprintf(stderr, "Specifying a local user doesn't make "
"sense without -r.\n");
usage(1);
}
ret = initiate_many(service, Dflag, Nflag, Mflag, count);
goto done;
}
@@ -703,7 +673,7 @@ main(int argc, char **argv)
}
do {
ret = accept_one(service, ccname, localuser, Nflag);
ret = accept_one(service, ccname, Nflag);
} while (lflag && !ret && !feof(stdin));
done:
+1 -1
View File
@@ -926,7 +926,7 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred_from
NULL, time_rec, NULL, actual_mechs);
if (ret != GSS_S_COMPLETE) {
if (handle->mechanisms != NULL)
gss_release_oid_set(minor_status, &handle->mechanisms);
gss_release_oid_set(NULL, &handle->mechanisms);
HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
krb5_free_principal(context, handle->principal);
free(handle);
+1 -2
View File
@@ -238,7 +238,6 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred_from (
failure:
if (handle) {
OM_uint32 tmp_status;
if (handle->principal)
krb5_free_principal(context, handle->principal);
if (handle->keytab)
@@ -246,7 +245,7 @@ failure:
if (handle->ccache)
krb5_cc_destroy(context, handle->ccache);
if (handle->mechanisms)
gss_release_oid_set(&tmp_status, &handle->mechanisms);
gss_release_oid_set(NULL, &handle->mechanisms);
free(handle);
}
if (cred && output_cred_handle)
+15 -15
View File
@@ -308,7 +308,7 @@ _gssapi_get_mic_arcfour(OM_uint32 * minor_status,
}
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
EVP_Cipher(rc4_key, p, p, 8) != 8) {
EVP_Cipher(rc4_key, p, p, 8) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -392,7 +392,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
}
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, (void *)k6_data, NULL, 0) != 1 ||
EVP_Cipher(rc4_key, SND_SEQ, p, 8) != 8) {
EVP_Cipher(rc4_key, SND_SEQ, p, 8) != 1) {
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
return GSS_S_FAILURE;
@@ -553,7 +553,7 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status,
}
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
EVP_Cipher(rc4_key, p0 + 24, p0 + 24, 8 + datalen) != 8 + datalen) {
EVP_Cipher(rc4_key, p0 + 24, p0 + 24, 8 + datalen) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -581,7 +581,7 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status,
}
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
EVP_Cipher(rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8) != 8) {
EVP_Cipher(rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -690,7 +690,7 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
}
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
EVP_Cipher(rc4_key, SND_SEQ, p0 + 8, 8) != 8) {
EVP_Cipher(rc4_key, SND_SEQ, p0 + 8, 8) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -747,8 +747,8 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
}
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
EVP_Cipher(rc4_key, Confounder, p0 + 24, 8) != 8 ||
EVP_Cipher(rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen) != datalen) {
EVP_Cipher(rc4_key, Confounder, p0 + 24, 8) != 1 ||
EVP_Cipher(rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -1149,7 +1149,7 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
/* Confounder */
EVP_Cipher(rc4_key, p0 + 24, p0 + 24, 8) != 8) {
EVP_Cipher(rc4_key, p0 + 24, p0 + 24, 8) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -1166,7 +1166,7 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,
}
if (EVP_Cipher(rc4_key, iov[i].buffer.value,
iov[i].buffer.value, iov[i].buffer.length) != iov[i].buffer.length) {
iov[i].buffer.value, iov[i].buffer.length) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -1177,7 +1177,7 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,
/* Padding */
if (padding &&
EVP_Cipher(rc4_key, padding->buffer.value,
padding->buffer.value, padding->buffer.length) != padding->buffer.length) {
padding->buffer.value, padding->buffer.length) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -1206,7 +1206,7 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,
}
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
EVP_Cipher(rc4_key, p0 + 8, p0 + 8, 8) != 8 /* SND_SEQ */) {
EVP_Cipher(rc4_key, p0 + 8, p0 + 8, 8) != 1 /* SND_SEQ */) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -1357,7 +1357,7 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,
}
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
EVP_Cipher(rc4_key, snd_seq, p0 + 8, 8) != 8 /* SND_SEQ */) {
EVP_Cipher(rc4_key, snd_seq, p0 + 8, 8) != 1 /* SND_SEQ */) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -1410,7 +1410,7 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,
if (EVP_CIPHER_CTX_init(rc4_key) != 1 ||
EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 ||
/* Confounder */
EVP_Cipher(rc4_key, Confounder, p0 + 24, 8) != 8) {
EVP_Cipher(rc4_key, Confounder, p0 + 24, 8) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -1427,7 +1427,7 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,
}
if (EVP_Cipher(rc4_key, iov[i].buffer.value,
iov[i].buffer.value, iov[i].buffer.length) != iov[i].buffer.length) {
iov[i].buffer.value, iov[i].buffer.length) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
@@ -1438,7 +1438,7 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,
/* Padding */
if (padding &&
EVP_Cipher(rc4_key, padding->buffer.value,
padding->buffer.value, padding->buffer.length) != padding->buffer.length) {
padding->buffer.value, padding->buffer.length) != 1) {
EVP_CIPHER_CTX_free(rc4_key);
_krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL");
*minor_status = KRB5_CRYPTO_INTERNAL;
+3 -4
View File
@@ -100,12 +100,11 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_context (
return GSS_S_COMPLETE;
failed:
{ OM_uint32 tmp_status;
if (src_name)
_gsskrb5_release_name(&tmp_status, src_name);
_gsskrb5_release_name(NULL, src_name);
if (targ_name)
_gsskrb5_release_name(&tmp_status, targ_name);
}
_gsskrb5_release_name(NULL, targ_name);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
return ret;
}
+1 -2
View File
@@ -40,7 +40,6 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_mechs_for_name (
)
{
OM_uint32 ret;
OM_uint32 tmp_status;
ret = gss_create_empty_oid_set(minor_status, mech_types);
if (ret)
@@ -50,7 +49,7 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_mechs_for_name (
GSS_KRB5_MECHANISM,
mech_types);
if (ret)
gss_release_oid_set(&tmp_status, mech_types);
gss_release_oid_set(NULL, mech_types);
return ret;
}
+1 -2
View File
@@ -48,7 +48,6 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_names_for_mech (
)
{
OM_uint32 ret;
OM_uint32 tmp_status;
int i;
*minor_status = 0;
@@ -72,7 +71,7 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_names_for_mech (
}
if (ret != GSS_S_COMPLETE)
gss_release_oid_set(&tmp_status, name_types);
gss_release_oid_set(NULL, name_types);
return GSS_S_COMPLETE;
}
+2 -19
View File
@@ -83,25 +83,8 @@ set_proc(OM_uint32 *minor, gss_buffer_set_t env)
#ifndef WIN32
size_t i;
for (i = 0; i < env->count; i++) {
char *var = (char *)env->elements[i].value;
char *eq = strchr(var, '=');
char *val;
int e;
if (eq == NULL) {
*minor = EINVAL;
return GSS_S_FAILURE;
}
val = eq + 1;
*eq = '\0';
e = setenv(var, val, 1);
*eq = '=';
if (e != 0) {
*minor = errno ? errno : EINVAL;
return GSS_S_FAILURE;
}
}
for (i = 0; i < env->count; i++)
putenv(env->elements[i].value);
#endif
return GSS_S_COMPLETE;
}
+1 -10
View File
@@ -265,14 +265,12 @@ gss_accept_sec_context(OM_uint32 *minor_status,
*delegated_cred_handle = GSS_C_NO_CREDENTIAL;
_mg_buffer_zero(output_token);
_gss_mg_log(10, "gss-asc: enter ctx=%p", ctx);
if (!*context_handle) {
ctx = calloc(1, sizeof(*ctx));
if (!ctx) {
*minor_status = ENOMEM;
return (GSS_S_DEFECTIVE_TOKEN);
}
_gss_mg_log(10, "gss-asc: allocated ctx=%p", ctx);
*context_handle = (gss_ctx_id_t)ctx;
ctx->gc_initial = 1;
}
@@ -320,9 +318,6 @@ gss_accept_sec_context(OM_uint32 *minor_status,
&mech_ret_flags,
time_rec,
&delegated_mc);
_gss_mg_log(10, "gss-asc: ctx=%p tried \"%s\", "
"returned %u", ctx, m->gm_name,
major_status);
if (major_status == GSS_S_DEFECTIVE_TOKEN) {
/*
* Try to retain and output one error token for
@@ -365,9 +360,6 @@ gss_accept_sec_context(OM_uint32 *minor_status,
&mech_ret_flags,
time_rec,
&delegated_mc);
_gss_mg_log(10, "gss-asc: ctx=%p tried \"%s\", "
"returned %u", ctx, m->gm_name,
major_status);
if (major_status == GSS_S_DEFECTIVE_TOKEN) {
if (output_token->length &&
defective_token_error.length == 0) {
@@ -518,8 +510,7 @@ got_one:
}
}
_gss_mg_log(10, "gss-asc: ctx=%p return %d/%d", ctx,
(int)major_status, (int)*minor_status);
_gss_mg_log(10, "gss-asc: return %d/%d", (int)major_status, (int)*minor_status);
if (ret_flags)
*ret_flags = mech_ret_flags;
-3
View File
@@ -38,7 +38,6 @@ gss_display_name(OM_uint32 *minor_status,
struct _gss_name *name = rk_UNCONST(input_name);
struct _gss_mechanism_name *mn;
_gss_mg_log(10, "gdn: enter gss_display_name: %p", input_name);
_mg_buffer_zero(output_name_buffer);
if (output_name_type)
*output_name_type = GSS_C_NO_OID;
@@ -69,8 +68,6 @@ gss_display_name(OM_uint32 *minor_status,
return (GSS_S_COMPLETE);
} else {
HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) {
_gss_mg_log(10, "gdn: trying mech \"%s\"",
mn->gmn_mech->gm_name);
major_status = mn->gmn_mech->gm_display_name(
minor_status, mn->gmn_name,
output_name_buffer,
-34
View File
@@ -28,8 +28,6 @@
#include "mech_locl.h"
#include <vis.h>
static OM_uint32
_gss_import_export_name(OM_uint32 *minor_status,
const gss_buffer_t input_name_buffer,
@@ -46,8 +44,6 @@ _gss_import_export_name(OM_uint32 *minor_status,
gss_name_t new_canonical_name;
int composite = 0;
_gss_mg_log(10, "gin: importing exported name");
*minor_status = 0;
*output_name = 0;
@@ -173,32 +169,6 @@ _gss_import_export_name(OM_uint32 *minor_status,
return (GSS_S_COMPLETE);
}
static void
log_import_name(gss_buffer_t input_name_buffer)
{
char *name;
size_t len;
if (!_gss_mg_log_level(10))
return;
if (input_name_buffer->length > (SIZE_MAX - 1) / 4) {
_gss_mg_log(10, "gin: importing name (%zu bytes)",
input_name_buffer->length);
return;
}
len = input_name_buffer->length * 4 + 1;
name = malloc(len);
if (name == NULL)
return;
strsvisx(name, input_name_buffer->value, input_name_buffer->length,
VIS_CSTYLE | VIS_TAB | VIS_NL, "\"");
_gss_mg_log(10, "gin: importing name \"%s\"", name);
free(name);
}
/**
* Convert a GGS-API name from contiguous string to internal form.
*
@@ -260,7 +230,6 @@ gss_import_name(OM_uint32 *minor_status,
name_type, output_name);
}
log_import_name(input_name_buffer);
*minor_status = 0;
name = _gss_create_name(NULL, NULL);
@@ -293,9 +262,6 @@ gss_import_name(OM_uint32 *minor_status,
HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
int present = 0;
_gss_mg_log(10, "gin: attempting mech \"%s\"",
m->gm_mech.gm_name);
if ((m->gm_mech.gm_flags & GM_USE_MG_NAME))
continue;
+2 -5
View File
@@ -167,8 +167,7 @@ do { \
m->gm_mech.gm_ ## name = (_gss_##name##_t *)dlsym(so, "gss_" #name); \
if (!m->gm_mech.gm_ ## name || \
m->gm_mech.gm_ ##name == gss_ ## name) { \
_gss_mg_log(1, "can't find symbol gss_" #name \
" in %s", lib); \
_gss_mg_log(1, "can't find symbol gss_" #name "\n"); \
goto bad; \
} \
} while (0)
@@ -335,11 +334,9 @@ _gss_load_mech(void)
/*
* Check for duplicates, already loaded mechs.
*/
_gss_mg_log(10, "loading \"%s\"", name);
found = 0;
HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
if (gss_oid_equal(&m->gm_mech.gm_mech_oid, mech_oid)) {
_gss_mg_log(10, "duplicate mech, not loading");
found = 1;
break;
}
@@ -349,7 +346,7 @@ _gss_load_mech(void)
so = dlopen(lib, RTLD_LAZY | RTLD_LOCAL | RTLD_GROUP);
if (so == NULL) {
_gss_mg_log(1, "dlopen: %s", dlerror());
_gss_mg_log(1, "dlopen: %s\n", dlerror());
goto bad;
}
+21 -168
View File
@@ -99,8 +99,6 @@ static int help_flag = 0;
static int env_flag = 0;
static int def_flag = 0;
static int overwrite_flag = 0;
static int store_cred_flag = 0;
static char *password = NULL;
static struct getargs args[] = {
{"version", 0, arg_flag, &version_flag, "print version", NULL },
@@ -111,133 +109,16 @@ static struct getargs args[] = {
"switch credential store default principal", NULL },
{"overwrite", 0, arg_flag, &overwrite_flag,
"overwrite matching credential", NULL },
{"store-cred", 0, arg_flag, &store_cred_flag,
"use gss_store_cred instead of gss_store_cred_into2", NULL },
{"password", 0, arg_string, &password,
"acquire source credential with this password", "password" },
};
static void
usage(int ret)
{
arg_printusage(args, sizeof(args)/sizeof(*args),
NULL, "from_ccache to_ccache | source_name target_name");
NULL, "from_ccache to_ccache");
exit(ret);
}
static void
add_krb5_mech(gss_OID_set *mechs)
{
OM_uint32 major, minor;
major = gss_create_empty_oid_set(&minor, mechs);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_C_NO_OID,
"failed to create OID set");
major = gss_add_oid_set_member(&minor, GSS_KRB5_MECHANISM, mechs);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_C_NO_OID,
"failed to add krb5 mechanism to OID set");
}
static void
acquire_from_password(const char *source_name,
const char *source_password,
gss_cred_id_t *cred)
{
OM_uint32 major, minor;
gss_buffer_desc namebuf, pwbuf;
gss_name_t name = GSS_C_NO_NAME;
gss_OID_set mechs = GSS_C_NO_OID_SET;
namebuf.value = rk_UNCONST(source_name);
namebuf.length = strlen(source_name);
major = gss_import_name(&minor, &namebuf, GSS_C_NT_USER_NAME, &name);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_C_NO_OID,
"failed to import source name %s", source_name);
pwbuf.value = rk_UNCONST(source_password);
pwbuf.length = strlen(source_password);
add_krb5_mech(&mechs);
major = gss_acquire_cred_with_password(&minor, name, &pwbuf,
GSS_C_INDEFINITE, mechs,
GSS_C_INITIATE, cred, NULL, NULL);
(void) gss_release_oid_set(&minor, &mechs);
(void) gss_release_name(&minor, &name);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_KRB5_MECHANISM,
"failed to acquire creds with password for %s", source_name);
}
static void
check_init_sec_context(gss_cred_id_t cred, const char *target)
{
OM_uint32 major, minor;
gss_buffer_desc namebuf;
gss_buffer_desc output_token = { 0, NULL };
gss_name_t target_name = GSS_C_NO_NAME;
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
namebuf.value = rk_UNCONST(target);
namebuf.length = strlen(target);
major = gss_import_name(&minor, &namebuf, GSS_C_NT_HOSTBASED_SERVICE,
&target_name);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_C_NO_OID,
"failed to import target name %s", target);
major = gss_init_sec_context(&minor, cred, &ctx, target_name,
GSS_KRB5_MECHANISM, 0, GSS_C_INDEFINITE,
GSS_C_NO_CHANNEL_BINDINGS,
GSS_C_NO_BUFFER, NULL, &output_token,
NULL, NULL);
(void) gss_release_buffer(&minor, &output_token);
(void) gss_delete_sec_context(&minor, &ctx, GSS_C_NO_BUFFER);
(void) gss_release_name(&minor, &target_name);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_KRB5_MECHANISM,
"failed to use source cred for %s after storing", target);
}
static void
acquire_from_ccache(const char *ccache, gss_cred_id_t *cred)
{
OM_uint32 major, minor;
gss_key_value_element_desc element;
gss_key_value_set_desc store;
element.key = "ccache";
element.value = ccache;
store.count = 1;
store.elements = &element;
major = gss_add_cred_from(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,
GSS_KRB5_MECHANISM, GSS_C_INITIATE,
GSS_C_INDEFINITE, GSS_C_INDEFINITE,
&store, cred, NULL, NULL, NULL);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_KRB5_MECHANISM,
"failed to acquire stored creds from %s", ccache);
}
static void
check_default_ccache(gss_cred_id_t from_cred, const char *target)
{
OM_uint32 minor;
const char *ccache = getenv("KRB5CCNAME");
gss_cred_id_t to_cred = GSS_C_NO_CREDENTIAL;
if (ccache == NULL)
errx(1, "KRB5CCNAME not set");
acquire_from_ccache(ccache, &to_cred);
check_init_sec_context(from_cred, target);
check_init_sec_context(to_cred, target);
(void) gss_release_cred(&minor, &to_cred);
}
int
main(int argc, char **argv)
{
@@ -276,42 +157,30 @@ main(int argc, char **argv)
if (argc > 2)
errx(1, "too many arguments");
if (password) {
if (!store_cred_flag)
errx(1, "--password requires --store-cred");
acquire_from_password(argv[0], password, &from_cred);
} else {
from_elements.key = "ccache";
from_elements.value = argv[0];
from.count = 1;
from.elements = &from_elements;
from_elements.key = "ccache";
from_elements.value = argv[0];
from.count = 1;
from.elements = &from_elements;
major = gss_add_cred_from(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,
GSS_KRB5_MECHANISM, GSS_C_INITIATE,
GSS_C_INDEFINITE, GSS_C_INDEFINITE,
&from, &from_cred, NULL, NULL, NULL);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_KRB5_MECHANISM,
"failed to acquire creds from %s", argv[0]);
}
to_elements.key = "ccache";
to_elements.value = argv[1];
to.count = 1;
to.elements = &to_elements;
if (store_cred_flag) {
major = gss_store_cred(&minor, from_cred, GSS_C_INITIATE,
GSS_KRB5_MECHANISM, overwrite_flag, def_flag,
NULL, NULL);
} else {
to_elements.key = "ccache";
to_elements.value = argv[1];
to.count = 1;
to.elements = &to_elements;
major = gss_store_cred_into2(&minor, from_cred, GSS_C_INITIATE,
GSS_KRB5_MECHANISM, store_flags, &to, NULL,
NULL, env_flag ? &env : NULL);
}
major = gss_add_cred_from(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,
GSS_KRB5_MECHANISM, GSS_C_INITIATE,
GSS_C_INDEFINITE, GSS_C_INDEFINITE,
&from, &from_cred, NULL, NULL, NULL);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_KRB5_MECHANISM,
"failed to store creds");
"failed to acquire creds from %s", argv[0]);
major = gss_store_cred_into2(&minor, from_cred, GSS_C_INITIATE,
GSS_KRB5_MECHANISM, store_flags, &to, NULL,
NULL, env_flag ? &env : NULL);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_KRB5_MECHANISM,
"failed to store creds into %s", argv[1]);
if (env_flag) {
size_t i;
@@ -335,22 +204,6 @@ main(int argc, char **argv)
"gss_store_cred_into2()");
}
if (password)
check_default_ccache(from_cred, argv[1]);
if (store_cred_flag) {
(void) gss_release_cred(&minor, &from_cred);
return 0;
}
major = gss_add_cred_from(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,
GSS_KRB5_MECHANISM, GSS_C_INITIATE,
GSS_C_INDEFINITE, GSS_C_INDEFINITE,
&to, &to_cred, NULL, NULL, NULL);
if (major != GSS_S_COMPLETE)
gss_err(1, major, minor, GSS_KRB5_MECHANISM,
"failed to acquire stored creds from %s", argv[1]);
(void) gss_release_cred(&minor, &from_cred);
(void) gss_release_cred(&minor, &to_cred);
+1 -1
View File
@@ -483,7 +483,7 @@ loop(gss_OID mechoid,
if (*deleg_cred != GSS_C_NO_CREDENTIAL)
errx(1, "got delegated cred but didn't expect one");
} else if (*deleg_cred == GSS_C_NO_CREDENTIAL)
errx(1, "asked for delegated cred but did get one");
errx(1, "asked for delegarated cred but did get one");
} else if (*deleg_cred != GSS_C_NO_CREDENTIAL)
errx(1, "got deleg_cred cred but didn't ask");
+45
View File
@@ -149,10 +149,55 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
* enctypes should work.
*/
/* Debug: record the requested principal and keytab context */
{
char *princ_name = NULL;
if (krb5_unparse_name(context, principal, &princ_name) == 0) {
krb5_warnx(context, "hkt_fetch_kvno: looking up principal=%s in keytab=%s kvno=%u flags=0x%x",
princ_name ? princ_name : "<unparsed>",
k->path ? k->path : "<unknown>",
(unsigned)kvno,
(unsigned)flags);
} else {
krb5_warnx(context, "hkt_fetch_kvno: looking up <unparsed principal> in keytab=%s kvno=%u flags=0x%x",
k->path ? k->path : "<unknown>",
(unsigned)kvno,
(unsigned)flags);
}
free(princ_name);
}
ret = krb5_kt_get_entry(context, k->keytab, principal, kvno, 0, &ktentry);
if (ret) {
char *princ_name2 = NULL;
if (krb5_unparse_name(context, principal, &princ_name2) == 0) {
krb5_warnx(context, "hkt_fetch_kvno: krb5_kt_get_entry returned %d for principal=%s keytab=%s",
ret, princ_name2 ? princ_name2 : "<unparsed>", k->path ? k->path : "<unknown>");
} else {
krb5_warnx(context, "hkt_fetch_kvno: krb5_kt_get_entry returned %d for <unparsed principal> keytab=%s",
ret, k->path ? k->path : "<unknown>");
}
free(princ_name2);
ret = HDB_ERR_NOENTRY;
goto out;
} else {
/* Success: record what the keytab returned for inspection */
{
char *entry_princ = NULL;
if (krb5_unparse_name(context, ktentry.principal, &entry_princ) == 0) {
krb5_warnx(context, "hkt_fetch_kvno: krb5_kt_get_entry succeeded: entry_principal=%s vno=%d enctype=%d keytab=%s",
entry_princ ? entry_princ : "<unparsed>",
ktentry.vno,
ktentry.keyblock.keytype,
k->path ? k->path : "<unknown>");
} else {
krb5_warnx(context, "hkt_fetch_kvno: krb5_kt_get_entry succeeded: entry_principal=<unparsed> vno=%d enctype=%d keytab=%s",
ktentry.vno,
ktentry.keyblock.keytype,
k->path ? k->path : "<unknown>");
}
free(entry_princ);
}
}
ret = krb5_copy_principal(context, principal, &entry->principal);
+1 -5
View File
@@ -169,15 +169,12 @@ fuzz_jose_SOURCES = fuzz_jose.c
fuzz_jose_LDADD = libhx509.la $(LIB_roken) $(top_builddir)/lib/base/libheimbase.la
fuzz_jose.$(OBJEXT): $(HX509_PROTOS) $(nodist_include_HEADERS)
test_expr_LDADD = libhx509.la $(LIB_roken) $(top_builddir)/lib/asn1/libasn1.la
test_cert_binary_CPPFLAGS = $(AM_CPPFLAGS) -DSRCDIR=\"$(srcdir)\"
test_cert_binary_LDADD = libhx509.la $(LIB_roken) $(top_builddir)/lib/asn1/libasn1.la
TESTS = $(SCRIPT_TESTS) $(PROGRAM_TESTS)
PROGRAM_TESTS = \
test_name \
test_expr \
test_cert_binary
test_expr
SCRIPT_TESTS = \
test_ca \
@@ -339,7 +336,6 @@ EXTRA_DIST = \
data/key2.der \
data/nist-data \
data/nist-data2 \
data/notafter-2338.pem \
data/no-proxy-test.crt \
data/no-proxy-test.key \
data/ocsp-req1.der \
+2 -14
View File
@@ -66,18 +66,6 @@ struct hx509_ca_tbs {
AlgorithmIdentifier *sigalg;
};
static int
use_utc_time(time_t t)
{
if (t < 1)
return 1;
#if SIZEOF_TIME_T > 4 || defined(TIME_T_UNSIGNED)
if ((uint64_t)t >= 2524608000ULL)
return 0;
#endif
return 1;
}
/**
* Allocate an to-be-signed certificate object that will be converted
* into an certificate.
@@ -1785,13 +1773,13 @@ ca_sign(hx509_context context,
*
* Both, ...u.generalTime and ...u..utcTime are time_t.
*/
if (use_utc_time(notBefore))
if (notBefore < 1 || (int64_t)notBefore < 2524608000)
tbsc->validity.notBefore.element = choice_Time_utcTime;
else
tbsc->validity.notBefore.element = choice_Time_generalTime;
tbsc->validity.notBefore.u.generalTime = notBefore;
if (use_utc_time(notAfter))
if (notAfter < 1 || (int64_t)notAfter < 2524608000)
tbsc->validity.notAfter.element = choice_Time_utcTime;
else
tbsc->validity.notAfter.element = choice_Time_generalTime;
+1 -38
View File
@@ -78,7 +78,6 @@ struct hx509_cert_data {
unsigned int ref;
char *friendlyname;
Certificate *data;
heim_octet_string encoding;
hx509_private_key private_key;
struct _hx509_cert_attrs attrs;
hx509_name basename;
@@ -636,8 +635,6 @@ cert_init(hx509_context context, heim_error_t *error)
cert->release = NULL;
cert->ctx = NULL;
cert->data= NULL;
cert->encoding.data = NULL;
cert->encoding.length = 0;
return cert;
}
@@ -696,23 +693,7 @@ hx509_cert_copy_no_private_key(hx509_context context,
hx509_cert src,
heim_error_t *error)
{
hx509_cert cert;
int ret;
cert = hx509_cert_init(context, src->data, error);
if (cert == NULL)
return NULL;
ret = der_copy_octet_string(&src->encoding, &cert->encoding);
if (ret) {
hx509_cert_free(cert);
if (error)
*error = heim_error_create_enomem();
errno = ret;
return NULL;
}
return cert;
return hx509_cert_init(context, src->data, error);
}
/**
@@ -766,7 +747,6 @@ hx509_cert_init_data(hx509_context context,
heim_error_t *error)
{
hx509_cert cert;
heim_octet_string os;
Certificate t;
size_t size;
int ret;
@@ -789,19 +769,6 @@ hx509_cert_init_data(hx509_context context,
cert = hx509_cert_init(context, &t, error);
free_Certificate(&t);
if (cert == NULL)
return NULL;
os.length = len;
os.data = rk_UNCONST(ptr);
ret = der_copy_octet_string(&os, &cert->encoding);
if (ret) {
hx509_cert_free(cert);
if (error)
*error = heim_error_create_enomem();
errno = ret;
return NULL;
}
return cert;
}
@@ -857,7 +824,6 @@ hx509_cert_free(hx509_cert cert)
if (cert->data)
free_Certificate(cert->data);
free(cert->data);
der_free_octet_string(&cert->encoding);
for (i = 0; i < cert->attrs.len; i++) {
der_free_octet_string(&cert->attrs.val[i]->data);
@@ -4091,9 +4057,6 @@ hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
os->data = NULL;
os->length = 0;
if (c->encoding.data != NULL)
return der_copy_octet_string(&c->encoding, os);
ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
_hx509_get_cert(c), &size, ret);
if (ret) {
-25
View File
@@ -1,25 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFATCCAumgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUwOSBUZXN0IFJv
b3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwMloYDzIzMzgwMTE5MDMxNDA4WjAhMQsw
CQYDVQQGEwJTRTESMBAGA1UEAwwJVGVzdCBjZXJ0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
CgKCAgEA2h1NylGd8Z/XpHpF+HWYZrLFfVPeQjV0gc0en/ND16eDf/uizjxEN4BPITam9slRdJ7i
m7+t5OtyEWQ2iLOpkWPH7jjE9YwGceUJt+tXXb/bW3IHxSnobzOzoifvH1DwVTNjQSPgsvchd0ur
nXMqu7ZOiH985cY3PrYgwVc+bVd47w1H6UHn+rYtMj9CBY1Wr/XEuG6ZGucH1aE/KX3OsjmmqwZ6
4iY52JaeO8iveT6aJE5Lsq/kBw5x3C9wJ5c8ovppm1dLxVNeKAywx1cforImD1+/00V4kFos/Gpn
M7bBfs0XwFieuoXFFVpaZ9u/LwXNONmUyZV/m2iwYv83ks/Yd77Lcj0PuYBEV8DJEAH9ByUw69hI
Ba+Y+sRkbVmmao0b1EvzB5ho47tZySH4EbSighsN6IzgpeEcccrDLZBDw+6ZLH1BSDnIAHINgDkj
oTon7QfKMo80yrudZxN9Me1K2zV6zrOJ42SdPkdO07e9qxIWELtm6Bp3TCrguRZpZhSDTkrzb6uF
anDGm86Tq3U2o6Wqn0XWon8Xx2/59ec1UaV1xQe+Js57Pyk6dGsXeU7PTAppdVjb66jd8ebMoxhT
pcWlWqHPN2qxn9PU6w8CQNKuaM68xUbj7viXiO7IpwF6oSOv8zEsKm8Sd9w8UZ1A9Joqe4UpHz7D
1TeObgkCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFBv07DRCuotn
rFXyN120aKnYXlh7MA0GCSqGSIb3DQEBBQUAA4ICAQCV9xyZckJP0726P3p1uwE6rc5re7c9XTtG
UeqaNpRwNhw7/Lqdiw1ENgitpnOCvCPt+VoJj51iEcGUfGFmH4u5Ctw6tesiVN6j5YqUEB+EUm3+
J8jly6WOqYMWlQ1sPleF4eyCBUdtKK0NhPpAoJb0hKrR4Qu3keJHTwWX+BCg6Fe97UhlVXXa5TTo
8SCV1kCMQr+02VXIMOjVztgdMGWQOevig+0RA80HwOHEkYSgl45tIuZ1dyF8MotI7dayGS6vJq19
bM4J4Xi2cmFgIpK430JrNGtfNe/x08Z/kgU80Ah3AWb3V7hl3tPSsb+TsYyjJ+bU4iubzZ2+MYJb
U91avTkFX4xW8n+bt+/mB5a/itmNu2KYht6qkcP+57unH/D9H2ymBATwwlGhkYya7vmHQjd+nCdy
WdxgqI7RgZfxFcPYqU6aCemBdjk2swih5V6XN7pDjwYacGk7/nmmXi0mBOm8X1fJ0IDCDUvHDt0E
5RVJndf/7qMcBFZ94qDTORpZvYWw61TqgYvhF5Sl/uMM0HRC7kr0ZpBJS2S8RzX1smCOdAXQptKU
tOAPSz816irgJFjBbtBlblj34ZACrkAjJemAmtKn6l38bfhFD9tTkVUyRuNqwFQKWkzoGh6mMz7+
7batz2o8L7JsR3XxKUMxacMMQlZb2biZe/8rUIc0Lg==
-----END CERTIFICATE-----
-17
View File
@@ -47,23 +47,6 @@ for a in $srcdir/data/*.crt; do
${hxtool} print --content FILE:"$a" > /dev/null 2>/dev/null
done
echo "print certificate with 2338 notAfter"
${hxtool} print --content FILE:$srcdir/data/notafter-2338.pem > cert-2338.tmp || exit 1
config=$objdir/../../include/config.h
if grep '^#define SIZEOF_TIME_T 4$' "$config" > /dev/null; then
if grep '^#define TIME_T_UNSIGNED' "$config" > /dev/null; then
notafter='notAfter 2106-02-07 06:28:15'
else
notafter='notAfter 2038-01-19 03:14:07'
fi
else
notafter='notAfter 2338-01-19 03:14:08'
fi
grep "$notafter" cert-2338.tmp > /dev/null || {
cat cert-2338.tmp
exit 1
}
echo "print NULL"
${hxtool} print --content NULL: > /dev/null || exit 1
-179
View File
@@ -1,179 +0,0 @@
#include "hx_locl.h"
#include <err.h>
#ifndef SRCDIR
#define SRCDIR "."
#endif
struct pem_cert {
heim_octet_string der;
int found;
};
static int
pem_cert_reader(hx509_context context, const char *type,
const hx509_pem_header *headers,
const void *data, size_t length, void *ctx)
{
struct pem_cert *pem = ctx;
(void)context;
(void)headers;
if (strcmp(type, "CERTIFICATE") != 0)
return 0;
if (pem->found)
return 0;
pem->der.data = malloc(length);
if (pem->der.data == NULL)
return ENOMEM;
memcpy(pem->der.data, data, length);
pem->der.length = length;
pem->found = 1;
return 0;
}
static void
read_cert_der(hx509_context context, const char *path, heim_octet_string *der)
{
struct pem_cert pem;
FILE *f;
int ret;
memset(&pem, 0, sizeof(pem));
f = fopen(path, "r");
if (f == NULL)
err(1, "fopen: %s", path);
ret = hx509_pem_read(context, f, pem_cert_reader, &pem);
fclose(f);
if (ret)
hx509_err(context, 1, ret, "hx509_pem_read: %s", path);
if (!pem.found)
errx(1, "did not find a certificate in %s", path);
*der = pem.der;
}
static void
compare_octet_string(const char *what,
const heim_octet_string *expected,
const heim_octet_string *actual)
{
if (actual->length != expected->length)
errx(1, "%s length changed from %lu to %lu",
what, (unsigned long)expected->length,
(unsigned long)actual->length);
if (memcmp(actual->data, expected->data, expected->length) != 0)
errx(1, "%s data changed", what);
}
static void
check_cert_binary(hx509_context context, const heim_octet_string *der)
{
heim_octet_string os;
hx509_cert cert;
int ret;
memset(&os, 0, sizeof(os));
cert = hx509_cert_init_data(context, der->data, der->length, NULL);
if (cert == NULL)
err(1, "hx509_cert_init_data");
ret = hx509_cert_binary(context, cert, &os);
if (ret)
hx509_err(context, 1, ret, "hx509_cert_binary");
compare_octet_string("certificate encoding", der, &os);
der_free_octet_string(&os);
hx509_cert_free(cert);
}
static char *
make_store_name(void)
{
char *store_name = NULL;
if (asprintf(&store_name, "FILE:%s/data/test.crt,%s/data/test.key",
SRCDIR, SRCDIR) == -1 || store_name == NULL)
err(1, "asprintf");
return store_name;
}
static void
check_keyless_store_cert_encoding(hx509_context context,
const heim_octet_string *der)
{
heim_octet_string os;
hx509_certs certs = NULL;
hx509_cert cert = NULL;
char *store_name;
int ret;
memset(&os, 0, sizeof(os));
ret = hx509_certs_init(context, "MEMORY:test-keyless-certs",
HX509_CERTS_NO_PRIVATE_KEYS, NULL, &certs);
if (ret)
hx509_err(context, 1, ret, "hx509_certs_init");
store_name = make_store_name();
ret = hx509_certs_append(context, certs, NULL, store_name);
free(store_name);
if (ret)
hx509_err(context, 1, ret, "hx509_certs_append");
ret = hx509_get_one_cert(context, certs, &cert);
if (ret)
hx509_err(context, 1, ret, "hx509_get_one_cert");
if (hx509_cert_have_private_key(cert))
errx(1, "HX509_CERTS_NO_PRIVATE_KEYS store kept a private key");
ret = hx509_cert_binary(context, cert, &os);
if (ret)
hx509_err(context, 1, ret, "hx509_cert_binary on keyless cert");
compare_octet_string("keyless store certificate encoding", der, &os);
der_free_octet_string(&os);
hx509_cert_free(cert);
hx509_certs_free(&certs);
}
int
main(int argc, char **argv)
{
heim_octet_string der;
hx509_context context;
char *cert_path = NULL;
int ret;
(void)argc;
(void)argv;
memset(&der, 0, sizeof(der));
ret = hx509_context_init(&context);
if (ret)
errx(1, "hx509_context_init failed with %d", ret);
if (asprintf(&cert_path, "%s/data/test.crt", SRCDIR) == -1 ||
cert_path == NULL)
err(1, "asprintf");
read_cert_der(context, cert_path, &der);
free(cert_path);
check_cert_binary(context, &der);
check_keyless_store_cert_encoding(context, &der);
der_free_octet_string(&der);
hx509_context_free(&context);
return 0;
}
+3 -13
View File
@@ -46,23 +46,14 @@ if have_gcd
# stops building on recent OS X releases unless we disable this warning.
WFLAGS += -Wno-deprecated-declarations
heim_ipc.stamp: heim_ipc.defs
heim_ipc.h heim_ipcUser.c heim_ipcServer.c heim_ipcServer.h: heim_ipc.defs
mig -header heim_ipc.h -user heim_ipcUser.c -sheader heim_ipcServer.h -server heim_ipcServer.c -I$(srcdir) $(srcdir)/heim_ipc.defs
touch $@
heim_ipc.h heim_ipcUser.c heim_ipcServer.c heim_ipcServer.h: heim_ipc.stamp
heim_ipc_async.stamp: heim_ipc_async.defs
heim_ipc_async.h heim_ipc_asyncUser.c heim_ipc_asyncServer.c heim_ipc_asyncServer.h: heim_ipc_async.defs
mig -header heim_ipc_async.h -user heim_ipc_asyncUser.c -sheader heim_ipc_asyncServer.h -server heim_ipc_asyncServer.c -I$(srcdir) $(srcdir)/heim_ipc_async.defs
touch $@
heim_ipc_async.h heim_ipc_asyncUser.c heim_ipc_asyncServer.c heim_ipc_asyncServer.h: heim_ipc_async.stamp
heim_ipc_reply.stamp: heim_ipc_reply.defs
heim_ipc_reply.h heim_ipc_replyUser.c: heim_ipc_reply.defs
mig -header heim_ipc_reply.h -user heim_ipc_replyUser.c -sheader /dev/null -server /dev/null -I$(srcdir) $(srcdir)/heim_ipc_reply.defs
touch $@
heim_ipc_reply.h heim_ipc_replyUser.c: heim_ipc_reply.stamp
built_ipcc = heim_ipc.h heim_ipcUser.c
built_ipcc += heim_ipc_asyncServer.c heim_ipc_asyncServer.h
@@ -78,7 +69,6 @@ nodist_libheim_ipcs_la_SOURCES = $(built_ipcs)
libheim_ipcs_la_LIBADD += -lbsm
CLEANFILES = $(built_ipcc) $(built_ipcs)
CLEANFILES += heim_ipc.stamp heim_ipc_async.stamp heim_ipc_reply.stamp
$(srcdir)/client.c: $(built_ipcc)
$(srcdir)/server.c: $(built_ipcs)
+2
View File
@@ -41,6 +41,8 @@
#include <sys/un.h>
#endif
#include <poll.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
-11
View File
@@ -53,17 +53,6 @@
#define LOG_VERSION_FIRST 1
#define LOG_VERSION_UBER 0
#define LOG_HEADER_SZ ((off_t)(sizeof(uint32_t) * 4))
#define LOG_TRAILER_SZ ((off_t)(sizeof(uint32_t) * 2))
#define LOG_WRAPPER_SZ ((off_t)(LOG_HEADER_SZ + LOG_TRAILER_SZ))
#define LOG_UBER_LEN ((off_t)(sizeof(uint64_t) + sizeof(uint32_t) * 2))
#define LOG_UBER_SZ ((off_t)(LOG_WRAPPER_SZ + LOG_UBER_LEN))
struct kadm5_log_snap {
char bytes;
char buf[LOG_UBER_SZ + LOG_HEADER_SZ];
};
#include <krb5.h>
#define KRB5_KDB_DISALLOW_POSTDATED 0x00000001
+153 -21
View File
@@ -191,6 +191,20 @@ _kadm5_c_init_context(kadm5_client_context **ctx,
}
if ((*ctx)->readonly_kadmind_port == 0)
(*ctx)->readonly_kadmind_port = (*ctx)->kadmind_port;
/*
* Extra debug: emit context-level info to help trace client init-time
* decisions in test logs.
*/
krb5_warnx(context,
"_kadm5_c_init_context: realm=%s admin_server=%s readonly_admin_server=%s kadmind_port=%u readonly_port=%u (pid=%d)",
(*ctx)->realm ? (*ctx)->realm : "<null>",
(*ctx)->admin_server ? (*ctx)->admin_server : "<null>",
(*ctx)->readonly_admin_server ? (*ctx)->readonly_admin_server : "<null>",
(unsigned)ntohs((*ctx)->kadmind_port),
(unsigned)ntohs((*ctx)->readonly_kadmind_port),
(int)getpid());
return 0;
}
@@ -203,10 +217,12 @@ kadm5_c_dup_context(void *vin, void **out)
kadm5_client_context *ctx;
*out = NULL;
ctx = calloc(1, sizeof(*ctx));
ctx = malloc(sizeof(*ctx));
if (ctx == NULL)
return krb5_enomem(in->context);
memset(ctx, 0, sizeof(*ctx));
set_funcs(ctx);
ctx->readonly_kadmind_port = in->readonly_kadmind_port;
ctx->kadmind_port = in->kadmind_port;
@@ -224,13 +240,18 @@ kadm5_c_dup_context(void *vin, void **out)
if (in->readonly_admin_server &&
(ctx->readonly_admin_server = strdup(in->readonly_admin_server)) == NULL)
ret = krb5_enomem(context);
if (in->client_name != NULL &&
(ctx->client_name = strdup(in->client_name)) == NULL)
/* Preserve client identity and prompter behavior in duplicated context */
if (in->client_name && (ctx->client_name = strdup(in->client_name)) == NULL)
ret = krb5_enomem(context);
if (in->keytab && (ctx->keytab = strdup(in->keytab)) == NULL)
if (in->service_name && (ctx->service_name = strdup(in->service_name)) == NULL)
ret = krb5_enomem(context);
/* Copy the prompter pointer so duplicated contexts behave the same
with respect to prompting vs keytab-based auth. */
ctx->prompter = in->prompter;
if (in->keytab && (ctx->keytab = strdup(in->keytab)) == NULL)
ret = krb5_enomem(context);
if (in->ccache) {
char *fullname = NULL;
@@ -295,7 +316,24 @@ get_new_cache(krb5_context context,
krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
/*
* Extra debug: record the inputs to credential selection so tests can
* observe why keytab vs password paths were chosen.
*/
krb5_warnx(context,
"get_new_cache: entry client=%s password_provided=%d prompter=%p keytab=%s server_name=%s (pid=%d)",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>",
password ? 1 : 0,
(void *)prompter,
keytab ? keytab : "<default>",
server_name ? server_name : "<null>",
(int)getpid());
if(password == NULL && prompter == NULL) {
/* Debug: choosing keytab-based initial credentials */
krb5_warnx(context, "get_new_cache: choosing keytab auth (keytab=%s, client=%s)",
keytab ? keytab : "<default>",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>");
krb5_keytab kt;
if(keytab == NULL)
ret = krb5_kt_default(context, &kt);
@@ -312,8 +350,21 @@ get_new_cache(krb5_context context,
0,
server_name,
opt);
/* Log success/failure of keytab credential attempt for diagnostics */
if (ret == 0) {
krb5_warnx(context, "get_new_cache: krb5_get_init_creds_keytab succeeded for principal=%s using keytab=%s",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>",
keytab ? keytab : "<default>");
} else {
krb5_warn(context, ret, "get_new_cache: krb5_get_init_creds_keytab failed (keytab=%s)", keytab ? keytab : "<default>");
}
krb5_kt_close(context, kt);
} else {
/* Debug: choosing password-based initial credentials */
krb5_warnx(context, "get_new_cache: choosing password auth (password_provided=%d prompter=%p client=%s)",
password ? 1 : 0,
(void *)prompter,
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>");
ret = krb5_get_init_creds_password (context,
&cred,
client,
@@ -323,6 +374,13 @@ get_new_cache(krb5_context context,
0,
server_name,
opt);
if (ret == 0) {
krb5_warnx(context, "get_new_cache: krb5_get_init_creds_password succeeded for principal=%s",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>");
} else {
krb5_warn(context, ret, "get_new_cache: krb5_get_init_creds_password failed for principal=%s",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>");
}
}
krb5_get_init_creds_opt_free(context, opt);
switch(ret){
@@ -451,6 +509,27 @@ _kadm5_c_get_cred_cache(krb5_context context,
if(server_name == NULL)
server_name = KADM5_ADMIN_SERVICE;
/*
* Extra debug: log the invocation and environment so we can correlate
* with test harness behavior (e.g. whether KRB5_KTNAME / KRB5CCNAME
* were set).
*/
{
const char *env_kt = secure_getenv ? secure_getenv("KRB5_KTNAME") : getenv("KRB5_KTNAME");
const char *env_cc = secure_getenv ? secure_getenv("KRB5CCNAME") : getenv("KRB5CCNAME");
krb5_warnx(context,
"_kadm5_c_get_cred_cache: called client_name=%s server_name=%s password_provided=%d prompter=%p keytab=%s ccache=%p env.KRB5_KTNAME=%s env.KRB5CCNAME=%s (pid=%d)",
client_name ? client_name : "<null>",
server_name ? server_name : "<null>",
password ? 1 : 0,
(void *)prompter,
keytab ? keytab : "<null>",
(void *)ccache,
env_kt ? env_kt : "<unset>",
env_cc ? env_cc : "<unset>",
(int)getpid());
}
if(client_name != NULL) {
ret = krb5_parse_name(context, client_name, &client);
if(ret)
@@ -458,19 +537,9 @@ _kadm5_c_get_cred_cache(krb5_context context,
}
if(ccache != NULL) {
char *fullname = NULL;
ret = krb5_cc_get_full_name(context, ccache, &fullname);
if (ret)
return ret;
ret = krb5_cc_resolve(context, fullname, &id);
free(fullname);
if (ret)
return ret;
ret = krb5_cc_get_principal(context, id, &client);
if (ret)
id = ccache;
ret = krb5_cc_get_principal(context, id, &client);
if(ret)
return ret;
} else {
/* get principal from default cache, ok if this doesn't work */
@@ -515,26 +584,47 @@ _kadm5_c_get_cred_cache(krb5_context context,
if(id && client && (default_client == NULL ||
krb5_principal_compare(context, client, default_client) != 0)) {
/* Debug: attempting to obtain kadmin ticket from existing credential cache */
krb5_warnx(context, "_kadm5_c_get_cred_cache: trying credential cache to get kadmin ticket (client=%s)",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>");
ret = get_kadm_ticket(context, id, client, server_name);
if(ret == 0) {
krb5_warnx(context, "_kadm5_c_get_cred_cache: got kadmin ticket from cache for client=%s",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>");
*ret_cache = id;
krb5_free_principal(context, default_client);
if (default_client != client)
krb5_free_principal(context, client);
return 0;
}
krb5_warn(context, ret, "_kadm5_c_get_cred_cache: get_kadm_ticket from cache failed for client=%s", client ? krb5_principal_get_comp_string(context, client, 0) : "<null>");
if(ccache != NULL)
/* couldn't get ticket from cache */
return -1;
}
/* get creds via AS request */
if (id)
if(id && (id != ccache))
krb5_cc_close(context, id);
if (client != default_client)
krb5_free_principal(context, default_client);
ret = get_new_cache(context, client, password, prompter, keytab,
server_name, ret_cache);
/*
* Extra debug: report the result of get_new_cache so caller logs
* can show why auth succeeded/failed.
*/
if (ret == 0) {
krb5_warnx(context, "_kadm5_c_get_cred_cache: get_new_cache succeeded for client=%s (pid=%d)",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>",
(int)getpid());
} else {
krb5_warn(context, ret, "_kadm5_c_get_cred_cache: get_new_cache failed for client=%s (pid=%d)",
client ? krb5_principal_get_comp_string(context, client, 0) : "<null>",
(int)getpid());
}
krb5_free_principal(context, client);
return ret;
}
@@ -558,6 +648,17 @@ kadm_connect(kadm5_client_context *ctx)
krb5_context context = ctx->context;
int writable = 0;
/*
* Extra debug: record connect intent and client context pointers
* to help correlate kadmin network activity with credential selection.
*/
krb5_warnx(context, "kadm_connect: entering (client_name=%s prompter=%p keytab=%s ccache=%p pid=%d)",
ctx->client_name ? ctx->client_name : "<null>",
(void *)ctx->prompter,
ctx->keytab ? ctx->keytab : "<null>",
(void *)ctx->ccache,
(int)getpid());
if (ctx->ac)
krb5_auth_con_free(context, ctx->ac);
ctx->ac = NULL;
@@ -671,6 +772,12 @@ out:
rk_closesocket(s);
krb5_auth_con_free(context, ctx->ac);
ctx->ac = NULL;
} else {
/* Extra debug: successful connect and auth */
krb5_warnx(context, "kadm_connect: success connected_to_writable=%d sock=%d (pid=%d)",
(int)ctx->connected_to_writable,
(int)ctx->sock,
(int)getpid());
}
return ret;
}
@@ -717,12 +824,25 @@ kadm5_c_init_with_context(krb5_context context,
kadm5_client_context *ctx = NULL;
krb5_ccache cc;
/*
* Extra debug: record initialization flags and pointers so we can later
* understand whether a prompter was provided (which affects keytab vs
* password selection) and whether a keytab or ccache was requested.
*/
krb5_warnx(context, "kadm5_c_init_with_context: client_name=%s password_provided=%d prompter=%p keytab=%s ccache=%p service_name=%s (pid=%d)",
client_name ? client_name : "<null>",
password ? 1 : 0,
(void *)prompter,
keytab ? keytab : "<null>",
(void *)ccache,
service_name ? service_name : "<null>",
(int)getpid());
ret = _kadm5_c_init_context(&ctx, realm_params, context);
if (ret)
return ret;
if ((password != NULL && *password != '\0') ||
(client_name && !keytab)) {
if (password != NULL && *password != '\0') {
ret = _kadm5_c_get_cred_cache(context,
client_name,
service_name,
@@ -750,6 +870,19 @@ kadm5_c_init_with_context(krb5_context context,
ctx->sock = -1;
*server_handle = ctx;
/*
* Extra debug: final context values after init so logs show what the
* kadm client will carry into subsequent connect attempts.
*/
krb5_warnx(context, "kadm5_c_init_with_context: done ctx=%p client_name=%s prompter=%p keytab=%s ccache=%p (pid=%d)",
(void *)ctx,
ctx->client_name ? ctx->client_name : "<null>",
(void *)ctx->prompter,
ctx->keytab ? ctx->keytab : "<null>",
(void *)ctx->ccache,
(int)getpid());
return 0;
}
@@ -936,4 +1069,3 @@ kadm5_init(char *client_name, char *pass,
{
}
#endif
+176 -285
View File
@@ -86,46 +86,37 @@ make_signal_socket (krb5_context context)
#endif
}
static int
listen_port(krb5_context context, const char *port_str)
{
int port;
if (port_str) {
port = krb5_getportbyname(context, port_str, "tcp", 0);
if (port == 0) {
char *ptr;
long num;
num = strtol(port_str, &ptr, 10);
if (num == 0 && ptr == port_str)
krb5_errx(context, 1, "bad port `%s'", port_str);
port = htons(num);
}
} else {
port = krb5_getportbyname(context, IPROP_SERVICE,
"tcp", IPROP_PORT);
}
return port;
}
static krb5_socket_t
make_listen_socket(krb5_context context, int port)
make_listen_socket (krb5_context context, const char *port_str)
{
krb5_socket_t fd;
int one = 1;
struct sockaddr_in addr;
fd = socket(AF_INET, SOCK_STREAM, 0);
fd = socket (AF_INET, SOCK_STREAM, 0);
if (rk_IS_BAD_SOCKET(fd))
krb5_err (context, 1, rk_SOCK_ERRNO, "socket AF_INET");
(void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
memset (&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = port;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (port_str) {
addr.sin_port = krb5_getportbyname (context,
port_str, "tcp",
0);
if (addr.sin_port == 0) {
char *ptr;
long port;
port = strtol (port_str, &ptr, 10);
if (port == 0 && ptr == port_str)
krb5_errx (context, 1, "bad port `%s'", port_str);
addr.sin_port = htons(port);
}
} else {
addr.sin_port = krb5_getportbyname (context, IPROP_SERVICE,
"tcp", IPROP_PORT);
}
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
krb5_err (context, 1, errno, "bind");
if (listen(fd, SOMAXCONN) < 0)
@@ -133,68 +124,15 @@ make_listen_socket(krb5_context context, int port)
return fd;
}
#ifdef AF_INET6
static krb5_socket_t
make_listen_socket6(krb5_context context, int port)
{
krb5_socket_t fd;
int one = 1;
struct sockaddr_in6 addr;
fd = socket(AF_INET6, SOCK_STREAM, 0);
if (rk_IS_BAD_SOCKET(fd)) {
#ifdef EAFNOSUPPORT
if (rk_SOCK_ERRNO != EAFNOSUPPORT)
#endif
krb5_warn(context, rk_SOCK_ERRNO, "socket AF_INET6");
return rk_INVALID_SOCKET;
}
(void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
socket_set_ipv6only(fd, 1);
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_port = port;
addr.sin6_addr = in6addr_any;
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
krb5_warn(context, errno, "bind AF_INET6");
rk_closesocket(fd);
return rk_INVALID_SOCKET;
}
if (listen(fd, SOMAXCONN) < 0) {
krb5_warn (context, errno, "listen AF_INET6");
rk_closesocket(fd);
return rk_INVALID_SOCKET;
}
return fd;
}
#endif
static void
make_listen_sockets(krb5_context context, const char *port_str,
krb5_socket_t *fds, int *num_fds)
{
krb5_socket_t fd;
int port = listen_port(context, port_str);
*num_fds = 0;
#ifdef AF_INET6
fd = make_listen_socket6(context, port);
if (!rk_IS_BAD_SOCKET(fd))
fds[(*num_fds)++] = fd;
#endif
fds[(*num_fds)++] = make_listen_socket(context, port);
}
struct slave {
krb5_socket_t fd;
struct sockaddr_storage addr;
struct sockaddr_in addr;
char *name;
krb5_auth_context ac;
uint32_t version;
uint32_t version_tstamp;
uint32_t version_ack;
time_t seen;
unsigned long flags;
#define SLAVE_F_DEAD 0x1
@@ -438,6 +376,7 @@ add_slave (krb5_context context, krb5_keytab keytab, slave **root,
krb5_warnx (context, "connection from %s", s->name);
s->version = 0;
s->version_ack = 0;
s->flags = 0;
slave_seen(s);
s->next = *root;
@@ -923,11 +862,8 @@ diffready(krb5_context context, slave *s)
* Don't send any diffs until slave has sent an I_HAVE telling us the
* initial version number!
*/
if ((s->flags & SLAVE_F_READY) == 0) {
if (verbose)
krb5_warnx(context, "not sending diffs to not-ready slave %s", s->name);
if ((s->flags & SLAVE_F_READY) == 0)
return 0;
}
if (s->flags & SLAVE_F_DEAD) {
if (verbose)
@@ -936,11 +872,8 @@ diffready(krb5_context context, slave *s)
}
/* Write any remainder of previous write, if we can. */
if (send_tail(context, s) != 0 && have_tail(s)) {
if (verbose)
krb5_warnx(context, "not sending diffs to busy slave %s", s->name);
if (send_tail(context, s) != 0)
return 0;
}
return 1;
}
@@ -948,6 +881,10 @@ diffready(krb5_context context, slave *s)
static int
nodiffs(krb5_context context, slave *s, uint32_t current_version)
{
krb5_storage *sp;
krb5_data data;
int ret;
if (s->version < current_version)
return 0;
@@ -960,20 +897,6 @@ nodiffs(krb5_context context, slave *s, uint32_t current_version)
if (verbose)
krb5_warnx(context, "slave %s version %ld already sent", s->name,
(long)s->version);
return 1;
}
static void
send_you_have_last_version(krb5_context context, slave *s)
{
krb5_storage *sp;
krb5_data data;
int ret;
if (verbose)
krb5_warnx(context, "slave %s version %ld is latest", s->name,
(long)s->version);
sp = krb5_storage_emem();
if (sp == NULL)
krb5_errx(context, IPROPD_RESTART, "krb5_storage_from_mem");
@@ -986,17 +909,19 @@ send_you_have_last_version(krb5_context context, slave *s)
krb5_storage_free(sp);
if (ret == 0) {
ret = mk_priv_tail(context, s, &data);
if (ret)
krb5_err(context, IPROPD_RESTART, ret,
"sending you have last version");
krb5_data_free(&data);
}
if (ret == 0)
send_tail(context, s);
return 1;
}
/*
* Lock the log and return initial version and timestamp
*/
static int
get_first(kadm5_server_context *server_context,
get_first(kadm5_server_context *server_context, int log_fd,
uint32_t *initial_verp, uint32_t *initial_timep)
{
krb5_context context = server_context->context;
@@ -1006,14 +931,19 @@ get_first(kadm5_server_context *server_context,
* We don't want to perform tight retry loops on log access errors, so on
* error mark the slave dead. The slave reconnect after a delay...
*/
if (flock(log_fd, LOCK_SH) == -1) {
krb5_warn(context, errno, "could not obtain shared lock on log file");
return -1;
}
ret = kadm5_log_get_version_fd(server_context, -1, LOG_VERSION_FIRST,
ret = kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_FIRST,
initial_verp, initial_timep);
if (ret == HEIM_ERR_EOF || ret == KADM5_LOG_EMPTY)
ret = kadm5_log_get_version_fd(server_context, -1,
if (ret == HEIM_ERR_EOF)
ret = kadm5_log_get_version_fd(server_context, log_fd,
LOG_VERSION_UBER, initial_verp,
initial_timep);
if (ret != 0) {
flock(log_fd, LOCK_UN);
krb5_warn(context, ret, "could not read initial log entry");
return -1;
}
@@ -1024,20 +954,17 @@ get_first(kadm5_server_context *server_context,
/*-
* Find the left end of the diffs in the log we want to send.
*
* - On success, return a positive offset to the first new entry.
* - On error, return a negative offset.
* - On success, return a positive offset to the first new entry, retaining
* a read lock on the log file.
* - On error, return a negative offset, with the lock released.
* - If we simply find no successor entry in the log, return zero
* with the lock released, which indicates that fallback to send_complete()
* is needed.
*
* The caller must use kadm5_log_snapshot()/kadm5_log_snapshot_verify() to
* ensure that the data read here is consistent because there have been only
* append writes and/or there have been no log rotations.
*/
static off_t
get_left(kadm5_server_context *server_context, slave *s, krb5_storage *sp,
uint32_t current_version, uint32_t *initial_verp,
uint32_t *initial_timep)
int log_fd, uint32_t current_version,
uint32_t *initial_verp, uint32_t *initial_timep)
{
krb5_context context = server_context->context;
off_t pos;
@@ -1047,13 +974,17 @@ get_left(kadm5_server_context *server_context, slave *s, krb5_storage *sp,
for (;;) {
uint32_t ver = s->version;
ret = get_first(server_context, initial_verp, initial_timep);
/* This acquires a read lock on success */
ret = get_first(server_context, log_fd,
initial_verp, initial_timep);
if (ret != 0)
return -1;
/* When the slave version is out of range, send the whole database. */
if (ver == 0 || ver + 1 < *initial_verp || ver > current_version)
if (ver == 0 || ver < *initial_verp || ver > current_version) {
flock(log_fd, LOCK_UN);
return 0;
}
/* Avoid seeking past the last committed record */
if (kadm5_log_goto_end(server_context, sp) != 0 ||
@@ -1085,12 +1016,13 @@ get_left(kadm5_server_context *server_context, slave *s, krb5_storage *sp,
goto err;
/*
* Slow path: seek backwards, entry by entry, from the end.
*
* Try to find the left entry by seeking backward from the end of the
* end of the log. If we succeed, update "next_diff", and retry the
* fast-path.
* Drop the lock and try to find the left entry by seeking backward
* from the end of the end of the log. If we succeed, re-acquire the
* lock, update "next_diff", and retry the fast-path.
*/
flock(log_fd, LOCK_UN);
/* Slow path: seek backwards, entry by entry, from the end */
for (;;) {
enum kadm_ops op;
uint32_t len;
@@ -1106,7 +1038,7 @@ get_left(kadm5_server_context *server_context, slave *s, krb5_storage *sp,
/*
* We don't expect to reach the slave's version, unless the log
* has been rotated.
* has been modified after we released the lock.
*/
if (ver == s->version) {
krb5_warnx(context, "iprop log truncated while sending diffs "
@@ -1128,28 +1060,33 @@ get_left(kadm5_server_context *server_context, slave *s, krb5_storage *sp,
/*
* If we loop then we're hoping to hit the fast path so we can return a
* non-zero, positive left offset.
* non-zero, positive left offset with the lock held.
*
* We just updated the fast path pre-conditions, so unless a log
* truncation event happens again, we will hit the fast path.
* truncation event happens between the point where we dropped the lock
* and the point where we rearcuire it above, we will hit the fast
* path.
*/
}
err:
flock(log_fd, LOCK_UN);
return -1;
}
static off_t
get_right(krb5_context context, krb5_storage *sp, int lastver, slave *s,
off_t left, uint32_t *verp)
get_right(krb5_context context, int log_fd, krb5_storage *sp,
int lastver, slave *s, off_t left, uint32_t *verp)
{
int ret = 0;
int i = 0;
uint32_t ver = s->version;
off_t right = krb5_storage_seek(sp, left, SEEK_SET);
if (right <= 0)
if (right <= 0) {
flock(log_fd, LOCK_UN);
return -1;
}
/* The "lastver" bound should preclude us reaching EOF */
for (; ret == 0 && i < SEND_DIFFS_MAX_RECORDS && ver < lastver; ++i) {
@@ -1164,23 +1101,18 @@ get_right(krb5_context context, krb5_storage *sp, int lastver, slave *s,
right = krb5_storage_seek(sp, 0, SEEK_CUR);
else
right = -1;
if (right <= 0)
if (right <= 0) {
flock(log_fd, LOCK_UN);
return -1;
}
*verp = ver;
return right;
}
/*
* This function _must_ send something to the client unless it's dead, and if
* dead it must mark it so (and so close the connection). It is an error to
* return from this function without having done so _unless_ the client is
* either dead or not ready.
*/
static kadm5_ret_t
send_diffs(kadm5_server_context *server_context, slave *s,
static void
send_diffs(kadm5_server_context *server_context, slave *s, int log_fd,
const char *database, uint32_t current_version)
{
struct kadm5_log_snap snap;
krb5_context context = server_context->context;
krb5_storage *sp;
uint32_t initial_version;
@@ -1190,122 +1122,84 @@ send_diffs(kadm5_server_context *server_context, slave *s,
off_t right = 0;
krb5_ssize_t bytes;
krb5_data data;
kadm5_ret_t ret = 0;
int ret = 0;
/*
* diffready() can send part of an extant buffer, and does nothing if the
* client is either dead or not ready.
*/
if (!diffready(context, s))
return 0;
/* From this point onwards we cannot return without having sent anything */
if (nodiffs(context, s, current_version)) {
if (verbose)
krb5_warnx(context, "not sending diffs to up-to-date slave %s (no diffs)", s->name);
send_you_have_last_version(context, s);
return 0;
}
if (!diffready(context, s) || nodiffs(context, s, current_version))
return;
if (verbose)
krb5_warnx(context, "sending diffs to live-seeming slave %s", s->name);
ret = kadm5_log_snapshot(server_context, &snap);
if (ret) {
/*
* Here ret would be KADM5_LOG_CORRUPT. What can we do?
*/
send_you_have_last_version(context, s);
return 0;
}
sp = krb5_storage_from_fd(server_context->log_context.log_fd);
sp = krb5_storage_from_fd(log_fd);
if (sp == NULL)
krb5_err(context, IPROPD_RESTART_SLOW, ENOMEM,
"send_diffs: out of memory");
left = get_left(server_context, s, sp, current_version,
left = get_left(server_context, s, sp, log_fd, current_version,
&initial_version, &initial_tstamp);
if (left < 0) {
/* Some sort of error; fallback on full prop */
krb5_storage_free(sp);
if (verbose)
krb5_warnx(context, "sending full prop to slave %s "
"(could not find offset for incremental)", s->name);
send_complete(context, s, database, current_version,
initial_version, initial_tstamp);
return 0;
slave_dead(context, s);
return;
}
if (left == 0) {
/* Slave's version is not in the log, fall back on send_complete() */
krb5_storage_free(sp);
if (verbose)
krb5_warnx(context, "sending full prop to slave %s "
"(their version is too old)", s->name);
send_complete(context, s, database, current_version,
initial_version, initial_tstamp);
return 0;
return;
}
right = get_right(server_context->context, sp, current_version,
/* We still hold the read lock, if right > 0 */
right = get_right(server_context->context, log_fd, sp, current_version,
s, left, &ver);
if (right == left) {
/* Shouldn't happen */
flock(log_fd, LOCK_UN);
krb5_storage_free(sp);
if (verbose)
krb5_warnx(context, "not sending diffs to up-to-date slave %s (weird)", s->name);
send_you_have_last_version(context, s);
return 0;
return;
}
if (right < left) {
assert(right < 0);
krb5_storage_free(sp);
slave_dead(context, s);
return 0;
return;
}
if (krb5_storage_seek(sp, left, SEEK_SET) != left) {
krb5_warn(context, errno ? errno : EIO, "send_diffs: krb5_storage_seek");
ret = errno ? errno : EIO;
flock(log_fd, LOCK_UN);
krb5_warn(context, ret, "send_diffs: krb5_storage_seek");
krb5_storage_free(sp);
slave_dead(context, s);
return 0;
return;
}
ret = krb5_data_alloc(&data, right - left + 4);
if (ret)
krb5_err(context, IPROPD_RESTART_SLOW, ENOMEM, "out of memory");
if (ret) {
flock(log_fd, LOCK_UN);
krb5_warn(context, ret, "send_diffs: krb5_data_alloc");
krb5_storage_free(sp);
slave_dead(context, s);
return;
}
bytes = krb5_storage_read(sp, (char *)data.data + 4, data.length - 4);
flock(log_fd, LOCK_UN);
krb5_storage_free(sp);
if (bytes != data.length - 4) {
krb5_warnx(context, "send_diffs: log rotated");
return KADM5_LOG_SNAPSHOT_INVALID;
}
ret = kadm5_log_snapshot_verify(server_context, &snap);
if (ret) {
krb5_data_free(&data);
if (ret == KADM5_LOG_SNAPSHOT_INVALID) {
krb5_warnx(context, "send_diffs: log rotated");
return ret;
}
krb5_err(context, IPROPD_RESTART_SLOW, ENOMEM, "out of memory");
}
if (bytes != data.length - 4)
krb5_errx(context, IPROPD_RESTART, "locked log truncated???");
sp = krb5_storage_from_data(&data);
if (sp == NULL)
if (sp == NULL) {
krb5_err(context, IPROPD_RESTART_SLOW, ENOMEM, "out of memory");
return;
}
ret = krb5_store_uint32(sp, FOR_YOU);
krb5_storage_free(sp);
if (ret == 0) {
if (ret == 0)
ret = mk_priv_tail(context, s, &data);
if (ret == ENOMEM)
krb5_err(context, IPROPD_RESTART_SLOW, ENOMEM, "out of memory");
}
krb5_data_free(&data);
if (ret == 0) {
/* Save the fast-path continuation */
@@ -1327,10 +1221,10 @@ send_diffs(kadm5_server_context *server_context, slave *s,
krb5_warn(context, ret, "send_diffs: making or sending "
"KRB-PRIV message");
slave_dead(context, s);
return ret;
return;
}
slave_seen(s);
return 0;
return;
}
/* Sensible bound on slave message size */
@@ -1405,7 +1299,7 @@ read_msg(krb5_context context, slave *s, krb5_data *out)
}
static int
process_msg(kadm5_server_context *server_context, slave *s,
process_msg(kadm5_server_context *server_context, slave *s, int log_fd,
const char *database, uint32_t current_version)
{
krb5_context context = server_context->context;
@@ -1413,7 +1307,6 @@ process_msg(kadm5_server_context *server_context, slave *s,
krb5_data out;
krb5_storage *sp;
uint32_t tmp;
int tries = 3;
ret = read_msg(context, s, &out);
if (ret) {
@@ -1479,9 +1372,9 @@ process_msg(kadm5_server_context *server_context, slave *s,
krb5_warnx(context, "slave %s ready for updates from version %u",
s->name, tmp);
}
do {
ret = send_diffs(server_context, s, database, current_version);
} while (ret == KADM5_LOG_SNAPSHOT_INVALID && tries--);
if ((s->version_ack = tmp) < s->version)
break;
send_diffs(server_context, s, log_fd, database, current_version);
break;
case I_AM_HERE :
if (verbose)
@@ -1597,7 +1490,7 @@ write_stats(krb5_context context, slave *slaves, uint32_t current_version)
} else
rtbl_add_column_entry(tbl, SLAVE_ADDRESS, "<unknown>");
snprintf(str, sizeof(str), "%u", (unsigned)slaves->version);
snprintf(str, sizeof(str), "%u", (unsigned)slaves->version_ack);
rtbl_add_column_entry(tbl, SLAVE_VERSION, str);
if (slaves->flags & SLAVE_F_DEAD)
@@ -1677,14 +1570,14 @@ main(int argc, char **argv)
void *kadm_handle;
kadm5_server_context *server_context;
kadm5_config_params conf;
krb5_socket_t signal_fd, listen_fds[2];
krb5_socket_t signal_fd, listen_fd;
int log_fd;
slave *slaves = NULL;
uint32_t current_version = 0, old_version = 0;
krb5_keytab keytab;
char **files;
int aret;
int optidx = 0;
int num_listen_fds = 0;
int restarter_fd = -1;
struct stat st;
@@ -1782,19 +1675,24 @@ main(int argc, char **argv)
server_context = (kadm5_server_context *)kadm_handle;
ret = kadm5_log_init_nolock(server_context);
if (ret)
krb5_err(context, 1, ret, "Could not open iprop log file");
log_fd = open (server_context->log_context.log_file, O_RDONLY, 0);
if (log_fd < 0)
krb5_err (context, 1, errno, "open %s",
server_context->log_context.log_file);
if (fstat(server_context->log_context.log_fd, &st) == -1)
if (fstat(log_fd, &st) == -1)
krb5_err(context, 1, errno, "stat %s",
server_context->log_context.log_file);
kadm5_log_get_version_fd(server_context, -1, LOG_VERSION_LAST,
if (flock(log_fd, LOCK_SH) == -1)
krb5_err(context, 1, errno, "shared flock %s",
server_context->log_context.log_file);
kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST,
&current_version, NULL);
flock(log_fd, LOCK_UN);
signal_fd = make_signal_socket (context);
make_listen_sockets(context, port_str, listen_fds, &num_listen_fds);
listen_fd = make_listen_socket (context, port_str);
krb5_warnx(context, "ipropd-master started at version: %lu",
(unsigned long)current_version);
@@ -1806,28 +1704,22 @@ main(int argc, char **argv)
slave *p;
fd_set readset, writeset;
int max_fd = 0;
int nready;
int i;
struct timeval to = {30, 0};
uint32_t vers;
struct stat st2;
struct stat st2;;
#ifndef NO_LIMIT_FD_SETSIZE
if (signal_fd >= FD_SETSIZE || restarter_fd >= FD_SETSIZE)
if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE ||
restarter_fd >= FD_SETSIZE)
krb5_errx (context, IPROPD_RESTART, "fd too large");
for (i = 0; i < num_listen_fds; i++)
if (listen_fds[i] >= FD_SETSIZE)
krb5_errx (context, IPROPD_RESTART, "fd too large");
#endif
FD_ZERO(&readset);
FD_ZERO(&writeset);
FD_SET(signal_fd, &readset);
max_fd = max(max_fd, signal_fd);
for (i = 0; i < num_listen_fds; i++) {
FD_SET(listen_fds[i], &readset);
max_fd = max(max_fd, listen_fds[i]);
}
FD_SET(listen_fd, &readset);
max_fd = max(max_fd, listen_fd);
if (restarter_fd > -1) {
FD_SET(restarter_fd, &readset);
max_fd = max(max_fd, restarter_fd);
@@ -1849,7 +1741,6 @@ main(int argc, char **argv)
else
krb5_err (context, IPROPD_RESTART, errno, "select");
}
nready = ret;
if (stat(server_context->log_context.log_file, &st2) == -1) {
krb5_warn(context, errno, "could not stat log file by path");
@@ -1857,24 +1748,36 @@ main(int argc, char **argv)
}
if (st2.st_dev != st.st_dev || st2.st_ino != st.st_ino) {
kadm5_log_end(server_context);
(void) close(log_fd);
ret = kadm5_log_init_nolock(server_context);
if (ret)
krb5_err(context, IPROPD_RESTART_SLOW, ret,
"Could not re-open iprop log file");
log_fd = open(server_context->log_context.log_file, O_RDONLY, 0);
if (log_fd < 0)
krb5_err(context, IPROPD_RESTART_SLOW, errno, "open %s",
server_context->log_context.log_file);
if (fstat(server_context->log_context.log_fd, &st) == -1)
if (fstat(log_fd, &st) == -1)
krb5_err(context, IPROPD_RESTART_SLOW, errno, "stat %s",
server_context->log_context.log_file);
kadm5_log_get_version_fd(server_context, -1, LOG_VERSION_LAST,
if (flock(log_fd, LOCK_SH) == -1)
krb5_err(context, IPROPD_RESTART, errno, "shared flock %s",
server_context->log_context.log_file);
kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST,
&current_version, NULL);
flock(log_fd, LOCK_UN);
}
if (nready == 0) {
kadm5_log_get_version_fd(server_context, -1, LOG_VERSION_LAST,
if (ret == 0) {
/* Recover from failed transactions */
if (kadm5_log_init_nb(server_context) == 0)
kadm5_log_end(server_context);
if (flock(log_fd, LOCK_SH) == -1)
krb5_err(context, IPROPD_RESTART, errno,
"could not lock log file");
kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST,
&current_version, NULL);
flock(log_fd, LOCK_UN);
if (current_version > old_version) {
if (verbose)
@@ -1883,25 +1786,21 @@ main(int argc, char **argv)
(unsigned long)old_version,
(unsigned long)current_version);
for (p = slaves; p != NULL; p = p->next) {
int tries = 3;
if (p->flags & SLAVE_F_DEAD)
continue;
do {
ret = send_diffs(server_context, p, database,
current_version);
} while (ret == KADM5_LOG_SNAPSHOT_INVALID && tries--);
send_diffs(server_context, p, log_fd, database,
current_version);
}
old_version = current_version;
}
}
if (nready && restarter_fd > -1 && FD_ISSET(restarter_fd, &readset)) {
if (ret && FD_ISSET(restarter_fd, &readset)) {
exit_flag = SIGTERM;
break;
}
if (nready && FD_ISSET(signal_fd, &readset)) {
if (ret && FD_ISSET(signal_fd, &readset)) {
#ifndef NO_UNIX_SOCKETS
struct sockaddr_un peer_addr;
#else
@@ -1914,11 +1813,15 @@ main(int argc, char **argv)
krb5_warn (context, errno, "recvfrom");
continue;
}
--nready;
assert(nready >= 0);
--ret;
assert(ret >= 0);
old_version = current_version;
kadm5_log_get_version_fd(server_context, -1, LOG_VERSION_LAST,
if (flock(log_fd, LOCK_SH) == -1)
krb5_err(context, IPROPD_RESTART, errno, "shared flock %s",
server_context->log_context.log_file);
kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST,
&current_version, NULL);
flock(log_fd, LOCK_UN);
if (current_version != old_version) {
/*
* If current_version < old_version then the log got
@@ -1938,14 +1841,10 @@ main(int argc, char **argv)
(unsigned long)old_version,
(unsigned long)current_version);
for (p = slaves; p != NULL; p = p->next) {
int tries = 3;
if (p->flags & SLAVE_F_DEAD)
continue;
do {
ret = send_diffs(server_context, p, database,
current_version);
} while (ret == EAGAIN && tries--);
send_diffs(server_context, p, log_fd, database,
current_version);
}
} else {
if (verbose)
@@ -1960,39 +1859,31 @@ main(int argc, char **argv)
FD_ISSET(p->fd, &writeset) &&
((have_tail(p) && send_tail(context, p) == 0) ||
(!have_tail(p) && more_diffs(p)))) {
int tries = 3;
do {
ret = send_diffs(server_context, p, database,
current_version);
} while (ret == KADM5_LOG_SNAPSHOT_INVALID && tries--);
send_diffs(server_context, p, log_fd, database,
current_version);
}
}
for(p = slaves; p != NULL; p = p->next) {
if (p->flags & SLAVE_F_DEAD)
continue;
if (nready && FD_ISSET(p->fd, &readset)) {
--nready;
assert(nready >= 0);
ret = process_msg(server_context, p, database,
if (ret && FD_ISSET(p->fd, &readset)) {
--ret;
assert(ret >= 0);
ret = process_msg(server_context, p, log_fd, database,
current_version);
if (ret && ret != EWOULDBLOCK) {
krb5_warn(context, ret, "process_msg()");
if (ret && ret != EWOULDBLOCK)
slave_dead(context, p);
}
} else if (slave_gone_p (p))
slave_dead(context, p);
else if (slave_missing_p (p))
send_are_you_there (context, p);
}
for (i = 0; nready && i < num_listen_fds; i++) {
if (FD_ISSET(listen_fds[i], &readset)) {
add_slave(context, keytab, &slaves, listen_fds[i]);
--nready;
assert(nready >= 0);
}
if (ret && FD_ISSET(listen_fd, &readset)) {
add_slave (context, keytab, &slaves, listen_fd);
--ret;
assert(ret >= 0);
}
write_stats(context, slaves, current_version);
}
+36 -6
View File
@@ -124,14 +124,16 @@ connect_to_master (krb5_context context, const char *master,
}
static void
get_creds(krb5_context context, krb5_ccache *cache)
get_creds(krb5_context context, krb5_ccache *cache, const char *serverhost)
{
krb5_keytab keytab;
krb5_principal client;
krb5_error_code ret;
krb5_get_init_creds_opt *init_opts;
krb5_creds creds;
char *server;
char keytab_buf[256];
int aret;
if (no_keytab_flag) {
/* We're using an externally refreshed ccache */
@@ -174,8 +176,13 @@ get_creds(krb5_context context, krb5_ccache *cache)
ret = krb5_get_init_creds_opt_alloc(context, &init_opts);
if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
aret = asprintf (&server, "%s/%s", IPROP_NAME, serverhost);
if (aret == -1 || server == NULL)
krb5_errx (context, 1, "malloc: no memory");
ret = krb5_get_init_creds_keytab(context, &creds, client, keytab,
0, NULL, init_opts);
0, server, init_opts);
free (server);
krb5_get_init_creds_opt_free(context, init_opts);
if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds");
@@ -348,6 +355,11 @@ receive_loop(krb5_context context,
if (verbose)
krb5_warnx(context, "receiving diffs");
ret = kadm5_log_exclusivelock(server_context);
if (ret)
krb5_err(context, IPROPD_RESTART, ret,
"Failed to lock iprop log for writes");
/*
* Seek to the first entry in the message from the master that is
* past the current version of the local database.
@@ -465,6 +477,9 @@ receive(krb5_context context,
if (ret)
krb5_err(context, IPROPD_RESTART_SLOW, ret, "db->close");
(void) kadm5_log_sharedlock(server_context);
if (verbose)
krb5_warnx(context, "downgraded iprop log lock to shared");
kadm5_log_signal_master(server_context);
if (verbose)
krb5_warnx(context, "signaled master for hierarchical iprop");
@@ -516,6 +531,9 @@ reinit_log(krb5_context context,
ret = kadm5_log_reinit(server_context, vno);
if (ret)
krb5_err(context, IPROPD_RESTART_SLOW, ret, "kadm5_log_reinit");
(void) kadm5_log_sharedlock(server_context);
if (verbose)
krb5_warnx(context, "downgraded iprop log lock to shared");
}
@@ -535,6 +553,10 @@ receive_everything(krb5_context context, int fd,
krb5_warnx(context, "receive complete database");
ret = kadm5_log_exclusivelock(server_context);
if (ret)
krb5_err(context, IPROPD_RESTART, ret,
"Failed to lock iprop log for writes");
if (server_context->db->hdb_method_name) {
ret = asprintf(&dbname, "%.*s:%s-NEW",
(int) strlen(server_context->db->hdb_method_name) - 1,
@@ -878,12 +900,15 @@ main(int argc, char **argv)
ret = kadm5_log_init(server_context);
if (ret)
krb5_err(context, 1, ret, "kadm5_log_init");
(void) kadm5_log_sharedlock(server_context);
if (verbose)
krb5_warnx(context, "downgraded iprop log lock to shared");
ret = server_context->db->hdb_close(context, server_context->db);
if (ret)
krb5_err(context, 1, ret, "db->close");
get_creds(context, &ccache);
get_creds(context, &ccache, master);
ret = krb5_sname_to_principal (context, master, IPROP_NAME,
KRB5_NT_SRV_HST, &server);
@@ -949,7 +974,7 @@ main(int argc, char **argv)
krb5_auth_con_free(context, auth_context);
auth_context = NULL;
}
get_creds(context, &ccache);
get_creds(context, &ccache, master);
if (verbose)
krb5_warnx(context, "authenticating to master");
ret = krb5_sendauth (context, &auth_context, &master_fd,
@@ -1066,6 +1091,9 @@ main(int argc, char **argv)
krb5_err(context, IPROPD_RESTART, ret, "kadm5_log_init while "
"handling a message from the master");
}
(void) kadm5_log_sharedlock(server_context);
if (verbose)
krb5_warnx(context, "downgraded iprop log lock to shared");
ret = server_context->db->hdb_close (context, server_context->db);
if (ret)
@@ -1097,6 +1125,7 @@ main(int argc, char **argv)
krb5_warnx(context, "master sent us a full dump");
ret = receive_everything(context, master_fd, server_context,
auth_context);
(void) kadm5_log_sharedlock(server_context);
if (ret == 0) {
ret = ihave(context, auth_context, master_fd,
server_context->log_context.version);
@@ -1105,6 +1134,8 @@ main(int argc, char **argv)
connected = FALSE;
else
is_up_to_date(context, status_file, server_context);
if (verbose)
krb5_warnx(context, "downgraded iprop log lock to shared");
kadm5_log_signal_master(server_context);
if (verbose)
krb5_warnx(context, "signaled master for hierarchical iprop");
@@ -1121,7 +1152,6 @@ main(int argc, char **argv)
*
* So we don't ihave() here.
*/
is_up_to_date(context, status_file, server_context);
send_im_here(context, master_fd, auth_context);
break;
case YOU_HAVE_LAST_VERSION:
@@ -1145,7 +1175,7 @@ main(int argc, char **argv)
slave_status(context, status_file, "disconnected from master");
retry:
if (connected == FALSE)
krb5_warnx (context, "disconnected from server");
krb5_warnx (context, "disconnected for server");
if (exit_flag)
krb5_warnx (context, "got an exit signal");
-2
View File
@@ -73,8 +73,6 @@ error_code OLD_SERVER_HOOK_VERSION, "KADM5 server hook is too old for this versi
error_code NEW_SERVER_HOOK_VERSION, "KADM5 server hook is too new for this version of Heimdal"
error_code READ_ONLY, "Database is read-only; try primary server"
error_code PASS_Q_GENERIC, "Unspecified password quality failure"
error_code LOG_SNAPSHOT_INVALID, "Incremental propagation log rotated; restart operation"
error_code LOG_EMPTY, "Incremental propagation log is empty"
# MIT has:
-1
View File
@@ -86,7 +86,6 @@
#include <hdb.h>
#include <der.h>
#include <parse_units.h>
#include "private.h"
#endif /* __KADM5_LOCL_H__ */
-2
View File
@@ -85,8 +85,6 @@ EXPORTS
kadm5_log_init_sharedlock
kadm5_log_next
kadm5_log_nop
kadm5_log_snapshot
kadm5_log_snapshot_verify
kadm5_log_truncate
kadm5_log_modify
_kadm5_acl_check_permission
+15 -175
View File
@@ -174,6 +174,12 @@ RCSID("$Id$");
* will deadlock with ipropd-slave -- don't do that.
*/
#define LOG_HEADER_SZ ((off_t)(sizeof(uint32_t) * 4))
#define LOG_TRAILER_SZ ((off_t)(sizeof(uint32_t) * 2))
#define LOG_WRAPPER_SZ ((off_t)(LOG_HEADER_SZ + LOG_TRAILER_SZ))
#define LOG_UBER_LEN ((off_t)(sizeof(uint64_t) + sizeof(uint32_t) * 2))
#define LOG_UBER_SZ ((off_t)(LOG_WRAPPER_SZ + LOG_UBER_LEN))
#define LOG_NOPEEK 0
#define LOG_DOPEEK 1
@@ -484,46 +490,12 @@ kadm5_log_get_version_fd(kadm5_server_context *server_context, int fd,
{
kadm5_ret_t ret = 0;
krb5_storage *sp;
uint32_t tmp;
if (tstamp == NULL)
tstamp = &tmp;
*ver = 0;
*tstamp = 0;
if (fd == -1)
fd = server_context->log_context.log_fd;
sp = krb5_storage_from_fd(fd);
if (sp == NULL)
return errno ? errno : ENOMEM;
ret = kadm5_log_get_version_sp(server_context, sp, which, ver, tstamp);
krb5_storage_free(sp);
return ret;
}
kadm5_ret_t
kadm5_log_get_version_sp(kadm5_server_context *server_context, krb5_storage *sp,
int which, uint32_t *ver, uint32_t *tstamp)
{
struct kadm5_log_snap snap;
kadm5_ret_t ret = 0;
enum kadm_ops op = kadm_get;
uint32_t len = 0;
uint32_t tmp;
/*
* If we're operating lock-less-ly then get a snapshot of the log so we can
* validate that what we read here is correct once we're done reading it.
*/
memset(&snap, 0, sizeof(snap));
if (server_context->log_context.lock_mode == LOCK_UN) {
ret = kadm5_log_snapshot(server_context, &snap);
if (ret)
return ret;
}
if (fd == -1)
return 0; /* /dev/null */
if (tstamp == NULL)
tstamp = &tmp;
@@ -531,6 +503,10 @@ kadm5_log_get_version_sp(kadm5_server_context *server_context, krb5_storage *sp,
*ver = 0;
*tstamp = 0;
sp = krb5_storage_from_fd(fd);
if (sp == NULL)
return errno ? errno : ENOMEM;
switch (which) {
case LOG_VERSION_LAST:
ret = kadm5_log_goto_end(server_context, sp);
@@ -555,92 +531,10 @@ kadm5_log_get_version_sp(kadm5_server_context *server_context, krb5_storage *sp,
break;
}
if (ret == 0 && server_context->log_context.lock_mode == LOCK_UN)
/* Validate the snapshot when operating lock-less-ly */
return kadm5_log_snapshot_verify(server_context, &snap);
krb5_storage_free(sp);
return ret;
}
/*
* For lock-less reading of the log first get a snapshot, then read, then
* verify the snapshot before using the data read. If snapshot verification
* fails, start over.
*
* This will be used in ipropd-master and iprop-log to avoid needing a lock on
* the iprop log. For example, when a client says I_HAVE $ver then the server
* gets a snapshot, finds the offset to $ver and the offset to the end of the
* log, reads all that into memory, then the server veerifies the snapshot, and
* finally it sends the data to client, but if the snapshot verification fails
* then the server starts over the process of finding the offset to $ver.
*
* The way this works is that as long as the log is not rotated and truncated,
* then we can expect the header of the first record after the uber-record to
* remain the same.
*/
kadm5_ret_t
kadm5_log_snapshot(kadm5_server_context *server_context,
struct kadm5_log_snap *snap)
{
ssize_t bytes;
assert(sizeof(snap->buf) < CHAR_MAX);
snap->bytes = 0;
bytes = pread(server_context->log_context.log_fd,
snap->buf, sizeof(snap->buf), 0);
if (bytes < 0)
return errno;
if (bytes < LOG_UBER_SZ)
return KADM5_LOG_CORRUPT;
if (bytes < sizeof(snap->buf))
bytes = LOG_UBER_SZ;
snap->bytes = bytes;
return 0;
}
/*
* kadm5_log_snapshot_verify() checks that the iprop log has not been rotated
* since the given `snap` snapshot. Returns -1 if the log has been rotated.
*/
kadm5_ret_t
kadm5_log_snapshot_verify(kadm5_server_context *server_context,
struct kadm5_log_snap *snap)
{
struct kadm5_log_snap v;
kadm5_ret_t ret;
assert(sizeof(snap->buf) < CHAR_MAX);
if (snap->bytes < LOG_UBER_SZ)
return KADM5_LOG_SNAPSHOT_INVALID;
ret = kadm5_log_snapshot(server_context, &v);
if (ret)
return ret;
if (v.bytes < LOG_UBER_SZ)
return KADM5_LOG_CORRUPT;
/* The two snapshots are equal -> no log rotation, no log change at all */
if (snap->bytes == v.bytes && memcmp(snap->buf, v.buf, v.bytes) == 0)
return 0;
/*
* Both snapshots capture the first record's header past the uber record?
* Check that that first record's header is the same for both.
*/
if (snap->bytes == v.bytes && v.bytes == sizeof(v.buf) &&
memcmp(snap->buf + LOG_UBER_SZ, v.buf + LOG_UBER_SZ,
LOG_HEADER_SZ) == 0)
return 0; /* No log rotation, but the log did change */
/*
* Log rotated, or we don't have any log entries but the uber record
* changed.
*/
return KADM5_LOG_SNAPSHOT_INVALID;
}
/* Get the version of the last confirmed entry in the log */
kadm5_ret_t
kadm5_log_get_version(kadm5_server_context *server_context, uint32_t *ver)
@@ -2239,7 +2133,7 @@ kadm5_log_goto_first(kadm5_server_context *server_context, krb5_storage *sp)
if (ret)
return ret;
if (op == kadm_nop && len == LOG_UBER_LEN && seek_next(sp) == -1)
return KADM5_LOG_EMPTY;
return KADM5_LOG_CORRUPT;
return 0;
}
@@ -2609,13 +2503,6 @@ load_entries(kadm5_server_context *context, krb5_data *p,
/*
* Truncate the log, retaining at most `keep' entries and at most `maxbytes'.
* If `maxbytes' is zero, keep at most the default log size limit.
*
* I.e., rotate the log, except we don't rename a new log into place.
*
* Ensures that the log will be smaller than prior to truncation. This is
* important as it ensures that the log snapshot approach used by ipropd-master
* to read the log lock-less-ly will work. See also kadm5_log_snapshot() and
* kadm5_log_snapshot_verify().
*/
kadm5_ret_t
kadm5_log_truncate(kadm5_server_context *context, size_t keep, size_t maxbytes)
@@ -2627,10 +2514,7 @@ kadm5_log_truncate(kadm5_server_context *context, size_t keep, size_t maxbytes)
krb5_storage *sp;
ssize_t bytes;
uint64_t sz;
off_t off, fsz;
if ((fsz = lseek(context->log_context.log_fd, 0, SEEK_END)) < 0)
return errno;
off_t off;
if (maxbytes == 0)
maxbytes = get_max_log_size(context->context);
@@ -2665,50 +2549,6 @@ kadm5_log_truncate(kadm5_server_context *context, size_t keep, size_t maxbytes)
return EOVERFLOW; /* caller should ask for fewer entries */
}
/* Ensure that the iprop log will be smaller, or defer truncation */
if (sz >= fsz) {
uint32_t skip;
krb5_data_free(&entries);
if (first > last)
first = 1;
skip = (last - first) / 2;
if (skip < 2) {
/*
* There must be an entry that is just large enough, or larger,
* that it alone causes the log to exceed the log size
* limit.
*/
krb5_warnx(context->context,
"Unable to truncate log due to very large record; "
"deferring truncation");
return 0;
}
first += (last - first) / 2;
ret = load_entries(context, &entries, last - first, maxbytes, &first, &last);
if (ret)
return ret;
sz = LOG_UBER_SZ + entries.length;
off = (off_t)sz;
if (off < 0 || off != sz || sz < entries.length) {
krb5_data_free(&entries);
return EOVERFLOW; /* caller should ask for fewer entries */
}
if (sz >= fsz) {
/* Should never happen! */
krb5_data_free(&entries);
krb5_warnx(context->context,
"Unable to truncate log due to very large record; "
"deferring truncation");
return 0;
}
}
/* Truncate to zero size and seek to zero offset */
if (ftruncate(context->log_context.log_fd, 0) < 0 ||
lseek(context->log_context.log_fd, 0, SEEK_SET) < 0) {
-2
View File
@@ -87,8 +87,6 @@ HEIMDAL_KAMD5_SERVER_1.0 {
kadm5_log_init_sharedlock;
kadm5_log_next;
kadm5_log_nop;
kadm5_log_snapshot;
kadm5_log_snapshot_verify;
kadm5_log_truncate;
kadm5_log_modify;
_kadm5_acl_check_permission;
+30 -33
View File
@@ -704,30 +704,25 @@ change_password_loop (krb5_context context,
* do the SOCKS4a I/O.
*/
while (!_krb5_socks4a_connected(socks4a)) {
struct pollfd pfd;
fd_set readfds, writefds;
int nready;
pfd.fd = sock;
pfd.events = 0;
pfd.revents = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
if (_krb5_socks4a_reading(socks4a))
pfd.events |= POLLIN;
FD_SET(sock, &readfds);
if (_krb5_socks4a_writing(socks4a))
pfd.events |= POLLOUT;
nready = poll(&pfd, 1, -1); /* blocking */
if (nready < 0) {
if (errno == EINTR)
continue;
FD_SET(sock, &writefds);
nready = select(sock + 1, &readfds, &writefds,
/*exceptfds*/NULL, /*timeout*/NULL);
if (nready == -1) {
ret = errno;
break;
}
if (nready == 0) {
if (nready <= 0) {
ret = EIO; /* timeout should be impossible */
break;
}
ret = _krb5_socks4a_io(socks4a);
if (ret)
break;
@@ -738,6 +733,9 @@ change_password_loop (krb5_context context,
}
for (i = 0; !done && i < 5; ++i) {
fd_set fdset;
struct timeval tv;
if (!replied) {
replied = 0;
@@ -755,28 +753,27 @@ change_password_loop (krb5_context context,
}
}
struct pollfd pfd;
int timeout_ms;
timeout_ms = (1 + (1 << i)) * 1000;
pfd.fd = sock;
pfd.events = POLLIN;
pfd.revents = 0;
ret = poll(&pfd, 1, timeout_ms);
if (ret < 0) {
if (errno == EINTR)
continue;
rk_closesocket(sock);
ret = errno;
goto out;
#ifndef NO_LIMIT_FD_SETSIZE
if (sock >= FD_SETSIZE) {
ret = ERANGE;
krb5_set_error_message(context, ret,
"fd %d too large", sock);
rk_closesocket (sock);
goto out;
}
#endif
if (ret == 0) {
ret = KRB5_KDC_UNREACH;
continue;
FD_ZERO(&fdset);
FD_SET(sock, &fdset);
tv.tv_usec = 0;
tv.tv_sec = 1 + (1 << i);
ret = select (sock + 1, &fdset, NULL, NULL, &tv);
if (rk_IS_SOCKET_ERROR(ret) && rk_SOCK_ERRNO != EINTR) {
rk_closesocket(sock);
goto out;
}
if (pfd.revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) {
if (ret == 1) {
ret = (*proc->process_rep) (context,
auth_context,
is_stream,
+4 -4
View File
@@ -489,7 +489,7 @@ init_context_from_config_file(krb5_context context)
tmp = secure_getenv("KRB5_TRACE");
if (tmp)
heim_add_trace_dest(context->hcontext, "libkrb5", tmp);
heim_add_debug_dest(context->hcontext, "libkrb5", tmp);
s = krb5_config_get_strings(context, NULL, "logging", "krb5", NULL);
if (s) {
char **p;
@@ -1108,15 +1108,15 @@ krb5_kerberos_enctypes(krb5_context context)
};
static const krb5_enctype weak[] = {
ETYPE_AES256_CTS_HMAC_SHA384_192,
ETYPE_AES128_CTS_HMAC_SHA256_128,
ETYPE_AES256_CTS_HMAC_SHA1_96,
ETYPE_AES128_CTS_HMAC_SHA1_96,
ETYPE_AES256_CTS_HMAC_SHA384_192,
ETYPE_AES128_CTS_HMAC_SHA256_128,
ETYPE_ARCFOUR_HMAC_MD5,
ETYPE_NULL
};
if (krb5_enctype_valid(context, ETYPE_ARCFOUR_HMAC_MD5) == 0)
if (krb5_enctype_valid(context, ETYPE_ARCFOUR_HMAC_MD5))
return weak;
return strong;
-16
View File
@@ -608,12 +608,8 @@ krb5_create_checksum(krb5_context context,
}
if (arcfour_checksum_p(ct, crypto)) {
#ifdef HEIM_ARCFOUR
keyusage = usage;
_krb5_usage2arcfour(context, &keyusage);
#else
return KRB5_PROG_SUMTYPE_NOSUPP;
#endif /* HEIM_ARCFOUR */
} else
keyusage = CHECKSUM_USAGE(usage);
@@ -742,12 +738,8 @@ krb5_verify_checksum(krb5_context context,
}
if (arcfour_checksum_p(ct, crypto)) {
#ifdef HEIM_ARCFOUR
keyusage = usage;
_krb5_usage2arcfour(context, &keyusage);
#else
return KRB5_PROG_SUMTYPE_NOSUPP;
#endif /* HEIM_ARCFOUR */
} else
keyusage = CHECKSUM_USAGE(usage);
@@ -2075,12 +2067,8 @@ krb5_create_checksum_iov(krb5_context context,
}
if (arcfour_checksum_p(ct, crypto)) {
#ifdef HEIM_ARCFOUR
keyusage = usage;
_krb5_usage2arcfour(context, &keyusage);
#else
return KRB5_PROG_SUMTYPE_NOSUPP;
#endif /* HEIM_ARCFOUR */
} else
keyusage = CHECKSUM_USAGE(usage);
@@ -2146,12 +2134,8 @@ krb5_verify_checksum_iov(krb5_context context,
}
if (arcfour_checksum_p(ct, crypto)) {
#ifdef HEIM_ARCFOUR
keyusage = usage;
_krb5_usage2arcfour(context, &keyusage);
#else
return KRB5_PROG_SUMTYPE_NOSUPP;
#endif /* HEIM_ARCFOUR */
} else
keyusage = CHECKSUM_USAGE(usage);
+17 -4
View File
@@ -69,17 +69,22 @@ krb5_expand_hostname (krb5_context context,
int error;
if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0 ||
krb5_config_get_bool(context, NULL, "libdefaults", "block_dns", NULL))
krb5_config_get_bool(context, NULL, "libdefaults", "block_dns", NULL)) {
krb5_warnx(context, "krb5_expand_hostname: DNS canonicalization disabled or blocked for hostname %s", orig_hostname);
return copy_hostname (context, orig_hostname, new_hostname);
}
memset (&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
if (error)
if (error) {
krb5_warnx(context, "krb5_expand_hostname: getaddrinfo(%s) failed: %s", orig_hostname, gai_strerror(error));
return copy_hostname (context, orig_hostname, new_hostname);
}
for (a = ai; a != NULL; a = a->ai_next) {
if (a->ai_canonname != NULL) {
krb5_warnx(context, "krb5_expand_hostname: canonical name for %s -> %s", orig_hostname, a->ai_canonname);
*new_hostname = strdup (a->ai_canonname);
freeaddrinfo (ai);
if (*new_hostname == NULL)
@@ -89,6 +94,7 @@ krb5_expand_hostname (krb5_context context,
}
}
freeaddrinfo (ai);
krb5_warnx(context, "krb5_expand_hostname: no canonical name found for %s, falling back to copy_hostname", orig_hostname);
return copy_hostname (context, orig_hostname, new_hostname);
}
@@ -145,20 +151,25 @@ krb5_expand_hostname_realms (krb5_context context,
int error;
krb5_error_code ret = 0;
if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0)
if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0) {
krb5_warnx(context, "krb5_expand_hostname_realms: DNS canonicalization disabled for hostname %s", orig_hostname);
return vanilla_hostname (context, orig_hostname, new_hostname,
realms);
}
memset (&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
if (error)
if (error) {
krb5_warnx(context, "krb5_expand_hostname_realms: getaddrinfo(%s) failed: %s", orig_hostname, gai_strerror(error));
return vanilla_hostname (context, orig_hostname, new_hostname,
realms);
}
for (a = ai; a != NULL; a = a->ai_next) {
if (a->ai_canonname != NULL) {
krb5_warnx(context, "krb5_expand_hostname_realms: canonical name for %s -> %s", orig_hostname, a->ai_canonname);
ret = copy_hostname (context, a->ai_canonname, new_hostname);
if (ret) {
freeaddrinfo (ai);
@@ -168,11 +179,13 @@ krb5_expand_hostname_realms (krb5_context context,
ret = krb5_get_host_realm (context, *new_hostname, realms);
if (ret == 0) {
freeaddrinfo (ai);
krb5_warnx(context, "krb5_expand_hostname_realms: host %s mapped to realm %s", *new_hostname, realms && *realms ? (*realms)[0] : "<unknown>");
return 0;
}
free (*new_hostname);
}
}
freeaddrinfo(ai);
krb5_warnx(context, "krb5_expand_hostname_realms: no canonical name/realm found for %s, falling back to vanilla_hostname", orig_hostname);
return vanilla_hostname (context, orig_hostname, new_hostname, realms);
}
+1 -1
View File
@@ -1081,6 +1081,7 @@ cred_delete(krb5_context context,
ret = krb5_storage_to_data(sp, &orig_cred_data);
if (ret)
goto out;
krb5_storage_free(sp);
cred_data_in_file = malloc(orig_cred_data.length);
if (cred_data_in_file == NULL)
@@ -1102,7 +1103,6 @@ cred_delete(krb5_context context,
goto out;
}
krb5_storage_free(sp);
sp = krb5_storage_emem();
if (sp == NULL)
goto out;
+1 -1
View File
@@ -645,7 +645,7 @@ get_cred_kdc(krb5_context context,
krb5_sendto_ctx stctx;
ret = krb5_sendto_ctx_alloc(context, &stctx);
if (ret)
goto out;
return ret;
krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
if (kdc_hostname)
+114 -2
View File
@@ -217,6 +217,31 @@ krb5_kt_resolve(krb5_context context,
residual = keytab_name(name, &type, &type_len);
/*
* Aggressive process-context logging:
* Print pid/ppid/uid/gid and the raw name string being resolved
* so test captures show which process attempted to resolve which
* keytab and with what parsed type/residual.
*
* We intentionally always emit this via krb5_warnx to make sure it
* appears in stderr/journal during tests.
*/
{
pid_t pid = getpid();
pid_t ppid = getppid();
uid_t uid = getuid();
gid_t gid = getgid();
krb5_warnx(context,
"krb5_kt_resolve: pid=%d ppid=%d uid=%d gid=%d resolving name=\"%s\" parsed_type=\"%.*s\" residual=\"%s\"",
(int)pid,
(int)ppid,
(int)uid,
(int)gid,
name ? name : "<null>",
(int)type_len, type ? type : "<null>",
residual ? residual : "<null>");
}
for(i = 0; i < context->num_kt_types; i++) {
if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0)
break;
@@ -251,8 +276,15 @@ static const char *default_ktname(krb5_context context)
const char *tmp = NULL;
tmp = secure_getenv("KRB5_KTNAME");
if(tmp != NULL)
if(tmp != NULL) {
/* Aggressive logging: record environment override */
krb5_warnx(context, "default_ktname: using KRB5_KTNAME from env: \"%s\" (pid=%d)", tmp, (int)getpid());
return tmp;
}
/* Aggressive logging: record context default choice as well */
krb5_warnx(context, "default_ktname: using context->default_keytab: \"%s\" (pid=%d)",
context->default_keytab ? context->default_keytab : "<null>",
(int)getpid());
return context->default_keytab;
}
@@ -597,6 +629,13 @@ _krb5_kt_principal_not_found(krb5_context context,
else
kvno_str[0] = '\0';
/* Provide a concise debug line so tests can see what principal/keytab/enctype failed */
krb5_warnx(context, "kt_principal_not_found: principal=%s kvno=%s keytab=%s enctype=%s",
princ ? princ : "<unknown>",
kvno_str[0] ? kvno_str : "<none>",
kt_name ? kt_name : "unknown keytab",
enctype_str ? enctype_str : "unknown enctype");
krb5_set_error_message(context, ret,
N_("Failed to find %s%s in keytab %s (%s)",
"principal, kvno, keytab file, enctype"),
@@ -636,27 +675,81 @@ krb5_kt_get_entry_wrapped(krb5_context context,
entry->vno = 0;
while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) {
/* Always-log the entry we're inspecting and what is being requested */
{
char *entry_unp = NULL;
char *want_unp = NULL;
(void) krb5_unparse_name(context, tmp.principal, &entry_unp);
(void) krb5_unparse_name(context, principal, &want_unp);
krb5_warnx(context, "krb5_kt_get_entry_wrapped: inspecting entry=%s vno=%d enctype=%d against requested=%s kvno=%u enctype=%d",
entry_unp ? entry_unp : "<unparsed>",
tmp.vno,
tmp.keyblock.keytype,
want_unp ? want_unp : "<unparsed>",
(unsigned)kvno,
(int)enctype);
free(entry_unp);
free(want_unp);
}
if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) {
/* the file keytab might only store the lower 8 bits of
the kvno, so only compare those bits */
if (kvno == tmp.vno
|| (tmp.vno < 256 && kvno % 256 == tmp.vno)) {
/* Matched principal and kvno -> return this entry */
{
char *matched = NULL;
(void) krb5_unparse_name(context, tmp.principal, &matched);
krb5_warnx(context, "krb5_kt_get_entry_wrapped: matched entry=%s vno=%d enctype=%d -- returning",
matched ? matched : "<unparsed>",
tmp.vno,
tmp.keyblock.keytype);
free(matched);
}
krb5_kt_copy_entry_contents (context, &tmp, entry);
krb5_kt_free_entry (context, &tmp);
krb5_kt_end_seq_get(context, id, &cursor);
return 0;
} else if (kvno == 0 && tmp.vno > entry->vno) {
/* Matched principal but kvno selection logic prefers a higher vno */
{
char *matched = NULL;
(void) krb5_unparse_name(context, tmp.principal, &matched);
krb5_warnx(context, "krb5_kt_get_entry_wrapped: matched principal %s but kvno differs (entry.vno=%d tmp.vno=%d); selecting higher vno for now",
matched ? matched : "<unparsed>",
entry->vno,
tmp.vno);
free(matched);
}
if (entry->vno)
krb5_kt_free_entry (context, entry);
krb5_kt_copy_entry_contents (context, &tmp, entry);
} else {
/* Matched name but kvno didn't match and we are not in kvno-selection mode; log it. */
char *matched = NULL;
(void) krb5_unparse_name(context, tmp.principal, &matched);
krb5_warnx(context, "krb5_kt_get_entry_wrapped: matched principal %s but kvno mismatch (tmp.vno=%d requested_kvno=%u); continuing iteration",
matched ? matched : "<unparsed>",
tmp.vno,
(unsigned)kvno);
free(matched);
}
}
krb5_kt_free_entry(context, &tmp);
}
krb5_kt_end_seq_get (context, id, &cursor);
if (entry->vno == 0)
if (entry->vno == 0) {
/* No matching kvno was found in the keytab iteration; log and return */
krb5_warnx(context, "krb5_kt_get_entry_wrapped: no matching entry found -> invoking _krb5_kt_principal_not_found");
return _krb5_kt_principal_not_found(context, KRB5_KT_NOTFOUND,
id, principal, enctype, kvno);
}
krb5_warnx(context, "krb5_kt_get_entry_wrapped: returning selected entry vno=%d enctype=%d",
entry->vno, entry->keyblock.keytype);
return 0;
}
@@ -688,6 +781,25 @@ krb5_kt_get_entry(krb5_context context,
krb5_const_principal try_princ;
krb5_name_canon_iterator name_canon_iter;
/* Debug: record incoming keytab lookup request (always emitted) */
{
char *want_unp = NULL;
char *kt_full = NULL;
if (principal && krb5_unparse_name(context, principal, &want_unp) != 0)
want_unp = NULL;
(void) krb5_kt_get_full_name(context, id, &kt_full);
krb5_warnx(context, "krb5_kt_get_entry: requested principal=%s keytab=%s kvno=%u enctype=%d",
want_unp ? want_unp : "<null>",
kt_full ? kt_full : "<unknown>",
(unsigned)kvno,
(int)enctype);
free(want_unp);
free(kt_full);
}
if (!principal)
/* Use `NULL' instead of `principal' to quiet static analizers */
return krb5_kt_get_entry_wrapped(context, id, NULL, kvno, enctype,
+61 -12
View File
@@ -380,13 +380,21 @@ fkt_start_seq_get_int(krb5_context context,
d->filename, strerror(ret));
return ret;
}
/* Loud logging: record that we opened the keytab file and process info */
krb5_warnx(context, "fkt_start_seq_get_int: opened keytab \"%s\" fd=%d flags=0x%x pid=%d uid=%d",
d->filename ? d->filename : "<null>",
c->fd,
(unsigned)flags,
(int)getpid(),
(int)getuid());
rk_cloexec(c->fd);
if (exclusive) {
ret = _krb5_xlock(context, c->fd, exclusive, d->filename);
if (ret) {
close(c->fd);
return ret;
}
ret = _krb5_xlock(context, c->fd, exclusive, d->filename);
if (ret) {
krb5_warnx(context, "fkt_start_seq_get_int: failed to lock keytab \"%s\": ret=%d", d->filename ? d->filename : "<null>", ret);
close(c->fd);
return ret;
}
if ((flags & O_ACCMODE) == O_RDWR && (flags & O_APPEND))
stdio_mode = "ab+";
@@ -396,6 +404,7 @@ fkt_start_seq_get_int(krb5_context context,
stdio_mode = "wb";
c->sp = krb5_storage_stdio_from_fd(c->fd, stdio_mode);
if (c->sp == NULL) {
krb5_warnx(context, "fkt_start_seq_get_int: krb5_storage_stdio_from_fd returned NULL for \"%s\"", d->filename ? d->filename : "<null>");
close(c->fd);
return krb5_enomem(context);
}
@@ -405,12 +414,17 @@ fkt_start_seq_get_int(krb5_context context,
krb5_storage_free(c->sp);
close(c->fd);
krb5_clear_error_message(context);
krb5_warnx(context, "fkt_start_seq_get_int: failed reading pvno from \"%s\": ret=%d", d->filename ? d->filename : "<null>", ret);
return ret;
}
/* Log the pvno read */
krb5_warnx(context, "fkt_start_seq_get_int: keytab \"%s\" pvno=%d", d->filename ? d->filename : "<null>", (int)pvno);
if(pvno != 5) {
krb5_storage_free(c->sp);
close(c->fd);
krb5_clear_error_message (context);
krb5_warnx(context, "fkt_start_seq_get_int: keytab \"%s\" has bad vno (%d)", d->filename ? d->filename : "<null>", (int)pvno);
return KRB5_KEYTAB_BADVNO;
}
ret = krb5_ret_int8(c->sp, &tag);
@@ -418,10 +432,19 @@ fkt_start_seq_get_int(krb5_context context,
krb5_storage_free(c->sp);
close(c->fd);
krb5_clear_error_message(context);
krb5_warnx(context, "fkt_start_seq_get_int: failed reading tag from \"%s\": ret=%d", d->filename ? d->filename : "<null>", ret);
return ret;
}
/* Log the tag/version we read */
krb5_warnx(context, "fkt_start_seq_get_int: keytab \"%s\" header tag=%d", d->filename ? d->filename : "<null>", (int)tag);
id->version = tag;
storage_set_flags(context, c->sp, id->version);
/* Final confirmation log */
krb5_warnx(context, "fkt_start_seq_get_int: keytab \"%s\" opened successfully (fd=%d, version=%d)", d->filename ? d->filename : "<null>", c->fd, (int)id->version);
return 0;
}
@@ -452,26 +475,50 @@ fkt_next_entry_int(krb5_context context,
pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
loop:
ret = krb5_ret_int32(cursor->sp, &len);
if (ret)
if (ret) {
krb5_warnx(context, "fkt_next_entry_int: krb5_ret_int32 returned %d for keytab \"%s\" at pos=%lld", ret, d->filename ? d->filename : "<null>", (long long)pos);
return ret;
}
if(len < 0) {
pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR);
goto loop;
}
ret = krb5_kt_ret_principal (context, d, cursor->sp, &entry->principal);
if (ret)
if (ret) {
krb5_warnx(context, "fkt_next_entry_int: krb5_kt_ret_principal failed for keytab \"%s\" at pos=%lld: ret=%d", d->filename ? d->filename : "<null>", (long long)pos, ret);
goto out;
}
ret = krb5_ret_uint32(cursor->sp, &utmp32);
entry->timestamp = utmp32;
if (ret)
if (ret) {
krb5_warnx(context, "fkt_next_entry_int: failed reading timestamp for keytab \"%s\" at pos=%lld: ret=%d", d->filename ? d->filename : "<null>", (long long)pos, ret);
goto out;
}
ret = krb5_ret_int8(cursor->sp, &tmp8);
if (ret)
if (ret) {
krb5_warnx(context, "fkt_next_entry_int: failed reading vno (8bit) for keytab \"%s\" at pos=%lld: ret=%d", d->filename ? d->filename : "<null>", (long long)pos, ret);
goto out;
}
entry->vno = tmp8;
ret = krb5_kt_ret_keyblock (context, d, cursor->sp, &entry->keyblock);
if (ret)
if (ret) {
krb5_warnx(context, "fkt_next_entry_int: krb5_kt_ret_keyblock failed for keytab \"%s\" at pos=%lld: ret=%d", d->filename ? d->filename : "<null>", (long long)pos, ret);
goto out;
}
/* Log the entry we just read (principal, vno, enctype, timestamp) */
{
char *princname = NULL;
(void) krb5_unparse_name(context, entry->principal, &princname);
krb5_warnx(context, "fkt_next_entry_int: read entry principal=%s pos=%lld timestamp=%u vno=%d enctype=%d",
princname ? princname : "<unparsed>",
(long long)pos,
(unsigned)entry->timestamp,
entry->vno,
entry->keyblock.keytype);
free(princname);
}
/* there might be a 32 bit kvno here
* if it's zero, assume that the 8bit one was right,
* otherwise trust the new value */
@@ -494,8 +541,10 @@ loop:
if(start) *start = pos;
if(end) *end = pos + 4 + len;
out:
if (ret)
if (ret) {
krb5_warnx(context, "fkt_next_entry_int: error reading keytab \"%s\" at pos=%lld: ret=%d", d->filename ? d->filename : "<null>", (long long)pos, ret);
krb5_kt_free_entry(context, entry);
}
krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET);
return ret;
}
+26 -6
View File
@@ -35,6 +35,7 @@
.Dt KRB5_CONTEXT 3
.Os HEIMDAL
.Sh NAME
.Nm krb5_add_et_list ,
.Nm krb5_add_extra_addresses ,
.Nm krb5_add_ignore_addresses ,
.Nm krb5_context ,
@@ -47,7 +48,7 @@
.Nm krb5_get_ignore_addresses ,
.Nm krb5_get_kdc_sec_offset ,
.Nm krb5_get_max_time_skew ,
.Nm krb5_get_use_admin_kdc ,
.Nm krb5_get_use_admin_kdc
.Nm krb5_init_context ,
.Nm krb5_init_ets ,
.Nm krb5_prepend_config_files ,
@@ -58,7 +59,7 @@
.Nm krb5_set_fcache_version ,
.Nm krb5_set_ignore_addresses ,
.Nm krb5_set_max_time_skew ,
.Nm krb5_set_use_admin_kdc
.Nm krb5_set_use_admin_kdc ,
.Nd create, modify and delete krb5_context structures
.Sh LIBRARY
Kerberos 5 Library (libkrb5, -lkrb5)
@@ -80,6 +81,11 @@ Kerberos 5 Library (libkrb5, -lkrb5)
.Fa "krb5_context context"
.Fc
.Ft krb5_error_code
.Fo krb5_add_et_list
.Fa "krb5_context context"
.Fa "void (*func)(struct et_list **)"
.Fc
.Ft krb5_error_code
.Fo krb5_add_extra_addresses
.Fa "krb5_context context"
.Fa "krb5_addresses *addresses"
@@ -198,11 +204,23 @@ or that Kerberos should not be used
.Bq ENXIO .
.Pp
.Fn krb5_init_ets
is retained for ABI compatibility.
It does not perform any action.
Any initialization it used to provide is done by
adds all
.Xr com_err 3
libs to
.Fa context .
This is done by
.Fn krb5_init_context .
.Pp
.Fn krb5_add_et_list
adds a
.Xr com_err 3
error-code handler
.Fa func
to the specified
.Fa context .
The error handler must generated by the the re-rentrant version of the
.Xr compile_et 1
program.
.Fn krb5_add_extra_addresses
add a list of addresses that should be added when requesting tickets.
.Pp
@@ -284,5 +302,7 @@ and
get and sets the maximum allowed time skew between client and server.
.Sh SEE ALSO
.Xr errno 2 ,
.Xr krb5.conf 5 ,
.Xr krb5 3 ,
.Xr krb5_config 3 ,
.Xr krb5_context 3 ,
.Xr kerberos 8
+4 -6
View File
@@ -91,13 +91,11 @@ cleans the the structure, must be used before trying to pass it in to
.Fn krb5_verify_init_creds .
.Pp
.Fn krb5_verify_init_creds_opt_set_ap_req_nofail
controls the behavior if
controls controls the behavior if
.Fa ap_req_server
does not exist in the local keytab or in the KDC's database.
If it is true, those errors will not be ignored.
Errors from AP_REQ verification with a present key, such as an integrity
check failure, are always returned.
Note that ignoring the error is possibly insecure.
doesn't exists in the local keytab or in the KDC's database, if it's
true, the error will be ignored. Note that this use is possible
insecure.
.Sh SEE ALSO
.Xr krb5 3 ,
.Xr krb5_get_init_creds 3 ,
+5
View File
@@ -231,6 +231,11 @@ main(int argc, char **argv)
}
.Ed
.Sh SEE ALSO
.Xr krb5_cc_gen_new 3 ,
.Xr krb5_cc_initialize 3 ,
.Xr krb5_cc_resolve 3 ,
.Xr krb5_err 3 ,
.Xr krb5_free_principal 3 ,
.Xr krb5_init_context 3 ,
.Xr krb5_kt_default 3 ,
.Xr krb5.conf 5
+19 -25
View File
@@ -1193,35 +1193,29 @@ krcc_get_next(krb5_context context,
if (krcursor == NULL)
return KRB5_CC_END;
for (;;) {
if (krcursor->currkey >= krcursor->numkeys)
return KRB5_CC_END;
/*
* If we're pointing at the entry with the principal, or at the key
* with the time offsets, skip it.
*/
while (krcursor->keys[krcursor->currkey] == krcursor->princ_id ||
krcursor->keys[krcursor->currkey] == krcursor->offsets_id) {
krcursor->currkey++;
if (krcursor->currkey >= krcursor->numkeys)
return KRB5_CC_END;
/*
* If we're pointing at the entry with the principal, or at the key
* with the time offsets, skip it.
*/
while (krcursor->keys[krcursor->currkey] == krcursor->princ_id ||
krcursor->keys[krcursor->currkey] == krcursor->offsets_id) {
krcursor->currkey++;
if (krcursor->currkey >= krcursor->numkeys)
return KRB5_CC_END;
}
ret = keyctl_read_krb5_data(krcursor->keys[krcursor->currkey],
&payload);
krcursor->currkey++;
if (ret == KRB5_FCC_NOFILE)
continue;
if (ret) {
_krb5_debug(context, 10, "Error reading key %d: %s\n",
krcursor->keys[krcursor->currkey - 1],
strerror(errno));
return ret;
}
break;
}
ret = keyctl_read_krb5_data(krcursor->keys[krcursor->currkey], &payload);
if (ret) {
_krb5_debug(context, 10, "Error reading key %d: %s\n",
krcursor->keys[krcursor->currkey],
strerror(errno));
return ret;
}
krcursor->currkey++;
sp = krb5_storage_from_data(&payload);
if (sp == NULL) {
ret = KRB5_CC_IO;
+54 -36
View File
@@ -1466,18 +1466,23 @@ krb5_sname_to_principal(krb5_context context,
for (cp = remote_host; *cp; cp++)
if (isupper((unsigned char) (*cp)))
*cp = tolower((unsigned char) (*cp));
/* Debug-ish: record the input/normalized hostname and service for tracing. */
krb5_warnx(context, "krb5_sname_to_principal: remote_host=%s sname=%s type=%d",
remote_host ? remote_host : "<null>",
sname ? sname : "<null>",
(int)type);
/*
* If there is only one name canon rule and it says to
* canonicalize the old way, do that now, as we used to.
*/
ret = _krb5_get_name_canon_rules(context, &rules);
if (ret) {
_krb5_debug(context, 5, "Failed to get name canon rules: ret = %d",
ret);
free(remote_host);
return ret;
}
ret = _krb5_get_name_canon_rules(context, &rules);
if (ret) {
krb5_warnx(context, "Failed to get name canon rules: ret = %d",
ret);
free(remote_host);
return ret;
}
if (rules[0].type == KRB5_NCRT_NSS &&
rules[1].type == KRB5_NCRT_BOGUS) {
_krb5_debug(context, 5, "Using nss for name canon immediately");
@@ -1895,6 +1900,17 @@ apply_name_canon_rule(krb5_context context, krb5_name_canon_rule rules,
_krb5_debug(context, 5, N_("Applying a name rule (type %d) to %s", ""),
rule->type, orig_hostname);
/* Extra debug: print rule details to help trace name canonicalization. */
krb5_warnx(context, "name_canon: rule_idx=%zu type=%d mindots=%u maxdots=%u match_domain=%s match_realm=%s realm=%s domain=%s options=0x%x",
rule_idx,
(int)rule->type,
(unsigned)rule->mindots,
(unsigned)rule->maxdots,
rule->match_domain ? rule->match_domain : "<null>",
rule->match_realm ? rule->match_realm : "<null>",
rule->realm ? rule->realm : "<null>",
rule->domain ? rule->domain : "<null>",
(int)rule->options);
if (rule->mindots > 0 || rule->maxdots > 0) {
for (cp = strchr(orig_hostname, '.'); cp && *cp; cp = strchr(cp + 1, '.'))
@@ -1929,36 +1945,38 @@ apply_name_canon_rule(krb5_context context, krb5_name_canon_rule rules,
new_hostname = tmp_hostname;
break;
case KRB5_NCRT_NSS:
if ((rule->options & KRB5_NCRO_USE_DNSSEC)) {
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
krb5_set_error_message(context, ret,
"Secure hostname resolution not supported");
goto out;
}
_krb5_debug(context, 5, "Using name service lookups");
ret = krb5_sname_to_principal_old(context, rule->realm,
orig_hostname, sname,
KRB5_NT_SRV_HST,
&nss);
if (rules[rule_idx + 1].type != KRB5_NCRT_BOGUS &&
(ret == KRB5_ERR_BAD_HOSTNAME ||
ret == KRB5_ERR_HOST_REALM_UNKNOWN)) {
/*
* Bad hostname / realm unknown -> rule inapplicable if
* there's more rules. If it's the last rule then we want
* to return all errors from krb5_sname_to_principal_old()
* here.
*/
ret = 0;
goto out;
}
if (ret)
goto out;
case KRB5_NCRT_NSS:
if ((rule->options & KRB5_NCRO_USE_DNSSEC)) {
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
krb5_set_error_message(context, ret,
"Secure hostname resolution not supported");
goto out;
}
_krb5_debug(context, 5, "Using name service lookups");
ret = krb5_sname_to_principal_old(context, rule->realm,
orig_hostname, sname,
KRB5_NT_SRV_HST,
&nss);
/* If subsequent rule exists and we got a hostname/realm error,
* treat this rule as inapplicable (unless last rule). */
if (rules[rule_idx + 1].type != KRB5_NCRT_BOGUS &&
(ret == KRB5_ERR_BAD_HOSTNAME ||
ret == KRB5_ERR_HOST_REALM_UNKNOWN)) {
ret = 0;
goto out;
}
if (ret) {
_krb5_debug(context, 3, "krb5_sname_to_principal_old failed for %s: ret=%d", orig_hostname, ret);
goto out;
}
new_hostname = krb5_principal_get_comp_string(context, nss, 1);
new_realm = krb5_principal_get_realm(context, nss);
break;
new_hostname = krb5_principal_get_comp_string(context, nss, 1);
new_realm = krb5_principal_get_realm(context, nss);
/* Log what nss resolution produced for inspection in tests */
_krb5_debug(context, 3, "krb5_sname_to_principal_old: resolved %s -> canonical=%s realm=%s", orig_hostname,
new_hostname ? new_hostname : "<null>",
new_realm ? new_realm : "<null>");
break;
default:
/* Can't happen */
+53 -69
View File
@@ -1084,6 +1084,13 @@ submit_request(krb5_context context, krb5_sendto_ctx ctx, krb5_krbhst_info *hi)
continue;
rk_cloexec(fd);
#ifndef NO_LIMIT_FD_SETSIZE
if (fd >= FD_SETSIZE) {
_krb5_debug(context, 0, "fd too large for select");
rk_closesocket(fd);
continue;
}
#endif
socket_set_nonblocking(fd, 1);
host = heim_alloc(sizeof(*host), "sendto-host", deallocate_host);
@@ -1155,11 +1162,9 @@ submit_request(krb5_context context, krb5_sendto_ctx ctx, krb5_krbhst_info *hi)
struct wait_ctx {
krb5_context context;
krb5_sendto_ctx ctx;
struct pollfd *pfds;
struct host **hosts;
nfds_t nfds;
fd_set rfds;
fd_set wfds;
rk_socket_t max_fd;
int got_reply;
time_t timenow;
};
@@ -1170,8 +1175,6 @@ wait_setup(heim_object_t obj, void *iter_ctx, int *stop)
struct wait_ctx *wait_ctx = iter_ctx;
struct host *h = (struct host *)obj;
short events = 0;
if (h->state == CONNECT) {
if (h->timeout >= wait_ctx->timenow)
return;
@@ -1195,32 +1198,31 @@ wait_setup(heim_object_t obj, void *iter_ctx, int *stop)
host_connected(wait_ctx->context, wait_ctx->ctx, h);
}
}
#ifndef NO_LIMIT_FD_SETSIZE
heim_assert(h->fd < FD_SETSIZE, "fd too large");
#endif
switch (h->state) {
case WAITING_REPLY:
events |= POLLIN;
FD_SET(h->fd, &wait_ctx->rfds);
break;
case CONNECTING:
case CONNECTED:
events |= POLLIN | POLLOUT;
FD_SET(h->fd, &wait_ctx->rfds);
FD_SET(h->fd, &wait_ctx->wfds);
break;
case PROXYING:
if (_krb5_socks4a_reading(h->socks4a))
events |= POLLIN;
FD_SET(h->fd, &wait_ctx->rfds);
if (_krb5_socks4a_writing(h->socks4a))
events |= POLLOUT;
FD_SET(h->fd, &wait_ctx->wfds);
break;
default:
debug_host(wait_ctx->context, 5, h, "invalid sendto host state");
heim_abort("invalid sendto host state");
}
wait_ctx->pfds[wait_ctx->nfds].fd = h->fd;
wait_ctx->pfds[wait_ctx->nfds].events = events;
wait_ctx->pfds[wait_ctx->nfds].revents = 0;
wait_ctx->hosts[wait_ctx->nfds] = h;
wait_ctx->nfds++;
if (h->fd > wait_ctx->max_fd || wait_ctx->max_fd == rk_INVALID_SOCKET)
wait_ctx->max_fd = h->fd;
}
static int
@@ -1240,39 +1242,39 @@ wait_accelerate(heim_object_t obj, void *ctx, int *stop)
}
static void
wait_process(struct wait_ctx *wait_ctx)
wait_process(heim_object_t obj, void *ctx, int *stop)
{
for (nfds_t i = 0; i < wait_ctx->nfds; i++) {
struct host *h = wait_ctx->hosts[i];
struct pollfd *pfd = &wait_ctx->pfds[i];
struct wait_ctx *wait_ctx = ctx;
struct host *h = (struct host *)obj;
int readable, writeable;
heim_assert(h->state != DEAD, "dead host resurected");
int readable = pfd->revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL);
int writeable = pfd->revents & POLLOUT;
#ifndef NO_LIMIT_FD_SETSIZE
heim_assert(h->fd < FD_SETSIZE, "fd too large");
#endif
readable = FD_ISSET(h->fd, &wait_ctx->rfds);
writeable = FD_ISSET(h->fd, &wait_ctx->wfds);
if (readable || writeable || h->state == CONNECT)
wait_ctx->got_reply |= eval_host_state(
wait_ctx->context,
wait_ctx->ctx,
h,
readable,
writeable
);
if (readable || writeable || h->state == CONNECT)
wait_ctx->got_reply |= eval_host_state(wait_ctx->context, wait_ctx->ctx, h, readable, writeable);
if (wait_ctx->got_reply)
return;
}
/* if there is already a reply, just fall though the array */
if (wait_ctx->got_reply)
*stop = 1;
}
static krb5_error_code
wait_response(krb5_context context, int *action, krb5_sendto_ctx ctx)
{
struct wait_ctx wait_ctx;
struct timeval tv;
int ret;
memset(&wait_ctx, 0, sizeof(wait_ctx));
wait_ctx.context = context;
wait_ctx.ctx = ctx;
FD_ZERO(&wait_ctx.rfds);
FD_ZERO(&wait_ctx.wfds);
wait_ctx.max_fd = rk_INVALID_SOCKET;
/* oh, we have a reply, it must be a plugin that got it for us */
if (ctx->response.length) {
@@ -1282,8 +1284,10 @@ wait_response(krb5_context context, int *action, krb5_sendto_ctx ctx)
wait_ctx.timenow = time(NULL);
size_t max_hosts = heim_array_get_length(ctx->hosts);
if (max_hosts == 0) {
heim_array_iterate_f(ctx->hosts, &wait_ctx, wait_setup);
heim_array_filter_f(ctx->hosts, &wait_ctx, wait_filter_dead);
if (heim_array_get_length(ctx->hosts) == 0) {
if (ctx->stateflags & KRBHST_COMPLETED) {
_krb5_debug(context, 5, "no more hosts to send/recv packets to/from "
"trying to pulling more hosts");
@@ -1296,18 +1300,7 @@ wait_response(krb5_context context, int *action, krb5_sendto_ctx ctx)
return 0;
}
wait_ctx.pfds = calloc(max_hosts, sizeof(struct pollfd));
wait_ctx.hosts = calloc(max_hosts, sizeof(struct host *));
if (!wait_ctx.pfds || !wait_ctx.hosts) {
free(wait_ctx.pfds);
free(wait_ctx.hosts);
return ENOMEM;
}
heim_array_filter_f(ctx->hosts, &wait_ctx, wait_filter_dead);
heim_array_iterate_f(ctx->hosts, &wait_ctx, wait_setup);
if (wait_ctx.nfds == 0) {
if (wait_ctx.max_fd == rk_INVALID_SOCKET) {
/*
* If we don't find a host which can make progress, then
* we accelerate the process by moving all of the contestants
@@ -1315,36 +1308,27 @@ wait_response(krb5_context context, int *action, krb5_sendto_ctx ctx)
*/
_krb5_debug(context, 5, "wait_response: moving the contestants forward");
heim_array_iterate_f(ctx->hosts, &wait_ctx, wait_accelerate);
free(wait_ctx.pfds);
free(wait_ctx.hosts);
return 0;
}
ret = poll(wait_ctx.pfds, wait_ctx.nfds, 1000); /* 1s */
tv.tv_sec = 1;
tv.tv_usec = 0;
if (ret < 0) {
free(wait_ctx.pfds);
free(wait_ctx.hosts);
return errno;
}
ret = select(wait_ctx.max_fd + 1, &wait_ctx.rfds, &wait_ctx.wfds, NULL, &tv);
if (ret < 0)
return errno;
if (ret == 0) {
*action = KRB5_SENDTO_TIMEOUT;
free(wait_ctx.pfds);
free(wait_ctx.hosts);
return 0;
*action = KRB5_SENDTO_TIMEOUT;
return 0;
}
wait_ctx.got_reply = 0;
wait_process(&wait_ctx);
heim_array_iterate_f(ctx->hosts, &wait_ctx, wait_process);
if (wait_ctx.got_reply)
*action = KRB5_SENDTO_FILTER;
else
*action = KRB5_SENDTO_CONTINUE;
free(wait_ctx.pfds);
free(wait_ctx.hosts);
return 0;
}
+1 -2294
View File
File diff suppressed because it is too large Load Diff
-37
View File
@@ -239,47 +239,10 @@ check_escaped_strings(void)
krb5_free_context(context);
}
static void
check_dash_underscore(void)
{
krb5_context context;
krb5_config_section *c = NULL;
krb5_error_code ret;
const char *s;
char **ps;
ret = krb5_init_context(&context);
if (ret)
errx(1, "krb5_init_context %d", ret);
ret = krb5_config_parse_file(context, "test_config_strings.out", &c);
if (ret)
krb5_errx(context, 1, "krb5_config_parse_file()");
s = krb5_config_get_string(context, c, "dash-test", "final-value", NULL);
if (s == NULL || strcmp(s, "through-section") != 0)
errx(1, "dash/underscore lookup failed");
ps = krb5_config_get_strings(context, c, "dash-test", "same-name", NULL);
if (ps == NULL ||
ps[0] == NULL || strcmp(ps[0], "first") != 0 ||
ps[1] == NULL || strcmp(ps[1], "second") != 0 ||
ps[2] != NULL)
errx(1, "dash/underscore iteration failed");
krb5_config_free_strings(ps);
ret = krb5_config_file_free(context, c);
if (ret)
krb5_errx(context, 1, "krb5_config_file_free()");
krb5_free_context(context);
}
int
main(int argc, char **argv)
{
check_config_files();
check_escaped_strings();
check_dash_underscore();
return 0;
}
-5
View File
@@ -10,8 +10,3 @@
internal2 = "TownOf Sandwich: Massachusetts"Oldest Town In "Cape Cod"
internal3 = "Begins and"ends In One String
longer_strings = "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:" "1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer." "2. 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." "3. Neither the name of the Institute nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission." "THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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." "Why do we test with such long strings? Because some people have config files" That look "Like this."
[dash_test]
final_value = through-section
same_name = first
same-name = second

Some files were not shown because too many files have changed in this diff Show More