-#
-# Makefile for the Squid Object Cache server
-#
-# $Id: Makefile.am,v 1.2 2008/01/07 15:25:14 hno Exp $
-#
+EXTRA_DIST = reconf configure
+SUBDIRS =
-libexec_PROGRAMS = squid_kerb_auth
+bin_PROGRAMS = squid_kerb_auth squid_kerb_auth_test
-SPNEGO = spnegohelp/derparse.c spnegohelp/derparse.h spnegohelp/Makefile spnegohelp/spnego.c spnegohelp/spnego.h spnegohelp/spnegohelp.c spnegohelp/spnegohelp.h spnegohelp/spnegoparse.c spnegohelp/spnegoparse.h
-SOURCE = squid_kerb_auth.c base64.c base64.h
-EXTRA_DIST = readme.txt do.sh
+if HAVE_SPNEGO
+squid_kerb_auth_SOURCES = squid_kerb_auth.c base64.c
+squid_kerb_auth_test_SOURCES = squid_kerb_auth_test.c base64.c
+else
+squid_kerb_auth_SOURCES = squid_kerb_auth.c base64.c spnegohelp/derparse.c spnegohelp/spnego.c spnegohelp/spnegohelp.c spnegohelp/spnegoparse.c
+INCLUDES = -Ispnegohelp
+squid_kerb_auth_test_SOURCES = squid_kerb_auth_test.c base64.c
+endif
-squid_kerb_auth_SOURCES = $(SOURCE) $(SPNEGO)
-
-CPPFLAGS = $(KERBINC) -I$(srcdir)/spnegohelp -I. -I$(top_srcdir)/include
-LDADD = -L$(top_builddir)/lib -lmiscutil $(XTRA_LIBS) $(KERBLIBS)
-
-# HEIMDAL
-#KERBINC = -DHEIMDAL -I/usr/include/heimdal
-#KERBLIBS = -lgssapi -lkrb5 -lcom_err -lasn1 -lroken
-
-# MIT
-KERBINC =
-KERBLIBS = -lgssapi_krb5 -lkrb5 -lcom_err
+squid_kerb_auth_LDFLAGS =
+squid_kerb_auth_LDADD =
+squid_kerb_auth_test_LDFLAGS =
+squid_kerb_auth_test_LDADD =
2 Building and Installation
-# Linux:
-# -D__LITTLE_ENDIAN__
-# Solaris:
-# -D__BIG_ENDIAN__
-#
-#DEFINE_SPNEGO=-DHAVE_SPNEGO
-#HEIMDAL
-# DEFINE="-DHEIMDAL $DEFINE_SPNEGO -D__LITTLE_ENDIAN__"
-# INCLUDE=-I/usr/include/heimdal -Ispnegohelp
-# LIBS="-lgssapi -lkrb5 -lcom_err -lasn1 -lroken"
-#MIT
- DEFINE="$DEFINE_SPNEGO -D__LITTLE_ENDIAN__"
- INCLUDE=-Ispnegohelp
- LIBS="-lgssapi_krb5 -lkrb5 -lcom_err"
-#
-SPNEGO="spnegohelp/derparse.c spnegohelp/spnego.c spnegohelp/spnegohelp.c spnegohelp/spnegoparse.c"
-SOURCE="squid_kerb_auth.c base64.c"
-gcc -o squid_kerb_auth $DEFINE $INCLUDE $SOURCE $SPNEGO $LIBS
+Run ./configure
+
+for help use ./configure --help
Copy the helper squid_kerb_auth to an apropriate directory.
4 Miscellaneous
-The -i options creates informational messages whereas -d creates full debug output
-
If squid_kerb_auth doesn't determine for some reason the right service principal you can provide
it with -s HTTP/fqdn.
#include "base64.h"
-static void base64_init(void);
+static void ska_base64_init(void);
static int base64_initialized = 0;
#define BASE64_VALUE_SZ 256
static void
-base64_init(void)
+ska_base64_init(void)
{
int i;
base64_initialized = 1;
}
-void base64_decode(char* result, const char *data, int result_size)
+void ska_base64_decode(char* result, const char *data, int result_size)
{
int j;
int c;
if (!data)
return;
if (!base64_initialized)
- base64_init();
+ ska_base64_init();
val = c = 0;
for (j = 0; *data ;data++) {
}
/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */
-void base64_encode(char* result, const char *data, int result_size, int data_size)
+void ska_base64_encode(char* result, const char *data, int result_size, int data_size)
{
int bits = 0;
int char_count = 0;
return;
if (!base64_initialized)
- base64_init();
+ ska_base64_init();
while (data_size--) {
int c = (unsigned char) *data++;
return;
}
-int base64_encode_len(int len)
+int ska_base64_encode_len(int len)
{
return ((len+2)/3*4)+1;
}
-int base64_decode_len(const char *data)
+int ska_base64_decode_len(const char *data)
{
int i,j;
* Markus Moeller has modified the following code from Squid
*/
-void base64_decode(char* result, const char *data, int result_size);
-void base64_encode(char* result, const char *data, int result_size, int data_size);
+void ska_base64_decode(char* result, const char *data, int result_size);
+void ska_base64_encode(char* result, const char *data, int result_size, int data_size);
-int base64_encode_len(int len);
-int base64_decode_len(const char *data);
+int ska_base64_encode_len(int len);
+int ska_base64_decode_len(const char *data);
--- /dev/null
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl Process this file with autoconf to produce a configure script.
+
+
+AC_INIT([squid_kerb_auth],[1.0.3],[markus_moeller@compuserve.com])
+AM_INIT_AUTOMAKE(squid_kerb_auth,1.0.3)
+
+AC_PROG_CC
+AC_PROG_CPP
+
+AC_TRY_COMPILE([int main()
+ {
+ return;
+ }
+])
+
+SPARCV9=""
+sys=`uname`
+case $sys in
+ Linux) w_flag="-Wl,-R"
+ w_flag_2=""
+ ;;
+ AIX) w_flag="-Wl,-blibpath:"
+ w_flag_2=":/usr/lib:/lib"
+ ;;
+ SunOS) w_flag="-R"
+ w_flag_2=""
+ rel=`uname -r`
+ case $rel in
+ 5.10|5.11) AC_DEFINE(HAVE_NEW_SEAM_KERBEROS,1,[Define to 1 if you have New Solaris 10/OpenSolaris Kerberos])
+ ;;
+ *) ;;
+ esac
+ ;;
+ FreeBSD) w_flag="-Wl,-R"
+ w_flag_2=""
+ ;;
+ *) w_flag="-Wl,-rpath"
+ w_flag_2=""
+ ;;
+esac
+
+
+enable_arg="no"
+check_mit() {
+ if test "x$ac_krb5_config" = "xyes" ; then
+ ac_heimdal=`krb5-config --version 2>/dev/null | grep heimdal`
+ if test "x$ac_heimdal" != "x" ; then
+ check_heimdal
+ return
+ fi
+ fi
+ AC_DEFINE(HAVE_MIT_KERBEROS,1,[Define to 1 if you have MIT Kerberos])
+ ac_gss_libs="resolv com_err des425 k5crypto krb5 gssapi_krb5"
+ ac_includedir=""
+ ac_libdir=""
+ case $sys in
+ Linux) if test "x$enableval" != "xyes" -a "x$enableval" != "x" ; then
+ ac_libdir=$enableval/lib
+ ac_includedir=$enableval/include
+ else
+ ac_libdir=`rpm -q -l krb5 2>/dev/null | grep "/libgssapi_krb5" | sed -e 's/\/libgssapi_krb5.*//' | head -1`
+ ac_includedir=`rpm -q -l krb5-devel 2>/dev/null | grep /krb5.h$ | sed -e 's/\/krb5.h//' | head -1`
+ fi
+ if test "x$ac_includedir" != "x" ; then
+ CPPFLAGS="$CPPFLAGS -I$ac_includedir"
+ else
+ ac_gssapi_cflags=`krb5-config --cflags gssapi 2>/dev/null`
+ if test "x$ac_gssapi_cflags" != "x" ; then
+ CPPFLAGS="$CPPFLAGS $ac_gssapi_cflags"
+ fi
+ fi
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_krb5.h gssapi/gssapi_generic.h)
+ if test "x$ac_libdir" != "x" ; then
+ LDFLAGS="$LDFLAGS -L$ac_libdir $w_flag$ac_libdir$w_flag_2"
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ else
+ ac_gssapi_libs=`krb5-config --libs gssapi 2>/dev/null`
+ if test "x$ac_gssapi_libs" != "x" ; then
+ LDFLAGS="$LDFLAGS $ac_gssapi_libs"
+ else
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ fi
+ fi
+ ;;
+ *) if test "x$enableval" != "xyes" -a "x$enableval" != "x" ; then
+ ac_libdir=$enableval/lib
+ ac_includedir=$enableval/include
+ CPPFLAGS="$CPPFLAGS -I$ac_includedir"
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_krb5.h gssapi/gssapi_generic.h)
+ LDFLAGS="$LDFLAGS -L$ac_libdir $w_flag$ac_libdir$w_flag_2"
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ else
+ ac_gssapi_cflags=`krb5-config --cflags gssapi 2>/dev/null`
+ if test "x$ac_gssapi_cflags" != "x" ; then
+ CPPFLAGS="$CPPFLAGS $ac_gssapi_cflags"
+ fi
+ ac_gssapi_libs=`krb5-config --libs gssapi 2>/dev/null`
+ if test "x$ac_gssapi_libs" != "x" ; then
+ LDFLAGS="$LDFLAGS $ac_gssapi_libs"
+ else
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ fi
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_krb5.h gssapi/gssapi_generic.h)
+ fi
+ ;;
+ esac
+ enable_arg="mit"
+}
+check_heimdal(){
+ if test "x$ac_krb5_config" = "xyes" ; then
+ ac_heimdal=`krb5-config --version 2>/dev/null | grep heimdal`
+ if test "x$ac_heimdal" = "x" ; then
+ check_mit
+ return
+ fi
+ fi
+ AC_DEFINE(HAVE_HEIMDAL_KERBEROS,1,[Define to 1 if you have Heimdal Kerberos])
+ ac_gss_libs="resolv crypto des crypt roken com_err asn1 krb5 gssapi"
+ ac_includedir=""
+ ac_libdir=""
+ case $sys in
+ Linux) if test "x$enableval" != "xyes" -a "x$enableval" != "x" ; then
+ ac_libdir=$enableval/lib
+ ac_includedir=$enableval/include
+ else
+ ac_libdir=`rpm -q -l heimdal-devel 2>/dev/null | grep "/libroken" | sed -e 's/\/libroken.*//' | head -1`
+ ac_includedir=`rpm -q -l heimdal-devel 2>/dev/null | grep /krb5.h$ | sed -e 's/\/krb5.h//' | head -1`
+ fi
+ if test "x$ac_includedir" != "x" ; then
+ CPPFLAGS="$CPPFLAGS -I$ac_includedir"
+ else
+ ac_gssapi_cflags=`krb5-config --cflags gssapi 2>/dev/null`
+ if test "x$ac_gssapi_cflags" != "x" ; then
+ CPPFLAGS="$CPPFLAGS $ac_gssapi_cflags"
+ fi
+ fi
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h)
+ if test "x$ac_libdir" != "x" ; then
+ LDFLAGS="$LDFLAGS -L$ac_libdir $w_flag$ac_libdir$w_flag_2"
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ else
+ ac_gssapi_libs=`krb5-config --libs gssapi 2>/dev/null`
+ if test "x$ac_gssapi_libs" != "x" ; then
+ ac_libdir=`echo $ac_gssapi_libs | grep "\-L"`
+ if test "x$ac_libdir" != "x" ; then
+ ac_libdir=`echo $ac_gssapi_libs | sed -e 's/.*-L//' | sed -e 's/ .*//'`
+ LDFLAGS="$LDFLAGS $w_flag$ac_libdir$w_flag_2"
+ fi
+ LDFLAGS="$LDFLAGS $ac_gssapi_libs"
+ else
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ fi
+ fi
+ ;;
+ *) if test "x$enableval" != "xyes" -a "x$enableval" != "x" ; then
+ ac_libdir=$enableval/lib
+ ac_includedir=$enableval/include
+ CPPFLAGS="$CPPFLAGS -I$ac_includedir"
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h)
+ LDFLAGS="$LDFLAGS -L$ac_libdir $w_flag$ac_libdir$w_flag_2"
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ else
+ ac_gssapi_cflags=`krb5-config --cflags gssapi 2>/dev/null`
+ if test "x$ac_gssapi_cflags" != "x" ; then
+ CPPFLAGS="$CPPFLAGS $ac_gssapi_cflags"
+ fi
+ ac_gssapi_libs=`krb5-config --libs gssapi 2>/dev/null`
+ if test "x$ac_gssapi_libs" != "x" ; then
+ ac_libdir=`echo $ac_gssapi_libs | grep "\-L"`
+ if test "x$ac_libdir" != "x" ; then
+ ac_libdir=`echo $ac_gssapi_libs | sed -e 's/.*-L//' | sed -e 's/ .*//'`
+ LDFLAGS="$LDFLAGS $w_flag$ac_libdir$w_flag_2"
+ fi
+ LDFLAGS="$LDFLAGS $ac_gssapi_libs"
+ else
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ fi
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h)
+ fi
+ ;;
+ esac
+ enable_arg="heimdal"
+}
+check_nas(){
+ AC_DEFINE(HAVE_NAS_KERBEROS,1,[Define to 1 if you have NAS Kerberos])
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_krb5.h gssapi/gssapi_generic.h)
+ LDFLAGS="$LDFLAGS -L/usr/lib"
+ ac_gss_libs="krb5 gssapi_krb5 ksvc";
+ for lib in $ac_gss_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ enable_arg="nas"
+}
+
+check_seam_64(){
+ SPARCV9s="/sparcv9"
+ check_seam
+ enable_arg="seam64"
+}
+
+check_seam(){
+ AC_DEFINE(HAVE_SEAM_KERBEROS,1,[Define to 1 if you have SEAM Kerberos])
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_ext.h)
+ ac_sol_libs="nsl socket resolv gss"
+ for lib in $ac_sol_libs; do
+ AC_CHECK_LIB($lib,main)
+ done
+ enable_arg="seam"
+}
+
+dnl Define MIT libraries
+AC_ARG_ENABLE(mit,
+ [ --enable-mit[=DIR] enable use of MIT package (default=yes) ],
+ [
+ if test "x$enableval" != "xno" ; then
+ check_mit
+ fi ])
+
+dnl Define Heimdal libraries
+AC_ARG_ENABLE(heimdal,
+ [ --enable-heimdal[=DIR] enable use of Heimdal package (default=no) ],
+ [
+ if test "x$enableval" != "xno" ; then
+ check_heimdal
+ fi ])
+
+dnl Define NAS libraries
+AC_ARG_ENABLE(nas,
+ [ --enable-nas enable use of NAS(AIX) package (default=no) ],
+ [
+ if test "x$enableval" != "xno" ; then
+ check_nas
+ fi ])
+
+dnl Define SEAM libraries
+AC_ARG_ENABLE(seam,
+ [ --enable-seam[=SRC] enable use of SEAM(Solaris) package (default=no) ],
+ [
+ if test "x$enableval" != "xno" ; then
+ check_seam
+ fi ])
+
+dnl Define SEAM libraries
+AC_ARG_ENABLE(seam-64,
+ [ --enable-seam-64[=SRC] enable use of 64bit SEAM(Solaris) package (default=no) ],
+ [
+ if test "x$enableval" != "xno" ; then
+ check_seam_64
+ fi ])
+
+dnl Define system default
+if test "$enable_arg" = "no"; then
+ dnl Autodetect system
+ dnl Check krb5-config first
+ AC_CHECK_PROG(ac_krb5_config,krb5-config,yes,no)
+ case $sys in
+ Linux) rpm -q heimdal-lib >/dev/null 2>&1
+ if test $? == 0 ; then
+ check_heimdal
+ else
+ check_mit
+ fi
+ ;;
+ AIX) lslpp -L krb5.client.rte >/dev/null 2>&1
+ if test $? == 0 ; then
+ check_nas
+ else
+ check_mit
+ fi
+ ;;
+ SunOS) pkginfo SUNWgss >/dev/null 2>&1
+ if test $? == 0 ; then
+ check_seam
+ else
+ check_mit
+ fi
+ ;;
+ FreeBSD) check_heimdal
+ ;;
+ *) check_mit
+ ;;
+ esac
+fi
+
+
+old_LIBS=$LIBS
+AC_CACHE_CHECK([for SPNEGO support],ac_cv_have_spnego,[
+ AC_TRY_RUN([
+#ifdef HAVE_HEIMDAL_KERBEROS
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#endif
+#else
+#ifdef HAVE_SEAM_KERBEROS
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#else /*MIT*/
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+#endif
+#endif
+
+int main(int argc, char *argv[]) {
+ OM_uint32 major_status,minor_status;
+ gss_OID_set gss_mech_set;
+ int i;
+
+static gss_OID_desc _gss_mech_spnego = {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
+gss_OID gss_mech_spnego = &_gss_mech_spnego;
+
+ major_status = gss_indicate_mechs( &minor_status, &gss_mech_set);
+
+ for (i=0;i<gss_mech_set->count;i++) {
+ if (!memcmp(gss_mech_set->elements[i].elements,gss_mech_spnego->elements,gss_mech_set->elements[i].length)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}],
+ ac_cv_have_spnego=yes,
+ ac_cv_have_spnego=no)])
+if test x"$ac_cv_have_spnego" = x"yes"; then
+ AC_DEFINE(HAVE_SPNEGO,1, [Define to 1 if you have SPNEGO support])
+fi
+LIBS=$old_LIBS
+
+AC_C_BIGENDIAN
+
+eval ac_p_include=$includedir
+CPPFLAGS="$CPPFLAGS -I$ac_p_include -I../../../include"
+AC_CACHE_CHECK([for SQUID],ac_cv_have_squid,[
+AC_TRY_RUN([
+#include <config.h>
+int main(int argc, char *argv[]) {
+#ifdef SQUID_CONFIG_H
+return 0;
+#else
+return 1;
+#endif
+}],
+ ac_cv_have_squid=yes,
+ ac_cv_have_squid=no)])
+eval ac_p_lib=$libdir
+LDFLAGS="$LDFLAGS -L../../../lib -L$ac_p_lib $w_flag$ac_p_lib$w_flag_2"
+if test x"$ac_cv_have_squid" = x"yes"; then
+ AC_DEFINE(HAVE_SQUID,1, [Define to 1 if you have SQUID])
+ AC_CHECK_HEADERS(getaddrinfo.h getnameinfo.h util.h)
+ AC_CHECK_DECLS([xgetaddrinfo], [], [], [[#include <getaddrinfo.h>]])
+ AC_CHECK_DECLS([xfreeaddrinfo], [], [], [[#include <getaddrinfo.h>]])
+ AC_CHECK_DECLS([xgai_strerror], [], [], [[#include <getaddrinfo.h>]])
+ AC_CHECK_DECLS([xgetnameinfo], [], [], [[#include <getnameinfo.h>]])
+ AC_CHECK_DECLS([xstrdup], [], [], [[#include <util.h>]])
+ AC_CHECK_DECLS([xmalloc], [], [], [[#include <util.h>]])
+ AC_CHECK_DECLS([xfree], [], [], [[#include <util.h>]])
+ AC_CHECK_LIB(m,main)
+ AC_CHECK_LIB(mw,main)
+ LIBS="-lmiscutil $LIBS"
+fi
+
+AC_CONFIG_HEADER(config.h)
+AH_TOP([/*
+ * -----------------------------------------------------------------------------
+ *
+ * Author: Markus Moeller (|MAIL|)
+ *
+ * Copyright (C) 2007 Markus Moeller. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * As a special exemption, M Moeller gives permission to link this program
+ * with MIT, Heimdal or other GSS/Kerberos libraries, and distribute
+ * the resulting executable, without including the source code for
+ * the Libraries in the source distribution.
+ *
+ * -----------------------------------------------------------------------------
+ */
+])
+AH_BOTTOM([
+#ifdef HAVE_HEIMDAL_KERBEROS
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#endif
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#else
+#ifdef HAVE_SEAM_KERBEROS
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#else /*MIT*/
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+#endif
+#endif
+
+])
+
+echo "configure: ## -----------------------------##"
+echo "configure: ##"
+echo "configure: ## $enable_arg has been selected"
+echo "configure: ##"
+echo "configure: ## -----------------------------##"
+
+dnl set variable for use in automakefile(s)
+AM_CONDITIONAL(HAVE_SPNEGO, test x"$ac_cv_have_spnego" = x"yes" )
+
+MY_CFLAGS="-Wall -Wextra -Werror -Wcomment -Wpointer-arith -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wdeclaration-after-statement -Wshadow"
+for ac_cv_my_cflag in $MY_CFLAGS; do
+echo "int main()
+ {
+ return 0;
+ };" > conftest.c
+${CC} $ac_cv_my_cflag -c conftest.c 2>/dev/null
+res=$?
+rm -f conftest.*
+if test "$res" = "0"; then
+ CFLAGS="$CFLAGS $ac_cv_my_cflag"
+fi
+done
+
+AC_OUTPUT(Makefile)
+
+echo "configure: updating config.h"
+sed -e "s/|MAIL|/"$PACKAGE_BUGREPORT"/" config.h > .config.h.tmp
+mv .config.h.tmp config.h
+++ /dev/null
-#!/bin/sh
-#
-# Linux:
-# -D__LITTLE_ENDIAN__
-# Solaris:
-# -D__BIG_ENDIAN__
-#
-CC=gcc
-#CFLAGS="-Wall -Wextra -Werror -Wcomment -Wpointer-arith -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wdeclaration-after-statement -Wshadow -O2"
-CFLAGS="-Wall -Werror -Wcomment -Wpointer-arith -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -O2"
-if [ "$1" = "HEIMDAL" ]; then
- DEFINE="-DHEIMDAL -D__LITTLE_ENDIAN__"
- INCLUDE="-I/usr/include/heimdal -Ispnegohelp"
- LIBS="-lgssapi -lkrb5 -lcom_err -lasn1 -lroken"
-else
-if [ "$1" = "SOLARIS" ]; then
-#MIT
- CC=cc
- CFLAGS=""
- DEFINE="-D__BIG_ENDIAN__ -DSOLARIS_11"
- INCLUDE="-Ispnegohelp -Iinclude -Iinclude/kerberosv5"
- LIBS="-R/usr/lib/gss -L/usr/lib/gss -lgss /usr/lib/gss/mech_krb5.so -lsocket"
-else
-#MIT
- DEFINE="-D__LITTLE_ENDIAN__"
- INCLUDE=-Ispnegohelp
- LIBS="-lgssapi_krb5 -lkrb5 -lcom_err"
-fi
-fi
-SPNEGO="spnegohelp/derparse.c spnegohelp/spnego.c spnegohelp/spnegohelp.c spnegohelp/spnegoparse.c"
-SOURCE="squid_kerb_auth.c base64.c"
-$CC -g $CFLAGS -o squid_kerb_auth $DEFINE $INCLUDE $SOURCE $SPNEGO $LIBS
+++ /dev/null
-#
-# Linux:
-# -D__LITTLE_ENDIAN__
-# Solaris:
-# -D__BIG_ENDIAN__
-#
-
-CFLAGS = -fpic
-
-LIB = libspnegohelp.a
-SLIB = libspnegohelp.so
-
-OBJS = derparse.o spnego.o spnegohelp.o spnegoparse.o
-
-all:
- make `uname`
-
-debug:
- make CFLAGS="$(CFLAGS) -DDEBUG" `uname`
-
-SunOS:
- make CFLAGS="$(CFLAGS) -D__BIG_ENDIAN__" libs
-
-AIX:
- make CFLAGS="$(CFLAGS) -D__BIG_ENDIAN__" libs
-
-Linux:
- make CFLAGS="$(CFLAGS) -D__LITTLE_ENDIAN__" libs
-
-libs: $(LIB) $(SLIB)
-
-$(LIB): $(OBJS)
- ar -r $(LIB) $(OBJS)
-
-$(SLIB): $(OBJS)
- gcc --shared -o $(SLIB) $(OBJS)
-
-derparse.o: derparse.c derparse.h spnego.h Makefile
- gcc -c $(CFLAGS) derparse.c -o $@
-
-spnego.o: spnego.c derparse.h spnego.h spnegoparse.h Makefile
- gcc -c $(CFLAGS) spnego.c -o $@
-
-spnegoparse.o: spnegoparse.c derparse.h spnego.h spnegoparse.h Makefile
- gcc -c $(CFLAGS) spnegoparse.c -o $@
-
-spnegohelp.o: spnegohelp.c spnego.h spnegohelp.h Makefile
- gcc -c $(CFLAGS) spnegohelp.c -o $@
-
-clean:
- rm $(OBJS) $(LIB) $(SLIB)
// Bump by 1 byte
pbLengthData++;
- #ifdef __LITTLE_ENDIAN__
+ #if defined(__LITTLE_ENDIAN__) || !defined(WORDS_BIGENDIAN)
// There may be a cleaner way to do this, but for now, this seems to be
// an easy way to do the transformation
// Point to where we'll actually write the length
pbData++;
-#ifdef __LITTLE_ENDIAN__
+#if defined(__LITTLE_ENDIAN__) || !defined(WORDS_BIGENDIAN)
// There may be a cleaner way to do this, but for now, this seems to be
// an easy way to do the transformation
-/* -----------------------------------------------------------------------------
- * spnegohelp.c defines RFC 2478 SPNEGO GSS-API mechanism APIs.
- *
- * Author: Frank Balluffi
- *
- * Copyright (C) 2002-2003 All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- *
- * -----------------------------------------------------------------------------
- */
-
-#include "spnegohelp.h"
-#include "spnego.h"
-
-#include <stdlib.h>
-
-int makeNegTokenTarg (const unsigned char * kerberosToken,
- size_t kerberosTokenLength,
- const unsigned char ** negTokenTarg,
- size_t * negTokenTargLength)
-{
- SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL;
- int rc1 = 1;
- int rc2 = SPNEGO_E_SUCCESS;
-
- /* Check arguments. */
-
- if (!kerberosToken ||
- !negTokenTarg ||
- !negTokenTargLength)
- return 10;
-
- /* Does IIS reply with 1.2.840.48018.1.2.2 or 1.2.840.113554.1.2.2? */
-
- /* Does IIS always reply with accept_completed? */
-
- /* IIS does not include a MIC. */
-
- rc2 = spnegoCreateNegTokenTarg (spnego_mech_oid_Kerberos_V5_Legacy,
- spnego_negresult_success,
- (unsigned char *) kerberosToken,
- kerberosTokenLength,
- NULL,
- 0,
- &hSpnegoToken);
-
- if (rc2 != SPNEGO_E_SUCCESS)
- {
- rc1 = abs(rc2)+100;
- goto cleanup;
- }
-
- /* Get NegTokenTarg length. */
-
- rc2 = spnegoTokenGetBinary (hSpnegoToken,
- NULL,
- (unsigned long*) negTokenTargLength);
-
- if (rc2 != SPNEGO_E_BUFFER_TOO_SMALL)
- {
- rc1 = abs(rc2)+200;
- goto cleanup;
- }
-
- *negTokenTarg = malloc (*negTokenTargLength);
-
- if (!*negTokenTarg)
- {
- rc1 = abs(rc2)+300;
- goto cleanup;
- }
-
- /* Get NegTokenTarg data. */
-
- rc2 = spnegoTokenGetBinary (hSpnegoToken,
- (unsigned char *) *negTokenTarg,
- (unsigned long*) negTokenTargLength);
-
-
- if (rc2 != SPNEGO_E_SUCCESS)
- {
- rc1 = abs(rc2)+400;
- goto error;
- }
-
- rc1 = 0;
-
- goto cleanup;
-
-error:
-
- if (*negTokenTarg)
- {
- free ((unsigned char *) *negTokenTarg);
- *negTokenTarg = NULL;
- *negTokenTargLength = 0;
- }
-
-cleanup:
-
- if (hSpnegoToken)
- spnegoFreeData (hSpnegoToken);
-
- LOG(("makeNegTokenTarg returned %d\n",rc1));
- return rc1;
-}
-
-int parseNegTokenInit (const unsigned char * negTokenInit,
- size_t negTokenInitLength,
- const unsigned char ** kerberosToken,
- size_t * kerberosTokenLength)
-{
- SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL;
- int pindex = -1;
- int rc1 = 1;
- int rc2 = SPNEGO_E_SUCCESS;
- unsigned char reqFlags = 0;
- int tokenType = 0;
-
- /* Check arguments. */
-
- if (!negTokenInit ||
- !kerberosToken ||
- !kerberosTokenLength)
- return 10;
-
- /* Decode SPNEGO token. */
-
- rc2 = spnegoInitFromBinary ((unsigned char *) negTokenInit,
- negTokenInitLength,
- &hSpnegoToken);
-
- if (rc2 != SPNEGO_E_SUCCESS)
- {
- rc1 = abs(rc2)+100;
- goto cleanup;
- }
-
- /* Check for negTokenInit choice. */
-
- rc2 = spnegoGetTokenType (hSpnegoToken,
- &tokenType);
-
- if (rc2 != SPNEGO_E_SUCCESS)
- {
- rc1 = abs(rc2)+200;
- goto cleanup;
- }
-
- if (tokenType != SPNEGO_TOKEN_INIT)
- {
- rc1 = abs(rc2)+300;
- goto cleanup;
- }
-
- /*
- Check that first mechType is 1.2.840.113554.1.2.2 or 1.2.840.48018.1.2.2.
- */
-
- /*
- IE seems to reply with 1.2.840.48018.1.2.2 and then 1.2.840.113554.1.2.2.
- */
-
- rc2 = spnegoIsMechTypeAvailable (hSpnegoToken,
- spnego_mech_oid_Kerberos_V5_Legacy,
- &pindex);
-
- if (rc2 != SPNEGO_E_SUCCESS ||
- pindex != 0)
- {
- rc2 = spnegoIsMechTypeAvailable (hSpnegoToken,
- spnego_mech_oid_Kerberos_V5,
- &pindex);
-
- if (rc2 != SPNEGO_E_SUCCESS ||
- pindex != 0)
- {
- rc1 = abs(rc2)+400;
- goto cleanup;
- }
- }
-
- /* Check for no reqFlags. */
-
- /* Does IE ever send reqFlags? */
-
- rc2 = spnegoGetContextFlags (hSpnegoToken,
- &reqFlags);
-
- if (rc2 == SPNEGO_E_SUCCESS)
- {
- rc1 = abs(rc2)+500;
- goto cleanup;
- }
-
- /* Get mechanism token length. */
-
- rc2 = spnegoGetMechToken (hSpnegoToken,
- NULL,
- (unsigned long*) kerberosTokenLength);
-
- if (rc2 != SPNEGO_E_BUFFER_TOO_SMALL)
- {
- rc1 = abs(rc2)+600;
- goto cleanup;
- }
-
- *kerberosToken = malloc (*kerberosTokenLength);
-
- if (!*kerberosToken)
- {
- rc1 = abs(rc2)+700;
- goto cleanup;
- }
-
- /* Get mechanism token data. */
-
- rc2 = spnegoGetMechToken (hSpnegoToken,
- (unsigned char *) *kerberosToken,
- (unsigned long*) kerberosTokenLength);
-
- if (rc2 != SPNEGO_E_SUCCESS)
- {
- rc1 = abs(rc2)+800;
- goto error;
- }
-
- /* According to Microsoft, IE does not send a MIC. */
-
- rc1 = 0;
-
- goto cleanup;
-
-error:
-
- if (*kerberosToken)
- {
- free ((unsigned char *) *kerberosToken);
- *kerberosToken = NULL;
- *kerberosTokenLength = 0;
- }
-
-cleanup:
-
- if (hSpnegoToken)
- spnegoFreeData (hSpnegoToken);
-
- LOG(("parseNegTokenInit returned %d\n",rc1));
- return rc1;
-}
+/* -----------------------------------------------------------------------------\r
+ * spnegohelp.c defines RFC 2478 SPNEGO GSS-API mechanism APIs.\r
+ *\r
+ * Author: Frank Balluffi\r
+ *\r
+ * Copyright (C) 2002-2003 All rights reserved.\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.\r
+ *\r
+ * -----------------------------------------------------------------------------\r
+ */\r
+\r
+#include "spnegohelp.h"\r
+#include "spnego.h"\r
+\r
+#include <stdlib.h>\r
+\r
+int makeNegTokenTarg (const unsigned char * kerberosToken,\r
+ size_t kerberosTokenLength,\r
+ const unsigned char ** negTokenTarg,\r
+ size_t * negTokenTargLength)\r
+{\r
+ SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL;\r
+ int rc1 = 1;\r
+ int rc2 = SPNEGO_E_SUCCESS;\r
+\r
+ /* Check arguments. */\r
+\r
+ if (!kerberosToken ||\r
+ !negTokenTarg ||\r
+ !negTokenTargLength)\r
+ return 10;\r
+\r
+ /* Does IIS reply with 1.2.840.48018.1.2.2 or 1.2.840.113554.1.2.2? */\r
+\r
+ /* Does IIS always reply with accept_completed? */\r
+\r
+ /* IIS does not include a MIC. */\r
+\r
+ rc2 = spnegoCreateNegTokenTarg (spnego_mech_oid_Kerberos_V5_Legacy,\r
+ spnego_negresult_success,\r
+ (unsigned char *) kerberosToken,\r
+ kerberosTokenLength,\r
+ NULL,\r
+ 0,\r
+ &hSpnegoToken);\r
+\r
+ if (rc2 != SPNEGO_E_SUCCESS)\r
+ {\r
+ rc1 = abs(rc2)+100;\r
+ goto cleanup;\r
+ }\r
+\r
+ /* Get NegTokenTarg length. */\r
+\r
+ rc2 = spnegoTokenGetBinary (hSpnegoToken,\r
+ NULL,\r
+ (unsigned long*) negTokenTargLength);\r
+\r
+ if (rc2 != SPNEGO_E_BUFFER_TOO_SMALL)\r
+ {\r
+ rc1 = abs(rc2)+200;\r
+ goto cleanup;\r
+ }\r
+\r
+ *negTokenTarg = malloc (*negTokenTargLength);\r
+\r
+ if (!*negTokenTarg)\r
+ {\r
+ rc1 = abs(rc2)+300;\r
+ goto cleanup;\r
+ }\r
+\r
+ /* Get NegTokenTarg data. */\r
+\r
+ rc2 = spnegoTokenGetBinary (hSpnegoToken,\r
+ (unsigned char *) *negTokenTarg,\r
+ (unsigned long*) negTokenTargLength);\r
+\r
+\r
+ if (rc2 != SPNEGO_E_SUCCESS)\r
+ {\r
+ rc1 = abs(rc2)+400;\r
+ goto error;\r
+ }\r
+\r
+ rc1 = 0;\r
+\r
+ goto cleanup;\r
+\r
+error:\r
+\r
+ if (*negTokenTarg)\r
+ {\r
+ free ((unsigned char *) *negTokenTarg);\r
+ *negTokenTarg = NULL;\r
+ *negTokenTargLength = 0;\r
+ }\r
+\r
+cleanup:\r
+\r
+ if (hSpnegoToken)\r
+ spnegoFreeData (hSpnegoToken);\r
+\r
+ LOG(("makeNegTokenTarg returned %d\n",rc1));\r
+ return rc1;\r
+}\r
+\r
+int parseNegTokenInit (const unsigned char * negTokenInit,\r
+ size_t negTokenInitLength,\r
+ const unsigned char ** kerberosToken,\r
+ size_t * kerberosTokenLength)\r
+{\r
+ SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL;\r
+ int pindex = -1;\r
+ int rc1 = 1;\r
+ int rc2 = SPNEGO_E_SUCCESS;\r
+ unsigned char reqFlags = 0;\r
+ int tokenType = 0;\r
+\r
+ /* Check arguments. */\r
+\r
+ if (!negTokenInit ||\r
+ !kerberosToken ||\r
+ !kerberosTokenLength)\r
+ return 10;\r
+\r
+ /* Decode SPNEGO token. */\r
+\r
+ rc2 = spnegoInitFromBinary ((unsigned char *) negTokenInit,\r
+ negTokenInitLength,\r
+ &hSpnegoToken);\r
+\r
+ if (rc2 != SPNEGO_E_SUCCESS)\r
+ {\r
+ rc1 = abs(rc2)+100;\r
+ goto cleanup;\r
+ }\r
+\r
+ /* Check for negTokenInit choice. */\r
+\r
+ rc2 = spnegoGetTokenType (hSpnegoToken,\r
+ &tokenType);\r
+\r
+ if (rc2 != SPNEGO_E_SUCCESS)\r
+ {\r
+ rc1 = abs(rc2)+200;\r
+ goto cleanup;\r
+ }\r
+\r
+ if (tokenType != SPNEGO_TOKEN_INIT)\r
+ {\r
+ rc1 = abs(rc2)+300;\r
+ goto cleanup;\r
+ }\r
+\r
+ /*\r
+ Check that first mechType is 1.2.840.113554.1.2.2 or 1.2.840.48018.1.2.2.\r
+ */\r
+\r
+ /*\r
+ IE seems to reply with 1.2.840.48018.1.2.2 and then 1.2.840.113554.1.2.2.\r
+ */\r
+\r
+ rc2 = spnegoIsMechTypeAvailable (hSpnegoToken,\r
+ spnego_mech_oid_Kerberos_V5_Legacy,\r
+ &pindex);\r
+\r
+ if (rc2 != SPNEGO_E_SUCCESS ||\r
+ pindex != 0)\r
+ {\r
+ rc2 = spnegoIsMechTypeAvailable (hSpnegoToken,\r
+ spnego_mech_oid_Kerberos_V5,\r
+ &pindex);\r
+\r
+ if (rc2 != SPNEGO_E_SUCCESS ||\r
+ pindex != 0)\r
+ {\r
+ rc1 = abs(rc2)+400;\r
+ goto cleanup;\r
+ }\r
+ }\r
+\r
+ /* Check for no reqFlags. */\r
+\r
+ /* Does IE ever send reqFlags? */\r
+\r
+ rc2 = spnegoGetContextFlags (hSpnegoToken,\r
+ &reqFlags);\r
+\r
+ if (rc2 == SPNEGO_E_SUCCESS)\r
+ {\r
+ rc1 = abs(rc2)+500;\r
+ goto cleanup;\r
+ }\r
+\r
+ /* Get mechanism token length. */\r
+\r
+ rc2 = spnegoGetMechToken (hSpnegoToken,\r
+ NULL,\r
+ (unsigned long*) kerberosTokenLength);\r
+\r
+ if (rc2 != SPNEGO_E_BUFFER_TOO_SMALL)\r
+ {\r
+ rc1 = abs(rc2)+600;\r
+ goto cleanup;\r
+ }\r
+\r
+ *kerberosToken = malloc (*kerberosTokenLength);\r
+\r
+ if (!*kerberosToken)\r
+ {\r
+ rc1 = abs(rc2)+700;\r
+ goto cleanup;\r
+ }\r
+\r
+ /* Get mechanism token data. */\r
+\r
+ rc2 = spnegoGetMechToken (hSpnegoToken,\r
+ (unsigned char *) *kerberosToken,\r
+ (unsigned long*) kerberosTokenLength);\r
+\r
+ if (rc2 != SPNEGO_E_SUCCESS)\r
+ {\r
+ rc1 = abs(rc2)+800;\r
+ goto error;\r
+ }\r
+\r
+ /* According to Microsoft, IE does not send a MIC. */\r
+\r
+ rc1 = 0;\r
+\r
+ goto cleanup;\r
+\r
+error:\r
+\r
+ if (*kerberosToken)\r
+ {\r
+ free ((unsigned char *) *kerberosToken);\r
+ *kerberosToken = NULL;\r
+ *kerberosTokenLength = 0;\r
+ }\r
+\r
+cleanup:\r
+\r
+ if (hSpnegoToken)\r
+ spnegoFreeData (hSpnegoToken);\r
+\r
+ LOG(("parseNegTokenInit returned %d\n",rc1));\r
+ return rc1;\r
+}\r
-/* -----------------------------------------------------------------------------
- * spnegohelp.c declares RFC 2478 SPNEGO GSS-API mechanism APIs.
- *
- * Author: Frank Balluffi
- *
- * Copyright (C) 2002-2003. All rights reserved.
- * -----------------------------------------------------------------------------
- */
-
-#ifndef SPNEGOHELP_H
-#define SPNEGOHELP_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stddef.h>
-
-/* -----------------------------------------------------------------------------
- * makeNegTokenTarg makes an RFC 2478 SPNEGO NegTokenTarg (token) from an
- * RFC 1964 Kerberos GSS-API token.
- *
- * If makeNegTokenTarg is successful, call free (*negTokenTarg) to free the
- * memory allocated by parseNegTokenInit.
- *
- * Returns 0 if successful, 1 otherwise.
- * -----------------------------------------------------------------------------
- */
-
-int makeNegTokenTarg (const unsigned char * kerberosToken,
- size_t kerberosTokenLength,
- const unsigned char ** negTokenTarg,
- size_t * negTokenTargLength);
-
-/* -----------------------------------------------------------------------------
- * parseNegTokenInit parses an RFC 2478 SPNEGO NegTokenInit (token) to extract
- * an RFC 1964 Kerberos GSS-API token.
- *
- * If the NegTokenInit does cotain a Kerberos GSS-API token, parseNegTokenInit
- * returns an error.
- *
- * If parseNegTokenInit is successful, call free (*kerberosToken) to
- * free the memory allocated by parseNegTokenInit.
- *
- * Returns 0 if successful, 1 otherwise.
- * -----------------------------------------------------------------------------
- */
-
-int parseNegTokenInit (const unsigned char * negTokenInit,
- size_t negTokenInitLength,
- const unsigned char ** kerberosToken,
- size_t * kerberosTokenLength);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* SPNEGOHELP_H */
+/* -----------------------------------------------------------------------------\r
+ * spnegohelp.c declares RFC 2478 SPNEGO GSS-API mechanism APIs.\r
+ *\r
+ * Author: Frank Balluffi\r
+ *\r
+ * Copyright (C) 2002-2003. All rights reserved.\r
+ * -----------------------------------------------------------------------------\r
+ */\r
+\r
+#ifndef SPNEGOHELP_H\r
+#define SPNEGOHELP_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include <stddef.h>\r
+\r
+/* -----------------------------------------------------------------------------\r
+ * makeNegTokenTarg makes an RFC 2478 SPNEGO NegTokenTarg (token) from an\r
+ * RFC 1964 Kerberos GSS-API token.\r
+ *\r
+ * If makeNegTokenTarg is successful, call free (*negTokenTarg) to free the\r
+ * memory allocated by parseNegTokenInit.\r
+ *\r
+ * Returns 0 if successful, 1 otherwise.\r
+ * -----------------------------------------------------------------------------\r
+ */\r
+\r
+int makeNegTokenTarg (const unsigned char * kerberosToken,\r
+ size_t kerberosTokenLength,\r
+ const unsigned char ** negTokenTarg,\r
+ size_t * negTokenTargLength);\r
+\r
+/* -----------------------------------------------------------------------------\r
+ * parseNegTokenInit parses an RFC 2478 SPNEGO NegTokenInit (token) to extract\r
+ * an RFC 1964 Kerberos GSS-API token.\r
+ *\r
+ * If the NegTokenInit does cotain a Kerberos GSS-API token, parseNegTokenInit\r
+ * returns an error.\r
+ *\r
+ * If parseNegTokenInit is successful, call free (*kerberosToken) to\r
+ * free the memory allocated by parseNegTokenInit.\r
+ *\r
+ * Returns 0 if successful, 1 otherwise.\r
+ * -----------------------------------------------------------------------------\r
+ */\r
+\r
+int parseNegTokenInit (const unsigned char * negTokenInit,\r
+ size_t negTokenInitLength,\r
+ const unsigned char ** kerberosToken,\r
+ size_t * kerberosTokenLength);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* SPNEGOHELP_H */\r
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
+ * As a special exemption, M Moeller gives permission to link this program
+ * with MIT, Heimdal or other GSS/Kerberos libraries, and distribute
+ * the resulting executable, without including the source code for
+ * the Libraries in the source distribution.
+ *
* -----------------------------------------------------------------------------
*/
/*
#include <time.h>
#include <sys/time.h>
+#include "config.h"
+
+#ifdef HAVE_SQUID
+#ifdef PACKAGE
+#undef PACKAGE
+#endif
+#ifdef PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#endif
+#ifdef PACKAGE_NAME
+#undef PACKAGE_NAME
+#endif
+#ifdef PACKAGE_STRING
+#undef PACKAGE_STRING
+#endif
+#ifdef PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#endif
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
+#ifdef VERSION
+#undef VERSION
+#endif
+#ifdef HAVE_GETADDRINFO_H
#include "getaddrinfo.h"
+#endif
+#ifdef HAVE_GETNAMEINFO_H
#include "getnameinfo.h"
+#endif
+#ifdef HAVE_UTIL_H
+#include "util.h"
+#endif
+#ifdef PACKAGE
+#undef PACKAGE
+#endif
+#ifdef PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#endif
+#ifdef PACKAGE_NAME
+#undef PACKAGE_NAME
+#endif
+#ifdef PACKAGE_STRING
+#undef PACKAGE_STRING
+#endif
+#ifdef PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#endif
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
+#ifdef VERSION
+#undef VERSION
+#endif
+/*
+ * Reset varibles
+ */
+#include "config.h"
+#endif
+#if !defined(HAVE_DECL_XGETADDRINFO) || !HAVE_DECL_XGETADDRINFO
+#define xgetaddrinfo getaddrinfo
+#endif
+#if !defined(HAVE_DECL_XFREEADDRINFO) || !HAVE_DECL_XFREEADDRINFO
+#define xfreeaddrinfo freeaddrinfo
+#endif
+#if !defined(HAVE_DECL_XGAI_STRERROR) || !HAVE_DECL_XGAI_STRERROR
+#define xgai_strerror gai_strerror
+#endif
+#if !defined(HAVE_DECL_XGETNAMEINFO) || !HAVE_DECL_XGETNAMEINFO
+#define xgetnameinfo getnameinfo
+#endif
+#if !defined(HAVE_DECL_XMALLOC) || !HAVE_DECL_XMALLOC
+#define xmalloc malloc
+#endif
+#if !defined(HAVE_DECL_XSTRDUP) || !HAVE_DECL_XSTRDUP
+#define xstrdup strdup
+#endif
+#if !defined(HAVE_DECL_XFREE) || !HAVE_DECL_XFREE
+#define xfree free
+#endif
#include "base64.h"
#ifndef HAVE_SPNEGO
#include "spnegohelp.h"
#endif
-// AYJ: must match the definition in src/auth/negotiate/auth_negotiate.cc
-#define MAX_AUTHTOKEN_LEN 32768
-
-// AYJ: match define in include/rfc2181.h
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 256
-#endif
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN HOST_NAME_MAX
-#endif
-
#define PROGRAM "squid_kerb_auth"
-#ifdef HEIMDAL
-#include <gssapi.h>
-#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
-#else
-#include <gssapi/gssapi.h>
-#ifndef SOLARIS_11
-#include <gssapi/gssapi_generic.h>
-#else
-#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
-#endif
+
+#ifndef MAX_AUTHTOKEN_LEN
+#define MAX_AUTHTOKEN_LEN 65535
#endif
-#include <krb5.h>
-int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int loging);
+int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int log);
char *gethost_name(void);
static const char *LogTime(void);
gettimeofday(&now, NULL);
if (now.tv_sec != last_t) {
- tm = localtime(&now.tv_sec);
+ tm = localtime((time_t *)&now.tv_sec);
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
last_t = now.tv_sec;
}
return buf;
}
-// AYJ: this looks like a duplicate of the lib/gethostname function */
char *gethost_name(void) {
- char hostname[MAXHOSTNAMELEN];
+ char hostname[sysconf(_SC_HOST_NAME_MAX)];
struct addrinfo *hres=NULL, *hres_list;
int rc,count;
- rc = gethostname(hostname,MAXHOSTNAMELEN);
+ rc = gethostname(hostname,sysconf(_SC_HOST_NAME_MAX));
if (rc)
{
fprintf(stderr, "%s| %s: error while resolving hostname '%s'\n", LogTime(), PROGRAM, hostname);
rc = xgetaddrinfo(hostname,NULL,NULL,&hres);
if (rc != 0) {
fprintf(stderr, "%s| %s: error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc));
- xfreeaddrinfo(hres);
return NULL;
}
hres_list=hres;
count++;
hres_list=hres_list->ai_next;
}
- rc = xgetnameinfo(hres->ai_addr, hres->ai_addrlen,hostname, sizeof (hostname), NULL, 0, 0);
+ rc = xgetnameinfo (hres->ai_addr, hres->ai_addrlen,hostname, sizeof (hostname), NULL, 0, 0);
if (rc != 0) {
fprintf(stderr, "%s| %s: error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc));
xfreeaddrinfo(hres);
}
xfreeaddrinfo(hres);
- hostname[MAXHOSTNAMELEN]='\0';
- return(strdup(hostname));
+ hostname[sysconf(_SC_HOST_NAME_MAX)-1]='\0';
+ return(xstrdup(hostname));
}
-int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int loging) {
+int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int log) {
if (GSS_ERROR(major_status)) {
OM_uint32 maj_stat,min_stat;
OM_uint32 msg_ctx = 0;
}
gss_release_buffer(&min_stat, &status_string);
}
- if (debug)
+ if (debug)
fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
- fprintf(stdout, "NA %s failed: %s\n",function, buf);
- if (loging)
+ fprintf(stdout, "BH %s failed: %s\n",function, buf);
+ if (log)
fprintf(stderr, "%s| %s: User not authenticated\n", LogTime(), PROGRAM);
return(1);
}
return(0);
}
+
+
int main(int argc, char * const argv[])
{
char buf[MAX_AUTHTOKEN_LEN];
char *c;
int length=0;
static int err=0;
- int opt, rc, debug=0, loging=0;
+ int opt, debug=0, log=0;
+#ifndef HAVE_SPNEGO
+ int rc;
+#endif
OM_uint32 ret_flags=0, spnego_flag=0;
char *service_name=(char *)"HTTP",*host_name=NULL;
char *token = NULL;
gss_name_t client_name = GSS_C_NO_NAME;
gss_name_t server_name = GSS_C_NO_NAME;
gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL;
- gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
const unsigned char *kerberosToken = NULL;
+#ifndef HAVE_SPNEGO
size_t kerberosTokenLength = 0;
+#endif
const unsigned char *spnegoToken = NULL ;
size_t spnegoTokenLength = 0;
debug = 1;
break;
case 'i':
- loging = 1;
+ log = 1;
break;
case 's':
- service_principal = strdup(optarg);
+ service_principal = xstrdup(optarg);
break;
case 'h':
- fprintf(stdout, "Usage: \n");
- fprintf(stdout, "squid_kerb_auth -d [-s SPN]\n");
- fprintf(stdout, "SPN = service principal name\n");
- fprintf(stdout, "Can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
- fprintf(stdout, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
- break;
+ fprintf(stderr, "Usage: \n");
+ fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-h]\n");
+ fprintf(stderr, "-d full debug\n");
+ fprintf(stderr, "-i informational messages\n");
+ fprintf(stderr, "-s service principal name\n");
+ fprintf(stderr, "-h help\n");
+ fprintf(stderr, "The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
+ fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
+ exit(0);
default:
fprintf(stderr, "%s| %s: unknown option: -%c.\n", LogTime(), PROGRAM, opt);
}
}
+ if (debug)
+ fprintf(stderr, "%s| %s: Starting version %s\n", LogTime(), PROGRAM, VERSION);
if (service_principal && strcasecmp(service_principal,"GSS_C_NO_NAME") ) {
service.value = service_principal;
service.length = strlen((char *)service.value);
host_name=gethost_name();
if ( !host_name ) {
fprintf(stderr, "%s| %s: Local hostname could not be determined. Please specify the service principal\n", LogTime(), PROGRAM);
+ fprintf(stdout, "BH hostname error\n");
exit(-1);
}
- service.value = malloc(strlen(service_name)+strlen(host_name)+2);
+ service.value = xmalloc(strlen(service_name)+strlen(host_name)+2);
snprintf(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",service_name,host_name);
service.length = strlen((char *)service.value);
}
fprintf(stderr, "%s| %s: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin),
strerror(ferror(stdin)));
+ fprintf(stdout, "BH input error\n");
exit(1); /* BIIG buffer */
}
+ fprintf(stdout, "BH input error\n");
exit(0);
}
if (err) {
if (debug)
fprintf(stderr, "%s| %s: Oversized message\n", LogTime(), PROGRAM);
- fprintf(stdout, "NA Oversized message\n");
+ fprintf(stdout, "BH Oversized message\n");
err = 0;
continue;
}
if (debug)
- fprintf(stderr, "%s| %s: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf?buf:"NULL",length);
+ fprintf(stderr, "%s| %s: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf,length);
if (buf[0] == '\0') {
if (debug)
fprintf(stderr, "%s| %s: Invalid request\n", LogTime(), PROGRAM);
- fprintf(stdout, "NA Invalid request\n");
+ fprintf(stdout, "BH Invalid request\n");
continue;
}
if (strlen(buf) < 2) {
if (debug)
fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
- fprintf(stdout, "NA Invalid request\n");
+ fprintf(stdout, "BH Invalid request\n");
continue;
}
gss_release_buffer(&minor_status, &output_token);
gss_release_buffer(&minor_status, &service);
gss_release_cred(&minor_status, &server_creds);
- gss_release_cred(&minor_status, &delegated_cred);
- gss_release_name(&minor_status, &server_name);
- gss_release_name(&minor_status, &client_name);
- gss_delete_sec_context(&minor_status, &gss_context, NULL);
+ if (server_name)
+ gss_release_name(&minor_status, &server_name);
+ if (client_name)
+ gss_release_name(&minor_status, &client_name);
+ if (gss_context != GSS_C_NO_CONTEXT )
+ gss_delete_sec_context(&minor_status, &gss_context, NULL);
if (kerberosToken) {
/* Allocated by parseNegTokenInit, but no matching free function exists.. */
if (!spnego_flag)
- free((char *)kerberosToken);
+ xfree((char *)kerberosToken);
kerberosToken=NULL;
}
if (spnego_flag) {
/* Allocated by makeNegTokenTarg, but no matching free function exists.. */
if (spnegoToken)
- free((char *)spnegoToken);
+ xfree((char *)spnegoToken);
spnegoToken=NULL;
}
if (token) {
- free(token);
+ xfree(token);
token=NULL;
}
if (host_name) {
- free(host_name);
+ xfree(host_name);
host_name=NULL;
}
+ fprintf(stdout, "BH quit command\n");
exit(0);
}
- if ( !strncmp(buf, "YR", 2) && !strncmp(buf, "KK", 2) ) {
+ if ( strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2) ) {
if (debug)
fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
- fprintf(stdout, "NA Invalid request\n");
+ fprintf(stdout, "BH Invalid request\n");
continue;
}
if ( !strncmp(buf, "YR", 2) ){
if (strlen(buf) <= 3) {
if (debug)
fprintf(stderr, "%s| %s: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf);
- fprintf(stdout, "NA Invalid negotiate request\n");
+ fprintf(stdout, "BH Invalid negotiate request\n");
continue;
}
- input_token.length = base64_decode_len(buf+3);
- input_token.value = malloc(input_token.length);
+ input_token.length = ska_base64_decode_len(buf+3);
+ if (debug)
+ fprintf(stderr, "%s| %s: Decode '%s' (decoded length: %d).\n", LogTime(), PROGRAM, buf+3,(int)input_token.length);
+ input_token.value = xmalloc(input_token.length);
- base64_decode(input_token.value,buf+3,input_token.length);
+ ska_base64_decode(input_token.value,buf+3,input_token.length);
#ifndef HAVE_SPNEGO
if ( rc < 100 || rc > 199 ) {
if (debug)
fprintf(stderr, "%s| %s: Invalid GSS-SPNEGO query [%s]\n", LogTime(), PROGRAM, buf);
- fprintf(stdout, "NA Invalid GSS-SPNEGO query\n");
+ fprintf(stdout, "BH Invalid GSS-SPNEGO query\n");
goto cleanup;
}
if ((input_token.length >= sizeof ntlmProtocol + 1) &&
(!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
if (debug)
fprintf(stderr, "%s| %s: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
- fprintf(stdout, "NA received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
+ fprintf(stdout, "BH received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
goto cleanup;
}
+ if (debug)
+ fprintf(stderr, "%s| %s: Token is possibly a GSSAPI token\n", LogTime(), PROGRAM);
spnego_flag=0;
} else {
gss_release_buffer(&minor_status, &input_token);
(!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
if (debug)
fprintf(stderr, "%s| %s: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
- fprintf(stdout, "NA received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
+ fprintf(stdout, "BH received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
goto cleanup;
}
#endif
gss_nt_service_name, &server_name);
}
- if ( check_gss_err(major_status,minor_status,"gss_import_name()",debug,loging) )
+ if ( check_gss_err(major_status,minor_status,"gss_import_name()",debug,log) )
goto cleanup;
major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds,
NULL, NULL);
- if (check_gss_err(major_status,minor_status,"gss_acquire_cred()",debug,loging) )
+ if (check_gss_err(major_status,minor_status,"gss_acquire_cred()",debug,log) )
goto cleanup;
major_status = gss_accept_sec_context(&minor_status,
&output_token,
&ret_flags,
NULL,
- &delegated_cred);
+ NULL);
if (output_token.length) {
&spnegoTokenLength))!=0 ) {
if (debug)
fprintf(stderr, "%s| %s: makeNegTokenTarg failed with rc=%d\n", LogTime(), PROGRAM, rc);
- fprintf(stdout, "NA makeNegTokenTarg failed with rc=%d\n",rc);
+ fprintf(stdout, "BH makeNegTokenTarg failed with rc=%d\n",rc);
goto cleanup;
}
} else {
spnegoToken = output_token.value;
spnegoTokenLength = output_token.length;
#endif
- token = malloc(base64_encode_len(spnegoTokenLength));
+ token = xmalloc(ska_base64_encode_len(spnegoTokenLength));
if (token == NULL) {
if (debug)
fprintf(stderr, "%s| %s: Not enough memory\n", LogTime(), PROGRAM);
- fprintf(stdout, "NA Not enough memory\n");
+ fprintf(stdout, "BH Not enough memory\n");
goto cleanup;
}
- base64_encode(token,(const char *)spnegoToken,base64_encode_len(spnegoTokenLength),spnegoTokenLength);
+ ska_base64_encode(token,(const char *)spnegoToken,ska_base64_encode_len(spnegoTokenLength),spnegoTokenLength);
- if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,loging) )
+ if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,log) )
goto cleanup;
if (major_status & GSS_S_CONTINUE_NEEDED) {
if (debug)
major_status = gss_display_name(&minor_status, client_name, &output_token,
NULL);
- if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,loging) )
+ if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,log) )
goto cleanup;
fprintf(stdout, "AF %s %s\n",token,(char *)output_token.value);
if (debug)
fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, token,(char *)output_token.value);
- if (loging)
+ if (log)
fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, (char *)output_token.value);
goto cleanup;
} else {
- if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,loging) )
+ if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,log) )
goto cleanup;
if (major_status & GSS_S_CONTINUE_NEEDED) {
if (debug)
fprintf(stderr, "%s| %s: continuation needed\n", LogTime(), PROGRAM);
- fprintf(stdout, "NA No token to return to continue\n");
+ fprintf(stdout, "NA %s\n",token);
goto cleanup;
}
gss_release_buffer(&minor_status, &output_token);
major_status = gss_display_name(&minor_status, client_name, &output_token,
NULL);
- if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,loging) )
+ if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,log) )
goto cleanup;
/*
* Return dummy token AA. May need an extra return tag then AF
fprintf(stdout, "AF %s %s\n","AA==",(char *)output_token.value);
if (debug)
fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, "AA==", (char *)output_token.value);
- if (loging)
+ if (log)
fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, (char *)output_token.value);
cleanup:
gss_release_buffer(&minor_status, &input_token);
gss_release_buffer(&minor_status, &output_token);
gss_release_cred(&minor_status, &server_creds);
- gss_release_cred(&minor_status, &delegated_cred);
- gss_release_name(&minor_status, &server_name);
- gss_release_name(&minor_status, &client_name);
+ if (server_name)
+ gss_release_name(&minor_status, &server_name);
+ if (client_name)
+ gss_release_name(&minor_status, &client_name);
if (kerberosToken) {
/* Allocated by parseNegTokenInit, but no matching free function exists.. */
if (!spnego_flag)
- free((char *)kerberosToken);
+ xfree((char *)kerberosToken);
kerberosToken=NULL;
}
if (spnego_flag) {
/* Allocated by makeNegTokenTarg, but no matching free function exists.. */
if (spnegoToken)
- free((char *)spnegoToken);
+ xfree((char *)spnegoToken);
spnegoToken=NULL;
}
if (token) {
- free(token);
+ xfree(token);
token=NULL;
}
continue;
--- /dev/null
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * Author: Markus Moeller (markus_moeller at compuserve.com)
+ *
+ * Copyright (C) 2007 Markus Moeller. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * -----------------------------------------------------------------------------
+ */
+/*
+ * Hosted at http://sourceforge.net/projects/squidkerbauth
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include "config.h"
+
+#ifdef HAVE_SQUID
+#ifdef PACKAGE
+#undef PACKAGE
+#endif
+#ifdef PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#endif
+#ifdef PACKAGE_NAME
+#undef PACKAGE_NAME
+#endif
+#ifdef PACKAGE_STRING
+#undef PACKAGE_STRING
+#endif
+#ifdef PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#endif
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
+#ifdef VERSION
+#undef VERSION
+#endif
+#ifdef HAVE_UTIL_H
+#include "util.h"
+#endif
+#ifdef PACKAGE
+#undef PACKAGE
+#endif
+#ifdef PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#endif
+#ifdef PACKAGE_NAME
+#undef PACKAGE_NAME
+#endif
+#ifdef PACKAGE_STRING
+#undef PACKAGE_STRING
+#endif
+#ifdef PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#endif
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
+#ifdef VERSION
+#undef VERSION
+#endif
+/*
+ * Reset varibles
+ */
+#include "config.h"
+#endif
+#if !defined(HAVE_DECL_XMALLOC) || !HAVE_DECL_XMALLOC
+#define xmalloc malloc
+#endif
+#if !defined(HAVE_DECL_XSTRDUP) || !HAVE_DECL_XSTRDUP
+#define xstrdup strdup
+#endif
+
+#include "base64.h"
+
+static const char *LogTime(void);
+
+int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function);
+
+const char *squid_kerb_proxy_auth(char *proxy);
+
+#define PROGRAM "squid_kerb_auth_test"
+
+static const char *LogTime()
+{
+ struct tm *tm;
+ struct timeval now;
+ static time_t last_t = 0;
+ static char buf[128];
+
+ gettimeofday(&now, NULL);
+ if (now.tv_sec != last_t) {
+ tm = localtime(&now.tv_sec);
+ strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
+ last_t = now.tv_sec;
+ }
+ return buf;
+}
+
+#ifdef HAVE_SPNEGO
+#ifndef gss_mech_spnego
+static gss_OID_desc _gss_mech_spnego = {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
+gss_OID gss_mech_spnego = &_gss_mech_spnego;
+#endif
+#endif
+
+int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function){
+ if (GSS_ERROR(major_status)) {
+ OM_uint32 maj_stat,min_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+ char buf[1024];
+ size_t len;
+
+ len = 0;
+ msg_ctx = 0;
+ while (!msg_ctx) {
+ /* convert major status code (GSS-API error) to text */
+ maj_stat = gss_display_status(&min_stat, major_status,
+ GSS_C_GSS_CODE,
+ GSS_C_NULL_OID,
+ &msg_ctx, &status_string);
+ if (maj_stat == GSS_S_COMPLETE) {
+ if (sizeof(buf) > len + status_string.length + 1) {
+ sprintf(buf+len, "%s", (char*) status_string.value);
+ len += status_string.length;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ break;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ }
+ if (sizeof(buf) > len + 2) {
+ sprintf(buf+len, "%s", ". ");
+ len += 2;
+ }
+ msg_ctx = 0;
+ while (!msg_ctx) {
+ /* convert minor status code (underlying routine error) to text */
+ maj_stat = gss_display_status(&min_stat, minor_status,
+ GSS_C_MECH_CODE,
+ GSS_C_NULL_OID,
+ &msg_ctx, &status_string);
+ if (maj_stat == GSS_S_COMPLETE) {
+ if (sizeof(buf) > len + status_string.length ) {
+ sprintf(buf+len, "%s", (char*) status_string.value);
+ len += status_string.length;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ break;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ }
+ fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
+ return(1);
+ }
+ return(0);
+}
+
+const char *squid_kerb_proxy_auth(char *proxy) {
+ OM_uint32 major_status, minor_status;
+ gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
+ gss_name_t server_name = GSS_C_NO_NAME;
+ gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+ char *token = NULL;
+
+ setbuf(stdout,NULL);
+ setbuf(stdin,NULL);
+
+ if (!proxy ) {
+ fprintf(stderr, "%s| %s: Error: No proxy server name\n", LogTime(), PROGRAM);
+ return NULL;
+ }
+
+ service.value = xmalloc(strlen("HTTP")+strlen(proxy)+2);
+ snprintf(service.value,strlen("HTTP")+strlen(proxy)+2,"%s@%s","HTTP",proxy);
+ service.length = strlen((char *)service.value);
+
+ major_status = gss_import_name(&minor_status, &service,
+ gss_nt_service_name, &server_name);
+
+ if (check_gss_err(major_status,minor_status,"gss_import_name()") )
+ goto cleanup;
+
+ major_status = gss_init_sec_context(&minor_status,
+ GSS_C_NO_CREDENTIAL,
+ &gss_context,
+ server_name,
+#ifdef HAVE_SPNEGO
+ gss_mech_spnego,
+#else
+ 0,
+#endif
+ 0,
+ 0,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &input_token,
+ NULL,
+ &output_token,
+ NULL,
+ NULL);
+
+ if (check_gss_err(major_status,minor_status,"gss_init_sec_context()") )
+ goto cleanup;
+
+ if (output_token.length) {
+ token=xmalloc(ska_base64_encode_len(output_token.length));
+ ska_base64_encode(token,(const char*)output_token.value,ska_base64_encode_len(output_token.length),output_token.length);
+ }
+
+
+cleanup:
+ gss_delete_sec_context(&minor_status, &gss_context, NULL);
+ gss_release_buffer(&minor_status, &service);
+ gss_release_buffer(&minor_status, &input_token);
+ gss_release_buffer(&minor_status, &output_token);
+ gss_release_name(&minor_status, &server_name);
+
+ return token;
+}
+
+int main(int argc, char *argv[]) {
+
+ const char *Token;
+
+ if (argc < 1) {
+ fprintf(stderr, "%s| %s: Error: No proxy server name given\n", LogTime(), PROGRAM);
+ exit(99);
+ }
+ Token = (const char *)squid_kerb_proxy_auth(argv[1]);
+ fprintf(stdout,"Token: %s\n",Token?Token:"NULL");
+
+ exit(0);
+}
+