From ca20eaa74e7e762c0611de26cc2267909ae27e02 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sat, 5 Mar 2005 23:28:34 +0000 Subject: [PATCH] (do_chroot_jail): paranoia security for webserver use. Patch by Sebastiano Vigna . --- ChangeLog | 5 +++ THANKS | 1 + VERSION | 2 +- lily/main.cc | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ed8d1f4407..0d52821b11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-03-06 Han-Wen Nienhuys + + * lily/main.cc (do_chroot_jail): paranoia security for webserver + use. Patch by Sebastiano Vigna . + 2005-03-05 Han-Wen Nienhuys * stepmake/bin/add-html-footer.py (do_file): make wiki link optional. diff --git a/THANKS b/THANKS index a85931e3f9..bd3534e343 100644 --- a/THANKS +++ b/THANKS @@ -23,6 +23,7 @@ Juliusz Chroboczek Mats Bengtsson Nicolas Sceaux Pal Benko +Sebastiano Vigna Tatsuya Ono Werner Lemberg Yuval Harel diff --git a/VERSION b/VERSION index 4871c881c2..f2bd041d8b 100644 --- a/VERSION +++ b/VERSION @@ -1,6 +1,6 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=2 MINOR_VERSION=5 -PATCH_LEVEL=13 +PATCH_LEVEL=14 MY_PATCH_LEVEL= diff --git a/lily/main.cc b/lily/main.cc index ce313b93d1..7ef3b516ff 100644 --- a/lily/main.cc +++ b/lily/main.cc @@ -109,6 +109,9 @@ _i (" This program is free software; you can redistribute it and/or\n" LOCAL_LILYPOND_DATADIR = /usr/share/lilypond/ */ char const *prefix_directories[] = {LILYPOND_DATADIR, LOCAL_LILYPOND_DATADIR, 0}; +/* The jail specification: USER,GROUP,JAIL,DIR. */ +String jail_spec; + /* The option parser */ static Getopt_long *option_parser = 0; @@ -129,6 +132,7 @@ static Long_option_init options_static[] = {_i ("DIR"), "include", 'I', _i ("add DIR to search path")}, {_i ("FILE"), "init", 'i', _i ("use FILE as init file")}, {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")}, + {_i ("USER,GROUP,JAIL,DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP and cd into DIR")}, {0, "preview", 'p', _i ("generate a preview")}, {0, "no-pages", 0, _i ("don't generate full pages")}, {0, "png", 0, _i ("generate PNG")}, @@ -251,6 +255,82 @@ void init_global_tweak_registry (); void init_fontconfig (); +static void +do_chroot_jail () +{ + /* Now we chroot, setuid/setgrp and chdir. If something goes wrong, we exit (this is a + security-sensitive area). First we split jail_spec into its components, then we + retrieve the user/group id (necessarily *before* chroot'ing!) and finally we perform + the actual actions. */ + + Array components = String_convert::split(jail_spec, ','); + if (components.size() < 3) + { + error (_ ("too few elements in jail specification")); + exit(1); + } + if (components.size() > 4) + { + error (_ ("too many elements in jail specification")); + exit(1); + } + + int uid, gid; + char *user_name = components[0].get_str0 (); + char *group_name = components[1].get_str0 (); + char *jail = components[2].get_str0 (); + char *wd = components[3].get_str0 (); + + errno = 0; + struct passwd *passwd = getpwnam(user_name); + if (passwd == NULL) + { + if (errno == 0) + error (_ ("user not found")); + else + error(_f ("can't get user id from user name (%s)", strerror (errno))); + exit (3); + } + uid = passwd->pw_uid; + + errno = 0; + struct group *group = getgrnam(group_name); + if (group == NULL) + { + if (errno == 0) + error (_ ("group not found")); + else + error(_f ("can't get group id from group name (%s)", strerror (errno))); + exit (3); + } + gid = group->gr_gid; + + if (chroot (jail)) + { + error (_f ("can't chroot (%s)", strerror (errno))); + exit (3); + } + + if (setgid (gid)) + { + error (_f ("can't change group id (%s)", strerror (errno))); + exit (3); + } + + if (setuid (uid)) + { + error (_f ("can't change user id (%s)", strerror (errno))); + exit (3); + } + + if (chdir (wd)) + { + error (_f ("can't change working directory (%s)", strerror (errno))); + exit (3); + } +} + + static void main_with_guile (void *, int, char **) { @@ -303,6 +383,9 @@ main_with_guile (void *, int, char **) exit (2); } + if (! jail_spec.is_empty ()) + do_chroot_jail (); + SCM result = scm_call_1 (ly_lily_module_constant ("lilypond-main"), files); (void) result; @@ -373,6 +456,9 @@ parse_argv (int argc, char **argv) output_name_global = file_name.to_string (); } break; + case 'j': + jail_spec = option_parser->optional_argument_str0_; + break; case 'e': init_scheme_code_string += option_parser->optional_argument_str0_; break; -- 2.39.5