importing current version of mod_auth_gssapi
authorkouril <kouril>
Wed, 15 Dec 2010 13:25:05 +0000 (13:25 +0000)
committerkouril <kouril>
Wed, 15 Dec 2010 13:25:05 +0000 (13:25 +0000)
LICENSE
Makefile.in
apxs.sh
config.h.in
configure.in
gss.c [new file with mode: 0644]
mod_auth_gssapi.c [new file with mode: 0644]
mod_auth_gssapi.h [new file with mode: 0644]

diff --git a/LICENSE b/LICENSE
index 7812b5a..8c3ba52 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1,36 +1,6 @@
-mod_auth_kerb license
+mod_auth_gssapi license
 ---------------------
-/*
- * Copyright (c) 2004-2006 Masarykova universita
- * (Masaryk University, Brno, Czech Republic)
- * All rights reserved.
- * 
- * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
- */
+XXXX
 
 
 This package also contains parts (see the spnego subdirectory) based on the
index 36f6046..e9005d8 100644 (file)
@@ -1,26 +1,23 @@
 APXS = @APXS@
-KRB5_CPPFLAGS = @KRB5_CPPFLAGS@
-KRB5_LDFLAGS = @KRB5_LDFLAGS@
-KRB4_CPPFLAGS = @KRB4_CPPFLAGS@
-KRB4_LDFLAGS = @KRB4_LDFLAGS@
-LIB_resolv = @LIB_resolv@
+GSS_CPPFLAGS = @GSS_CPPFLAGS@
+GSS_LDFLAGS = @GSS_LDFLAGS@
 SPNEGO_SRCS = @SPNEGO_SRCS@
 
-CPPFLAGS = -I. -Ispnegokrb5 $(KRB5_CPPFLAGS) $(KRB4_CPPFLAGS) $(DEFS)
-LDFLAGS = $(KRB5_LDFLAGS) $(KRB4_LDFLAGS) $(LIB_resolv)
+CPPFLAGS = -I. -Ispnegokrb5 $(GSS_CPPFLAGS) $(DEFS)
+LDFLAGS = $(GSS_LDFLAGS)
 CFLAGS =
 
-all: src/mod_auth_kerb.so
+all: mod_auth_gssapi.la
 
-src/mod_auth_kerb.so: src/mod_auth_kerb.c $(SPNEGO_SRCS)
-       ./apxs.sh "${CPPFLAGS}" "${LDFLAGS}" "${SPNEGO_SRCS}" "${APXS}" "-c" "src/mod_auth_kerb.c"
+mod_auth_gssapi.la: mod_auth_gssapi.c $(SPNEGO_SRCS)
+       ./apxs.sh "${CPPFLAGS}" "${LDFLAGS}" "${SPNEGO_SRCS}" "${APXS} -c"
 
 install:
-       ./apxs.sh "${CPPFLAGS}" "${LDFLAGS}" "${SPNEGO_SRCS}" "${APXS}" "-c -i" "src/mod_auth_kerb.c"
+       ./apxs.sh "${CPPFLAGS}" "${LDFLAGS}" "${SPNEGO_SRCS}" "${APXS} -c -i -n auth_gssapi"
 
 clean:
-       for i in . src spnegokrb5; do \
-               $(RM) $$i/*.{o,so,a,la,lo,slo} core; \
+       for i in . spnegokrb5; do \
+               (cd $$i && $(RM) *.o *.so *.a *.la *.lo *.slo); \
                $(RM) -rf $$i/.libs; \
        done
 
@@ -28,11 +25,4 @@ distclean: clean
        $(RM) config.h config.status Makefile config.log
        $(RM) -rf autom4te.cache
 
-make_release:
-       echo "Did you increase version numbers?"
-       autoconf
-       $(RM) -rf autom4te.cache
-       $(RM) -rf .cvsignore spnegokrb5/.cvsignore src/.cvsignore
-       $(RM) -rf CVS spnegokrb5/CVS src/CVS
-
 .PHONY: all install clean distclean
diff --git a/apxs.sh b/apxs.sh
index d8a776a..9dd608f 100755 (executable)
--- a/apxs.sh
+++ b/apxs.sh
@@ -1,5 +1,8 @@
 #!/bin/sh
+#
+# XXX cleanup desperately needed
+#
 cppflags=`[ -n "$1" ] && echo $1 | sed -e 's/\([^ ]\+\)/-Wc,\1/g'`
 ldflags=`[ -n "$2"  ] && echo $2 | sed -e 's/\([^ ]\+\)/-Wl,\1/g'`
-ret=eval "$4" $5 $cppflags $ldflags src/mod_auth_kerb.c $3
+ret=eval $4 $cppflags $ldflags mod_auth_gssapi.c $3
 exit $ret
index ca90d99..def453e 100644 (file)
@@ -1,4 +1,3 @@
-
 /* Define to the version of this package. */
 /* Conflicts with defintions from Apache */
 /* #undef PACKAGE_VERSION */
@@ -6,21 +5,9 @@
 /* Define to `unsigned' if <sys/types.h> does not define. */
 #undef size_t
 
-/* Define if you are using the Heimdal implementation of Krb5 */
-#undef HEIMDAL
-
-/* Define if you want to enable support for Kerberos5 */
-#undef KRB5
-
-/* Define if you want to enable support for Kerberos4 */
-#undef KRB4
-
 /* Define if your GSSAPI library supports handling SPNEGO tokens */
 #undef GSSAPI_SUPPORTS_SPNEGO
 
