The attached patch follows on from the first.  This makes everything
work nicely.  Once I've done a bit more testing, and cleaned up a few
other bits, I'll create a set of test packages.


Regards,
Roger

-- 
Roger Leigh
                Printing on GNU/Linux?  http://gutenprint.sourceforge.net/
                Debian GNU/Linux        http://www.debian.org/
                GPG Public Key: 0x25BFB848.  Please sign and encrypt your mail.
Index: schroot/sbuild-session.cc
===================================================================
--- schroot/sbuild-session.cc	(revision 761)
+++ schroot/sbuild-session.cc	(working copy)
@@ -587,98 +587,110 @@
   /* Run login shell */
   if (command.empty() ||
       command[0].empty()) // No command
+    get_login_command(session_chroot, file, command);
+  else
+    get_user_command(session_chroot, file, command);
+}
+
+void
+session::get_login_command (sbuild::chroot::ptr& session_chroot,
+			    std::string&         file,
+			    string_list&         command) const
+{
+  command.clear();
+
+  std::string shell = get_shell();
+  file = shell;
+
+  if (get_environment().empty() &&
+      session_chroot->get_command_prefix().empty())
+    // Not keeping environment and can setup argv correctly; login shell
     {
-      command.clear();
+      std::string shellbase = basename(shell, '/');
+      std::string loginshell = "-" + shellbase;
+      command.push_back(loginshell);
 
-      std::string shell = get_shell();
-      file = shell;
+      log_debug(DEBUG_NOTICE)
+	<< format("Running login shell: %1%") % shell << endl;
+      syslog(LOG_USER|LOG_NOTICE,
+	     "[%s chroot] (%s->%s) Running login shell: \"%s\"",
+	     session_chroot->get_name().c_str(),
+	     get_ruser().c_str(), get_user().c_str(),
+	     shell.c_str());
+    }
+  else
+    {
+      command.push_back(shell);
+      log_debug(DEBUG_NOTICE)
+	<< format("Running shell: %1%") % shell << endl;
+      syslog(LOG_USER|LOG_NOTICE,
+	     "[%s chroot] (%s->%s) Running shell: \"%s\"",
+	     session_chroot->get_name().c_str(),
+	     get_ruser().c_str(), get_user().c_str(),
+	     shell.c_str());
+    }
 
-      if (get_environment().empty() &&
-	  session_chroot->get_command_prefix().empty())
-	// Not keeping environment and can setup argv correctly; login shell
+  if (get_verbosity() != auth::VERBOSITY_QUIET)
+    {
+      std::string format_string;
+      if (get_ruid() == get_uid())
 	{
-	  std::string shellbase = basename(shell, '/');
-	  std::string loginshell = "-" + shellbase;
-	  command.push_back(loginshell);
-
-	  log_debug(DEBUG_NOTICE)
-	    << format("Running login shell: %1%") % shell << endl;
-	  syslog(LOG_USER|LOG_NOTICE,
-		 "[%s chroot] (%s->%s) Running login shell: \"%s\"",
-		 session_chroot->get_name().c_str(),
-		 get_ruser().c_str(), get_user().c_str(),
-		 shell.c_str());
+	  if (get_environment().empty() &&
+	      session_chroot->get_command_prefix().empty())
+	    format_string = _("[%1% chroot] Running login shell: \"%4%\"");
+	  else
+	    format_string = _("[%1% chroot] Running shell: \"%4%\"");
 	}
       else
 	{
-	  command.push_back(shell);
-	  log_debug(DEBUG_NOTICE)
-	    << format("Running shell: %1%") % shell << endl;
-	  syslog(LOG_USER|LOG_NOTICE,
-		 "[%s chroot] (%s->%s) Running shell: \"%s\"",
-		 session_chroot->get_name().c_str(),
-		 get_ruser().c_str(), get_user().c_str(),
-		 shell.c_str());
+	  if (get_environment().empty() &&
+	      session_chroot->get_command_prefix().empty())
+	    format_string = _("[%1% chroot] (%2%->%3%) Running login shell: \"%4%\"");
+	  else
+	    format_string = _("[%1% chroot] (%2%->%3%) Running shell: \"%4%\"");
 	}
 
-      if (get_verbosity() != auth::VERBOSITY_QUIET)
-	{
-	  std::string format_string;
-	  if (get_ruid() == get_uid())
-	    {
-	      if (get_environment().empty() &&
-		  session_chroot->get_command_prefix().empty())
-		format_string = _("[%1% chroot] Running login shell: \"%4%\"");
-	      else
-		format_string = _("[%1% chroot] Running shell: \"%4%\"");
-	    }
-	  else
-	    {
-	      if (get_environment().empty() &&
-		  session_chroot->get_command_prefix().empty())
-		format_string = _("[%1% chroot] (%2%->%3%) Running login shell: \"%4%\"");
-	      else
-		format_string = _("[%1% chroot] (%2%->%3%) Running shell: \"%4%\"");
-	    }
-
-	  format fmt(format_string);
-	  fmt % session_chroot->get_name()
-	      % get_ruser() % get_user()
-	      % shell;
-	  log_info() << fmt << endl;
-	}
+      format fmt(format_string);
+      fmt % session_chroot->get_name()
+	% get_ruser() % get_user()
+	% shell;
+      log_info() << fmt << endl;
     }
-  else
-    {
-      /* Search for program in path. */
-      environment env = get_pam_environment();
-      std::string path;
-      if (!env.get("PATH", path))
-	path.clear();
+}
 
-      file = find_program_in_path(command[0], path, "");
-      if (file.empty())
-	file = command[0];
-      std::string commandstring = string_list_to_string(command, " ");
-      log_debug(DEBUG_NOTICE)
-	<< format("Running command: %1%") % commandstring << endl;
-      syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running command: \"%s\"",
-	     session_chroot->get_name().c_str(), get_ruser().c_str(), get_user().c_str(), commandstring.c_str());
+void
+session::get_user_command (sbuild::chroot::ptr& session_chroot,
+			   std::string&         file,
+			   string_list&         command) const
+{
+  /* Search for program in path. */
+  environment env = get_pam_environment();
+  std::string path;
+  if (!env.get("PATH", path))
+    path.clear();
 
-      if (get_verbosity() != auth::VERBOSITY_QUIET)
-	{
-	  std::string format_string;
-	  if (get_ruid() == get_uid())
-	    format_string = _("[%1% chroot] Running command: \"%4%\"");
-	  else
-	    format_string = (_("[%1% chroot] (%2%->%3%) Running command: \"%4%\""));
+  file = find_program_in_path(command[0], path, "");
+  if (file.empty())
+    file = command[0];
+  std::string commandstring = string_list_to_string(command, " ");
+  log_debug(DEBUG_NOTICE)
+    << format("Running command: %1%") % commandstring << endl;
+  syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running command: \"%s\"",
+	 session_chroot->get_name().c_str(), get_ruser().c_str(), get_user().c_str(), commandstring.c_str());
 
-	  format fmt(format_string);
-	  fmt % session_chroot->get_name()
-	      % get_ruser() % get_user()
-	      % commandstring;
-	  log_info() << fmt << endl;
-	}
+  if (get_verbosity() != auth::VERBOSITY_QUIET)
+    {
+      std::string format_string;
+      if (get_ruid() == get_uid())
+	format_string = _("[%1% chroot] Running command: \"%4%\"");
+      else
+	format_string = (_("[%1% chroot] (%2%->%3%) Running command: \"%4%\""));
+
+      format fmt(format_string);
+      fmt % session_chroot->get_name()
+	% get_ruser() % get_user()
+	% commandstring;
+      log_info() << fmt << endl;
     }
 }
 
