Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 115082
Collapse All | Expand All

(-)CHROOT (-11 / +13 lines)
Lines 148-154 Link Here
148
/lib/libnss_files.so.? into the chroot jail.  Without it, the scp command
148
/lib/libnss_files.so.? into the chroot jail.  Without it, the scp command
149
failed, complaining that my user ID was an unknown user.  If you use LDAP
149
failed, complaining that my user ID was an unknown user.  If you use LDAP
150
authentication on the server, you will probably need to also copy
150
authentication on the server, you will probably need to also copy
151
libnss_ldap.so.? into your chroot jail.
151
libnss_ldap.so.? into your chroot jail.  Similar requirements likely exist for
152
other authentication methods...
152
153
153
154
154
Logging
155
Logging
Lines 190-199 Link Here
190
Individual jails for different users
191
Individual jails for different users
191
------------------------------------
192
------------------------------------
192
193
193
In v2.1, you are now able to specify the location of different chroot jails
194
Since v2.1, you are now able to specify the location of different chroot jails
194
for different users, whether or not to chroot individual users, etc.  You
195
for different users, whether or not to chroot individual users, etc.  You
195
might be tempted to create individual jails for each different user, and you
196
might be tempted to create individual jails for each different user, and you
196
can do that, BUT...  It's probably a bad idea.
197
can do that, BUT... it's probably a very bad idea.
197
198
198
There are several reasons for this.  First, it uses lots of disk space,
199
There are several reasons for this.  First, it uses lots of disk space,
199
because you need to copy the libraries and such into each one (though in some
200
because you need to copy the libraries and such into each one (though in some
Lines 203-213 Link Here
203
above) in each of the chroot jails.  However, the number of sockets syslog can
204
above) in each of the chroot jails.  However, the number of sockets syslog can
204
listen to is generally limited.  On most Linux systems, that limit is a
205
listen to is generally limited.  On most Linux systems, that limit is a
205
maximum of 20, though it can be changed by editing the source code to syslogd.
206
maximum of 20, though it can be changed by editing the source code to syslogd.
206
So if you go with individual chroot jails, you either need to be satisfied
207
On other platforms, this may not even be possible.  So if you go with
207
without logging for most of your users, or recompile syslogd and manually
208
individual chroot jails, you either need to be satisfied without logging for
208
configure it to open a socket in each of your users' jails.  And while I
209
most of your users, or recompile syslogd and manually configure it to open a
209
haven't done it, I suspect creating large numbers of sockets for syslogd to
210
socket in each of your users' jails.  And while I haven't done it, I suspect
210
listen to will make logging to syslog somewhat painful.
211
creating large numbers of sockets for syslogd to listen to will make logging
212
to syslog somewhat painful.
211
213
212
My recommendation is, if you really really really need individual chroot
214
My recommendation is, if you really really really need individual chroot
213
jails, use them.  But if you can, configure a single jail where the majority
215
jails, use them.  But if you can, configure a single jail where the majority
Lines 221-229 Link Here
221
223
222
Setting up a proper chroot jail can be difficult, and it is always a very
224
Setting up a proper chroot jail can be difficult, and it is always a very
223
environment-specific operation.  Because of this, I can not and will not
225
environment-specific operation.  Because of this, I can not and will not
224
provide any sort of support for setting up chroot jails.  However, in the near
226
provide any sort of support for setting up chroot jails.  However, there is a
225
future, I will make sure there is a mailing list for rssh, where you can ask
227
mailing list for rssh, where you can ask questions.  See the rssh homepage for
226
questions.
228
details.
227
229
228
If you are having problems, make sure that you have logging set up properly,
230
If you are having problems, make sure that you have logging set up properly,
229
if nothing else.  Doing so will help you determine what kind of problems you
231
if nothing else.  Doing so will help you determine what kind of problems you
(-)ChangeLog (+8 lines)
Lines 1-3 Link Here
1
2.3.0
2
3
 - modified chroot_helper to parse the config file, to avoid arbitrary
4
   chroot() (and thus root compromise)
5
 - numerous documentation updates
6
 - fix for va_start()/va_end()-related segfault on 64-bit architecture
7
 - small bit of code cleanup
8
1
2.2.3
9
2.2.3
2
10
3
 - added checks for command execution arguments to scp, rdist, rsync
11
 - added checks for command execution arguments to scp, rdist, rsync
(-)Makefile.am (-1 / +4 lines)
Lines 6-12 Link Here
6
libexec_PROGRAMS = rssh_chroot_helper
6
libexec_PROGRAMS = rssh_chroot_helper
7
nodist_rssh_SOURCES = main.c pathnames.h config.h
7
nodist_rssh_SOURCES = main.c pathnames.h config.h
8
rssh_SOURCES = rssh.h rsshconf.h rsshconf.c log.c log.h util.c util.h argvec.c argvec.h
8
rssh_SOURCES = rssh.h rsshconf.h rsshconf.c log.c log.h util.c util.h argvec.c argvec.h
9
rssh_chroot_helper_SOURCES = rssh_chroot_helper.c log.c log.h argvec.c argvec.h
9
rssh_chroot_helper_SOURCES = rssh_chroot_helper.c log.c log.h argvec.c argvec.h util.c util.h rsshconf.c rsshconf.h rssh.h
10
dist_sysconf_DATA = rssh.conf
10
dist_sysconf_DATA = rssh.conf
11
man_MANS = rssh.1 rssh.conf.5
11
man_MANS = rssh.1 rssh.conf.5
12
EXTRA_DIST = $(man_MANS) CHROOT SECURITY rssh.spec mkchroot.sh conf_convert.sh
12
EXTRA_DIST = $(man_MANS) CHROOT SECURITY rssh.spec mkchroot.sh conf_convert.sh
Lines 16-18 Link Here
16
16
17
install-exec-hook:
17
install-exec-hook:
18
	chmod u+s $(libexecdir)/rssh_chroot_helper
18
	chmod u+s $(libexecdir)/rssh_chroot_helper
19
20
rpm:
21
	rpmbuild -tb `echo @PACKAGE_STRING@.tar.gz|tr " " "-"`
(-)NEWS (+1 lines)
Line 0 Link Here
1
Automake's insistance on the existence of this file is very lame.
(-)SECURITY (+21 lines)
Lines 1-6 Link Here
1
SECURITY
1
SECURITY
2
--------
2
--------
3
3
4
Please note: The man page now has detailed information about security concerns
5
and some tips for setting up rssh securely.  If you haven't read these, please
6
do so now.  What follows is mostly a summary of specific security issues which
7
have affected rssh since I started developing it.
8
9
Nov 27, 2005
10
11
Max Vozeler reported a scary problem whereby rssh_chroot_helper can be
12
exploited to chroot to arbitrary directories and thereby gain root access.
13
The 2.3.0 release of rssh fixes this problem by forcing the chroot helper
14
program to re-parse the config file instead of allowing the chroot home to be
15
specified on the command line.  Thus users not listed can not use it to chroot
16
(or will chroot to the default location, which hopefully the sysadmin has set
17
up securely), and users who are listed will be chrooted to the directories
18
where they are supposed to go only.
19
20
Numerous people reported a problem with the way I used va_start/va_end in
21
log.c which causes a segfault on 64-bit Linux platforms.  I don't know if this
22
is exploitable, but it's fixed.  Given the previously mentioned root
23
compromise, this probably doesn't matter much...  ;-)
24
4
Dec 3, 2004
25
Dec 3, 2004
5
26
6
Jason Wies has reported a problem whereby rssh can be bypassed in conjunction
27
Jason Wies has reported a problem whereby rssh can be bypassed in conjunction
(-)aclocal.m4 (-36 / +153 lines)
Lines 1-4 Link Here
1
# generated automatically by aclocal 1.8.3 -*- Autoconf -*-
1
# generated automatically by aclocal 1.9.2 -*- Autoconf -*-
2
2
3
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
4
# Free Software Foundation, Inc.
4
# Free Software Foundation, Inc.
Lines 33-46 Link Here
33
# ----------------------------
33
# ----------------------------
34
# Automake X.Y traces this macro to ensure aclocal.m4 has been
34
# Automake X.Y traces this macro to ensure aclocal.m4 has been
35
# generated from the m4 files accompanying Automake X.Y.
35
# generated from the m4 files accompanying Automake X.Y.
36
AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"])
36
AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
37
37
38
# AM_SET_CURRENT_AUTOMAKE_VERSION
38
# AM_SET_CURRENT_AUTOMAKE_VERSION
39
# -------------------------------
39
# -------------------------------
40
# Call AM_AUTOMAKE_VERSION so it can be traced.
40
# Call AM_AUTOMAKE_VERSION so it can be traced.
41
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
41
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
42
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
42
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
43
	 [AM_AUTOMAKE_VERSION([1.8.3])])
43
	 [AM_AUTOMAKE_VERSION([1.9.2])])
44
44
45
# AM_AUX_DIR_EXPAND
45
# AM_AUX_DIR_EXPAND
46
46
Lines 108-114 Link Here
108
108
109
# AM_CONDITIONAL                                              -*- Autoconf -*-
109
# AM_CONDITIONAL                                              -*- Autoconf -*-
110
110
111
# Copyright (C) 1997, 2000, 2001, 2003 Free Software Foundation, Inc.
111
# Copyright (C) 1997, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
112
112
113
# This program is free software; you can redistribute it and/or modify
113
# This program is free software; you can redistribute it and/or modify
114
# it under the terms of the GNU General Public License as published by
114
# it under the terms of the GNU General Public License as published by
Lines 145-152 Link Here
145
fi
145
fi
146
AC_CONFIG_COMMANDS_PRE(
146
AC_CONFIG_COMMANDS_PRE(
147
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
147
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
148
  AC_MSG_ERROR([conditional "$1" was never defined.
148
  AC_MSG_ERROR([[conditional "$1" was never defined.
149
Usually this means the macro was only invoked conditionally.])
149
Usually this means the macro was only invoked conditionally.]])
150
fi])])
150
fi])])
151
151
152
# serial 7						-*- Autoconf -*-
152
# serial 7						-*- Autoconf -*-
Lines 266-274 Link Here
266
       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
266
       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
267
       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
267
       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
268
      # icc doesn't choke on unknown options, it will just issue warnings
268
      # icc doesn't choke on unknown options, it will just issue warnings
269
      # (even with -Werror).  So we grep stderr for any message
269
      # or remarks (even with -Werror).  So we grep stderr for any message
270
      # that says an option was ignored.
270
      # that says an option was ignored or not supported.
271
      if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else
271
      # When given -MP, icc 7.0 and 7.1 complain thusly:
272
      #   icc: Command line warning: ignoring option '-M'; no argument required
273
      # The diagnosis changed in icc 8.0:
274
      #   icc: Command line remark: option '-MP' not supported