-/* Define if your krb supports krb5_cc_new_unique function to deal with threading issues */
-#undef HAVE_KRB5_CC_NEW_UNIQUE
-
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
index b00c43c..a189bf8 100644 (file)
@@ -1,20 +1,14 @@
 # Process this file with autoconf to produce a configure script.
 AC_REVISION($Revision$)
 AC_PREREQ(2.57)
-AC_INIT(mod_auth_kerb, 5.4, modauthkerb-developers@lists.sourceforge.net)
-AC_CONFIG_SRCDIR([src/mod_auth_kerb.c])
+AC_INIT(mod_auth_gssapi, 0.1, modauthkerb-developers@lists.sourceforge.net)
+AC_CONFIG_SRCDIR([mod_auth_gssapi.c])
 AC_CONFIG_HEADER([config.h])
 
 # Checks for programs.
 AC_PROG_CC
 AC_PROG_MAKE_SET
 
-# Checks for libraries.
-# FIXME: Replace `main' with a function in `-lresolv':
-LIB_resolv=""
-AC_CHECK_LIB([resolv], [main], [LIB_resolv=-lresolv])
-AC_SUBST(LIB_resolv)
-
 # Checks for header files.
 AC_HEADER_STDC
 AC_CHECK_HEADERS([limits.h netdb.h stddef.h stdlib.h string.h unistd.h])
@@ -24,149 +18,76 @@ AC_CHECK_HEADERS([limits.h netdb.h stddef.h stdlib.h string.h unistd.h])
 AC_TYPE_SIZE_T
 AC_STRUCT_TM
 
-# Checks for library functions.
-#AC_FUNC_MALLOC
-#AC_FUNC_MEMCMP
-#AC_CHECK_FUNCS([gethostbyname memset putenv strcasecmp strchr strdup strerror])
-
 #
-# kerberos5 enviroment
+# GSS-API enviroment
 #
 SPNEGO_SRCS=""
 
-AC_ARG_WITH(krb5,
-  AC_HELP_STRING([--with-krb5=dir],[use krb5 in dir]),
-  [ with_krb5="$withval" ])
-
-if test "x$with_krb5" = "xyes" ; then
-  with_krb5=""
+AC_ARG_WITH(gss,
+  AC_HELP_STRING([--with-gss=dir],[use gss in dir]),
+  [ with_gss="$withval" ])
+if test "x$with_gss" = "xyes" ; then
+  with_gss=""
 fi
 
-if test "x$with_krb5" != "xno" ; then
-
-  AC_PATH_PROG(krb5_config_command,krb5-config,:,[$PATH:/usr/kerberos/bin:/usr/krb5/bin])
-  if test $krb5_config_command = : ; then
-     AC_MSG_ERROR(krb5-config not found)
-  fi
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-  ac_save_LIBS="$LIBS"
+ac_save_CPPFLAGS="$CPPFLAGS"
+ac_save_LDFLAGS="$LDFLAGS"
+ac_save_LIBS="$LIBS"
    
-  if test -n "$with_krb5"; then
-     if test -x "$with_krb5/bin/krb5-config"; then
-        krb5_config_command="$with_krb5/bin/krb5-config"
-     else
-        krb5_config_command=""
-     fi
-  fi
-
-  dnl
-  dnl find header files
-  dnl
-
-  if test -z "$KRB5_CPPFLAGS"; then
-     TMP_KRB5_CPPFLAGS=""
-     if test -n "$krb5_config_command"; then
-        TMP_KRB5_CPPFLAGS=`$krb5_config_command --cflags gssapi 2>/dev/null`
-     fi
-     if test -z "$TMP_KRB5_CPPFLAGS" -a -n "with_krb5"; then
-        TMP_KRB5_CPPFLAGS="-I$with_krb5/include"
-     fi
-     CPPFLAGS="$CPPFLAGS $TMP_KRB5_CPPFLAGS"
-     AC_CHECK_HEADERS(gssapi.h, 
-                      [ KRB5_CPPFLAGS="$TMP_KRB5_CPPFLAGS" ])
-     if test -z "$KRB5_CPPFLAGS"; then
-        AC_CHECK_HEADERS(gssapi/gssapi.h, 
-                         [ KRB5_CPPFLAGS="$TMP_KRB5_CPPFLAGS" ])
-     fi
-     CPPFLAGS="$ac_save_CPPFLAGS" 
-  fi
-
-  dnl
-  dnl find libraries
-  dnl
-
-  if test -z "$KRB5_LDFLAGS" -a -n "$krb5_config_command"; then
-     TMP_KRB5_LDFLAGS=`$krb5_config_command --libs gssapi 2>/dev/null`
-     if test -n "$TMP_KRB5_LDFLAGS"; then
-        LIBS="$LIBS $TMP_KRB5_LDFLAGS $LIB_resolv"
-        AC_CHECK_LIB(krb5, krb5_init_context,
-                     [ KRB5_LDFLAGS="$TMP_KRB5_LDFLAGS" ])
-        LIBS="$ac_save_LIBS"
-     fi
-  fi
-  if test "x$with_krb5"="x"; then
-        tmp_lf_inc=""
-     else
-        tmp_lf_inc="-L"
-  fi
-  if test -z "$KRB5_LDFLAGS"; then
-     #try MIT
-     TMP_KRB5_LDFLAGS="$tmp_lf_inc$with_krb5/lib -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err"
-     LIBS="$LIBS $TMP_KRB5_LDFLAGS $LIB_resolv"
-     AC_CHECK_LIB(krb5, krb5_init_context, [ KRB5_LDFLAGS="$TMP_KRB5_LDFLAGS" ])
-     LIBS="$ac_save_LIBS"
-  fi
-
-  if test -z "$KRB5_LDFLAGS"; then
-     #Try Heimdal
-     TMP_KRB5_LDFLAGS="$tmp_lf_inc$with_krb5/lib -lgssapi -lkrb5 -lasn1 -lcrypto -lroken -lcrypt"
-     LIBS="$LIBS $TMP_KRB5_LDFLAGS $LIB_resolv"
-     AC_CHECK_LIB(krb5, krb5_init_context, [ KRB5_LDFLAGS="$TMP_KRB5_LDFLAGS" ])
-     LIBS="$ac_save_LIBS"
-  fi
-
-  if test -z "$KRB5_LDFLAGS"; then
-     #Try Heimdal on OpenBSD
-     TMP_KRB5_LDFLAGS="$tmp_lf_inc$with_krb5/lib -lgssapi -lkrb5 -lasn1 -ldes -lcrypto"
-     LIBS="$LIBS $TMP_KRB5_LDFLAGS $LIB_resolv"
-     AC_CHECK_LIB(krb5, krb5_init_context, [ KRB5_LDFLAGS="$TMP_KRB5_LDFLAGS" ])
-     LIBS="$ac_save_LIBS"
-  fi
+if test -z "$GSS_CPPFLAGS"; then
+   TMP_GSS_CPPFLAGS=""
+   if test -n "with_gss"; then
+      TMP_GSS_CPPFLAGS="-I$with_gss/include"
+   fi
+   CPPFLAGS="$CPPFLAGS $TMP_GSS_CPPFLAGS"
+   AC_CHECK_HEADERS(gssapi.h, 
+                    [ GSS_CPPFLAGS="$TMP_GSS_CPPFLAGS" ])
+   if test -z "$GSS_CPPFLAGS"; then
+      AC_CHECK_HEADERS(gssapi/gssapi.h, 
+                       [ GSS_CPPFLAGS="$TMP_GSS_CPPFLAGS" ])
+   fi
+   CPPFLAGS="$ac_save_CPPFLAGS" 
+fi
 