@@ -1006,7 +1018,7 @@
   if (exec (file, full_command, env))
     {
       log_error() << format(_("Could not exec \"%1%\": %2%"))
-	% command[0] % strerror(errno)
+	% file % strerror(errno)
 		  << endl;
       exit (EXIT_FAILURE);
     }
@@ -1090,7 +1102,6 @@
   else if (pid == 0)
     {
 #ifdef SBUILD_DEBUG
-      sbuild::debug_level = sbuild::DEBUG_NOTICE;
       while (child_wait)
 	;
 #endif
Index: schroot/sbuild-session.h
===================================================================
--- schroot/sbuild-session.h	(revision 761)
+++ schroot/sbuild-session.h	(working copy)
@@ -263,6 +263,32 @@
 		 std::string& file,
 		 string_list& command) const;
 
+    /**
+     * Get the command to run a login shell.
+     *
+     * @param session_chroot the chroot to setup.  This must be
+     * present in the chroot list and the chroot configuration object.
+     * @param file the filename to pass to execve(2).
+     * @param command the argv to pass to execve(2).
+     */
+    virtual void
+    get_login_command (chroot::ptr& session_chroot,
+		       std::string& file,
+		       string_list& command) const;
+
+    /**
+     * Get the command to run a user command.
+     *
+     * @param session_chroot the chroot to setup.  This must be
+     * present in the chroot list and the chroot configuration object.
+     * @param file the filename to pass to execve(2).
+     * @param command the argv to pass to execve(2).
+     */
+    virtual void
+    get_user_command (chroot::ptr& session_chroot,
+		      std::string& file,
+		      string_list& command) const;
+
   private:
     /**
      * execve wrapper.  Run the command specified by file (an absolute
Index: schroot/schroot.cc
===================================================================
--- schroot/schroot.cc	(revision 759)
+++ schroot/schroot.cc	(working copy)
@@ -38,6 +38,9 @@
 #include "dchroot-chroot-config.h"
 #include "dchroot-session.h"
 #endif
+#ifdef SBUILD_DCHROOT_DSA_COMPAT
+#include "dchroot-dsa-session.h"
+#endif
 
 using std::endl;
 using boost::format;
@@ -357,14 +360,16 @@
       // not require group access.  If loading schroot.conf, we always
       // want normal session management.
       sbuild::session::ptr session;
-#ifdef SBUILD_DCHROOT_COMPAT
-      if (options.compat != options::COMPAT_SCHROOT && use_dchroot_conf)
-	session = sbuild::session::ptr
-	  (new dchroot::session("schroot", config, sess_op, chroots));
-      else
+#if defined(SBUILD_DCHROOT_COMPAT) && !defined(SBUILD_DCHROOT_DSA_COMPAT)
+      session = sbuild::session::ptr
+	(new dchroot::session("schroot", config, sess_op, chroots, use_dchroot_conf));
+#elif defined(SBUILD_DCHROOT_DSA_COMPAT)
+      session = sbuild::session::ptr
+	(new dchroot_dsa::session("schroot", config, sess_op, chroots, use_dchroot_conf));
+#else
+      session = sbuild::session::ptr
+	(new sbuild::session("schroot", config, sess_op, chroots));
 #endif
-	session = sbuild::session::ptr
-	  (new sbuild::session("schroot", config, sess_op, chroots));
 
       try
 	{
Index: schroot/dchroot-dsa-session.h
===================================================================
--- schroot/dchroot-dsa-session.h	(revision 0)
+++ schroot/dchroot-dsa-session.h	(revision 0)
@@ -0,0 +1,87 @@
+/* Copyright © 2005-2006  Roger Leigh <[EMAIL PROTECTED]>
+ *
+ * schroot is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA  02111-1307  USA
+ *
+ *********************************************************************/
+
+#ifndef DCHROOT_DSA_SESSION_H
+#define DCHROOT_DSA_SESSION_H
+
+#include <string>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <grp.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "dchroot-session-base.h"
+
+namespace dchroot_dsa
+{
+
+  /**
+   * Session handler for dchroot sessions.
+   *
+   * This class provides the session handling for dchroot
+   * compatibility.  It derives from session, overriding the
+   * authentication checks to allow all users to access the service,
+   * and does not permit user switching.
+   */
+  class session : public dchroot::session_base
+  {
+  public:
+    /**
+     * The constructor.
+     *
+     * @param service the PAM service name.
+     * @param config a shared_ptr to the chroot configuration.
+     * @param operation the session operation to perform.
+     * @param chroots the chroots to act upon.
+     * @param compat true to enable full dchroot compatibility, or
+     * false to enable schroot compatiblity (permissions checks).
+     */
+    session (std::string const&         service,
+	     config_ptr&                config,
+	     operation                  operation,
+	     sbuild::string_list const& chroots,
+	     bool                       compat);
+
+    /// The destructor.
+    virtual ~session ();
+
+    virtual sbuild::auth::status
+    get_chroot_auth_status (sbuild::auth::status status,
+			    sbuild::chroot::ptr const& chroot) const;
+
+    virtual sbuild::string_list
+    get_login_directories () const;
+
+    virtual void
+    get_user_command (sbuild::chroot::ptr& session_chroot,
+		      std::string&         file,
+		      sbuild::string_list& command) const;
+  };
+
+}
+
+#endif /* DCHROOT_DSA_SESSION_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
Index: schroot/schroot-options.cc
===================================================================
--- schroot/schroot-options.cc	(revision 761)
+++ schroot/schroot-options.cc	(working copy)
@@ -140,7 +140,9 @@
   opt::options_description hidden(_("Hidden options"));
   hidden.add_options()
     ("command", opt::value<sbuild::string_list>(&this->command),
-     _("Command to run"));
+     _("Command to run"))
+    ("debug",
+     _("Enable debugging messages"));
 
   opt::positional_options_description pos;
   pos.add("command", -1);