275
      if (grep 'ignoring option' conftest.err ||
276
          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
272
        am_cv_$1_dependencies_compiler_type=$depmode
277
        am_cv_$1_dependencies_compiler_type=$depmode
273
        break
278
        break
274
      fi
279
      fi
Lines 314-320 Link Here
314
319
315
# Generate code to set up dependency tracking.   -*- Autoconf -*-
320
# Generate code to set up dependency tracking.   -*- Autoconf -*-
316
321
317
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
322
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
323
#   Free Software Foundation, Inc.
318
324
319
# This program is free software; you can redistribute it and/or modify
325
# This program is free software; you can redistribute it and/or modify
320
# it under the terms of the GNU General Public License as published by
326
# it under the terms of the GNU General Public License as published by
Lines 350-376 Link Here
350
  else
356
  else
351
    continue
357
    continue
352
  fi
358
  fi
353
  grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue
359
  # Extract the definition of DEPDIR, am__include, and am__quote
354
  # Extract the definition of DEP_FILES from the Makefile without
360
  # from the Makefile without running `make'.
355
  # running `make'.
356
  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
361
  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
357
  test -z "$DEPDIR" && continue
362
  test -z "$DEPDIR" && continue
363
  am__include=`sed -n 's/^am__include = //p' < "$mf"`
364
  test -z "am__include" && continue
365
  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
358
  # When using ansi2knr, U may be empty or an underscore; expand it
366
  # When using ansi2knr, U may be empty or an underscore; expand it
359
  U=`sed -n 's/^U = //p' < "$mf"`
367
  U=`sed -n 's/^U = //p' < "$mf"`
360
  test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR"
368
  # Find all dependency output files, they are included files with
361
  # We invoke sed twice because it is the simplest approach to
369
  # $(DEPDIR) in their names.  We invoke sed twice because it is the
362
  # changing $(DEPDIR) to its actual value in the expansion.
370
  # simplest approach to changing $(DEPDIR) to its actual value in the
363
  for file in `sed -n '
371
  # expansion.
364
    /^DEP_FILES = .*\\\\$/ {
372
  for file in `sed -n "
365
      s/^DEP_FILES = //
373
    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
366
      :loop
367
	s/\\\\$//
368
	p
369
	n
370
	/\\\\$/ b loop
371
      p
372
    }
373
    /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \
374
       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
374
       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
375
    # Make sure the directory exists.
375
    # Make sure the directory exists.
376
    test -f "$dirpart/$file" && continue
376
    test -f "$dirpart/$file" && continue
Lines 425-431 Link Here
425
# This macro actually does too much some checks are only needed if
425
# This macro actually does too much some checks are only needed if
426
# your package does certain things.  But this isn't really a big deal.
426
# your package does certain things.  But this isn't really a big deal.
427
427
428
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
428
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
429
# Free Software Foundation, Inc.
429
# Free Software Foundation, Inc.
430
430
431
# This program is free software; you can redistribute it and/or modify
431
# This program is free software; you can redistribute it and/or modify
Lines 501-507 Link Here
501
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
501
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
502
AM_MISSING_PROG(AUTOHEADER, autoheader)
502
AM_MISSING_PROG(AUTOHEADER, autoheader)
503
AM_MISSING_PROG(MAKEINFO, makeinfo)
503
AM_MISSING_PROG(MAKEINFO, makeinfo)
504
AM_MISSING_PROG(AMTAR, tar)
505
AM_PROG_INSTALL_SH
504
AM_PROG_INSTALL_SH
506
AM_PROG_INSTALL_STRIP
505
AM_PROG_INSTALL_STRIP
507
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
506
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
Lines 510-516 Link Here
510
AC_REQUIRE([AC_PROG_AWK])dnl
509
AC_REQUIRE([AC_PROG_AWK])dnl
511
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
510
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
512
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
511
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
513
512
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
513
              [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
514
	      		     [_AM_PROG_TAR([v7])])])
514
_AM_IF_OPTION([no-dependencies],,
515
_AM_IF_OPTION([no-dependencies],,
515
[AC_PROVIDE_IFELSE([AC_PROG_CC],
516
[AC_PROVIDE_IFELSE([AC_PROG_CC],
516
                  [_AM_DEPENDENCIES(CC)],
517
                  [_AM_DEPENDENCIES(CC)],
Lines 753-765 Link Here
753
# this.)
754
# this.)
754
AC_DEFUN([AM_PROG_MKDIR_P],
755
AC_DEFUN([AM_PROG_MKDIR_P],
755
[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
756
[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
756
  # Keeping the `.' argument allows $(mkdir_p) to be used without
757
  # We used to keeping the `.' as first argument, in order to
757
  # argument.  Indeed, we sometimes output rules like
758
  # allow $(mkdir_p) to be used without argument.  As in
758
  #   $(mkdir_p) $(somedir)
759
  #   $(mkdir_p) $(somedir)
759
  # where $(somedir) is conditionally defined.
760
  # where $(somedir) is conditionally defined.  However this is wrong
760
  # (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more
761
  # for two reasons:
761
  # expensive solution, as it forces Make to start a sub-shell.)
762
  #  1. if the package is installed by a user who cannot write `.'
762
  mkdir_p='mkdir -p -- .'
763
  #     make install will fail,
764
  #  2. the above comment should most certainly read
765
  #     $(mkdir_p) $(DESTDIR)$(somedir)
766
  #     so it does not work when $(somedir) is undefined and
767
  #     $(DESTDIR) is not.
768
  #  To support the latter case, we have to write
769
  #     test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
770
  #  so the `.' trick is pointless.
771
  mkdir_p='mkdir -p --'
763
else
772
else
764
  # On NextStep and OpenStep, the `mkdir' command does not
773
  # On NextStep and OpenStep, the `mkdir' command does not
765
  # recognize any option.  It will interpret all options as
774
  # recognize any option.  It will interpret all options as
Lines 925-927 Link Here
925
INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
934
INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
926
AC_SUBST([INSTALL_STRIP_PROGRAM])])
935
AC_SUBST([INSTALL_STRIP_PROGRAM])])
927
936
937
# Check how to create a tarball.                            -*- Autoconf -*-
938
939
# Copyright (C) 2004  Free Software Foundation, Inc.
940
941
# This program is free software; you can redistribute it and/or modify
942
# it under the terms of the GNU General Public License as published by
943
# the Free Software Foundation; either version 2, or (at your option)
944
# any later version.
945
946
# This program is distributed in the hope that it will be useful,
947
# but WITHOUT ANY WARRANTY; without even the implied warranty of
948
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
949
# GNU General Public License for more details.
950
951
# You should have received a copy of the GNU General Public License
952
# along with this program; if not, write to the Free Software
953
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
954
# 02111-1307, USA.
955
956
# serial 1
957
958
959
# _AM_PROG_TAR(FORMAT)
960
# --------------------
961
# Check how to create a tarball in format FORMAT.
962
# FORMAT should be one of `v7', `ustar', or `pax'.
963
#
964
# Substitute a variable $(am__tar) that is a command
965
# writing to stdout a FORMAT-tarball containing the directory
966
# $tardir.
967
#     tardir=directory && $(am__tar) > result.tar
968
#
969
# Substitute a variable $(am__untar) that extract such
970
# a tarball read from stdin.
971
#     $(am__untar) < result.tar
972
AC_DEFUN([_AM_PROG_TAR],
973
[# Always define AMTAR for backward compatibility.
974
AM_MISSING_PROG([AMTAR], [tar])
975
m4_if([$1], [v7],
976
     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
977
     [m4_case([$1], [ustar],, [pax],,
978
              [m4_fatal([Unknown tar format])])
979
AC_MSG_CHECKING([how to create a $1 tar archive])
980
# Loop over all known methods to create a tar archive until one works.
981
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
982
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
983
# Do not fold the above two line into one, because Tru64 sh and
984
# Solaris sh will not grok spaces in the rhs of `-'.
985
for _am_tool in $_am_tools
986
do
987
  case $_am_tool in
988
  gnutar)
989
    for _am_tar in tar gnutar gtar;
990
    do
991
      AM_RUN_LOG([$_am_tar --version]) && break
992
    done
993
    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
994
    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
995
    am__untar="$_am_tar -xf -"
996
    ;;
997
  plaintar)
998
    # Must skip GNU tar: if it does not support --format= it doesn't create
999
    # ustar tarball either.
1000
    (tar --version) >/dev/null 2>&1 && continue
1001
    am__tar='tar chf - "$$tardir"'
1002
    am__tar_='tar chf - "$tardir"'
1003
    am__untar='tar xf -'
1004
    ;;
1005
  pax)
1006
    am__tar='pax -L -x $1 -w "$$tardir"'
1007
    am__tar_='pax -L -x $1 -w "$tardir"'
1008
    am__untar='pax -r'
1009
    ;;
1010
  cpio)
1011
    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
1012
    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
1013
    am__untar='cpio -i -H $1 -d'
1014
    ;;
1015
  none)
1016
    am__tar=false
1017
    am__tar_=false
1018
    am__untar=false
1019
    ;;
1020
  esac
1021
1022
  # If the value was cached, stop now.  We just wanted to have am__tar
1023
  # and am__untar set.
1024
  test -n "${am_cv_prog_tar_$1}" && break
1025
1026
  # tar/untar a dummy directory, and stop if the command works
1027
  rm -rf conftest.dir
1028
  mkdir conftest.dir
1029
  echo GrepMe > conftest.dir/file
1030
  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
1031
  rm -rf conftest.dir
1032
  if test -s conftest.tar; then
1033
    AM_RUN_LOG([$am__untar <conftest.tar])
1034
    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
1035
  fi
1036
done
1037
rm -rf conftest.dir
1038
1039
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
1040
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
1041
AC_SUBST([am__tar])
1042
AC_SUBST([am__untar])
1043
]) # _AM_PROG_TAR
1044
(-)configure.ac (-1 / +1 lines)
Lines 1-5 Link Here
1
# Process this file with autoconf to produce a configure script.
1
# Process this file with autoconf to produce a configure script.
2
AC_INIT(rssh, 2.2.3, [rssh-discuss at lists dot sourceforge dot net])
2
AC_INIT(rssh, 2.3.0, [rssh-discuss at lists dot sourceforge dot net])
3
AM_INIT_AUTOMAKE
3
AM_INIT_AUTOMAKE
4
AC_CONFIG_SRCDIR([rssh.1])
4
AC_CONFIG_SRCDIR([rssh.1])
5
AM_CONFIG_HEADER([config.h])
5
AM_CONFIG_HEADER([config.h])
(-)log.c (-3 / +5 lines)
Lines 156-161 Link Here
156
	/* try to print msg to buffer, until we succeed or fail conclusively */
156
	/* try to print msg to buffer, until we succeed or fail conclusively */
157
	va_start( arglist, msg );
157
	va_start( arglist, msg );
158
	retc = vsnprintf( format_temp, length, msg, arglist );
158
	retc = vsnprintf( format_temp, length, msg, arglist );
159
	va_end( arglist );
159
160
160
	/* 
161
	/* 
161
	 * Check retc to make sure it fit account for differences in libc
162
	 * Check retc to make sure it fit account for differences in libc
Lines 171-177 Link Here
171
				"Could not allocate mem in log_msg(), log.c");
172
				"Could not allocate mem in log_msg(), log.c");
172
			exit(1);
173
			exit(1);
173
		}
174
		}
175
		va_start( arglist, msg );
174
		vsnprintf( format_temp, retc + 1, msg, arglist );
176
		vsnprintf( format_temp, retc + 1, msg, arglist );
177
		va_end( arglist );
175
	}
178
	}
176
	/* if retc == -1, we must be compiled under pre-C99 libc */
179
	/* if retc == -1, we must be compiled under pre-C99 libc */
177
	while ( retc == -1 ){
180
	while ( retc == -1 ){
Lines 183-193 Link Here
183
			exit(1);
186
			exit(1);
184
		}	
187
		}	
185
		memset( format_temp, 0, length );
188
		memset( format_temp, 0, length );
189
		va_start( arglist, msg );
186
		retc = vsnprintf( format_temp, length, msg, arglist );
190
		retc = vsnprintf( format_temp, length, msg, arglist );
191
		va_end( arglist );
187
	}
192
	}
188
189
	/* clean up arglist and log the string */
190
	va_end( arglist );
191
	syslog((facility | level), "%s", format_temp);
193
	syslog((facility | level), "%s", format_temp);
192
}
194
}
193
195
(-)main.c.in (-18 / +11 lines)
Lines 82-88 Link Here
82
char *progname;
82
char *progname;
83
char *username;
83
char *username;
84
char *version = "@PACKAGE_STRING@";
84
char *version = "@PACKAGE_STRING@";
85
char *copyr = "Copyright 2002-4 Derek D. Martin <@PACKAGE_BUGREPORT@>";
85
char *copyr = "Copyright 2002-5 Derek D. Martin <@PACKAGE_BUGREPORT@>";
86
86
87
/* MAIN PROGRAM */
87
/* MAIN PROGRAM */
88
int main( int argc, char **argv )
88
int main( int argc, char **argv )
Lines 116-122 Link Here
116
	log_open();