-  if test -z "$KRB5_LDFLAGS"; then
-     with_krb5=no
-  else
-     AC_DEFINE(KRB5)
-     AC_CHECK_LIB(krb5,
-                  krb5_cc_new_unique,
-                  [ AC_DEFINE(HAVE_KRB5_CC_NEW_UNIQUE) ])
+#if test "x$with_gss"="x"; then
+#      tmp_lf_inc=""
+#   else
+#      tmp_lf_inc="-L"
+#fi
+if test -z "$GSS_LDFLAGS"; then
+   TMP_GSS_LDFLAGS=""
+   if test -n "$with_gss"; then
+# XXX think about lib64, etc
+      TMP_GSS_LDFLAGS="-L $with_gss/lib"
+   fi
 
-     # check for Heimdal
-     have_heimdal=""
-     AC_MSG_CHECKING(whether we are using Heimdal)
-     ac_save_CFLAGS="$CFLAGS"
-     CFLAGS="$KRB5_CPPFLAGS"
-     AC_TRY_COMPILE([#include <krb5.h>],
-                   [ char *tmp = heimdal_version; ],
-                   [ AC_MSG_RESULT(yes)
-                     AC_DEFINE(HEIMDAL)
-                     have_heimdal=yes ],
-                   [ AC_MSG_RESULT(no) ])
-     CFLAGS="$ac_save_CFLAGS"
+   LIBS="$LIBS $TMP_GSS_LDFLAGS"
+   AC_CHECK_LIB(gssapi, gss_accept_sec_context, [ GSS_LDFLAGS="$TMP_GSS_LDFLAGS" ])
+   LIBS="$ac_save_LIBS"
+fi
+if test -z "$GSS_LDFLAGS"; then
+   AC_MSG_ERROR([failed to find a GSS-API library])
+fi
 
 # If SPNEGO is supported by the gssapi libraries, we shouln't build our support.
 # SPNEGO is supported as of Heimdal 0.7, and MIT 1.5.
-     gssapi_supports_spnego=""
-     AC_MSG_CHECKING(whether the GSSAPI libraries support SPNEGO)
+gssapi_supports_spnego=""
+AC_MSG_CHECKING(whether the GSSAPI libraries support SPNEGO)
 
-     ac_save_CFLAGS="$CFLAGS"
-     CFLAGS="$KRB5_CPPFLAGS"
-     ac_save_LDFLAGS="$LDFLAGS"
-     if test -n "$with_krb5"; then
-        LDFLAGS="$KRB5_LDFLAGS -Wl,-rpath -Wl,$with_krb5/lib"
-     else 
-        LDFLAGS="$KRB5_LDFLAGS"
-     fi
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS="$GSS_CPPFLAGS"
+
+ac_save_LDFLAGS=$LDFLAGS
+LDFLAGS="$GSS_LDFLAGS"
+# to make sure the testing binary can be launched:
+if test -n "$with_gss"; then
+   LDFLAGS="$LDFLAGS -Wl,-rpath -Wl,$with_gss/lib"
+fi
+#XXX schovat nebo dat primo do LDFLAGS:
+LIBS=-lgssapi
      AC_TRY_RUN([
 #include <string.h>
-#include <krb5.h>
-#ifdef HEIMDAL
 #include <gssapi.h>
-#else
-#include <gssapi/gssapi.h>
-#endif
 int main(int argc, char** argv)
 {
        OM_uint32 major_status, minor_status;
@@ -192,31 +113,21 @@ int main(int argc, char** argv)
                return (!SPNEGO);
        }
 }],
-                [ if test $? -eq 0; then 
-                     AC_MSG_RESULT(yes)
-                     AC_DEFINE(GSSAPI_SUPPORTS_SPNEGO)
-                     gssapi_supports_spnego=yes 
-                  else
-                     AC_MSG_RESULT(no)
-                  fi],
-                [AC_MSG_RESULT(no)])
-
-     CFLAGS="$ac_save_CFLAGS"
-     LDFLAGS="$ac_save_LDFLAGS"
-
-     if test -z "$gssapi_supports_spnego"; then
-       if test -n "$have_heimdal"; then SPNEGO_SRCS="\
-               spnegokrb5/asn1_MechType.c         \
-               spnegokrb5/asn1_MechTypeList.c     \
-               spnegokrb5/asn1_ContextFlags.c     \
-               spnegokrb5/asn1_NegTokenInit.c     \
-               spnegokrb5/asn1_NegTokenTarg.c     \
-               spnegokrb5/init_sec_context.c      \
-               spnegokrb5/accept_sec_context.c    \
-               spnegokrb5/encapsulate.c           \
-               spnegokrb5/decapsulate.c           \
-               spnegokrb5/external.c"
-       else SPNEGO_SRCS="\
+     [ if test $? -eq 0; then 
+         AC_MSG_RESULT(yes)
+         AC_DEFINE(GSSAPI_SUPPORTS_SPNEGO)
+         gssapi_supports_spnego=yes 
+       else
+         AC_MSG_RESULT(no)
+       fi],
+     [ AC_MSG_RESULT(no)]
+     )
+
+CFLAGS="$ac_save_CFLAGS"
+LDFLAGS="$ac_save_LDFLAGS"
+
+if test -z "$gssapi_supports_spnego"; then
+   SPNEGO_SRCS="\
                spnegokrb5/asn1_MechType.c         \
                spnegokrb5/asn1_MechTypeList.c     \
                spnegokrb5/asn1_ContextFlags.c     \
@@ -233,104 +144,12 @@ int main(int argc, char** argv)
                spnegokrb5/encapsulate.c           \
                spnegokrb5/decapsulate.c           \
                spnegokrb5/external.c"
