doc/fr/HTML/
doc/fr/man/
doc/fr/txt/
-
+configure
/* *********************************************************** */
+/* ****************************************************************** */
/* ****************************************************************** */
/* beginning of configurable stuff ********************************** */
/* end of configurable stuff **************************************** */
/* ****************************************************************** */
+/* ****************************************************************** */
+/* ****************************************************************** */
/* ****************************************************************** */
/* *** options which are set by configure script ******************** */
#undef CFLAGS
+/* ****************************************************************** */
/* *** paths *** */
+
#undef PROC
+/* ****************************************************************** */
+/* *** Compilation options *** */
+
/* 1 if we want to compile and install fcrondyn */
#undef FCRONDYN
#undef NOLOADAVG
/* special user for the system fcrontab */
#undef SYSFCRONTAB
+/* ****************************************************************** */
+/* *** Types *** */
+
/* Define to empty if the keyword does not work. */
#undef const
/* Define on System V Release 4. */
#undef SVR4
+/* ****************************************************************** */
+/* *** Functions *** */
+
/* Define if you have the crypt function. */
#undef HAVE_CRYPT
/* Define if you have the wait3 system call. */
#undef HAVE_WAIT3
+/* ****************************************************************** */
+/* *** Headers *** */
+
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if your <sys/time.h> declares struct tm. */
#undef TM_IN_SYS_TIME
+/* Define if you have the <cred.h> header file. */
+#undef HAVE_CRED_H
+
/* Define if you have the <crypt.h> header file. */
#undef HAVE_CRYPT_H
/* Define if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
+/* Define if you have the <sys/cred.h> header file. */
+#undef HAVE_SYS_CRED_H
+
/* Define if you have the <sys/dir.h> header file. */
#undef HAVE_SYS_DIR_H
/* Define if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
+/* Define if you have the <sys/ucred.h> header file. */
+#undef HAVE_SYS_UCRED_H
+
/* Define if you have the <sys/un.h> header file. */
#undef HAVE_SYS_UN_H
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
+/* Define if you have the <ucred.h> header file. */
+#undef HAVE_UCRED_H
+
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
#define O_SYNC O_FSYNC
#endif
+/* ****************************************************************** */
+/* *** Size of *** */
+
/* These SIZEOF_* constants are defined by the AC_CHECK_SIZEOF macro */
#undef SIZEOF_TIME_T
#undef SIZEOF_PID_T
VERSION="$vers"
-copyright_quoted="\"2000-2008\""
+copyright_quoted="\"2000-2009\""
cat >>confdefs.h <<_ACEOF
#define COPYRIGHT_QUOTED $copyright_quoted
_ACEOF
fi
+
+
+
+for ac_header in cred.h sys/cred.h ucred.h sys/ucred.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in getpeerucred
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
fcron_enable_checks=yes
# Check whether --enable-checks was given.
if test "${enable_checks+set}" = set; then
VERSION="$vers"
AC_SUBST(VERSION)
-copyright_quoted="\"2000-2008\""
+copyright_quoted="\"2000-2009\""
AC_DEFINE_UNQUOTED(COPYRIGHT_QUOTED, $copyright_quoted)
fi
+dnl --- sockets
dnl Check for post-Reno style struct sockaddr
AC_CACHE_CHECK([for sa_len],
ac_cv_sa_len,
AC_DEFINE(HAVE_SA_LEN)
fi
+dnl --- Socket authentication
+AC_CHECK_HEADERS(cred.h sys/cred.h ucred.h sys/ucred.h)
+AC_CHECK_FUNCS(getpeerucred)
+
dnl ---------------------------------------------------------------------
dnl Check for fcron more specific stuffs (paths, progs, ...)
dnl ---------------------------------------------------------------------
<sect1 id="changes">
<title>Changes</title>
+ <itemizedlist>
+ <title>From version 3.0.5 to 3.1.0</title>
+ <listitem>
+ <para>Pass fcrondyn client credentials through the socket when possible so as the user doesn't need to type his password when using fcrondyn.</para>
+ </listitem>
+ <listitem>
+ <para>Code clean-up: Implemented generic unordred list for lavgq / exeq.</para>
+ </listitem>
+ </itemizedlist>
+
<itemizedlist>
<title>From version 3.0.4 to 3.0.5</title>
<listitem>
sgml-parent-document:("fcron-doc.sgml" "book" "chapter" "sect1" "")
End:
-->
-
\ No newline at end of file
+
int talk_fcron(char *cmd_str, int fd);
int parse_cmd(char *cmd_str, long int **cmd, int *cmd_len);
int connect_fcron(void);
-int authenticate_user(int fd);
+int authenticate_user_password(int fd);
/* command line options */
#ifdef DEBUG
}
int
-authenticate_user(int fd)
+authenticate_user_password(int fd)
/* authenticate user */
{
char *password = NULL;
if ( connect(fd, (struct sockaddr *) &addr, sun_len) < 0 )
die_e("Cannot connect() to fcron (check if fcron is running)");
- if ( authenticate_user(fd) == ERR ) {
- fprintf(stderr, "Invalid password or too many authentication failures"
+/* Nothing to do on the client side if we use SO_PASSCRED */
+#ifndef SO_PASSCRED
+ if ( authenticate_user_password(fd) == ERR ) {
+ fprintf(stderr, "Invalid password or too many authentication failures"
" (try to connect later).\n(In the later case, fcron rejects all"
" new authentication during %d secs)\n", AUTH_WAIT);
die("Unable to authenticate user");
}
+#endif /* SO_PASSCRED */
return fd;
#include <sys/fcntl.h>
#endif
+#ifdef HAVE_CRED_H
+#include <cred.h>
+#endif
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
+#ifdef HAVE_SYS_CRED_H
+#include <sys/cred.h>
+#endif
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+
#ifdef HAVE_LIBPAM
#include "pam.h"
#endif
void remove_connection(struct fcrondyn_cl **client, struct fcrondyn_cl *prev_client);
void exe_cmd(struct fcrondyn_cl *client);
-void auth_client(struct fcrondyn_cl *client);
+void auth_client_password(struct fcrondyn_cl *client);
+void auth_client_so_passcred(struct fcrondyn_cl *client);
void cmd_ls(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root);
void print_fields(int fd, unsigned char *details);
void print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid, int index,
}
+#ifdef SO_PASSCRED
void
-auth_client(struct fcrondyn_cl *client)
- /* check client identity */
+auth_client_so_passcred(struct fcrondyn_cl *client)
+ /* check client identity by reading its credentials from the socket
+ * using getsockopt(SO_PASSCRED).
+ * Sets client->fcl_user on success, don't do anything on failure */
+{
+ const int true = 1;
+ /* There is no ucred.h (or equivalent) on linux to define struct ucred (!!)
+ * so we do it here */
+#if ! ( defined(HAVE_CRED_H) && defined(HAVE_UCRED_H) \
+ && defined(HAVE_SYS_CRED_H) && defined(HAVE_SYS_UCRED_H) )
+ struct ucred {
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+ };
+#endif
+ struct ucred cred;
+ socklen_t cred_size = sizeof(cred);
+ struct passwd *p_entry = NULL;
+
+ setsockopt(client->fcl_sock_fd, SOL_SOCKET, SO_PASSCRED, &true, sizeof(true));
+ if ( getsockopt(client->fcl_sock_fd, SOL_SOCKET, SO_PEERCRED,
+ &cred, &cred_size) != 0) {
+ error_e("Could not get client credentials using getsockopt(SO_PEERCRED)");
+ return;
+ }
+
+ p_entry = getpwuid(cred.uid);
+ if ( p_entry == NULL ) {
+ error_e("Could not find password entry for uid %d", cred.uid);
+ return;
+ }
+
+ /* Successfully identified user: */
+ client->fcl_user = strdup2(p_entry->pw_name);
+
+ explain("Client's pid=%d, uid=%d, gid=%d username=%s\n", cred.pid, cred.uid, cred.gid, client->fcl_user);
+
+}
+#endif /* SO_PASSCRED */
+
+void
+auth_client_password(struct fcrondyn_cl *client)
+ /* check client identity by asking him to input his password */
{
char *pass_cry = NULL;
char *pass_sys = NULL;
#endif
/* */
- debug("auth_client() : socket : %d", client->fcl_sock_fd);
+ debug("auth_client_password() : socket : %d", client->fcl_sock_fd);
/* */
/* we need to limit auth failures : otherwise fcron may be used to "read"
return;
}
- /* password is stored after user name */
+ /* the password is stored after the user name */
pass_str = &( (char *)client->fcl_cmd ) [ strlen( (char*)client->fcl_cmd ) + 1 ];
if ( (pass_cry = crypt(pass_str, pass_sys)) == NULL ) {
error_e("could not crypt()");
if ( FD_ISSET(listen_fd, &read_set) ) {
debug("got new connection ...");
- if ((fd = accept(listen_fd, (struct sockaddr *)&client_addr, &addr_len)) == -1) {
+ fd = accept(listen_fd, (struct sockaddr *)&client_addr, &addr_len);
+ if ( fd == -1 ) {
error_e("could not accept new connection : isset(listen_fd = %d) = %d",
listen_fd, FD_ISSET(listen_fd, &read_set));
}
fcrondyn_cl_num += 1;
debug("Added connection fd : %d - %d connections", fd, fcrondyn_cl_num);
+
+#ifdef SO_PASSCRED
+ auth_client_so_passcred(client);
+#endif /* SO_PASSCRED */
}
}
}
client->fcl_cmd = buf_int;
if ( client->fcl_user == NULL )
/* not authenticated yet */
- auth_client(client);
+ auth_client_password(client);
else {
/* we've just read a command ... */
client->fcl_idle_since = now;