autofs-5.0.6 - add sss lookup module From: Ian Kent Add a lookup module (initial implementation) to handle lookups for an sssd source. The % hack for mixed case map keys present in case insensitive schema still needs to be implemented. --- CHANGELOG | 1 Makefile.conf.in | 6 aclocal.m4 | 24 ++ configure | 238 ++++++++++-------- configure.in | 4 modules/Makefile | 6 modules/lookup_sss.c | 678 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 860 insertions(+), 97 deletions(-) create mode 100644 modules/lookup_sss.c diff --git a/CHANGELOG b/CHANGELOG index 918d35b..ba6f90c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,7 @@ - fix rpc build error. - fix improve mount location error reporting. - fix fix wait for master source mutex. +- add sss lookup module. 28/06/2011 autofs-5.0.6 ----------------------- diff --git a/Makefile.conf.in b/Makefile.conf.in index fa4936d..802318b 100644 --- a/Makefile.conf.in +++ b/Makefile.conf.in @@ -25,6 +25,9 @@ LDAP = @HAVE_LDAP@ LIBLDAP= @LIBLDAP@ LDAP_FLAGS = @LDAP_FLAGS@ +# sssd support +SSSD = @HAVE_SSS_AUTOFS@ + # SASL support: yes (1) no (0) XML_LIBS = @XML_LIBS@ XML_FLAGS = @XML_FLAGS@ @@ -70,6 +73,9 @@ DMALLOCLIB = @DMALLOCLIB@ prefix = @prefix@ exec_prefix = @exec_prefix@ +# SSS library module directory +ssslibdir=@sssldir@ + # Directory for autofs modules autofslibdir = @libdir@/autofs diff --git a/aclocal.m4 b/aclocal.m4 index 7cfc7ef..439d56f 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -32,6 +32,30 @@ fi AC_SUBST(PATH_$1)]) dnl -------------------------------------------------------------------------- +dnl AF_CHECK_SSS_LIB: +dnl +dnl Check if a sss autofs library exists. +dnl -------------------------------------------------------------------------- +AC_DEFUN(AF_CHECK_SSS_LIB, +[if test -z $sssldir; then + AC_MSG_CHECKING(for sssd autofs library) + for libd in /usr/lib64 /usr/lib; do + if test -z $sssldir; then + if test -e "$libd/sssd/modules/$2"; then + sssldir=$libd/sssd/modules + fi + fi + done + if test -n $sssldir; then + HAVE_$1=1 + AC_MSG_RESULT(yes) + else + HAVE_$1=0 + AC_MSG_RESULT(no) + fi +fi]) + +dnl -------------------------------------------------------------------------- dnl AF_SLOPPY_MOUNT dnl dnl Check to see if mount(8) supports the sloppy (-s) option, and define diff --git a/configure b/configure index 86a0d74..f78b322 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.66. +# Generated by GNU Autoconf 2.68. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -89,6 +89,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -214,11 +215,18 @@ IFS=$as_save_IFS # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : @@ -617,6 +625,8 @@ LIBRESOLV LIBNSL KRB5_CONFIG XML_CONFIG +sssldir +HAVE_SSS_AUTOFS PATH_RPCGEN RPCGEN PATH_RANLIB @@ -782,8 +792,9 @@ do fi case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -1123,7 +1134,7 @@ Try \`$0 --help' for more information" $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -1430,7 +1441,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.66 +generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation @@ -1476,7 +1487,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile @@ -1522,7 +1533,7 @@ fi # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link @@ -1548,7 +1559,7 @@ $as_echo "$ac_try_echo"; } >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } >/dev/null && { + test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : @@ -1559,7 +1570,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp @@ -1572,10 +1583,10 @@ fi ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval "test \"\${$3+set}\"" = set; then : + if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 @@ -1611,7 +1622,7 @@ if ac_fn_c_try_cpp "$LINENO"; then : else ac_header_preproc=no fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } @@ -1638,7 +1649,7 @@ $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" @@ -1647,7 +1658,7 @@ eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel @@ -1688,7 +1699,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run @@ -1702,7 +1713,7 @@ ac_fn_c_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1720,7 +1731,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile cat >config.log <<_ACEOF @@ -1728,7 +1739,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.66. Invocation command line was +generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2300,7 +2311,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2340,7 +2351,7 @@ if test -z "$ac_cv_prog_CC"; then set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2393,7 +2404,7 @@ if test -z "$CC"; then set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2433,7 +2444,7 @@ if test -z "$CC"; then set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2492,7 +2503,7 @@ if test -z "$CC"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2536,7 +2547,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2819,7 +2830,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : +if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2870,7 +2881,7 @@ OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2907,7 +2918,7 @@ ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag @@ -2985,7 +2996,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -3183,7 +3194,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_MOUNT+set}" = set; then : +if ${ac_cv_path_MOUNT+:} false; then : $as_echo_n "(cached) " >&6 else case $MOUNT in @@ -3243,7 +3254,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_UMOUNT+set}" = set; then : +if ${ac_cv_path_UMOUNT+:} false; then : $as_echo_n "(cached) " >&6 else case $UMOUNT in @@ -3303,7 +3314,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_E2FSCK+set}" = set; then : +if ${ac_cv_path_E2FSCK+:} false; then : $as_echo_n "(cached) " >&6 else case $E2FSCK in @@ -3362,7 +3373,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_E3FSCK+set}" = set; then : +if ${ac_cv_path_E3FSCK+:} false; then : $as_echo_n "(cached) " >&6 else case $E3FSCK in @@ -3421,7 +3432,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_E4FSCK+set}" = set; then : +if ${ac_cv_path_E4FSCK+:} false; then : $as_echo_n "(cached) " >&6 else case $E4FSCK in @@ -3480,7 +3491,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_MODPROBE+set}" = set; then : +if ${ac_cv_path_MODPROBE+:} false; then : $as_echo_n "(cached) " >&6 else case $MODPROBE in @@ -3540,7 +3551,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_LEX+set}" = set; then : +if ${ac_cv_path_LEX+:} false; then : $as_echo_n "(cached) " >&6 else case $LEX in @@ -3596,7 +3607,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_YACC+set}" = set; then : +if ${ac_cv_path_YACC+:} false; then : $as_echo_n "(cached) " >&6 else case $YACC in @@ -3652,7 +3663,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_RANLIB+set}" = set; then : +if ${ac_cv_path_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else case $RANLIB in @@ -3708,7 +3719,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_RPCGEN+set}" = set; then : +if ${ac_cv_path_RPCGEN+:} false; then : $as_echo_n "(cached) " >&6 else case $RPCGEN in @@ -3759,6 +3770,29 @@ else fi +if test -z $sssldir; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sssd autofs library" >&5 +$as_echo_n "checking for sssd autofs library... " >&6; } + for libd in /usr/lib64 /usr/lib; do + if test -z $sssldir; then + if test -e "$libd/sssd/modules/libsss_autofs.so"; then + sssldir=$libd/sssd/modules + fi + fi + done + if test -n $sssldir; then + HAVE_SSS_AUTOFS=1 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + HAVE_SSS_AUTOFS=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi +fi + + + # # Newer mounts have the -s (sloppy) option to ignore unknown options, # good for portability @@ -3785,7 +3819,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_XML_CONFIG+set}" = set; then : +if ${ac_cv_path_XML_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $XML_CONFIG in @@ -3860,7 +3894,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_KRB5_CONFIG+set}" = set; then : +if ${ac_cv_path_KRB5_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $KRB5_CONFIG in @@ -3920,7 +3954,7 @@ fi # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for yp_match in -lnsl" >&5 $as_echo_n "checking for yp_match in -lnsl... " >&6; } -if test "${ac_cv_lib_nsl_yp_match+set}" = set; then : +if ${ac_cv_lib_nsl_yp_match+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -3954,7 +3988,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_yp_match" >&5 $as_echo "$ac_cv_lib_nsl_yp_match" >&6; } -if test "x$ac_cv_lib_nsl_yp_match" = x""yes; then : +if test "x$ac_cv_lib_nsl_yp_match" = xyes; then : LIBNSL="-lnsl" fi @@ -3962,7 +3996,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5 $as_echo_n "checking for res_query in -lresolv... " >&6; } -if test "${ac_cv_lib_resolv_res_query+set}" = set; then : +if ${ac_cv_lib_resolv_res_query+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -3996,7 +4030,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_query" >&5 $as_echo "$ac_cv_lib_resolv_res_query" >&6; } -if test "x$ac_cv_lib_resolv_res_query" = x""yes; then : +if test "x$ac_cv_lib_resolv_res_query" = xyes; then : LIBRESOLV="-lresolv" fi @@ -4088,7 +4122,7 @@ if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then : + if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded @@ -4118,7 +4152,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4134,11 +4168,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -4177,7 +4211,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4193,11 +4227,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else @@ -4216,7 +4250,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then : +if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then @@ -4279,7 +4313,7 @@ $as_echo "$ac_cv_path_GREP" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then : +if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 @@ -4346,7 +4380,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -4474,7 +4508,7 @@ done ac_fn_c_check_header_mongrel "$LINENO" "rpcsvc/nis.h" "ac_cv_header_rpcsvc_nis_h" "$ac_includes_default" -if test "x$ac_cv_header_rpcsvc_nis_h" = x""yes; then : +if test "x$ac_cv_header_rpcsvc_nis_h" = xyes; then : HAVE_NISPLUS=1 fi @@ -4509,7 +4543,7 @@ if test -z "$HAVE_LDAP" -o "$HAVE_LDAP" != "0"; then LDAP_FLAGS="$LDAP_FLAGS -DLDAP_DEPRECATED=1" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_initialize in -lldap" >&5 $as_echo_n "checking for ldap_initialize in -lldap... " >&6; } -if test "${ac_cv_lib_ldap_ldap_initialize+set}" = set; then : +if ${ac_cv_lib_ldap_ldap_initialize+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4543,7 +4577,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_initialize" >&5 $as_echo "$ac_cv_lib_ldap_ldap_initialize" >&6; } -if test "x$ac_cv_lib_ldap_ldap_initialize" = x""yes; then : +if test "x$ac_cv_lib_ldap_ldap_initialize" = xyes; then : HAVE_LDAP=1 LIBLDAP="$LIBLDAP -lldap -llber -lresolv" fi @@ -4677,7 +4711,7 @@ then HAVE_SASL=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sasl_client_start in -lsasl2" >&5 $as_echo_n "checking for sasl_client_start in -lsasl2... " >&6; } -if test "${ac_cv_lib_sasl2_sasl_client_start+set}" = set; then : +if ${ac_cv_lib_sasl2_sasl_client_start+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4711,7 +4745,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sasl2_sasl_client_start" >&5 $as_echo "$ac_cv_lib_sasl2_sasl_client_start" >&6; } -if test "x$ac_cv_lib_sasl2_sasl_client_start" = x""yes; then : +if test "x$ac_cv_lib_sasl2_sasl_client_start" = xyes; then : HAVE_SASL=1 LIBSASL="$LIBSASL -lsasl2" fi @@ -4744,7 +4778,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -4784,7 +4818,7 @@ if test -z "$ac_cv_prog_CC"; then set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -4837,7 +4871,7 @@ if test -z "$CC"; then set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -4877,7 +4911,7 @@ if test -z "$CC"; then set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -4936,7 +4970,7 @@ if test -z "$CC"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -4980,7 +5014,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -5064,7 +5098,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -5101,7 +5135,7 @@ ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag @@ -5179,7 +5213,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -5432,7 +5466,7 @@ LTLIBOBJS=$ac_ltlibobjs -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" @@ -5533,6 +5567,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -5840,7 +5875,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.66. Invocation command line was +generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -5902,7 +5937,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.66, +configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. @@ -5920,11 +5955,16 @@ ac_need_defaults=: while test $# != 0 do case $1 in - --*=*) + --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; *) ac_option=$1 ac_optarg=$2 @@ -5946,6 +5986,7 @@ do $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; @@ -6041,9 +6082,10 @@ fi # after its creation but before its name has been assigned to `$tmp'. $debug || { - tmp= + tmp= ac_tmp= trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } @@ -6051,12 +6093,13 @@ $debug || { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -6078,7 +6121,7 @@ else ac_cs_awk_cr=$ac_cr fi -echo 'BEGIN {' >"$tmp/subs1.awk" && +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF @@ -6106,7 +6149,7 @@ done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h @@ -6154,7 +6197,7 @@ t delim rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" @@ -6186,7 +6229,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF @@ -6220,7 +6263,7 @@ fi # test -n "$CONFIG_FILES" # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then -cat >"$tmp/defines.awk" <<\_ACAWK || +cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF @@ -6232,8 +6275,8 @@ _ACEOF # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do - ac_t=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_t"; then + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 @@ -6353,7 +6396,7 @@ do for ac_f do case $ac_f in - -) ac_f="$tmp/stdin";; + -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. @@ -6388,7 +6431,7 @@ $as_echo "$as_me: creating $ac_file" >&6;} esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ + *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; @@ -6514,21 +6557,22 @@ s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} - rm -f "$tmp/stdin" + rm -f "$ac_tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; @@ -6539,20 +6583,20 @@ which seems to be undefined. Please make sure it is defined" >&2;} if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" - } >"$tmp/config.h" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" - mv "$tmp/config.h" "$ac_file" \ + mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; diff --git a/configure.in b/configure.in index 05ee67f..c017829 100644 --- a/configure.in +++ b/configure.in @@ -148,6 +148,10 @@ AF_CHECK_PROG(YACC, bison, , $searchpath) AF_CHECK_PROG(RANLIB, ranlib, , $searchpath) AF_CHECK_PROG(RPCGEN, rpcgen, , $searchpath) +AF_CHECK_SSS_LIB(SSS_AUTOFS, libsss_autofs.so) +AC_SUBST(HAVE_SSS_AUTOFS) +AC_SUBST(sssldir) + # # Newer mounts have the -s (sloppy) option to ignore unknown options, # good for portability diff --git a/modules/Makefile b/modules/Makefile index 6090127..939da7c 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -47,6 +47,12 @@ ifeq ($(LDAP), 1) endif endif +ifeq ($(SSSD), 1) + CFLAGS += -DSSS_LIB_DIR=\"$(ssslibdir)\" + SRCS += lookup_sss.c + MODS += lookup_sss.so +endif + CFLAGS += -I../include -I../lib -fPIC -D_GNU_SOURCE CFLAGS += -DAUTOFS_LIB_DIR=\"$(autofslibdir)\" CFLAGS += -DAUTOFS_MAP_DIR=\"$(autofsmapdir)\" diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c new file mode 100644 index 0000000..02a4be9 --- /dev/null +++ b/modules/lookup_sss.c @@ -0,0 +1,678 @@ +/* ----------------------------------------------------------------------- * + * + * lookup_sss.c - module for Linux automount to query sss service + * + * Copyright 2012 Ian Kent + * Copyright 2012 Red Hat, Inc. + * + * 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, Inc., 675 Mass Ave, Cambridge MA 02139, + * USA; either version 2 of the License, or (at your option) any later + * version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_LOOKUP +#include "automount.h" +#include "nsswitch.h" + +#define MAPFMT_DEFAULT "sun" + +#define MODPREFIX "lookup(sss): " + +#define SSS_SO_NAME "libsss_autofs" + +int _sss_setautomntent(const char *, void **); +int _sss_getautomntent_r(char **, char **, void *); +int _sss_getautomntbyname_r(char *, char **, void *); +int _sss_endautomntent(void **); + +typedef int (*setautomntent_t) (const char *, void **); +typedef int (*getautomntent_t) (char **, char **, void *); +typedef int (*getautomntbyname_t) (char *, char **, void *); +typedef int (*endautomntent_t) (void **); + +struct lookup_context { + const char *mapname; + void *dlhandle; + setautomntent_t setautomntent; + getautomntent_t getautomntent_r; + getautomntbyname_t getautomntbyname_r; + endautomntent_t endautomntent; + struct parse_mod *parse; +}; + +int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */ + +int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context) +{ + struct lookup_context *ctxt; + char buf[MAX_ERR_BUF]; + char dlbuf[PATH_MAX]; + char *estr; + void *dh; + size_t size; + + *context = NULL; + + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + estr = strerror_r(errno, buf, MAX_ERR_BUF); + logerr(MODPREFIX "malloc: %s", estr); + return 1; + } + + if (argc < 1) { + free(ctxt); + logerr(MODPREFIX "No map name"); + return 1; + } + ctxt->mapname = argv[0]; + + if (!mapfmt) + mapfmt = MAPFMT_DEFAULT; + + size = snprintf(dlbuf, sizeof(dlbuf), + "%s/%s.so", SSS_LIB_DIR, SSS_SO_NAME); + if (size >= sizeof(dlbuf)) { + free(ctxt); + logmsg(MODPREFIX "sss library path too long"); + return 1; + } + + dh = dlopen(dlbuf, RTLD_LAZY); + if (!dh) { + estr = strerror_r(errno, buf, MAX_ERR_BUF); + logerr(MODPREFIX "dlopen: %s", estr); + free(ctxt); + return 1; + } + ctxt->dlhandle = dh; + + ctxt->setautomntent = (setautomntent_t) dlsym(dh, "_sss_setautomntent"); + if (!ctxt->setautomntent) + goto lib_names_fail; + + ctxt->getautomntent_r = (getautomntent_t) dlsym(dh, "_sss_getautomntent_r"); + if (!ctxt->getautomntent_r) + goto lib_names_fail; + + ctxt->getautomntbyname_r = (getautomntbyname_t) dlsym(dh, "_sss_getautomntbyname_r"); + if (!ctxt->getautomntbyname_r) + goto lib_names_fail; + + ctxt->endautomntent = (endautomntent_t) dlsym(dh, "_sss_endautomntent"); + if (!ctxt->setautomntent) + goto lib_names_fail; + + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { + logmsg(MODPREFIX "failed to open parse context"); + dlclose(dh); + free(ctxt); + return 1; + } + *context = ctxt; + + return 0; + +lib_names_fail: + if ((estr = dlerror()) == NULL) + logmsg(MODPREFIX "failed to locate sss library entry points"); + else + logerr(MODPREFIX "dlsym: %s", estr); + dlclose(dh); + free(ctxt); + return 1; +} + +static int setautomntent(unsigned int logopt, + struct lookup_context *ctxt, const char *mapname, + void **sss_ctxt) +{ + int ret = ctxt->setautomntent(mapname, sss_ctxt); + if (ret) { + char buf[MAX_ERR_BUF]; + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(logopt, MODPREFIX "setautomntent: %s", estr); + if (*sss_ctxt) + free(*sss_ctxt); + return 0; + } + return 1; +} + +static int endautomntent(unsigned int logopt, + struct lookup_context *ctxt, void **sss_ctxt) +{ + int ret = ctxt->endautomntent(sss_ctxt); + if (ret) { + char buf[MAX_ERR_BUF]; + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(logopt, MODPREFIX "endautomntent: %s", estr); + return 0; + } + return 1; +} + +int lookup_read_master(struct master *master, time_t age, void *context) +{ + struct lookup_context *ctxt = (struct lookup_context *) context; + unsigned int timeout = master->default_timeout; + unsigned int logging = master->default_logging; + unsigned int logopt = master->logopt; + void *sss_ctxt = NULL; + char buf[MAX_ERR_BUF]; + char *buffer; + size_t buffer_len; + char *key; + char *value = NULL; + int count, ret; + + if (!setautomntent(logopt, ctxt, ctxt->mapname, &sss_ctxt)) + return NSS_STATUS_UNAVAIL; + + count = 0; + while (1) { + key = NULL; + value = NULL; + ret = ctxt->getautomntent_r(&key, &value, sss_ctxt); + if (ret && ret != ENOENT) { + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(logopt, MODPREFIX "getautomntent_r: %s", estr); + endautomntent(logopt, ctxt, &sss_ctxt); + if (key) + free(key); + if (value) + free(value); + return NSS_STATUS_UNAVAIL; + } + if (ret == ENOENT) { + if (!count) { + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(logopt, MODPREFIX "getautomntent_r: %s", estr); + endautomntent(logopt, ctxt, &sss_ctxt); + if (key) + free(key); + if (value) + free(value); + return NSS_STATUS_NOTFOUND; + } + break; + } + count++; + + buffer_len = strlen(key) + 1 + strlen(value) + 2; + buffer = malloc(buffer_len); + if (!buffer) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(logopt, MODPREFIX "malloc: %s", estr); + endautomntent(logopt, ctxt, &sss_ctxt); + free(key); + free(value); + return NSS_STATUS_UNAVAIL; + } + + /* + * TODO: implement sun % hack for key translation for + * mixed case keys in schema that are single case only. + */ + + strcpy(buffer, key); + strcat(buffer, " "); + strcat(buffer, value); + + /* + * TODO: handle cancelation. This almost certainly isn't + * handled properly by other lookup modules either so it + * should be done when cancelation is reviewed for the + * other modules. Ditto for the other lookup module entry + * points. + */ + master_parse_entry(buffer, timeout, logging, age); + + free(buffer); + free(key); + free(value); + } + + endautomntent(logopt, ctxt, &sss_ctxt); + + return NSS_STATUS_SUCCESS; +} + +int lookup_read_map(struct autofs_point *ap, time_t age, void *context) +{ + struct lookup_context *ctxt = (struct lookup_context *) context; + struct map_source *source; + struct mapent_cache *mc; + void *sss_ctxt = NULL; + char buf[MAX_ERR_BUF]; + char *key; + char *value = NULL; + char *s_key; + int count, ret; + + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + + /* + * If we don't need to create directories then there's no use + * reading the map. We always need to read the whole map for + * direct mounts in order to mount the triggers. + */ + if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) + return NSS_STATUS_SUCCESS; + + if (!setautomntent(ap->logopt, ctxt, ctxt->mapname, &sss_ctxt)) + return NSS_STATUS_UNAVAIL; + + count = 0; + while (1) { + key = NULL; + value = NULL; + ret = ctxt->getautomntent_r(&key, &value, sss_ctxt); + if (ret && ret != ENOENT) { + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(ap->logopt, + MODPREFIX "getautomntent_r: %s", estr); + endautomntent(ap->logopt, ctxt, &sss_ctxt); + if (key) + free(key); + if (value) + free(value); + return NSS_STATUS_UNAVAIL; + } + if (ret == ENOENT) { + if (!count) { + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(ap->logopt, + MODPREFIX "getautomntent_r: %s", estr); + endautomntent(ap->logopt, ctxt, &sss_ctxt); + if (key) + free(key); + if (value) + free(value); + return NSS_STATUS_NOTFOUND; + } + break; + } + + /* + * Ignore keys beginning with '+' as plus map + * inclusion is only valid in file maps. + */ + if (*key == '+') { + warn(ap->logopt, + MODPREFIX "ignoring '+' map entry - not in file map"); + free(key); + free(value); + continue; + } + + /* + * TODO: implement sun % hack for key translation for + * mixed case keys in schema that are single case only. + */ + + s_key = sanitize_path(key, strlen(key), ap->type, ap->logopt); + if (!s_key) { + error(ap->logopt, MODPREFIX "invalid path %s", key); + endautomntent(ap->logopt, ctxt, &sss_ctxt); + free(key); + free(value); + return NSS_STATUS_NOTFOUND; + } + + count++; + + cache_writelock(mc); + cache_update(mc, source, s_key, value, age); + cache_unlock(mc); + + free(s_key); + free(key); + free(value); + } + + endautomntent(ap->logopt, ctxt, &sss_ctxt); + + return NSS_STATUS_SUCCESS; +} + +static int lookup_one(struct autofs_point *ap, + char *qKey, int qKey_len, struct lookup_context *ctxt) +{ + struct map_source *source; + struct mapent_cache *mc; + struct mapent *we; + void *sss_ctxt = NULL; + time_t age = time(NULL); + char buf[MAX_ERR_BUF]; + char *value = NULL; + char *s_key; + int ret; + + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + + if (!setautomntent(ap->logopt, ctxt, ctxt->mapname, &sss_ctxt)) + return NSS_STATUS_UNAVAIL; + + ret = ctxt->getautomntbyname_r(qKey, &value, sss_ctxt); + if (ret && ret != ENOENT) { + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(ap->logopt, + MODPREFIX "getautomntbyname_r: %s", estr); + endautomntent(ap->logopt, ctxt, &sss_ctxt); + if (value) + free(value); + return NSS_STATUS_UNAVAIL; + } + if (ret != ENOENT) { + /* + * TODO: implement sun % hack for key translation for + * mixed case keys in schema that are single case only. + */ + s_key = sanitize_path(qKey, qKey_len, ap->type, ap->logopt); + if (!s_key) { + free(value); + value = NULL; + goto wild; + } + cache_writelock(mc); + ret = cache_update(mc, source, s_key, value, age); + cache_unlock(mc); + endautomntent(ap->logopt, ctxt, &sss_ctxt); + free(s_key); + free(value); + return NSS_STATUS_SUCCESS; + } + +wild: + ret = ctxt->getautomntbyname_r("/", &value, sss_ctxt); + if (ret && ret != ENOENT) { + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(ap->logopt, + MODPREFIX "getautomntbyname_r: %s", estr); + endautomntent(ap->logopt, ctxt, &sss_ctxt); + if (value) + free(value); + return NSS_STATUS_UNAVAIL; + } + if (ret == ENOENT) { + ret = ctxt->getautomntbyname_r("*", &value, sss_ctxt); + if (ret && ret != ENOENT) { + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(ap->logopt, + MODPREFIX "getautomntbyname_r: %s", estr); + endautomntent(ap->logopt, ctxt, &sss_ctxt); + if (value) + free(value); + return NSS_STATUS_UNAVAIL; + } + } + + if (ret == ENOENT) { + /* Failed to find wild entry, update cache if needed */ + cache_writelock(mc); + we = cache_lookup_distinct(mc, "*"); + if (we) { + /* Wildcard entry existed and is now gone */ + if (we->source == source) { + cache_delete(mc, "*"); + source->stale = 1; + } + } + + /* Not found in the map but found in the cache */ + struct mapent *exists = cache_lookup_distinct(mc, qKey); + if (exists && exists->source == source) { + if (exists->mapent) { + free(exists->mapent); + exists->mapent = NULL; + source->stale = 1; + exists->status = 0; + } + } + cache_unlock(mc); + endautomntent(ap->logopt, ctxt, &sss_ctxt); + return NSS_STATUS_NOTFOUND; + } + + cache_writelock(mc); + /* Wildcard not in map but now is */ + we = cache_lookup_distinct(mc, "*"); + if (!we) + source->stale = 1; + ret = cache_update(mc, source, "*", value, age); + cache_unlock(mc); + + endautomntent(ap->logopt, ctxt, &sss_ctxt); + free(value); + + return NSS_STATUS_SUCCESS; +} + +static int check_map_indirect(struct autofs_point *ap, + char *key, int key_len, + struct lookup_context *ctxt) +{ + struct map_source *source; + struct mapent_cache *mc; + struct mapent *me; + time_t now = time(NULL); + time_t t_last_read; + int ret, cur_state; + + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + + master_source_current_wait(ap->entry); + ap->entry->current = source; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + ret = lookup_one(ap, key, key_len, ctxt); + if (ret == NSS_STATUS_NOTFOUND) { + pthread_setcancelstate(cur_state, NULL); + return ret; + } else if (ret == NSS_STATUS_UNAVAIL) { + /* + * If the server is down and the entry exists in the cache + * and belongs to this map return success and use the entry. + */ + struct mapent *exists = cache_lookup(mc, key); + if (exists && exists->source == source) { + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_SUCCESS; + } + pthread_setcancelstate(cur_state, NULL); + + warn(ap->logopt, + MODPREFIX "lookup for %s failed: connection failed", key); + + return ret; + } + pthread_setcancelstate(cur_state, NULL); + + /* + * Check for map change and update as needed for + * following cache lookup. + */ + cache_readlock(mc); + t_last_read = ap->exp_runfreq + 1; + me = cache_lookup_first(mc); + while (me) { + if (me->source == source) { + t_last_read = now - me->age; + break; + } + me = cache_lookup_next(mc, me); + } + cache_unlock(mc); + + if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) + source->stale = 1; + + cache_readlock(mc); + me = cache_lookup_distinct(mc, "*"); + if (ret == CHE_MISSING && (!me || me->source != source)) { + cache_unlock(mc); + return NSS_STATUS_NOTFOUND; + } + cache_unlock(mc); + + return NSS_STATUS_SUCCESS; +} + +int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) +{ + struct lookup_context *ctxt = (struct lookup_context *) context; + struct map_source *source; + struct mapent_cache *mc; + struct mapent *me; + char key[KEY_MAX_LEN + 1]; + int key_len; + char *mapent = NULL; + char mapent_buf[MAPENT_MAX_LEN + 1]; + int ret; + + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + + debug(ap->logopt, MODPREFIX "looking up %s", name); + + key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); + if (key_len > KEY_MAX_LEN) + return NSS_STATUS_NOTFOUND; + + /* Check if we recorded a mount fail for this key anywhere */ + me = lookup_source_mapent(ap, key, LKP_DISTINCT); + if (me) { + if (me->status >= time(NULL)) { + cache_unlock(me->mc); + return NSS_STATUS_NOTFOUND; + } else { + struct mapent_cache *smc = me->mc; + struct mapent *sme; + + if (me->mapent) + cache_unlock(smc); + else { + cache_unlock(smc); + cache_writelock(smc); + sme = cache_lookup_distinct(smc, key); + /* Negative timeout expired for non-existent entry. */ + if (sme && !sme->mapent) + cache_delete(smc, key); + cache_unlock(smc); + } + } + } + + /* + * We can't check the direct mount map as if it's not in + * the map cache already we never get a mount lookup, so + * we never know about it. + */ + if (ap->type == LKP_INDIRECT && *key != '/') { + int status; + char *lkp_key; + + cache_readlock(mc); + me = cache_lookup_distinct(mc, key); + if (me && me->multi) + lkp_key = strdup(me->multi->key); + else + lkp_key = strdup(key); + cache_unlock(mc); + + if (!lkp_key) + return NSS_STATUS_UNKNOWN; + + master_source_current_wait(ap->entry); + ap->entry->current = source; + + status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); + free(lkp_key); + if (status) + return status; + } + + cache_readlock(mc); + me = cache_lookup(mc, key); + /* Stale mapent => check for entry in alternate source or wildcard */ + if (me && !me->mapent) { + while ((me = cache_lookup_key_next(me))) + if (me->source == source) + break; + if (!me) + me = cache_lookup_distinct(mc, "*"); + } + if (me && me->mapent && (me->source == source || *me->key == '/')) { + strcpy(mapent_buf, me->mapent); + mapent = mapent_buf; + } + cache_unlock(mc); + + if (!mapent) + return NSS_STATUS_TRYAGAIN; + + master_source_current_wait(ap->entry); + ap->entry->current = source; + + debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent); + ret = ctxt->parse->parse_mount(ap, key, key_len, + mapent, ctxt->parse->context); + if (ret) { + time_t now = time(NULL); + int rv = CHE_OK; + + /* Record the the mount fail in the cache */ + cache_writelock(mc); + me = cache_lookup_distinct(mc, key); + if (!me) + rv = cache_update(mc, source, key, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, key); + me->status = now + ap->negative_timeout; + } + cache_unlock(mc); + return NSS_STATUS_TRYAGAIN; + } + + return NSS_STATUS_SUCCESS; +} + +int lookup_done(void *context) +{ + struct lookup_context *ctxt = (struct lookup_context *) context; + int rv = close_parse(ctxt->parse); + dlclose(ctxt->dlhandle); + free(ctxt); + return rv; +}