-       fi
-     fi
-  fi
 fi
-AC_SUBST(KRB5_CPPFLAGS)
-AC_SUBST(KRB5_LDFLAGS)
+AC_SUBST(GSS_CPPFLAGS)
+AC_SUBST(GSS_LDFLAGS)
 AC_SUBST(SPNEGO_SRCS)
 
 #
-# Kerberos4 enviroment
-#
-
-AC_ARG_WITH(krb4,
-  AC_HELP_STRING([--with-krb4=dir], [use krb4 in dir]),
-  [ with_krb4="$withval" ])
-
-if test "x$with_krb4" = "xyes" ; then
-  with_krb4=""
-fi
-
-if test "x$with_krb4" != "xno"; then
-  AC_MSG_CHECKING([for Kerberos4 installation])
-  if test "x$with_krb4" != "x"; then
-     if test -x "$with_krb4/bin/krb4-config"; then
-        KRB4_CPPFLAGS=`$with_krb4/bin/krb4-config --cflags krb4 2>/dev/null`
-        KRB4_LDFLAGS=`$with_krb4/bin/krb4-config --libs krb4 2>/dev/null`
-     elif test -x "$with_krb4/bin/krb5-config"; then
-        KRB4_CPPFLAGS=`$with_krb4/bin/krb5-config --cflags krb4 2>/dev/null`
-        KRB4_LDFLAGS=`$with_krb4/bin/krb5-config --libs krb4 2>/dev/null`
-     else
-        AC_MSG_ERROR([failed to find krb4-config or krb5-config in $with_krb4/bin])
-     fi
-  else
-     KRB4_CPPFLAGS=`krb4-config --cflags krb4 2>/dev/null`
-     KRB4_LDFLAGS=`krb4-config --libs krb4 2>/dev/null`
-     if test "x$KRB4_LDFLAGS" = "x" -a -n "$krb5_config_command"; then
-        KRB4_CPPFLAGS=`$krb5_config_command --cflags krb4 2>/dev/null`
-        KRB4_LDFLAGS=`$krb5_config_command --libs krb4 2>/dev/null`
-        if test $? -ne 0; then
-           KRB4_CPPFLAGS=""
-           KRB4_LDFLAGS=""
-        fi
-     fi
-  fi
-  if test "x$KRB4_LDFLAGS" = "x"; then
-     with_krb4=no
-     AC_MSG_RESULT(no)
-  else
-     AC_MSG_RESULT(yes)
-
-     ac_save_CFLAGS=$CFLAGS
-     ac_save_CPPFLAGS=$CPPFLAGS
-     ac_save_LDFLAGS=$LDFLAGS
-     ac_save_LIBS=$LIBS
-     CFLAGS="$CFLAGS $KRB4_CPPFLAGS"
-     CPPFLAGS="$CFLAGS $KRB4_CPPFLAGS"
-     LDFLAGS="$LDFLAGS $KRB4_LDFLAGS"
-     LIBS="$LIBS $LDFLAGS $LIB_resolv"
-
-#    if not found krb.h suppose it's in the kerberosIV subdirectory
-     AC_CHECK_HEADER(krb.h, , with_krb4=no)
-     if test "x$with_krb4" = "xno"; then
-         KRB4_CPPFLAGS="$KRB4_CPPFLAGS ${KRB4_CPPFLAGS}/kerberosIV"
-#        second run of AC_CHECK_HEADER for the same library returns the cached
-#        result created by previous run :-(
-         AC_CHECK_HEADER(kerberosIV/krb.h, with_krb4=yes,
-                         [  with_krb4=no
-                            KRB4_CPPFLAGS=""
-                            KRB4_LDFLAGS=""])
-     fi
-
-     if test "x$with_krb4" != "xno"; then
-        AC_CHECK_LIB(krb4, krb_get_pw_in_tkt, [], [with_krb4=no])
-        if test "x$with_krb4" = "xno"; then
-           AC_CHECK_LIB(krb, krb_get_pw_in_tkt, [with_krb4=yes], 
-                        [with_krb4=no
-                         KRB4_CPPFLAGS=""
-                         KRB4_LDFLAGS=""])
-        fi
-     fi
-
-     CFLAGS=$ac_save_CFLAGS
-     CPPFLAGS=$ac_save_CPPFLAGS
-     LDFLAGS=$ac_save_LDFLAGS
-     LIBS=$ac_save_LIBS
-
-     AC_DEFINE(KRB4)
-  fi
-fi
-AC_SUBST(KRB4_CPPFLAGS)
-AC_SUBST(KRB4_LDFLAGS)
-
-
-if test "x$with_krb5" = "xno" -a "x$with_krb4" = "xno"; then
-  AC_MSG_ERROR([No Kerberos enviroment found])
-fi
-
-#
 # Apache enviroment
 #
 AC_ARG_WITH(apache,
diff --git a/gss.c b/gss.c
new file mode 100644 (file)
index 0000000..6b04e53
--- /dev/null
+++ b/gss.c
@@ -0,0 +1,322 @@
+#include "mod_auth_gssapi.h"
+
+static const char *
+get_gss_error(request_rec *r, OM_uint32 err_maj, OM_uint32 err_min, char *prefix)
+{
+   OM_uint32 maj_stat, min_stat; 
+   OM_uint32 msg_ctx = 0;
+   gss_buffer_desc status_string;
+   char *err_msg;
+   int first_pass;
+
+   gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
+          "GSS-API major_status:%8.8x, minor_status:%8.8x",
+          err_maj, err_min);
+
+   err_msg = apr_pstrdup(r->pool, prefix);
+   do {
+      maj_stat = gss_display_status (&min_stat,
+                                    err_maj,
+                                    GSS_C_GSS_CODE,
+                                    GSS_C_NO_OID,
+                                    &msg_ctx,
+                                    &status_string);
+      if (!GSS_ERROR(maj_stat)) {
+         err_msg = apr_pstrcat(r->pool, err_msg,
+                              ": ", (char*) status_string.value, NULL);
+        gss_release_buffer(&min_stat, &status_string);
+        first_pass = 0;
+      }
+   } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
+
+   msg_ctx = 0;
+   err_msg = apr_pstrcat(r->pool, err_msg, " (", NULL);
+   first_pass = 1;
+   do {
+      maj_stat = gss_display_status (&min_stat,
+                                    err_min,
+                                    GSS_C_MECH_CODE,
+                                    GSS_C_NULL_OID,
+                                    &msg_ctx,
+                                    &status_string);
+      if (!GSS_ERROR(maj_stat)) {
+        err_msg = apr_pstrcat(r->pool, err_msg,
+                              (first_pass) ? "" : ", ",
+                              (char *) status_string.value,
+                              NULL);
+        gss_release_buffer(&min_stat, &status_string);
+        first_pass = 0;
+      }
+   } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
+   err_msg = apr_pstrcat(r->pool, err_msg, ")", NULL);
+
+   return err_msg;
+}
+
+static int
+get_gss_creds(request_rec *r,
+              gss_auth_config *conf,
+             gss_cred_id_t *server_creds)
+{
+   gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+   OM_uint32 major_status, minor_status, minor_status2;
+   gss_name_t server_name = GSS_C_NO_NAME;
+   char buf[1024];
+   int have_server_princ;
+
+   if (conf->service_name && strcmp(conf->service_name, "Any") == 0) {
+       *server_creds = GSS_C_NO_CREDENTIAL;
+       return 0;
+   }
+
+   have_server_princ = conf->service_name && strchr(conf->service_name, '/') != NULL;
+   if (have_server_princ)
+       strncpy(buf, conf->service_name, sizeof(buf));
+   else
+       snprintf(buf, sizeof(buf), "%s@%s",
+              (conf->service_name) ? conf->service_name : SERVICE_NAME,
+              ap_get_server_name(r));
+
+   token.value = buf;
+   token.length = strlen(buf) + 1;
+
+   major_status = gss_import_name(&minor_status, &token,
+                                 (have_server_princ) ? (gss_OID) GSS_KRB5_NT_PRINCIPAL_NAME : (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
+                                 &server_name);
+   memset(&token, 0, sizeof(token));
+   if (GSS_ERROR(major_status)) {
+      gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+             "%s", get_gss_error(r, major_status, minor_status,
+             "gss_import_name() failed"));
+      return HTTP_INTERNAL_SERVER_ERROR;
+   }
+
+   major_status = gss_display_name(&minor_status, server_name, &token, NULL);
+   if (GSS_ERROR(major_status)) {
+      /* Perhaps we could just ignore this error but it's safer to give up now,
+         I think */
+      gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+             "%s", get_gss_error(r, major_status, minor_status,
+                                 "gss_display_name() failed"));
+      return HTTP_INTERNAL_SERVER_ERROR;
+   }
+
+   gss_log(APLOG_MARK, APLOG_DEBUG, 0, r, "Acquiring creds for %s", token.value);
+   gss_release_buffer(&minor_status, &token);
+   
+   major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
+                                  GSS_C_NO_OID_SET, GSS_C_ACCEPT,
+                                  server_creds, NULL, NULL);
+   gss_release_name(&minor_status2, &server_name);
+   if (GSS_ERROR(major_status)) {
+      gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+             "%s", get_gss_error(r, major_status, minor_status,
+                                 "Failed to load GSS-API credentials"));
+      return HTTP_INTERNAL_SERVER_ERROR;
+   }
+
+   return 0;
+}
+
+static int
+cmp_gss_type(gss_buffer_t token, gss_OID oid)
+{
+   unsigned char *p;
+   size_t len;
+
+   if (token->length == 0)
+      return GSS_S_DEFECTIVE_TOKEN;
+
+   p = token->value;
+   if (*p++ != 0x60)
+      return GSS_S_DEFECTIVE_TOKEN;
+   len = *p++;
+   if (len & 0x80) {
+      if ((len & 0x7f) > 4)
+        return GSS_S_DEFECTIVE_TOKEN;
+      p += len & 0x7f;
+   }
+   if (*p++ != 0x06)
+      return GSS_S_DEFECTIVE_TOKEN;
+
+   if (((OM_uint32) *p++) != oid->length)
+      return GSS_S_DEFECTIVE_TOKEN;
+
+   return memcmp(p, oid->elements, oid->length);
+}
+
+int
+gss_authenticate(request_rec *r, gss_auth_config *conf, gss_conn_ctx ctx,
+                const char *auth_line, char **negotiate_ret_value)
+{
+  OM_uint32 major_status, minor_status, minor_status2;
+  gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+  const char *auth_param = NULL;
+  int ret;
+  gss_name_t client_name = GSS_C_NO_NAME;
+  gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
+  gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL;
+  OM_uint32 ret_flags = 0;
+  gss_OID_desc spnego_oid;
+  OM_uint32 (*accept_sec_context)
+               (OM_uint32 *, gss_ctx_id_t *, const gss_cred_id_t,
+                const gss_buffer_t, const gss_channel_bindings_t,
+                gss_name_t *, gss_OID *, gss_buffer_t, OM_uint32 *,
+                OM_uint32 *, gss_cred_id_t *);
+
+  *negotiate_ret_value = "\0";
+
+  spnego_oid.length = 6;
+  spnego_oid.elements = (void *)"\x2b\x06\x01\x05\x05\x02";
+
+  if (conf->krb5_keytab) {
+     char *ktname;
+     /* we don't use the ap_* calls here, since the string passed to putenv()
+      * will become part of the enviroment and shouldn't be free()ed by apache
+      */
+     ktname = malloc(strlen("KRB5_KTNAME=") + strlen(conf->krb5_keytab) + 1);
+     if (ktname == NULL) {
+       gss_log(APLOG_MARK, APLOG_ERR, 0, r, "malloc() failed: not enough memory");
+       ret = HTTP_INTERNAL_SERVER_ERROR;
+       goto end;
+     }
+     sprintf(ktname, "KRB5_KTNAME=%s", conf->krb5_keytab);
+     putenv(ktname);
+#ifdef HEIMDAL
+     /* Seems to be also supported by latest MIT */
+     gsskrb5_register_acceptor_identity(conf->krb_5_keytab);
+#endif
+  }
+
+  ret = get_gss_creds(r, conf, &server_creds);
+  if (ret)
+     goto end;
+
+  /* ap_getword() shifts parameter */
+  auth_param = ap_getword_white(r->pool, &auth_line);
+  if (auth_param == NULL) {
+     gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+            "No Authorization parameter in request from client");
+     ret = HTTP_UNAUTHORIZED;
+     goto end;
+  }
+
+  if (ctx->state == GSS_CTX_ESTABLISHED) {
+      gss_delete_sec_context(&minor_status, &ctx->context, GSS_C_NO_BUFFER);
+      ctx->context = GSS_C_NO_CONTEXT;
+      ctx->state = GSS_CTX_EMPTY;
+  }
+
+  input_token.length = apr_base64_decode_len(auth_param) + 1;
+  input_token.value = apr_pcalloc(r->connection->pool, input_token.length);
+  if (input_token.value == NULL) {
+     gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+            "ap_pcalloc() failed (not enough memory)");
+     ret = HTTP_INTERNAL_SERVER_ERROR;
+     goto end;
+  }
+  input_token.length = apr_base64_decode(input_token.value, auth_param);
+
+  /* LOG length, type */
+
+#ifdef GSSAPI_SUPPORTS_SPNEGO
+  accept_sec_context = gss_accept_sec_context;
+#else
+  accept_sec_context = (cmp_gss_type(&input_token, &spnego_oid) == 0) ?
+                     gss_accept_sec_context_spnego : gss_accept_sec_context;
+#endif  
+
+  major_status = accept_sec_context(&minor_status,
+                                 &ctx->context,
+                                 server_creds,
+                                 &input_token,
+                                 GSS_C_NO_CHANNEL_BINDINGS,
+                                 NULL,
+                                 NULL,
+                                 &output_token,
+                                 &ret_flags,
+                                 NULL,
+                                 &delegated_cred);
+  gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
+         "Client %s us their credential",
+         (ret_flags & GSS_C_DELEG_FLAG) ? "delegated" : "didn't delegate");
+  if (output_token.length) {
+     char *token = NULL;
+     size_t len;
+     
+     len = apr_base64_encode_len(output_token.length) + 1;
+     token = apr_pcalloc(r->connection->pool, len + 1);
+     if (token == NULL) {
+       gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+               "ap_pcalloc() failed (not enough memory)");
+        ret = HTTP_INTERNAL_SERVER_ERROR;
+       gss_release_buffer(&minor_status2, &output_token);
+       goto end;
+     }
+     apr_base64_encode(token, output_token.value, output_token.length);
+     token[len] = '\0';
+     *negotiate_ret_value = token;
+     gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
+            "GSS-API token of length %d bytes will be sent back",
+            output_token.length);
+     gss_release_buffer(&minor_status2, &output_token);
+  }
+
+  if (GSS_ERROR(major_status)) {
+     gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+            "%s", get_gss_error(r, major_status, minor_status,
+                                "Failed to establish authentication"));
+     /* Don't offer the Negotiate method again if call to GSS layer failed */
+     /* XXX ... which means we don't return the "error" output */
+     *negotiate_ret_value = NULL;
+     ret = HTTP_UNAUTHORIZED;
+     goto end;
+  }
+
+  if (major_status & GSS_S_CONTINUE_NEEDED) {
+     ctx->state = GSS_CTX_IN_PROGRESS;
+     ret = HTTP_UNAUTHORIZED;
+     goto end;
+  }
+
+  major_status = gss_inquire_context(&minor_status, ctx->context, &client_name,
+                                    NULL, NULL, NULL, NULL, NULL, NULL);
+  if (GSS_ERROR(major_status)) {
+      gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+             "%s", get_gss_error(r, major_status, minor_status, "gss_inquire_context() failed"));
+      ret = HTTP_INTERNAL_SERVER_ERROR;
+      goto end;
+  }
+
+  major_status = gss_display_name(&minor_status, client_name, &output_token, NULL);
+  gss_release_name(&minor_status, &client_name); 
+  if (GSS_ERROR(major_status)) {
+    gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+           "%s", get_gss_error(r, major_status, minor_status,
+                               "gss_display_name() failed"));
+    ret = HTTP_INTERNAL_SERVER_ERROR;
+    goto end;
+  }
+
+  ctx->state = GSS_CTX_ESTABLISHED;
+  ctx->user = apr_pstrdup(r->pool, output_token.value);
+  gss_release_buffer(&minor_status, &output_token);
+
+  ret = OK;
+
+end:
+  if (delegated_cred)
+     gss_release_cred(&minor_status, &delegated_cred);
+
+  if (output_token.length) 
+     gss_release_buffer(&minor_status, &output_token);
+
+  if (client_name != GSS_C_NO_NAME)
+     gss_release_name(&minor_status, &client_name);
+
+  if (server_creds != GSS_C_NO_CREDENTIAL)
+     gss_release_cred(&minor_status, &server_creds);
+
+  return ret;
+}
diff --git a/mod_auth_gssapi.c b/mod_auth_gssapi.c
new file mode 100644 (file)
index 0000000..fb14416
--- /dev/null
@@ -0,0 +1,189 @@
+#include "mod_auth_gssapi.h"
+
+module AP_MODULE_DECLARE_DATA auth_gssapi_module;
+
+#define command(name, func, var, type, usage)           \
+  AP_INIT_ ## type (name, (void*) func,                 \
+        (void*)APR_OFFSETOF(gss_auth_config, var),      \
+        OR_AUTHCFG | RSRC_CONF, usage)
+
+static const command_rec gss_config_cmds[] = {
+    command("GSSServiceName", ap_set_string_slot, service_name,
+            TAKE1, "Service name used for Apache authentication."),
+
+    command("GSSKrb5Keytab", ap_set_string_slot, krb5_keytab,
+            TAKE1, "Location of Kerberos V5 keytab file."),
+
+    { NULL }
+};
+
+static void *
+gss_config_dir_create(apr_pool_t *p, char *d)
+{
+    gss_auth_config *conf;
+
+    conf = (gss_auth_config *) apr_pcalloc(p, sizeof(*conf));
+    return conf;
+}
+
+void
+gss_log(const char *file, int line, int level, int status,
+        const request_rec *r, const char *fmt, ...)
+{
+    char errstr[1024];
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(errstr, sizeof(errstr), fmt, ap);
+    va_end(ap);
+   
+    ap_log_rerror(file, line, level | APLOG_NOERRNO, status, r, "%s", errstr);
+}
+
+static void
+set_http_headers(request_rec *r, const gss_auth_config *conf,
+                char *negotiate_ret_value)
+{
+    char *negoauth_param;
+    const char *header_name = (r->proxyreq == PROXYREQ_PROXY) ?
+        "Proxy-Authenticate" : "WWW-Authenticate";
+
+    if (negotiate_ret_value == NULL)
+       return;
+
+    negoauth_param = (*negotiate_ret_value == '\0') ? "GSSAPI" :
+        apr_pstrcat(r->pool, "GSSAPI ", negotiate_ret_value, NULL);
+    apr_table_add(r->err_headers_out, header_name, negoauth_param);
+}
+
+static apr_status_t
+cleanup_conn_ctx(void *data)
+{
+    gss_conn_ctx ctx = (gss_conn_ctx) data;
+    OM_uint32 minor_status;
+
+    if (ctx && ctx->context != GSS_C_NO_CONTEXT)
+       gss_delete_sec_context(&minor_status, &ctx->context, GSS_C_NO_BUFFER);
+
+    return APR_SUCCESS;
+}
+
+static gss_conn_ctx
+gss_get_conn_ctx(request_rec *r)
+{
+    char key[1024];
+    gss_conn_ctx ctx = NULL;
+
+    snprintf(key, sizeof(key), "mod_auth_gssapi:conn_ctx");
+    apr_pool_userdata_get((void **)&ctx, key, r->connection->pool);
+    /* XXX LOG */
+    if (ctx == NULL) {
+       ctx = (gss_conn_ctx) apr_palloc(r->connection->pool, sizeof(*ctx));
+       if (ctx == NULL)
+           return NULL;
+       ctx->context = GSS_C_NO_CONTEXT;
+       ctx->state = GSS_CTX_EMPTY;
+       ctx->user = NULL;
+       apr_pool_userdata_set(ctx, key, cleanup_conn_ctx, r->connection->pool);
+    }
+    return ctx;
+}
+
+static int
+gss_authenticate_user(request_rec *r)
+{
+    gss_auth_config *conf = 
+        (gss_auth_config *) ap_get_module_config(r->per_dir_config,
+                                               &auth_gssapi_module);
+    const char *auth_line = NULL;
+    const char *type = NULL;
+    char *auth_type = NULL;
+    char *negotiate_ret_value = NULL;
+    gss_conn_ctx conn_ctx = NULL;
+    int ret;
+
+    gss_log(APLOG_MARK, APLOG_DEBUG, 0, r, "Entering GSSAPI authentication");
+   
+    /* get the type specified in Apache configuration */
+    type = ap_auth_type(r);
+    if (type == NULL || strcmp(type, "GSSAPI") != 0) {
+        gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
+               "AuthType '%s' is not for us, bailing out",
+               (type) ? type : "(NULL)");
+
+        return DECLINED;
+    }
+
+    /* get what the user sent us in the HTTP header */
+    auth_line = apr_table_get(r->headers_in, (r->proxyreq == PROXYREQ_PROXY)
+                                           ? "Proxy-Authorization"
+                                           : "Authorization");
+    if (auth_line == NULL) {
+        gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
+               "Client hasn't sent any authentication data, giving up");
+        set_http_headers(r, conf, "\0");
+        return HTTP_UNAUTHORIZED;
+    }
+
+    auth_type = ap_getword_white(r->pool, &auth_line);
+    if (strcasecmp(auth_type, "GSSAPI") != 0) {
+        gss_log(APLOG_MARK, APLOG_DEBUG, 0, r,
+               "Unsupported authentication type (%s) requested by client",
+               (auth_type) ? auth_type : "(NULL)");
+        set_http_headers(r, conf, "\0");
+        return HTTP_UNAUTHORIZED;
+    }
+
+    conn_ctx = gss_get_conn_ctx(r);
+    if (conn_ctx == NULL) {
+       gss_log(APLOG_MARK, APLOG_ERR, 0, r,
+               "Failed to create internal context: probably not enough memory");
+       return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    /* optimizing hack */
+    if (conn_ctx->state == GSS_CTX_ESTABLISHED && auth_line == NULL) {
+       r->user = apr_pstrdup(r->pool, conn_ctx->user);
+       r->ap_auth_type = "GSSAPI";
+       return OK;
+    }
+
+    /* XXXX subrequests ignored, only successful accesses taken into account! */
+    if (!ap_is_initial_req(r) && conn_ctx->state == GSS_CTX_ESTABLISHED) {
+       r->user = apr_pstrdup(r->pool, conn_ctx->user);
+       r->ap_auth_type = "GSSAPI";
+       return OK;
+    }
+
+    ret = gss_authenticate(r, conf, conn_ctx,
+                          auth_line, &negotiate_ret_value);
+    if (ret == HTTP_UNAUTHORIZED || ret == OK) {
+        /* LOG?? */
+        set_http_headers(r, conf, negotiate_ret_value);
+    }
+
+    if (ret == OK) {
+       r->user = apr_pstrdup(r->pool, conn_ctx->user);
+       r->ap_auth_type = "GSSAPI";
+    }
+
+    /* debug LOG ??? */
+
+    return ret;
+}
+
+static void
+gss_register_hooks(apr_pool_t *p)
+{
+    ap_hook_check_user_id(gss_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA auth_gssapi_module = {
+    STANDARD20_MODULE_STUFF,
+    gss_config_dir_create,
+    NULL,
+    NULL,
+    NULL,
+    gss_config_cmds,
+    gss_register_hooks
+};
diff --git a/mod_auth_gssapi.h b/mod_auth_gssapi.h
new file mode 100644 (file)
index 0000000..a8f8a8d
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __MOD_AUTH_GSSAPI_H__
+#define __MOD_AUTH_GSSAPI_H__
+
+#include <httpd.h>
+#include <http_config.h>
+#include <http_core.h>
+#include <http_log.h>
+#include <http_protocol.h>
+#include <http_request.h>
+
+#include <apr_base64.h>
+#include <apr_strings.h>
+
+#include <gssapi.h>
+/* XXX */
+#define GSS_KRB5_NT_PRINCIPAL_NAME 0xdeaddead
+
+#ifndef GSSAPI_SUPPORTS_SPNEGO
+#include "spnegokrb5.h"
+#endif
+
+#define SERVICE_NAME "HTTP"
+
+typedef struct {
+    const char *service_name;
+    const char *krb5_keytab;
+} gss_auth_config;
+
+typedef struct gss_conn_ctx_t {
+    gss_ctx_id_t context;
+    enum {
+       GSS_CTX_EMPTY,
+       GSS_CTX_IN_PROGRESS,
+       GSS_CTX_ESTABLISHED,
+    } state;
+    char *user;
+} *gss_conn_ctx;
+
+void
+gss_log(const char *file, int line, int level, int status,
+        const request_rec *r, const char *fmt, ...);
+
+int
+gss_authenticate(request_rec *r, gss_auth_config *conf, gss_conn_ctx ctx,
+                 const char *auth_line, char **negotiate_ret_value);
+#endif