116
	log_open();
117
117
118
	/* process the config file */
118
	/* process the config file */
119
	if ( !(read_shell_config(&opts, PATH_RSSH_CONFIG)) ){
119
	if ( !(read_shell_config(&opts, PATH_RSSH_CONFIG, 1)) ){
120
		log_set_priority(LOG_ERR);
120
		log_set_priority(LOG_ERR);
121
		log_msg("there were errors processing configuration file!");
121
		log_msg("there were errors processing configuration file!");
122
	}
122
	}
Lines 188-194 Link Here
188
	/* if we need to do chroot processing, do it */
188
	/* if we need to do chroot processing, do it */
189
	if ( opts->shell_flags & RSSH_USE_CHROOT ){
189
	if ( opts->shell_flags & RSSH_USE_CHROOT ){
190
		/* create vector of pointers to command line arguments */
190
		/* create vector of pointers to command line arguments */
191
		root = opts->chroot_path;
192
191
193
		/* 
192
		/* 
194
		 * we don't call build_arg_vector() here, because expanding
193
		 * we don't call build_arg_vector() here, because expanding
Lines 205-234 Link Here
205
		}
204
		}
206
205
207
		argvec[0] = PATH_CHROOT_HELPER;
206
		argvec[0] = PATH_CHROOT_HELPER;
208
		argvec[1] = root;
209
207
210
		/* which one is it? */
208
		/* which one is it? */
211
		if ( !(strcmp(*cmd, PATH_SCP)) )
209
		if ( !(strcmp(*cmd, PATH_SCP)) )
212
			argvec[2] = "1";
210
			argvec[1] = "1";
213
		else if ( !(strcmp(*cmd, PATH_SFTP_SERVER)) )
211
		else if ( !(strcmp(*cmd, PATH_SFTP_SERVER)) )
214
			argvec[2] = "2";
212
			argvec[1] = "2";
215
		else if ( !(strcmp(*cmd, PATH_CVS)) )
213
		else if ( !(strcmp(*cmd, PATH_CVS)) )
216
			argvec[2] = "3";
214
			argvec[1] = "3";
217
		else if ( !(strcmp(*cmd, PATH_RDIST)) )
215
		else if ( !(strcmp(*cmd, PATH_RDIST)) )
218
			argvec[2] = "4";
216
			argvec[1] = "4";
219
		else if ( !(strcmp(*cmd, PATH_RSYNC)) )
217
		else if ( !(strcmp(*cmd, PATH_RSYNC)) )
220
			argvec[2] = "5";
218
			argvec[1] = "5";
221
		else {
219
		else {
222
			log_set_priority(LOG_ERR);
220
			log_set_priority(LOG_ERR);
223
			log_msg("fatal error identifying the correct command "
221
			log_msg("fatal error identifying the correct command "
224
				"(this should never happen)");
222
				"(this should never happen)");
225
			exit(1);
223
			exit(1);
226
		}
224
		}
227
		if ( !(homedir = extract_root(root, uinfo.pw_dir)) )
225
		argvec[2] = cmdline;
228
			homedir = strdup("/");
226
		argvec[3] = NULL;
229
		argvec[3] = homedir;
230
		argvec[4] = cmdline;
231
		argvec[5] = NULL;
232
227
233
		/* change the command to run to the chroot helper */
228
		/* change the command to run to the chroot helper */
234
		*cmd = PATH_CHROOT_HELPER;
229
		*cmd = PATH_CHROOT_HELPER;
Lines 243-253 Link Here
243
		}
238
		}
244
239
245
		/* stuff the args into the buffer */
240
		/* stuff the args into the buffer */
246
		snprintf(temp, len, "%s \"%s\" %s \"%s\" %s",
241
		snprintf(temp, len, "%s %s \"%s\"",
247
			 PATH_CHROOT_HELPER,
242
			 PATH_CHROOT_HELPER,
248
			 root,
243
			 argvec[1],
249
			 argvec[2],
250
			 homedir,
251
			 cmdline);
244
			 cmdline);
252
245
253
		/* now log 'em */
246
		/* now log 'em */