@@ -234,6 +236,11 @@
   if (vm.count("force"))
     this->session_force = true;
 
+  if (vm.count("debug"))
+    sbuild::debug_level = sbuild::DEBUG_NOTICE;
+  else
+    sbuild::debug_level = sbuild::DEBUG_NONE;
+
   if (this->compat == COMPAT_DCHROOT_DSA)
     {
       // If no chroots specified, use the first non-option.
Index: schroot/dchroot-session.cc
===================================================================
--- schroot/dchroot-session.cc	(revision 761)
+++ schroot/dchroot-session.cc	(working copy)
@@ -47,8 +47,9 @@
 session::session (std::string const& service,
 		  config_ptr&        config,
 		  operation          operation,
-		  string_list const& chroots):
-  sbuild::session(service, config, operation, chroots)
+		  string_list const& chroots,
+		  bool               compat):
+  session_base(service, config, operation, chroots, compat)
 {
 }
 
@@ -60,57 +61,27 @@
 session::get_chroot_auth_status (sbuild::auth::status status,
 				 sbuild::chroot::ptr const& chroot) const
 {
-#ifndef SBUILD_DCHROOT_DSA_COMPAT
-  status = change_auth(status, auth::STATUS_NONE);
-#else
-  /* DSA dchroot checks for a valid user in the groups list, unless
-     the groups lists is empty in which case there are no
-     restrictions.  This only applies if not switching users (dchroot
-     does not support user switching) */
-
-  string_list const& users = chroot->get_users();
-  string_list const& groups = chroot->get_groups();
-
-  if (this->get_ruid() == this->get_uid() &&
-      users.empty() && groups.empty())
+  if (get_compat() == true)
     status = change_auth(status, auth::STATUS_NONE);
   else
     status = change_auth(status,
 			 sbuild::session::get_chroot_auth_status(status,
 								 chroot));
-#endif
 
   return status;
 }
 