(-)rssh.1 (-64 / +176 lines)
Lines 1-21 Link Here
1
.\" No comment!
1
.\" No comment!
2
.\"
2
.\"
3
.TH RSSH 1 "7 Jul 2003" "man pages" "Derek D. Martin"
3
.TH RSSH 1 "27 Nov 2005" "man pages" "Derek D. Martin"
4
.SH NAME 
4
.SH NAME 
5
rssh \- restricted secure shell allowing only scp and/or sftp 
5
rssh \- restricted secure shell allowing only scp and/or sftp 
6
.SH SYNOPSIS
6
.SH SYNOPSIS
7
.B rssh 
7
.B rssh 
8
.I -c scp|sftp-server 
9
.RI [ " options... " ] " " [ " ... " ]
8
.RI [ " options... " ] " " [ " ... " ]
10
.br
9
.br
10
.B rssh -v
11
.SH DESCRIPTION
11
.SH DESCRIPTION
12
.B rssh
12
.B rssh
13
is a restricted shell for providing limited access to a host via \fIssh\fP(1), 
13
is a restricted shell for providing limited access to a host via \fBssh\fP(1), 
14
allowing a user whose shell is configured to
14
allowing a user whose shell is configured to
15
.B rssh
15
.B rssh
16
to use one or more of the command(s) \fIscp\fP(1) or \fIsftp\fP(1)
16
to use one or more of the command(s) \fBscp\fP(1), \fBsftp\fP(1)
17
\fIcvs\fP(1), \fIrdist\fP(1), and \fIrsync\fP(1), and 
17
\fBcvs\fP(1), \fBrdist\fP(1), and \fBrsync\fP(1), and 
18
.B only
18
.I only
19
those commands.  It is intended primarily to work with OpenSSH (see
19
those commands.  It is intended primarily to work with OpenSSH (see
20
http://www.openssh.com), but may work with other implementations.
20
http://www.openssh.com), but may work with other implementations.
21
.P
21
.P
Lines 29-43 Link Here
29
.RE
29
.RE
30
.P
30
.P
31
If invoked with the 
31
If invoked with the 
32
.I -v 
32
.B -v 
33
option,
33
option,
34
.B rssh
34
.B rssh
35
will report its version, and exit.  All other arguments to 
35
will report its version, and exit.  All other arguments to 
36
.B rssh
36
.B rssh
37
are those specified by the remote \fIssh\fP(1) client, and aren't of much
37
are those specified by the remote \fBssh\fP(1) client, and aren't of much
38
concern to the average user.  The arguments provided must be what a shell on
38
concern to the average user.  The arguments provided must be what a shell on
39
the remote end would receive in order to pass control to \fIscp\fP(1) or
39
the remote end would receive in order to pass control to \fBscp\fP(1),
40
\fIsftp\fP(1).  If 
40
\fBsftp\fP(1), etc.  If 
41
.B rssh
41
.B rssh
42
receives arguments which do not conform, it will emit an error message and exit.
42
receives arguments which do not conform, it will emit an error message and exit.
43
If the program the user is trying to run is not allowed, or contains syntax
43
If the program the user is trying to run is not allowed, or contains syntax
Lines 45-106 Link Here
45
will also emit an error and exit.
45
will also emit an error and exit.
46
.P
46
.P
47
.B rssh
47
.B rssh
48
has a configuration file, rssh.conf(5), which allows some of the behavior of
48
has a configuration file, \fIrssh.conf\fP(5), which allows some of the
49
behavior of 
49
.B rssh
50
.B rssh
50
to be customized.  See that man page for details.
51
to be customized.  See that man page for details.
51
52
.SH SECURITY NOTES
52
.SH SECURITY NOTES
53
.I Read this section with exceptional care, or you may put your system at risk!
54
.SS Using rssh With CVS
55
If you are using \fBrssh\fP to allow CVS access, it should be noted that it is
56
not possible to prevent a user who is very familiar with CVS from bypassing
57
\fBrssh\fP and getting a shell, unless the user does not have write access in
58
the repository.  Obviously, the user must have write access to the repository
59
in order to update it, which allows them to upload arbitrary programs into the
60
repository.  CVS provides several mechanisms for executing such arbitrary
61
programs...  The only reasonably safe way to use \fBrssh\fP with CVS is to use
62
the chroot jail facilities to place the CVS repository within a chroot jail.
63
Please see below and all relevant documentation for details of how to set up
64
chroot jails.  Note that \fIusers will still be able to get shell access
65
within the jail\fP; the only protection which is provided is that they can not
66
escape the jail.  I have been pursuaded to retain support for CVS because this
67
protection is better than no protection.  
68
.I You have been warned.  Use CVS at your own risk.
69
.SS Potential root Compromise With Old Versions
53
70
54
.SS Command Line Parser
71
Before \fBrssh 2.3.0\fP, if a regular user had shell access to a machine where
55
56
As of 
57
.B rssh
72
.B rssh
58
version 2.2.3, the program must parse out the complete command line to avoid
73
was installed, a root compromise was possible due to 
59
command line options which cause the execution of arbitrary programs (and
74
.B rssh_chroot_helper
60
hence bypass the security of \fBrssh\fP).  In order to keep the program source
75
allowing a user to arbitrarily \fBchroot\fP(2) to anywhere on the filesystem.
61
code sane, the parser is a little over-zealous about matching command line
76
It is possible to mitigate this attack against affected versions of 
62
options.  In practice, this probably will not be an issue, but in theory it is
77
.B rssh
63
possible.  
78
using strict access controls to files, by making sure that the user can not
64
.P 
79
write to any file on the same partition as system executables, and that any
65
If you run into a problem where
80
partition where they can write files does not allow execution of SUID
66
.B rssh
81
programs.  As of \fBrssh 2.3.0\fP, this attack has been prevented by
67
refuses to run, claiming to be rejecting insecure command line options which
82
preventing arbitrary chroot(), \fIif your jail is set up securely\fP.  In
68
were not specified, try changing your command line such that all \fIshort\fP
83
particular, make sure that regular users can not write to directories inside
69
options are specified as single-letter option flags (e.g. -e -p instead of
84
the jail which contain the copied binaries.  That should be obvious, but it
70
-ep) and make sure you separate arguments from their respective options by a
85
needs to be said.  Though it should not be strictly necessary, to further
71
space (e.g. -p 123 instead of -p123).  In virtually all cases, this should
86
protect your system from possible compromise, it is also advisable to follow
72
solve the problem.  Admittedly, an exhaustive search was not performed, but no
87
the section below, entitled "Safeguards Against Bypassing rssh".
73
problematical cases were found which were likely to be common.
74
.P
75
The alternative would have been to include a complete command-line parser for
76
rcp, rdist, and rsync; this was way out of the scope of this project.  In
77
practice, the existing parser should suffice.  If, however, you find cases
78
where it does not, please post details to the rssh mailing list.  Details
79
about how to post to the mailing list can be found at the rssh homepage.
80
.SS Safeguards Against Bypassing rssh
88
.SS Safeguards Against Bypassing rssh
81
82
.B rssh
89
.B rssh
83
is designed to interact with several other programs.  Even if rssh is
90
is designed to interact with several other programs.  Even if rssh is
84
completely bug-free, changes in those other programs could possibly result in methods
91
completely bug-free, changes in those other programs could possibly result in
85
to circumvent the protection that
92
methods to circumvent the protection that
86
.B rssh
93
.B rssh
87
is intended to provide.  \fBIt is important for you, the system administrator,
94
is intended to provide.  \fIIt is important for you, the system administrator,
88
to stay current on the services you make available with rssh, to be sure that
95
to stay current on the services you make available with rssh, to be sure that
89
these commands do\fP \fInot\fP \fBprovide mechanisms to allow the user to run
96
these commands do not provide mechanisms to allow the user to run arbitrary
90
arbitrary commands.\fP Also, while the goal of every release is to be bug
97
commands.\fP Also, while the goal of every release is to be bug free, no one
91
free, no one is perfect...  There may be undiscovered bugs in 
98
is perfect...  There may be undiscovered bugs in 
92
.B rssh 
99
.B rssh 
93
which might allow a user to circumvent it.
100
which might allow a user to circumvent it.
94
.P
101
.P
95
You can protect your system from those who would take advantage of such
102
You can protect your system from those who would take advantage of such
96
weaknesses.  There are three basic steps:
103
weaknesses.  This is not required for \fBrssh\fP to work properly, but it is a
97
104
really good idea.  There are six basic steps:
98
.nf
105
.RS
99
	1. place your users in a chroot jail
106
.TP
100
	2. mount their home filesystem with the noexec option
107
1.
101
	3. use standard file permissions appropriately
108
protect all non-administrator accounts with rssh (i.e. no regular user should have shell access to the server)
102
.fi
109
.TP
103
110
2. 
111
place your users in a chroot jail
112
.TP
113
3. 
114
limit the binaries which live in the jail to the absolute minimum required
115
.TP
116
4. 
117
mount their home filesystem with the noexec/nosuid option (i.e. use
118
separate partitions in the jail for user home directories and all other files,
119
if possible/reasonable)
120
.TP
121
5.
122
create a group for rssh users, and limit executable access to the binaries to
123
users in that group.
124
.TP
125
6. 
126
use standard file permissions carefully and appropriately
127
.RE
128
.P
129
If possible, make sure that no regular user has any kind of shell access to
130
the system other than through \fBrssh\fP.  Otherwise, users with shell access
131
could potentially exploit undiscovered bugs in 
132
.B rssh_chroot_helper 
133
to gain root access to the server.
134
.P
104
.B rssh
135
.B rssh
105
gives the system administrator the ability to place the users in a chroot
136
gives the system administrator the ability to place the users in a chroot
106
jail.  See details in the man page for
137
jail.  See details in the man page for
Lines 113-143 Link Here
113
are trying to provide.  This prevents them from running standard system
144
are trying to provide.  This prevents them from running standard system
114
commands.
145
commands.
115
.P
146
.P
116
Then, make sure the user's files are on a seperate filesystem from your
147
Then, make sure the user's files inside the jail are on a seperate filesystem
117
system's executables.  Make sure you mount this filesystem using the
148
from your system's executables.  If possible in your environment, make sure
118
.I noexec
149
you mount this filesystem using the
119
option, if your operating system provides one.  This prevents the users from
150
.IR noexec " and " nosuid
151
options, if your operating system provides them.  This prevents the users from
120
being able to execute programs which they have uploaded to the target machine
152
being able to execute programs which they have uploaded to the target machine
121
(e.g. using scp) which might otherwise be executable.
153
(e.g. using scp) which might otherwise be executable, and prevents SUID
154
programs from respecting the SUID bits.  Note that these options necessitate
155
the users' files are on separate partitions from the binaries and libraries
156
that live in the jail.  Therefore you will need at least 2 partitions for your
157
jail to do this properly (one for the system binaries in the jail, the other
158
for the user directories).
159
.P
160
Additionally, create a group, for example "rsshuser", for rssh users.  Put all
161
your users who will be restricted by rssh in that group.  Set the ownership
162
and permissions on rssh and rssh_chroot_helper so that only those users can
163
execute them.  The following commands should illustrate:
164
.P
165
.RS
166
.B # groupadd rsshuser
167
.br
168
.B # chown root:rsshuser rssh rssh_chroot_helper
169
.br
170
.B # chmod 550 rssh
171
.br
172
.B # chmod 4550 rssh_chroot_helper
173
.br
174
.RE
122
.P
175
.P
123
Lastly, use standard Unix/POSIX file permissions to ensure they
176
Lastly, use standard Unix/POSIX file permissions to ensure they
124
can not access files they should not be able to within the chroot jail.
177
can not access files they should not be able to within the chroot jail.
178
.SS Command Line Parser
179
As of 
180
.B rssh
181
version 2.2.3, the program must parse out the complete command line to avoid
182
command line options which cause the execution of arbitrary programs (and
183
hence bypass the security of \fBrssh\fP).  In order to keep the program source
184
code sane, the parser is a little over-zealous about matching command line
185
options.  In practice, this probably will not be an issue, but in theory it is
186
possible.  
187
.P 
188
If you run into a problem where
189
.B rssh
190
refuses to run, claiming to be rejecting insecure command line options which
191
were not specified, try changing your command line such that all \fIshort\fP
192
options are specified as single-letter option flags (e.g. -e -p instead of
193
-ep) and make sure you separate arguments from their respective options by a
194
space (e.g. -p 123 instead of -p123).  In virtually all cases, this should
195
solve the problem.  Admittedly, an exhaustive search was not performed, but no
196
problematical cases were found which were likely to be common.
197
.P
198
The alternative would have been to include a complete command-line parser for
199
rcp, rdist, and rsync; this was way out of the scope of this project.  In
200
practice, the existing parser should suffice.  If, however, you find cases
201
where it does not, please post details to the rssh mailing list.  Details
202
about how to post to the mailing list can be found at the rssh homepage.
125
.SS "OpenSSH Versions and Bypassing rssh"
203
.SS "OpenSSH Versions and Bypassing rssh"
126
Prior to OpenSSH 3.5, \fIsshd\fP(8) will generally attempt to parse files in
204
Prior to OpenSSH 3.5, \fBsshd\fP(8) will generally attempt to parse files in
127
the user's home directory, and may also try to run a start-up script from the
205
the user's home directory, and may also try to run a start-up script from the
128
user's
206
user's
129
.I $HOME/.ssh
207
.I $HOME/.ssh
130
directory.  
208
directory.  
131
.B rssh 
209
.B rssh 
132
does not make use of the user's environment in any way.  The relevant command
210
does not make use of the user's environment in any way.  The relevant command
133
is executed by calling \fIexecv\fP(3) with the full path to the command, as
211
is executed by calling \fBexecv\fP(3) with the full path to the command, as
134
specified at compile time.  It does not depend upon the user's PATH variable,
212
specified at compile time.  It does not depend upon the user's PATH variable,
135
or on any other environment variable.
213
or on any other environment variable.
136
.P
214
.P
137
There are, however, several problems that can arise.  This is due entirely to
215
There are, however, several problems that can arise.  This is due entirely to
138
the way the OpenSSH Project's sshd works, and is in no way the fault of
216
the way the OpenSSH Project's sshd works, and is in no way the fault of
139
\fBrssh\fP.  For example, one problem which might exist is that, according to
217
\fBrssh\fP.  For example, one problem which might exist is that, according to
140
the \fIsshd\fP(8) man page from at least some releases of OpenSSH, the
218
the \fBsshd\fP(8) man page from at least some releases of OpenSSH, the
141
commands listed in the
219
commands listed in the
142
.I $HOME/.ssh/rc
220
.I $HOME/.ssh/rc
143
file are executed with
221
file are executed with
Lines 161-167 Link Here
161
.I is
239
.I is
162
vulnerable to this attack, there is a workaround for this problem, though it
240
vulnerable to this attack, there is a workaround for this problem, though it
163
is pretty restrictive.
241
is pretty restrictive.
164
.B  "The user's home directory absolutely must *not* be writable by the user."
242
.I  "The user's home directory absolutely must not be writable by the user."
165
If it is, the user can use sftp to remove the directory or rename it, and then
243
If it is, the user can use sftp to remove the directory or rename it, and then
166
create a new one, and fill it up with whatever environment files they like.  For
244
create a new one, and fill it up with whatever environment files they like.  For
167
providing file uploads, this means a user-writable directory must be created for
245
providing file uploads, this means a user-writable directory must be created for
Lines 193-199 Link Here
193
and disable the default of static compilation.
271
and disable the default of static compilation.
194
.SH BUGS
272
.SH BUGS
195
None.  =8^)
273
None.  =8^)
274
.SS A Note About Getting Help
275
If you are having trouble getting
276
.B rssh
277
working, or you think you've found a bug, please use the mailing list, and
278
.I do not e-mail me
279
\fIdirectly\fP. 
280
You must sign up for the list in order to post.  Information about how to sign
281
up is available on the rssh homepage.  If you mail me directly with questions,
282
I will almost certainly ignore you, or at the very least ask you to repost
283
your question on the mailing list.  Please also feel free to provide feedback
284
about rssh on the mailing list, whether positive or negative (especially
285
negative).
286
.SS Security Problems
287
The only exception to the above is if you believe you have found a security
288
problem with \fBrssh\fP.  If that is the case, then please \fIdo\fP contact me
289
privately.  If you are unable to find my direct contact info, post a message on
290
the mailing list requesting that I contact you about a potential security
291
problem.  Security problems should be dealt with privately, so that the threat
292
can be properly assessed, and so as not to needlessly endanger the
293
installations of \fBrssh\fP in production environments.  I take security
294
problems seriously, and will work to resolve them as quickly as possible.
295
.SS N.B.:
296
Before you e-mail me (or the mailing list) with questions, be sure to 
297
.I THOROUGHLY 
298
read all of the following files: README, INSTALL, CHROOT, SECURITY.  All of
299
these files are distributed with the rssh source code, as well as all binary
300
packages of \fBrssh\fP.  If you downloaded a binary package, these files
301
should be located wherever your distribution keeps its documentation files
302
(usually /usr/share/doc/rssh-version/ or something similar).  Also 
303
.I THOROUGHLY 
304
read the man pages for \fBrssh\fP(1), and \fBrssh.conf\fP(5).  Finally, if you
305
are still having problems, read the FAQ at
306
http://www.pizzashack.org/rssh/faq.shtml.  If it is clear to me that you have
307
not read these documents, I will ignore you.  In most cases, these documents
308
will already have everything you need to get rssh working, and I won't be able
309
to explain it any better on a mailing list than I did in those documents...
196
.SH SEE ALSO
310
.SH SEE ALSO
197
\fIrssh.conf\fP(5), \fIsshd\fP(8), \fIssh\fP(1), \fIscp\fP(1), \fIsftp\fP(1).
311
\fBrssh.conf\fP(5), \fBsshd\fP(8), \fBssh\fP(1), \fBscp\fP(1), \fBsftp\fP(1).
198
199
(-)rssh.conf (-9 / +12 lines)
Lines 19-28 Link Here
19
# the chroot jail will be located.
19
# the chroot jail will be located.
20
#
20
#
21
# if you DO NOT want to chroot users, LEAVE THIS COMMENTED OUT.
21
# if you DO NOT want to chroot users, LEAVE THIS COMMENTED OUT.
22
# You can quote anywhere, but quotes not required unless path contains a
22
# chrootpath = /usr/local/chroot
23
# space... as in this example.
24
23
25
#chrootpath = "/usr/local/chroot dir"
24
# You can quote anywhere, but quotes not required unless the path contains a
25
# space... as in this example.
26
#chrootpath = "/usr/local/my chroot"
26
27
27
##########################################
28
##########################################
28
# EXAMPLES of configuring per-user options
29
# EXAMPLES of configuring per-user options
Lines 30-39 Link Here
30
#user=rudy:077:00010:  # the path can simply be left out to not chroot
31
#user=rudy:077:00010:  # the path can simply be left out to not chroot
31
#user=rudy:077:00010   # the ending colon is optional
32
#user=rudy:077:00010   # the ending colon is optional
32
33
33
#spaces in the path must be quoted...
34
#user=rudy:011:00001:"/usr/local/chroot dir"  # scp with chroot
35
#user=rudy:011:00010:"/usr/local/chroot dir"  # sftp with chroot
36
#user=rudy:011:00011:"/usr/local/chroot dir"  # both with chroot
37
#user=rudy:011:00100:  # cvs, with no chroot 
34
#user=rudy:011:00100:  # cvs, with no chroot 
38
#user=rudy:011:01000:  # rdist, with no chroot
35
#user=rudy:011:01000:  # rdist, with no chroot
39
#user=rudy:011:10000:  # rsync, with no chroot
36
#user=rudy:011:10000:  # rsync, with no chroot
Lines 41-48 Link Here
41
#user=rudy:01"1:00001:/usr/local/chroot"  # or somewhere in the middle, freak!
38
#user=rudy:01"1:00001:/usr/local/chroot"  # or somewhere in the middle, freak!
42
#user=rudy:'011:00001:/usr/local/chroot'  # single quotes too
39
#user=rudy:'011:00001:/usr/local/chroot'  # single quotes too
43
40
41
# if your chroot_path contains spaces, it must be quoted...
42
# In the following examples, the chroot_path is "/usr/local/my chroot"
43
#user=rudy:011:00001:"/usr/local/my chroot"  # scp with chroot
44
#user=rudy:011:00010:"/usr/local/my chroot"  # sftp with chroot
45
#user=rudy:011:00011:"/usr/local/my chroot"  # both with chroot
46
44
# Spaces before or after the '=' are fine, but spaces in chrootpath need
47
# Spaces before or after the '=' are fine, but spaces in chrootpath need
45
# quotes.
48
# quotes.
46
#user = "rudy:011:00001:/usr/local/chroot dir"  
49
#user = "rudy:011:00001:/usr/local/my chroot"  
47
#user = "rudy:011:00001:/usr/local/chroot dir"  # neither do comments at line end
50
#user = "rudy:011:00001:/usr/local/my chroot"  # neither do comments at line end
48
51
(-)rssh.conf.5.in (-8 / +20 lines)
Lines 78-84 Link Here
78
Causes \fBrssh\fP (actually a helper program) to call the 
78
Causes \fBrssh\fP (actually a helper program) to call the 
79
.I chroot() 
79
.I chroot() 
80
system call, changing the root of the file system to whatever directory is
80
system call, changing the root of the file system to whatever directory is
81
specified.  For example:
81
specified.  Note that the value on the right hand side of the equal sign is
82
the name of a directory, not a command.  For example:
82
.P
83
.P
83
chrootpath=/usr/chroot
84
chrootpath=/usr/chroot
84
.P
85
.P
Lines 89-103 Link Here
89
distribution for hints about how to do this.  See also the \fIchroot\fP(2) man
90
distribution for hints about how to do this.  See also the \fIchroot\fP(2) man
90
page.
91
page.
91
.P
92
.P
92
If the user's home directory (as specified in /etc/password) is underneath the
93
If the user's home directory (as specified in \fI/etc/passwd\fP) is underneath
93
path specified by this keyword, then the user will be chdir'd into their home
94
the path specified by this keyword, then the user will be chdir'd into their
94
directory.  If it is not, then they will be chdir'd to the root of the chroot
95
home directory.  If it is not, then they will be chdir'd to the root of the
95
jail.
96
chroot jail.
97
.P
98
In other words, if the jail is \fI/chroot\fP, and your user's home directory
99
is \fI/chroot/home/user\fP, then once \fBrssh_chroot_helper\fP changes the
100
root of the system, it will cd into \fI/home/user\fP inside the jail.
101
However, if your user's home directory is given as \fI/home/user\fP in
102
\fI/etc/passwd\fP, then even if that directory exists in the jail, the chroot
103
helper will not try to cd there.  The user's normal home directory must live
104
inside the jail for this to work.
96
.RE
105
.RE
106
.P
97
.B user
107
.B user
98
.RS
108
.RS
99
The user keyword allows for the configuration of options on a per-user basis.
109
The user keyword allows for the configuration of options on a per-user basis.
100
.B THIS KEYWORD OVERRIDES ALL OTHER KEYWORDS FOR THE SPECIFIED USER.
110
.I THIS KEYWORD OVERRIDES ALL OTHER KEYWORDS FOR THE SPECIFIED USER.
101
That is, if you use a user keyword for user foo, then foo will use only the
111
That is, if you use a user keyword for user foo, then foo will use only the
102
settings in that user line, and not any of the settings set with the keywords
112
settings in that user line, and not any of the settings set with the keywords
103
above.  The user keyword's argument consists of a group of fields separated by
113
above.  The user keyword's argument consists of a group of fields separated by
Lines 119-125 Link Here
119
.RE
129
.RE
120
.B path
130
.B path
121
.RS
131
.RS
122
The path to which this user should be chrooted
132
The \fIdirectory\fP to which this user should be chrooted (this is not a
133
command, it is a directory name).  See \fBchroot_path\fP above for complete
134
details.
123
.RE
135
.RE
124
.P
136
.P
125
For example, you might have something like this:
137
For example, you might have something like this:
Lines 131-137 Link Here
131
specified, the user will 
143
specified, the user will 
132
.I not 
144
.I not 
133
be chrooted, 
145
be chrooted, 
134
.B regardless of default options set with the keywords above.
146
.I regardless of default options set with the keywords above.
135
If you wanted this user to be chrooted, you would need to specify the chroot
147
If you wanted this user to be chrooted, you would need to specify the chroot
136
path explicitly, even if it should be the same as that set using the
148
path explicitly, even if it should be the same as that set using the
137
chrootpath keyword.  Remember that if there are spaces in the path, you need
149
chrootpath keyword.  Remember that if there are spaces in the path, you need
(-)rssh_chroot_helper.c (-41 / +133 lines)
Lines 31-50 Link Here
31
#ifdef HAVE_CONFIG_H
31
#ifdef HAVE_CONFIG_H
32
#include "config.h"
32
#include "config.h"
33
#endif /* HAVE_CONFIG_H */
33
#endif /* HAVE_CONFIG_H */
34
#ifdef HAVE_CONFIG_H
35
#include "config.h"
36
#endif /* HAVE_CONFIG_H */
34
#include <stdio.h>
37
#include <stdio.h>
38
#ifdef HAVE_STDLIB_H
35
#include <stdlib.h>
39
#include <stdlib.h>
40
#endif /* HAVE_STDLIB_H */
41
#ifdef HAVE_UNISTD_H
36
#include <unistd.h>
42
#include <unistd.h>
43
#endif /* HAVE_UNISTD_H */
44
#ifdef HAVE_ERRNO_H 
37
#include <errno.h>
45
#include <errno.h>
46
#endif /* HAVE_ERRNO_H */
47
#ifdef HAVE_STRING_H
38
#include <string.h>
48
#include <string.h>
49
#endif /* HAVE_STRING_H */
50
#ifdef HAVE_LIBGEN_H
39
#include <libgen.h>
51
#include <libgen.h>
52
#endif /* HAVE_LIBGEN_H */
53
#ifdef HAVE_SYSLOG_H
40
#include <syslog.h>
54
#include <syslog.h>
55
#endif /* HAVE_SYSLOG_H */ 
56
#ifdef HAVE_PWD_H
41
#include <pwd.h>
57
#include <pwd.h>
58
#endif /* HAVE_PWD_H */
59
#ifdef HAVE_SYS_TYPES_H
42
#include <sys/types.h>
60
#include <sys/types.h>
61
#endif /* HAVE_SYS_TYPES_H */
62
#ifdef HAVE_SYS_STAT_H
43
#include <sys/stat.h>
63
#include <sys/stat.h>
64
#endif /* HAVE_SYS_STAT_H */
65
44
66
45
/* LOCAL INCLUDES */
67
/* LOCAL INCLUDES */
68
#include "rssh.h"
69
#include "rsshconf.h"
46
#include "pathnames.h"
70
#include "pathnames.h"
47
#include "log.h"
71
#include "log.h"
72
#include "util.h"
48
#include "argvec.h"
73
#include "argvec.h"
49
74
50
/* GLOBAL VARIABLES */
75
/* GLOBAL VARIABLES */
Lines 58-89 Link Here
58
/* FILE SCOPE FUNCTIONS */
83
/* FILE SCOPE FUNCTIONS */
59
84
60
85
61
char *get_username( void )
62
{
63
	struct passwd	*temp;
64
65
	if ( !(temp = getpwuid(getuid()) ) ) return NULL;
66
	return temp->pw_name;
67
}
68
69
70
void ch_start_logging( void )
86
void ch_start_logging( void )
71
{
87
{
72
	/* set up logging */
88
	/* set up logging - username should be set before this is called */
73
	if ( log_init ) return;
89
	if ( log_init ) return;
74
	username = get_username();
75
	log_set_facility(LOG_USER);
90
	log_set_facility(LOG_USER);
76
	log_set_priority(LOG_INFO);
91
	log_set_priority(LOG_INFO);
77
	log_open();
92
	log_open();
78
	log_msg("new session for %s, UID=%d", 
93
	log_msg("new session for %s, UID=%d", username, getuid());
79
		username ? username : "unknown user",
80
		getuid());
81
	/* all log messages from this point on are errors */
94
	/* all log messages from this point on are errors */
82
	log_set_priority(LOG_ERR);
95
	log_set_priority(LOG_ERR);
83
	log_init = 1;
96
	log_init = 1;
84
}
97
}
85
98
86
void ch_fatal_syscall( char *func, char *arg, char *strerr )
99
void ch_fatal_error( char *func, char *arg, char *strerr )
87
{
100
{
88
101
89
	/* drop privileges */
102
	/* drop privileges */
Lines 101-145 Link Here
101
int main( int argc, char **argv )
114
int main( int argc, char **argv )
102
{
115
{
103
	struct stat	s;
116
	struct stat	s;
117
	ShellOptions_t	opts;
104
	long int	cmd;
118
	long int	cmd;
105
	char		*conv;
119
	char		*conv;
106
	char		**argvec;
120
	char		**argvec;
121
	char		*cmd_path;
122
	char		*homedir;
123
	struct passwd	uinfo;
124
	struct passwd	*temp;
125
126
	/* 
127
	 * Unfortunately, in order to maintain security, a lot of the code
128
	 * from the rssh main program must be duplicated.  Specifically, the
129
	 * config file must be parsed to get the chroot path, in order to
130
	 * prevent a user from being able to chroot() arbitrarily, which leads
131
	 * to easy root compromise if a user has shell access to the system.
132
	 * build_arg_vector() must be done here instead of in the main
133
	 * program, in order to prevent a directory transversal attack.
134
	 */ 
135
136
	/*
137
	 * As a possible future security enhancement, it should be possible to
138
	 * have rssh_chroot_helper authenticate cryptographically that it was
139
	 * exec()'d by rssh.  If rssh is SGID to some rssh-users group, it
140
	 * could store the public key for rssh_chroot_helper in a file which
141
	 * is only readable by that group.  Since rssh_chroot_helper is
142
	 * already SUID root, it could store its private key in some file that
143
	 * is only readable by root.  Obviously, care should be taken that no
144
	 * user who has shell access to the system can become a member of the
145
	 * rssh-users group.  The only thing stopping me from coding that now
146
	 * is my lack of knowledge of cryptographic programming.  
147
	 *
148
	 * As a further precaution, all users whose accounts will be protected
149
	 * by rssh should be in the rssh-users group, and both rssh and
150
	 * rssh_chroot_helper should be executable only by that group.  This
151
	 * can be done now, even without any cryptography.
152
	 */
153
154
	/* THIS CODE IS EXPOSED AS ROOT! */
155
156
	/* initialize variables to defaults */
157
	opts.rssh_umask = 022;
158
	opts.shell_flags = 0;
159
	opts.chroot_path = NULL;
107
160
108
	/* figure out our name, and give it to the log module */
161
	/* figure out our name, and give it to the log module */
109
	progname = strdup(log_make_ident(basename(argv[0])));
162
	progname = strdup(log_make_ident(basename(argv[0])));
110
163
164
	/* get user's passwd info */
165
	if ( (temp = getpwuid(getuid())) ){
166
		uinfo = *temp;
167
		username = uinfo.pw_name;
168
	}
169
	else
170
		/* this probably should never happen */
171
		username = "unknown user!";
172
111
	/* make sure we have enough arguments, or exit with error */
173
	/* make sure we have enough arguments, or exit with error */
112
	if ( argc < 5 ) 
174
	if ( argc != 3 ) ch_fatal_error(progname, "invalid arguments", 
113
		/* cheating, since this isn't a system call problem... */
175
	                                "wrong number of arguments");
114
		ch_fatal_syscall("rssh_chroot_helper", "invalid argument(s)",
176
115
				 "not enough arguments");
177
	/* process the config file, don't log */
178
	if ( !(read_shell_config(&opts, PATH_RSSH_CONFIG, 0)) ){
179
		ch_fatal_error("read_shell_config()", PATH_RSSH_CONFIG,
180
				"errors processing configuration file!");
181
	}
116
182
117
	/* 
183
	/* 
118
	 * argv[1] is the directory to chroot to.  Check to make sure it
184
	 * opts.chroot_path is directory to chroot to.  Check to make sure it
119
	 * exists.  If it does, chroot and drop privileges, and cd to it.
185
	 * exists.  If it does, chroot and drop privileges, and cd to it.
120
	 */
186
	 */
121
187
122
	if ( stat(argv[1], &s) == -1 )
188
	if ( stat(opts.chroot_path, &s) == -1 )
123
		ch_fatal_syscall("stat()", argv[1], strerror(errno));
189
		ch_fatal_error("stat()", argv[1], strerror(errno));
124
	if ( chroot(argv[1]) == -1 )
190
	if ( chroot(opts.chroot_path) == -1 )
125
		ch_fatal_syscall("chroot()", argv[1], strerror(errno));
191
		ch_fatal_error("chroot()", argv[1], strerror(errno));
192
193
	/* END OF CODE EXPOSED AS ROOT! */
126
194
127
	setuid(getuid());
195
	setuid(getuid());
128
	ch_start_logging();
196
	ch_start_logging();
129
197
130
	if ( !(argvec = build_arg_vector(argv[4], 0)) )
198
	log_msg("user's home dir is %s", uinfo.pw_dir);
131
		ch_fatal_syscall("build_arg_vector()", argv[4],
132
				"bad expansion");
133
199
134
	/* make sure we can change directory to the user's dir */
200
	/* get the user's home dir */ 
135
	if ( chdir(argv[3]) == -1 ){
201
	if ( !(homedir = extract_root(opts.chroot_path, uinfo.pw_dir)) ){
136
		log_msg("could not cd to user's home dir: %s", argv[3]);
202
		log_msg("couldn't find %s in chroot jail", uinfo.pw_dir);
137
		if ( chdir("/") )
203
		homedir = strdup("/");
138
			ch_fatal_syscall("chdir()", "/", strerror(errno));
139
	}
204
	}
140
205
141
	/* argv[2] is "1" if scp, "2" if sftp, ... */
206
	log_msg("chrooted to %s", opts.chroot_path);
142
	cmd = strtol(argv[2], &conv, 10);
207
	log_msg("changing working directory to %s (inside jail)", homedir);
208
209
	/* cd into / to avoid possibility of breaking out of the jail */
210
	if ( chdir("/") )
211
		ch_fatal_error("chdir()", "/", strerror(errno));
212
213
	/* make sure we can change directory to the user's dir */
214
	if ( chdir(homedir) == -1 )
215
		log_msg("could not cd to user's home dir: %s", homedir);
216
217
	if ( !(argvec = build_arg_vector(argv[2], 0)) )
218
		ch_fatal_error("build_arg_vector()", argv[2],
219
				"bad expansion");
220
221
	/* 
222
	 * This is the old way to figure out what program to run.  Since we're
223
	 * re-parsing the config file in rssh_chroot helper, we could get rid
224
	 * of this and redetermine it from the command line, and re-parse
225
	 * whether or not it's ok to run that command.  But, I don't think
226
	 * that's really necessary, nor worth the effort.  A user who is
227
	 * restricted by rssh will not be able to gain access to manipulate
228
	 * this on the command line, and a user who has full shell access
229
	 * can't gain anything they couldn't already do by manipulating it...
230
	 * so it seems OK to leave as is.
231
	 */
232
233
	/* argv[1] is "1" if scp, "2" if sftp, ... */
234
	cmd = strtol(argv[1], &conv, 10);
143
	if ( *conv ){
235
	if ( *conv ){
144
		log_msg("command identifier contained invalid chars");
236
		log_msg("command identifier contained invalid chars");
145
		exit(2);
237
		exit(2);
Lines 148-166 Link Here
148
	/* ok... what were we supposed to run? */
240
	/* ok... what were we supposed to run? */
149
	switch (cmd){
241
	switch (cmd){
150
	case 1:
242
	case 1:
151
		argv[3] = PATH_SCP;
243
		cmd_path = PATH_SCP;
152
		break;
244
		break;
153
	case 2:
245
	case 2:
154
		argv[3] = PATH_SFTP_SERVER;
246
		cmd_path = PATH_SFTP_SERVER;
155
		break;
247
		break;
156
	case 3:
248
	case 3:
157
		argv[3] = PATH_CVS;
249
		cmd_path = PATH_CVS;
158
		break;
250
		break;
159
	case 4:
251
	case 4:
160
		argv[3] = PATH_RDIST;
252
		cmd_path = PATH_RDIST;
161
		break;
253
		break;
162
	case 5:
254
	case 5:
163
		argv[3] = PATH_RSYNC;
255
		cmd_path = PATH_RSYNC;
164
		break;
256
		break;
165
	default:
257
	default:
166
		log_msg("invalid command specified");
258
		log_msg("invalid command specified");
Lines 168-177 Link Here
168
	}
260
	}
169
261
170
	/* now run it */
262
	/* now run it */
171
	execv(argv[3], argvec);
263
	execv(cmd_path, argvec);
172
264
173
	/* we only get here if the exec fails */
265
	/* we only get here if the exec fails */
174
	ch_fatal_syscall("execv()", argv[3], strerror(errno));
266
	ch_fatal_error("execv()", cmd_path, strerror(errno));
175
	/* and we never get here, but it shuts gcc up */
267
	/* and we never get here, but it shuts gcc up */
176
	exit(1);
268
	exit(1);
177
}
269
}
(-)rsshconf.c (-71 / +135 lines)
Lines 78-83 Link Here
78
	NULL
78
	NULL
79
};
79
};
80
80
81
int log=0;
81
82
82
/* flag to tell config parser to stop processing config file */
83
/* flag to tell config parser to stop processing config file */
83
static bool got_user_config = FALSE;
84
static bool got_user_config = FALSE;
Lines 124-139 Link Here
124
/* EXTERNALLY VISIBLE FUNCTIONS */
125
/* EXTERNALLY VISIBLE FUNCTIONS */
125
126
126
/* returns FALSE if there was an error, TRUE if not */
127
/* returns FALSE if there was an error, TRUE if not */
127
int read_shell_config( ShellOptions_t *opts, const char *filename )
128
int read_shell_config( ShellOptions_t *opts, const char *filename, int do_log )
128
{
129
{
129
        FILE 	*cfg_file;		/* config file ptr */
130
        FILE 	*cfg_file;		/* config file ptr */
130
        int 	linenum;		/* cfg file line counter */
131
        int 	linenum;		/* cfg file line counter */
131
	int 	status = TRUE;		/* were all the cfg lines good? */
132
	int 	status = TRUE;		/* were all the cfg lines good? */
132
        char 	line[CFG_LINE_LEN + 1];	/* buffer to hold region */
133
        char 	line[CFG_LINE_LEN + 1];	/* buffer to hold region */
133
134
135
	log = do_log;
134
	memset(line, 0, CFG_LINE_LEN + 1);
136
	memset(line, 0, CFG_LINE_LEN + 1);
135
        cfg_file = fopen(filename, "r");
137
        cfg_file = fopen(filename, "r");
136
        if (!cfg_file) {
138
        if (!cfg_file && log ) {
137
		log_set_priority(LOG_WARNING);
139
		log_set_priority(LOG_WARNING);
138
		log_msg("config file (%s) missing, using defaults", filename);
140
		log_msg("config file (%s) missing, using defaults", filename);
139
                opts->shell_flags = RSSH_ALLOW_SCP;
141
                opts->shell_flags = RSSH_ALLOW_SCP;
Lines 169-176 Link Here
169
		*newline = '\0';
171
		*newline = '\0';
170
	else {
172
	else {
171
		/* there is no newline - log the error and find the EOL */
173
		/* there is no newline - log the error and find the EOL */
172
		log_set_priority(LOG_ERR);
174
		if (log){
173
		log_msg("line %d: line too long", lineno);
175
			log_set_priority(LOG_ERR);
176
			log_msg("line %d: line too long", lineno);
177
		}
174
		while ( fgets(tmp, CFG_LINE_LEN, cfg_file) ){
178
		while ( fgets(tmp, CFG_LINE_LEN, cfg_file) ){
175
			if ( (newline = strchr(line, '\n')) )
179
			if ( (newline = strchr(line, '\n')) )
176
				break;
180
				break;
Lines 234-242 Link Here
234
		return TRUE;
238
		return TRUE;
235
	default:
239
	default:
236
		/* the keyword is unknown */
240
		/* the keyword is unknown */
237
		log_set_priority(LOG_ERR);
241
		if (log){
238
		log_msg("line %d: syntax error parsing config file", lineno);
242
			log_set_priority(LOG_ERR);
239
		if ( keywrd[0] )
243
			log_msg("line %d: syntax error parsing config file",
244
				       	lineno);
245
		}
246
		if ( keywrd[0] && log )
240
			log_msg("unknown keyword: %s", keywrd);
247
			log_msg("unknown keyword: %s", keywrd);
241
		return FALSE;
248
		return FALSE;
242
	}
249
	}
Lines 320-327 Link Here
320
	/* initialize strings and pointers */
327
	/* initialize strings and pointers */
321
	memset(buf, 0, buflen);
328
	memset(buf, 0, buflen);
322
	if ( !(copy = strdup(str)) ){
329
	if ( !(copy = strdup(str)) ){
323
		log_set_priority(LOG_ERR);
330
		if (log){
324
		log_msg("OOM error in get_token() (fatal)");
331
			log_set_priority(LOG_ERR);
332
			log_msg("OOM error in get_token() (fatal)");
333
		}
325
		exit(1);
334
		exit(1);
326
	}
335
	}
327
	start = copy;
336
	start = copy;
Lines 421-431 Link Here
421
		       const int lineno )
430
		       const int lineno )
422
{
431
{
423
	if ( !eat_comment(line) ){
432
	if ( !eat_comment(line) ){
424
		log_msg("line %d: syntax error parsing config file", lineno);
433
		if (log) log_msg("line %d: syntax error parsing config file",
434
				       	lineno);
425
		return FALSE;
435
		return FALSE;
426
	}
436
	}
427
	log_set_priority(LOG_INFO);
437
	if (log){
428
	log_msg("allowing scp to all users");
438
		log_set_priority(LOG_INFO);
439
		log_msg("allowing scp to all users");
440
	}
429
	opts->shell_flags |= RSSH_ALLOW_SCP;
441
	opts->shell_flags |= RSSH_ALLOW_SCP;
430
	return TRUE;
442
	return TRUE;
431
}
443
}
Lines 445-455 Link Here
445
	int pos;
457
	int pos;
446
458
447
	if ( !(pos = eat_comment(line)) ){
459
	if ( !(pos = eat_comment(line)) ){
448
		log_msg("line %d: syntax error parsing config file", lineno);
460
		if (log) log_msg("line %d: syntax error parsing config file", 
461
				lineno);
449
		return FALSE;
462
		return FALSE;
450
	}
463
	}
451
	log_set_priority(LOG_INFO);
464
	if (log){
452
	log_msg("allowing sftp to all users");
465
		log_set_priority(LOG_INFO);
466
		log_msg("allowing sftp to all users");
467
	}
453
	opts->shell_flags |= RSSH_ALLOW_SFTP;
468
	opts->shell_flags |= RSSH_ALLOW_SFTP;
454
	return TRUE;
469
	return TRUE;
455
}
470
}
Lines 470-480 Link Here
470
	int pos;
485
	int pos;
471
486
472
	if ( !(pos = eat_comment(line)) ){
487
	if ( !(pos = eat_comment(line)) ){
473
		log_msg("line %d: syntax error parsing config file", lineno);
488
		if (log) log_msg("line %d: syntax error parsing config file", 
489
				lineno);
474
		return FALSE;
490
		return FALSE;
475
	}
491
	}
476
	log_set_priority(LOG_INFO);
492
	if (log){
477
	log_msg("allowing cvs to all users");
493
		log_set_priority(LOG_INFO);
494
		log_msg("allowing cvs to all users");
495
	}
478
	opts->shell_flags |= RSSH_ALLOW_CVS;
496
	opts->shell_flags |= RSSH_ALLOW_CVS;
479
	return TRUE;
497
	return TRUE;
480
}
498
}
Lines 495-506 Link Here
495
	int pos;
513
	int pos;
496
514
497
	if ( !(pos = eat_comment(line)) ){
515
	if ( !(pos = eat_comment(line)) ){
498
		log_msg("line %d: syntax error parsing config file", lineno);
516
		if (log) log_msg("line %d: syntax error parsing config file", 
517
				lineno);
499
		return FALSE;
518
		return FALSE;
500
	}
519
	}
501
	log_set_priority(LOG_INFO);
520
	log_set_priority(LOG_INFO);
502
	log_msg("allowing rdist to all users");
521
	if (log){
503
	opts->shell_flags |= RSSH_ALLOW_RDIST;
522
		log_msg("allowing rdist to all users");
523
		opts->shell_flags |= RSSH_ALLOW_RDIST;
524
	}
504
	return TRUE;
525
	return TRUE;
505
}
526
}
506
527
Lines 520-530 Link Here
520
	int pos;
541
	int pos;
521
542
522
	if ( !(pos = eat_comment(line)) ){
543
	if ( !(pos = eat_comment(line)) ){
523
		log_msg("line %d: syntax error parsing config file", lineno);
544
		if (log) log_msg("line %d: syntax error parsing config file", 
545
				lineno);
524
		return FALSE;
546
		return FALSE;
525
	}
547
	}
526
	log_set_priority(LOG_INFO);
548
	if (log){
527
	log_msg("allowing rsync to all users");
549
		log_set_priority(LOG_INFO);
550
		log_msg("allowing rsync to all users");
551
	}
528
	opts->shell_flags |= RSSH_ALLOW_RSYNC;
552
	opts->shell_flags |= RSSH_ALLOW_RSYNC;
529
	return TRUE;
553
	return TRUE;
530
}
554
}
Lines 546-552 Link Here
546
	 */
570
	 */
547
571
548
	if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){
572
	if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){
549
		log_msg("fatal error: can't allocate space for chroot path");
573
		if (log) log_msg("fatal error: can't allocate space for chroot path");
550
		exit(1);
574
		exit(1);
551
	}
575
	}
552
	/* get_asgn_param() eats trailing comments, so we won't */
576
	/* get_asgn_param() eats trailing comments, so we won't */
Lines 557-564 Link Here
557
	