-void
-session::run_impl ()
-{
-  if (get_ruid() != get_uid())
-    {
-      format fmt(_("(%1%->%2%): dchroot sessions do not support user switching"));
-      fmt % get_ruser().c_str() % get_user().c_str();
-      throw error(fmt.str(), USER_SWITCH, _("dchroot session restriction"));
-    }
-
-  sbuild::session::run_impl();
-}
-
 string_list
 session::get_login_directories () const
 {
   string_list ret;
 
-#ifndef SBUILD_DCHROOT_DSA_COMPAT
   // Set current working directory only if preserving environment.
   // Only change to home if not preserving the environment.
   if (!get_environment().empty())
     ret.push_back(this->sbuild::session::cwd);
   else
     ret.push_back(get_home());
-#else
-  ret.push_back(get_home());
-#endif
 
   // Final fallback to root.
   if (std::find(ret.begin(), ret.end(), "/") == ret.end())
@@ -119,116 +90,36 @@
   return ret;
 }
 
-string_list
-session::get_command_directories () const
-{
-  // dchroot does not treat logins differently from commands with
-  // respect to the cwd inside the chroot.
-  return get_login_directories();
-}
-
 void
-session::get_command (sbuild::chroot::ptr& session_chroot,
-		      std::string&         file,
-		      string_list&         command) const
+session::get_user_command (sbuild::chroot::ptr& session_chroot,
+			   std::string&         file,
+			   string_list&         command) const
 {
-  /* Run login shell */
-  if (command.empty() ||
-      command[0].empty()) // No command
-    {
-      command.clear();
+  std::string programstring = command[0];
 
-      std::string shell = get_shell();
-      file = shell;
+  command.clear();
+  command.push_back(get_shell());
+  command.push_back("-c");
+  command.push_back(programstring);
 
-      if (get_environment().empty() &&
-	  session_chroot->get_command_prefix().empty())
-	// Not keeping environment and can setup argv correctly; login shell
-	{
-	  std::string shellbase = sbuild::basename(shell, '/');
-	  std::string loginshell = "-" + shellbase;
-	  command.push_back(loginshell);
+  file = command[0];
 
-	  sbuild::log_debug(sbuild::DEBUG_NOTICE)
-	    << format("Running login shell: %1%") % shell << endl;
-	  syslog(LOG_USER|LOG_NOTICE,
-		 "[%s chroot] (%s->%s) Running login shell: \"%s\"",
-		 session_chroot->get_name().c_str(),
-		 get_ruser().c_str(), get_user().c_str(),
-		 shell.c_str());
-	}
-      else
-	{
-	  command.push_back(shell);
-	  sbuild::log_debug(sbuild::DEBUG_NOTICE)
-	    << format("Running shell: %1%") % shell << endl;
-	  syslog(LOG_USER|LOG_NOTICE,
-		 "[%s chroot] (%s->%s) Running shell: \"%s\"",
-		 session_chroot->get_name().c_str(),
-		 get_ruser().c_str(), get_user().c_str(),
-		 shell.c_str());
-	}
+  sbuild::log_debug(sbuild::DEBUG_NOTICE) << "file=" << file << endl;
 
-      if (get_verbosity() != auth::VERBOSITY_QUIET)
-	{
-	  std::string format_string;
-	  if (get_ruid() == get_uid())
-	    {
-	      if (get_environment().empty() &&
-		  session_chroot->get_command_prefix().empty())
-		format_string = _("[%1% chroot] Running login shell: \"%4%\"");
-	      else
-		format_string = _("[%1% chroot] Running shell: \"%4%\"");
-	    }
-	  else
-	    {
-	      if (get_environment().empty() &&
-		  session_chroot->get_command_prefix().empty())
-		format_string = _("[%1% chroot] (%2%->%3%) Running login shell: \"%4%\"");
-	      else
-		format_string = _("[%1% chroot] (%2%->%3%) Running shell: \"%4%\"");
-	    }
+  std::string commandstring = sbuild::string_list_to_string(command, " ");
+  sbuild::log_debug(sbuild::DEBUG_NOTICE)
+    << format("Running command: %1%") % commandstring << endl;
+  syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running command: \"%s\"",
+	 session_chroot->get_name().c_str(), get_ruser().c_str(), get_user().c_str(), commandstring.c_str());
 
-	  format fmt(format_string);
-	  fmt % session_chroot->get_name()
-	      % get_ruser() % get_user()
-	      % shell;
-	  sbuild::log_info() << fmt << endl;
-	}
-    }
-  else
+  if (get_verbosity() != auth::VERBOSITY_QUIET)
     {
-      std::string programstring = command[0];
-#ifdef SBUILD_DCHROOT_DSA_COMPAT
-      file = programstring;
-#else
-      command.clear();
-      command.push_back(get_shell());
-      command.push_back("-c");
-      command.push_back(programstring);
-#endif
+      std::string format_string;
+      format_string = (_("[%1% chroot] Running command: \"%2%\""));
 
-      std::string commandstring = sbuild::string_list_to_string(command, " ");
-      sbuild::log_debug(sbuild::DEBUG_NOTICE)
-	<< format("Running command: %1%") % commandstring << endl;
-      syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running command: \"%s\"",
-	     session_chroot->get_name().c_str(), get_ruser().c_str(), get_user().c_str(), commandstring.c_str());
-
-      if (get_verbosity() != auth::VERBOSITY_QUIET)
-	{
-	  std::string format_string;
-	  format_string = (_("[%1% chroot] Running command: \"%2%\""));
-
-	  format fmt(format_string);
-	  fmt % session_chroot->get_name()
-	      % programstring;
-	  sbuild::log_info() << fmt << endl;
-	}
+      format fmt(format_string);
+      fmt % session_chroot->get_name()
+	% programstring;
+      sbuild::log_info() << fmt << endl;
     }
 }
-
-/*
- * Local Variables:
- * mode:C++
- * End:
- */
Index: schroot/dchroot-session.h
===================================================================
--- schroot/dchroot-session.h	(revision 761)
+++ schroot/dchroot-session.h	(working copy)
@@ -28,7 +28,7 @@
 #include <pwd.h>
 #include <unistd.h>
 
-#include "sbuild-session.h"
+#include "dchroot-session-base.h"
 
 namespace dchroot
 {
@@ -41,7 +41,7 @@
    * authentication checks to allow all users to access the service,
    * and does not permit user switching.
    */
-  class session : public sbuild::session
+  class session : public session_base
   {
   public:
     /**
@@ -51,11 +51,14 @@
      * @param config a shared_ptr to the chroot configuration.
      * @param operation the session operation to perform.
      * @param chroots the chroots to act upon.
+     * @param compat true to enable full dchroot compatibility, or
+     * false to enable schroot compatiblity (permissions checks).
      */
     session (std::string const&         service,
 	     config_ptr&                config,
 	     operation                  operation,
-	     sbuild::string_list const& chroots);
+	     sbuild::string_list const& chroots,
+	     bool                       compat);
 
     /// The destructor.
     virtual ~session ();
@@ -64,19 +67,13 @@
     get_chroot_auth_status (sbuild::auth::status status,
 			    sbuild::chroot::ptr const& chroot) const;
 
-    virtual void
-    run_impl ();
-
     virtual sbuild::string_list
     get_login_directories () const;
 
-    virtual sbuild::string_list
-    get_command_directories () const;
-
     virtual void
-    get_command (sbuild::chroot::ptr& session_chroot,
-		 std::string&         file,
-		 sbuild::string_list& command) const;
+    get_user_command (sbuild::chroot::ptr& session_chroot,
+		      std::string&         file,
+		      sbuild::string_list& command) const;
   };
 
 }