581
	
558
	/* get rid of any old value for chroot path, assign new one */
582
	/* get rid of any old value for chroot path, assign new one */
559
	if ( opts->chroot_path ) free(opts->chroot_path);
583
	if ( opts->chroot_path ) free(opts->chroot_path);
560
	log_set_priority(LOG_INFO);
584
	if (log){
561
	log_msg("chrooting all users to %s", temp);
585
		log_set_priority(LOG_INFO);
586
		log_msg("chrooting all users to %s", temp);
587
	}
562
	/* we must not free temp, since opts points to it */
588
	/* we must not free temp, since opts points to it */
563
	opts->chroot_path = temp;
589
	opts->chroot_path = temp;
564
	opts->shell_flags |= RSSH_USE_CHROOT;
590
	opts->shell_flags |= RSSH_USE_CHROOT;
Lines 576-583 Link Here
576
	int	pos;
602
	int	pos;
577
603
578
	if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){
604
	if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){
579
		log_set_priority(LOG_ERR);
605
		if (log){
580
		log_msg("fatal error: can't allocate space for log facility");
606
			log_set_priority(LOG_ERR);
607
			log_msg("fatal error: can't allocate space for log facility");
608
		}
581
		exit(1);
609
		exit(1);
582
	}
610
	}
583
	/* this eats trailing comments */