Index: schroot/dchroot-dsa-session.cc
===================================================================
--- schroot/dchroot-dsa-session.cc	(revision 0)
+++ schroot/dchroot-dsa-session.cc	(revision 0)
@@ -0,0 +1,141 @@
+/* Copyright © 2005-2006  Roger Leigh <[EMAIL PROTECTED]>
+ *
+ * schroot is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA  02111-1307  USA
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include "sbuild.h"
+
+#include "dchroot-dsa-session.h"
+
+#include <cassert>
+#include <iostream>
+#include <memory>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <syslog.h>
+
+#include <boost/format.hpp>
+
+#include <uuid/uuid.h>
+
+using std::cout;
+using std::endl;
+using boost::format;
+using sbuild::string_list;
+using namespace dchroot_dsa;
+
+session::session (std::string const& service,
+		  config_ptr&        config,
+		  operation          operation,
+		  string_list const& chroots,
+		  bool               compat):
+  dchroot::session_base(service, config, operation, chroots, compat)
+{
+}
+
+session::~session ()
+{
+}
+
+sbuild::auth::status
+session::get_chroot_auth_status (sbuild::auth::status status,
+				 sbuild::chroot::ptr const& chroot) const
+{
+  /* DSA dchroot checks for a valid user in the groups list, unless
+     the groups lists is empty in which case there are no
+     restrictions.  This only applies if not switching users (dchroot
+     does not support user switching) */
+
+  if (get_compat() == true)
+    {
+      string_list const& users = chroot->get_users();
+      string_list const& groups = chroot->get_groups();
+
+      if (this->get_ruid() == this->get_uid() &&
+	  users.empty() && groups.empty())
+	status = change_auth(status, auth::STATUS_NONE);
+      else
+	status = change_auth(status,
+			     sbuild::session::get_chroot_auth_status(status,
+								     chroot));
+    }
+  else // schroot compatibility
+    {
+      status = change_auth(status,
+			   sbuild::session::get_chroot_auth_status(status,
+								   chroot));
+    }
+
+  return status;
+}
+
+string_list
+session::get_login_directories () const
+{
+  string_list ret;
+
+  ret.push_back(get_home());
+
+  // Final fallback to root.
+  if (std::find(ret.begin(), ret.end(), "/") == ret.end())
+    ret.push_back("/");
+
+  return ret;
+}
+
+void
+session::get_user_command (sbuild::chroot::ptr& session_chroot,
+			   std::string&         file,
+			   string_list&         command) const
+{
+  std::string programstring = command[0];
+  file = programstring;
+
+  if (file.empty() ||
+      (file.size() >= 1 && file[0] != '/'))
+    {
+      sbuild::log_error()
+	<< format(_("%1%: Command must have an absolute path"))
+	% file
+	<< endl;
+      exit (EXIT_FAILURE);
+    }
+
+
+  std::string commandstring = sbuild::string_list_to_string(command, " ");
+  sbuild::log_debug(sbuild::DEBUG_NOTICE)
+    << format("Running command: %1%") % commandstring << endl;
+  syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running command: \"%s\"",
+	 session_chroot->get_name().c_str(), get_ruser().c_str(), get_user().c_str(), commandstring.c_str());
+
+  if (get_verbosity() != auth::VERBOSITY_QUIET)
+    {
+      std::string format_string;
+      format_string = (_("[%1% chroot] Running command: \"%2%\""));
+
+      format fmt(format_string);
+      fmt % session_chroot->get_name()
+	% programstring;
+      sbuild::log_info() << fmt << endl;
+    }
+}
Index: schroot/dchroot-session-base.cc
===================================================================
--- schroot/dchroot-session-base.cc	(revision 0)
+++ schroot/dchroot-session-base.cc	(revision 0)
@@ -0,0 +1,98 @@
+/* Copyright © 2005-2006  Roger Leigh <[EMAIL PROTECTED]>
+ *
+ * schroot is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA  02111-1307  USA
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include "sbuild.h"
+
+#include "dchroot-session-base.h"
+
+#include <cassert>
+#include <iostream>
+#include <memory>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <syslog.h>
+
+#include <boost/format.hpp>
+
+#include <uuid/uuid.h>
+
+using std::cout;
+using std::endl;
+using boost::format;
+using sbuild::string_list;
+using namespace dchroot;
+
+session_base::session_base (std::string const& service,
+			    config_ptr&        config,
+			    operation          operation,
+			    string_list const& chroots,
+			    bool               compat):
+  sbuild::session(service, config, operation, chroots),
+  compat(compat)
+{
+}
+
+session_base::~session_base ()
+{
+}
+
+bool
+session_base::get_compat () const
+{
+  return this->compat;
+}
+
+void
+session_base::set_compat (bool state)
+{
+  this->compat = state;
+}
+
+void
+session_base::run_impl ()
+{
+  if (get_ruid() != get_uid())
+    {
+      format fmt(_("(%1%->%2%): dchroot sessions do not support user switching"));
+      fmt % get_ruser().c_str() % get_user().c_str();
+      throw error(fmt.str(), USER_SWITCH, _("dchroot session restriction"));
+    }
+
+  sbuild::session::run_impl();
+}
+
+string_list
+session_base::get_command_directories () const
+{
+  // dchroot does not treat logins differently from commands with
+  // respect to the cwd inside the chroot.
+  return get_login_directories();
+}
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
Index: schroot/dchroot-session-base.h
===================================================================
--- schroot/dchroot-session-base.h	(revision 0)
+++ schroot/dchroot-session-base.h	(revision 0)
@@ -0,0 +1,102 @@
+/* Copyright © 2005-2006  Roger Leigh <[EMAIL PROTECTED]>
+ *
+ * schroot is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA  02111-1307  USA
+ *
+ *********************************************************************/
+
+#ifndef DCHROOT_SESSION_BASE_H
+#define DCHROOT_SESSION_BASE_H
+
+#include <string>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <grp.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "sbuild-session.h"
+
+namespace dchroot
+{
+
+  /**
+   * Session handler for dchroot sessions.
+   *
+   * This class provides the session handling for dchroot
+   * compatibility.  It derives from session, overriding the
+   * authentication checks to allow all users to access the service,
+   * and does not permit user switching.
+   */
+  class session_base : public sbuild::session
+  {
+  public:
+    /**
+     * The constructor.
+     *
+     * @param service the PAM service name.
+     * @param config a shared_ptr to the chroot configuration.
+     * @param operation the session operation to perform.
+     * @param chroots the chroots to act upon.
+     * @param compat true to enable full dchroot compatibility, or
+     * false to enable schroot compatiblity (permissions checks).
+     */
+    session_base (std::string const&         service,
+		  config_ptr&                config,
+		  operation                  operation,
+		  sbuild::string_list const& chroots,
+		  bool                       compat);
+
+    /// The destructor.
+    virtual ~session_base ();
+
+    /**
+     * Get the dchroot compatibility state.
+     *
+     * @returns the state.
+     */
+    bool
+    get_compat () const;
+
+    /**
+     * Set the dchroot compatibility state.
+     *
+     * @param state the dchroot compatibility state.
+     */
+    void
+    set_compat (bool state);
+
+  protected:
+    virtual void
+    run_impl ();
+
+    virtual sbuild::string_list
+    get_command_directories () const;
+
+  private:
+    /// dchroot compatibility enabled?
+    bool compat;
+  };
+
+}
+
+#endif /* DCHROOT_SESSION_BASE_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
Index: schroot/Makefile.am
===================================================================
--- schroot/Makefile.am	(revision 756)
+++ schroot/Makefile.am	(working copy)
@@ -126,6 +126,8 @@
 	dchroot-chroot-config.cc	\
 	dchroot-session.h		\
 	dchroot-session.cc		\