611
	/* this eats trailing comments */
Lines 747-763 Link Here
747
775
748
	free(temp);
776
	free(temp);
749
	if ( !eat_comment(line + pos) ){
777
	if ( !eat_comment(line + pos) ){
750
		log_msg("line %d: syntax error parsing config file", lineno);
778
		if (log) log_msg("line %d: syntax error parsing config file", 
779
				lineno);
751
		return FALSE;
780
		return FALSE;
752
	}
781
	}
753
	if ( facname ){
782
	if ( facname ){
754
		log_set_priority(LOG_INFO);
783
		log_set_priority(LOG_INFO);
755
		log_msg("setting log facility to %s", facname);
784
		if (log) log_msg("setting log facility to %s", facname);
756
		log_set_facility(fac);
785
		log_set_facility(fac);
757
		return TRUE;
786
		return TRUE;
758
	}
787
	}
759
	log_msg("line %d: unknown log facility specified", lineno);
788
	if (log){
760
	log_set_facility(LOG_USER);
789
		log_msg("line %d: unknown log facility specified", lineno);
790
		log_set_facility(LOG_USER);
791
	}
761
	return FALSE;
792
	return FALSE;
762
}
793
}
763
794
Lines 770-777 Link Here
770
	int	mask;		/* umask */
801
	int	mask;		/* umask */
771
802
772
	if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){
803
	if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){
773
		log_set_priority(LOG_ERR);
804
		if (log){
774
		log_msg("fatal error: can't allocate space in process_umask()");
805
			log_set_priority(LOG_ERR);
806
			log_msg("fatal error: can't allocate space in process_umask()");
807
		}
775
		exit(1);
808
		exit(1);
776
	}
809
	}
777
	/* this eats trailing comments */
810
	/* this eats trailing comments */
Lines 782-796 Link Here
782
815
783
	/* convert the umask to a number */
816
	/* convert the umask to a number */
784
	if ( !validate_umask(temp, &mask) ){
817
	if ( !validate_umask(temp, &mask) ){
785
		log_set_priority(LOG_WARNING);
818
		if (log){
786
		log_msg("line %d: invalid umask specified, using default 077",
819
			log_set_priority(LOG_WARNING);
820
			log_msg("line %d: invalid umask specified, using default 077",
787
			lineno);
821
			lineno);
822
		}
788
		opts->rssh_umask = 077;
823
		opts->rssh_umask = 077;
789
		free(temp);
824
		free(temp);
790
		return FALSE;
825
		return FALSE;
791
	}
826
	}
792
	log_set_priority(LOG_INFO);
827
	if (log){
793
	log_msg("setting umask to %#o", mask);
828
		log_set_priority(LOG_INFO);
829
		log_msg("setting umask to %#o", mask);
830
	}
794
	opts->rssh_umask = mask;
831
	opts->rssh_umask = mask;
795
	free(temp);
832
	free(temp);
796
	return TRUE;
833
	return TRUE;
Lines 817-823 Link Here
817
854
818
	/* make space for user options */
855
	/* make space for user options */
819
	if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){
856
	if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){
820
		log_msg("fatal error: can't allocate space for user options");
857
		if (log) log_msg("fatal error: can't allocate space for user options");
821
		exit(1);
858
		exit(1);
822
	}
859
	}
823
860
Lines 831-838 Link Here
831
868
832
	/* now process individual config bits of temp */
869
	/* now process individual config bits of temp */
833
	if ( !(pos = get_token(temp, user, CFG_LINE_LEN + 1, TRUE, TRUE )) ){
870
	if ( !(pos = get_token(temp, user, CFG_LINE_LEN + 1, TRUE, TRUE )) ){
834
		log_set_priority(LOG_ERR);
871
		if (log){
835
		log_msg("syntax error parsing config file, line %d", lineno);
872
			log_set_priority(LOG_ERR);
873
			log_msg("syntax error parsing config file, line %d", 
874
					lineno);
875
		}
836
		return FALSE;
876
		return FALSE;
837
	}
877
	}
838
878
Lines 845-854 Link Here
845
	 * user lines we don't care about...
885
	 * user lines we don't care about...
846
	 */
886
	 */
847
	if ( (strcmp(user, username)) ) return TRUE;
887
	if ( (strcmp(user, username)) ) return TRUE;
848
	log_set_priority(LOG_INFO);
888
	if (log){
849
	log_msg("line %d: configuring user %s", lineno, user);
889
		log_set_priority(LOG_INFO);
890
		log_msg("line %d: configuring user %s", lineno, user);
891
	}
850
	if ( !(len = eat_colon(temp + pos)) ){
892
	if ( !(len = eat_colon(temp + pos)) ){
851
		log_msg("syntax error parsing config file: line %d ", lineno);
893
		if (log) log_msg("syntax error parsing config file: line %d ", 
894
				lineno);
852
		return FALSE;
895
		return FALSE;
853
	}
896
	}
854
	pos += len;
897
	pos += len;
Lines 856-883 Link Here
856
	/* do the umask, but validate it last, since it's non-fatal */
899
	/* do the umask, but validate it last, since it's non-fatal */
857
	if ( !(len = get_token(temp + pos, mask, CFG_LINE_LEN + 1, 
900
	if ( !(len = get_token(temp + pos, mask, CFG_LINE_LEN + 1, 
858
			       TRUE, FALSE)) ){
901
			       TRUE, FALSE)) ){
859
		log_set_priority(LOG_ERR);
902
		if (log){
860
		log_msg("syntax error parsing user umask, line %d", lineno);
903
			log_set_priority(LOG_ERR);
904
			log_msg("syntax error parsing user umask, line %d", lineno);
905
		}
861
		return FALSE;
906
		return FALSE;
862
	}
907
	}
863
	pos += len;
908
	pos += len;
864
909
865
	/* do the access bits */
910
	/* do the access bits */
866
	if ( !(len = eat_colon(temp + pos)) ){
911
	if ( !(len = eat_colon(temp + pos)) ){
867
		log_msg("syntax error parsing config file: line %d ", lineno);
912
		if (log) log_msg("syntax error parsing config file: line %d ", 
913
				lineno);
868
		return FALSE;
914
		return FALSE;
869
	}
915
	}
870
	pos += len;
916
	pos += len;
871
	if ( !(len = get_token(temp + pos, axs, CFG_LINE_LEN + 1, 
917
	if ( !(len = get_token(temp + pos, axs, CFG_LINE_LEN + 1, 
872
			       TRUE, FALSE)) ){
918
			       TRUE, FALSE)) ){
873
		log_set_priority(LOG_ERR);
919
		if (log){
874
		log_msg("syntax error parsing user access, line %d", lineno);
920
			log_set_priority(LOG_ERR);
921
			log_msg("syntax error parsing user access, line %d", lineno);
922
		}
875
		return FALSE;
923
		return FALSE;
876
	}
924
	}
877
	if ( !validate_access(axs, &allow_sftp, &allow_scp, &allow_cvs,
925
	if ( !validate_access(axs, &allow_sftp, &allow_scp, &allow_cvs,
878
			      &allow_rdist, &allow_rsync) ){
926
			      &allow_rdist, &allow_rsync) ){
879
		log_set_priority(LOG_ERR);
927
		if (log){
880
		log_msg("syntax error parsing access bits, line %d", lineno);
928
			log_set_priority(LOG_ERR);
929
			log_msg("syntax error parsing access bits, line %d", lineno);
930
		}
881
		return FALSE;
931
		return FALSE;
882
	}
932
	}
883
	pos += len;
933
	pos += len;
Lines 886-892 Link Here
886
	if ( !(len = eat_colon(temp + pos)) ) goto cleanup;
936
	if ( !(len = eat_colon(temp + pos)) ) goto cleanup;
887
	pos += len;
937
	pos += len;
888
	if ( !(path = (char *)malloc(CFG_LINE_LEN + 1)) ){
938
	if ( !(path = (char *)malloc(CFG_LINE_LEN + 1)) ){
889
		log_msg("fatal error: can't allocate space for chroot path");
939
		if (log) log_msg("fatal error: can't allocate space for chroot path");
890
		exit(1);
940
		exit(1);
891
	}
941
	}
892
	if ( !(len = get_token(temp + pos, path, CFG_LINE_LEN + 1, 
942
	if ( !(len = get_token(temp + pos, path, CFG_LINE_LEN + 1, 
Lines 900-919 Link Here
900
	/* make sure nothing is left */
950
	/* make sure nothing is left */
901
	while ( *(temp + pos) != '\0' && isspace(*(temp + pos)) ) pos++;
951
	while ( *(temp + pos) != '\0' && isspace(*(temp + pos)) ) pos++;
902
	if ( *(temp + pos) != '\0' ){
952
	if ( *(temp + pos) != '\0' ){
903
		log_set_priority(LOG_ERR);
953
		if (log){
904
		log_msg("syntax error parsing user config: line %d", lineno);
954
			log_set_priority(LOG_ERR);
955
			log_msg("syntax error parsing user config: line %d", lineno);
956
		}
905
		return FALSE;
957
		return FALSE;
906
	}
958
	}
907
959
908
	/* now finally validate the umask */
960
	/* now finally validate the umask */
909
	if ( !validate_umask(mask, &tmpmask) ){
961
	if ( !validate_umask(mask, &tmpmask) ){
910
		log_set_priority(LOG_WARNING);
962
		if (log){
911
		log_msg("line %d: invalid umask specified, using default",
963
			log_set_priority(LOG_WARNING);
964
			log_msg("line %d: invalid umask specified, using default",
912
			lineno);
965
			lineno);
966
		}
913
		tmpmask = 077;
967
		tmpmask = 077;
914
	} 
968
	} 
915
	log_set_priority(LOG_INFO);
969
	if (log){
916
	log_msg("setting %s's umask to %#o", user, tmpmask);
970
		log_set_priority(LOG_INFO);
971
		log_msg("setting %s's umask to %#o", user, tmpmask);
972
	}
917
	opts->rssh_umask = tmpmask;
973
	opts->rssh_umask = tmpmask;
918
974
919
	/* set the rest of the parameters */
975
	/* set the rest of the parameters */
Lines 922-948 Link Here
922
	opts->shell_flags = 0;
978
	opts->shell_flags = 0;
923
	/* now set the user-specific flags */
979
	/* now set the user-specific flags */
924
	if ( allow_scp ){
980
	if ( allow_scp ){
925
		log_msg("allowing scp to user %s", user);
981
		if (log) log_msg("allowing scp to user %s", user);
926
		opts->shell_flags |= RSSH_ALLOW_SCP;
982
		opts->shell_flags |= RSSH_ALLOW_SCP;
927
	}
983
	}
928
	if ( allow_sftp ){
984
	if ( allow_sftp ){
929
		log_msg("allowing sftp to user %s", user);
985
		if (log) log_msg("allowing sftp to user %s", user);
930
		opts->shell_flags |= RSSH_ALLOW_SFTP;
986
		opts->shell_flags |= RSSH_ALLOW_SFTP;
931
	}
987
	}
932
	if ( allow_cvs ){
988
	if ( allow_cvs ){
933
		log_msg("allowing cvs to user %s", user);
989
		if (log) log_msg("allowing cvs to user %s", user);
934
		opts->shell_flags |= RSSH_ALLOW_CVS;
990
		opts->shell_flags |= RSSH_ALLOW_CVS;
935
	}
991
	}
936
	if ( allow_rdist ){
992
	if ( allow_rdist ){
937
		log_msg("allowing rdist to user %s", user);
993
		if (log) log_msg("allowing rdist to user %s", user);
938
		opts->shell_flags |= RSSH_ALLOW_RDIST;
994
		opts->shell_flags |= RSSH_ALLOW_RDIST;
939
	}
995
	}
940
	if ( allow_rsync ){
996
	if ( allow_rsync ){
941
		log_msg("allowing rsync to user %s", user);
997
		if (log) log_msg("allowing rsync to user %s", user);
942
		opts->shell_flags |= RSSH_ALLOW_RSYNC;
998
		opts->shell_flags |= RSSH_ALLOW_RSYNC;
943
	}
999
	}
944
	if ( path ){
1000
	if ( path ){
945
		log_msg("chrooting %s to %s", user, path);
1001
		if (log) log_msg("chrooting %s to %s", user, path);
946
		opts->shell_flags |= RSSH_USE_CHROOT;
1002
		opts->shell_flags |= RSSH_USE_CHROOT;
947
	}
1003
	}
948
	opts->chroot_path = path;
1004
	opts->chroot_path = path;
Lines 961-982 Link Here
961
1017
962
	/* make sure '=' is next token, otherwise syntax error */
1018
	/* make sure '=' is next token, otherwise syntax error */
963
	if ( (pos = eat_assignment(line)) <= 0 ){
1019
	if ( (pos = eat_assignment(line)) <= 0 ){
964
		log_set_priority(LOG_ERR);
1020
		if (log){
965
		log_msg("error parsing config file at line %d: "
1021
			log_set_priority(LOG_ERR);
1022
			log_msg("error parsing config file at line %d: "
966
			"assignment expected", lineno);
1023
			"assignment expected", lineno);
1024
		}
967
		return FALSE;
1025
		return FALSE;
968
	}
1026
	}
969
	/* get the string parameter of the assignment */
1027
	/* get the string parameter of the assignment */
970
	if ( !(len = get_token((line + pos), buf, buflen, FALSE, FALSE)) ){
1028
	if ( !(len = get_token((line + pos), buf, buflen, FALSE, FALSE)) ){
971
		log_set_priority(LOG_ERR);
1029
		if (log){
972
		log_msg("syntax error parsing config file, line %d", lineno);
1030
			log_set_priority(LOG_ERR);
1031
			log_msg("syntax error parsing config file, line %d", 
1032
				lineno);
1033
		}
973
		return FALSE;
1034
		return FALSE;
974
	}
1035
	}
975
	pos += len;
1036
	pos += len;
976
	/* check for ending comment */
1037
	/* check for ending comment */
977
	if ( !eat_comment(line + pos) ){
1038
	if ( !eat_comment(line + pos) ){
978
		log_set_priority(LOG_ERR);
1039
		if (log){
979
		log_msg("syntax error parsing config file at line %d", lineno);
1040
			log_set_priority(LOG_ERR);
1041
			log_msg("syntax error parsing config file at line %d", 
1042
				lineno);
1043
		}
980
		return FALSE;
1044
		return FALSE;
981
	}
1045
	}
982
	return pos;
1046
	return pos;
(-)rsshconf.h (-1 / +1 lines)
Lines 49-55 Link Here
49
49
50
50
51
/* EXTERNALLY VISIBLE FUNCTION DECLARATIONS */
51
/* EXTERNALLY VISIBLE FUNCTION DECLARATIONS */
52
int 	read_shell_config( ShellOptions_t *opts, const char *filename );
52
int 	read_shell_config( ShellOptions_t *opts, const char *filename, int log );
53
53
54
54
55
#endif /* _rssh_config_h */
55
#endif /* _rssh_config_h */
(-)util.c (-6 / +24 lines)
Lines 122-133 Link Here
122
122
123
/*
123
/*
124
 * opt_exist() - takes a string representing a command line, and a single
124
 * opt_exist() - takes a string representing a command line, and a single
125
 *               character representing a command-line option to search for.
125
 *               character representing a command-line option flag (e.g. "-S")
126
 *               If the option exists in the command line, return TRUE.  This
126
 *               to search for.  If the option exists in the command line,
127
 *               function is a little over-zealous about returning a match,
127
 *               return TRUE.  This function is a little over-zealous about
128
 *               but in this case that is better than not being zealous
128
 *               returning a match, but in this case that is better than not
129
 *               enough.  And frankly, I don't want to spend the time required
129
 *               being zealous enough.  And frankly, I don't want to spend the
130
 *               to get it 100% right.  It's not worth the effort.
130
 *               time required to get it 100% right.  It's not worth the
131
 *               effort.
131
 */
132
 */
132
bool opt_exist(char *cl, char opt)
133
bool opt_exist(char *cl, char opt)
133
{
134
{
Lines 209-214 Link Here
209
	}
210
	}
210
211
211
	if ( check_command(cl, opts, PATH_CVS, RSSH_ALLOW_CVS) )
212
	if ( check_command(cl, opts, PATH_CVS, RSSH_ALLOW_CVS) )
213
		if ( opt_exist(cl, 'e') ){
214
			fprintf(stderr, "\ninsecure -e option not allowed.");
215
			log_msg("insecure -e option in cvs command line!");
216
			return NULL;
217
		}
212
		return PATH_CVS;
218
		return PATH_CVS;
213
219
214
	if ( check_command(cl, opts, PATH_RDIST, RSSH_ALLOW_RDIST) ){
220
	if ( check_command(cl, opts, PATH_RDIST, RSSH_ALLOW_RDIST) ){
Lines 321-324 Link Here
321
	return TRUE;
327
	return TRUE;
322
}
328
}
323
329
330
/*
331
 * get_username() - get the username of the user, or return unknown
332
 *
333
 */
334
char *get_username( void )
335
{
336
	struct passwd	*temp;
337
338
	if ( !(temp = getpwuid(getuid()) ) ) return "unknown user!";
339
	return temp->pw_name;
340
}
341
324
342
(-)util.h (-1 / +2 lines)
Lines 38-43 Link Here
38
int  validate_umask( const char *temp, int *mask );
38
int  validate_umask( const char *temp, int *mask );
39
int validate_access( const char *temp, bool *allow_sftp, bool *allow_scp,
39
int validate_access( const char *temp, bool *allow_sftp, bool *allow_scp,
40
	       	     bool *allow_cvs, bool *allow_rdist, bool *allow_rsync );
40
	       	     bool *allow_cvs, bool *allow_rdist, bool *allow_rsync );
41
bool opt_exist(char *cl, char opt);
41
bool opt_exist( char *cl, char opt );
42
char *get_username( void );
42
43
43
#endif /* _util_h */
44
#endif /* _util_h */

Return to bug 115082