+	dchroot-session-base.h		\
+	dchroot-session-base.cc		\
 	schroot-options.h		\
 	schroot-options.cc		\
 	schroot.cc
@@ -136,8 +138,10 @@
 dchroot_dsa_SOURCES =			\
 	dchroot-chroot-config.h		\
 	dchroot-chroot-config.cc	\
-	dchroot-session.h		\
-	dchroot-session.cc		\
+	dchroot-dsa-session.h		\
+	dchroot-dsa-session.cc		\
+	dchroot-session-base.h		\
+	dchroot-session-base.cc		\
 	schroot-options.h		\
 	schroot-options.cc		\
 	schroot.cc
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 761)
+++ ChangeLog	(working copy)
@@ -1,5 +1,42 @@
 2006-06-22  Roger Leigh  <[EMAIL PROTECTED]>
 
+	* schroot/schroot-options.cc: Add a --debug option to enable
+	debugging messages.
+
+	* schroot/Makefile.am
+	(dchroot_SOURCES): Add dchroot-session-base.(cc|h).
+	(dchroot_dsa_SOURCES): Add dchroot-session-base.(cc|h).  Use
+	dchroot-dsa-session.(cc|h) instead of dchroot-session.(cc|h).
+
+	* schroot/dchroot-dsa-session.(cc|h): New class, based upon
+	dchroot::session and derived from dchroot::session_base.  Remove
+	specialisations for dchroot.
+
+	* schroot/dchroot-session.(cc|h): Derive from
+	dchroot::session_base.  Remove specialisations for dchroot-dsa.
+
+	* schroot/dchroot-session-base.(cc|h): New class, split from
+	dchroot::session.  It includes functionality common to dchroot and
+	dchroot-dsa sessions, as well as recording a compatibility state
+	which influences session behaviour depending on whether
+	dchroot.conf or schroot.conf are used.
+
+	* schroot/schroot.cc: When building for dchroot-dsa, include the
+	dchroot-dsa-session.h header.
+	(main): When building for dchroot-dsa, create a
+	dchroot_dsa::session session.  dchroot-dsa and dchroot sessions
+	include a compatibility mode as a fifth argument.
+
+	* schroot/sbuild-session.cc
+	(get_login_command, get_user_command): Split the two parts of
+	get_command into separate protected virtual methods, so that they
+	may be independently overridden and chained up to by derived
+	session types.
+	(run_child): When reporting an exec error, use filename rather
+	than argv[0], which may differ for login shells.
+
+2006-06-22  Roger Leigh  <[EMAIL PROTECTED]>
+
 	* schroot/schroot-options.cc: dchroot and dchroot-dsa only permit
 	a single command option.
 

Attachment: pgpeTTP7yabdo.pgp
Description: PGP signature

Reply via email to