summaryrefslogtreecommitdiff
path: root/sbuild/sbuild-session.h
blob: f3f2ed7d8c110ab7ec3e9a1e99636db56d8f1db4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
/* Copyright © 2005-2007  Roger Leigh <rleigh@debian.org>
 *
 * 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 3 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, see
 * <http://www.gnu.org/licenses/>.
 *
 *********************************************************************/

#ifndef SBUILD_SESSION_H
#define SBUILD_SESSION_H

#include <sbuild/sbuild-auth.h>
#include <sbuild/sbuild-chroot-config.h>
#include <sbuild/sbuild-custom-error.h>

#include <string>

#include <signal.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>

namespace sbuild
{

  /**
   * Session handler.
   *
   * This class provides the session handling for schroot.  It uses
   * auth, which performs all the necessary PAM actions.  This allows
   * more sophisticated handling of user authorisation (users, groups,
   * root-users and root-groups membership in the configuration file)
   * and session management (setting up the session, entering the
   * chroot and running the requested command or shell).
   */
  class session
  {
  public:
    /// Session operations.
    enum operation
      {
	OPERATION_AUTOMATIC, ///< Begin, end and run a session automatically.
	OPERATION_BEGIN,     ///< Begin a session.
	OPERATION_RECOVER,   ///< Recover an existing (but inactive) session.
	OPERATION_END,       ///< End a session.
	OPERATION_RUN        ///< Run a command in an existing session.
      };

    /// Error codes.
    enum error_code
      {
	CHDIR,          ///< Failed to change to directory.
	CHDIR_FB,       ///< Falling back to directory.
	CHILD_CORE,     ///< Child dumped core.
	CHILD_FAIL,     ///< Child exited abnormally (reason unknown)
	CHILD_FORK,     ///< Failed to fork child.
	CHILD_SIGNAL,   ///< Child terminated by signal.
	CHILD_WAIT,     ///< Wait for child failed.
	CHROOT,         ///< Failed to change root to directory.
	CHROOT_ALIAS,   ///< No chroot found matching alias.
	CHROOT_LOCK,    ///< Failed to lock chroot.
	CHROOT_SETUP,   ///< Setup failed.
	CHROOT_UNKNOWN, ///< Failed to find chroot.
	CHROOT_UNLOCK,  ///< Failed to unlock chroot.
	COMMAND_ABS,    ///< Command must have an absolute path.
	EXEC,           ///< Failed to execute.
	GROUP_GET_SUP,  ///< Failed to get supplementary groups.
	GROUP_GET_SUPC, ///< Failed to get supplementary group count
	GROUP_SET,      ///< Failed to set group.
	GROUP_SET_SUP,  ///< Failed to set supplementary groups.
	GROUP_UNKNOWN,  ///< Group not found.
	PAM,            ///< PAM error.
	ROOT_DROP,      ///< Failed to drop root permissions.
        SET_SESSION_ID, ///< Chroot does not support setting a session ID.
	SHELL,          ///< Shell not available.
	SHELL_FB,       ///< Falling back to shell.
	SIGNAL_CATCH,   ///< Caught signal.
	SIGNAL_SET,     ///< Failed to set signal handler.
	USER_SET,       ///< Failed to set user.
	USER_SWITCH     ///< User switching is not permitted.
      };

    /// Exception type.
    typedef custom_error<error_code> error;

    /// A shared_ptr to a chroot_config object.
    typedef std::tr1::shared_ptr<chroot_config> config_ptr;

    /// A shared_ptr to a session object.
    typedef std::tr1::shared_ptr<session> ptr;

    /**
     * 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.
     */
    session (std::string const& service,
	     config_ptr&        config,
	     operation          operation,
	     string_list const& chroots);

    /// The destructor.
    virtual ~session ();

    /**
     * Get the authentication state associated with this session.
     *
     * @returns a shared_ptr to the authentication state.
     */
    auth::ptr const&
    get_auth () const;

    /**
     * Set the authentication state associated with this session.
     *
     * @param auth a shared_ptr to the authentication state.
     */
    void
    set_auth (auth::ptr& auth);

    /**
     * Get the configuration associated with this session.
     *
     * @returns a shared_ptr to the configuration.
     */
    config_ptr const&
    get_config () const;

    /**
     * Set the configuration associated with this session.
     *
     * @param config a shared_ptr to the configuration.
     */
    void
    set_config (config_ptr& config);

    /**
     * Get the chroots to use in this session.
     *
     * @returns a list of chroots.
     */
    string_list const&
    get_chroots () const;

    /**
     * Set the chroots to use in this session.
     *
     * @param chroots a list of chroots.
     */
    void
    set_chroots (string_list const& chroots);

    /**
     * Get the operation this session will perform.
     *
     * @returns the operation.
     */
    operation
    get_operation () const;

    /**
     * Set the operation this session will perform.
     *
     * @param operation the operation.
     */
    void
    set_operation (operation operation);

    /**
     * Get the session identifier.  The session identifier is a unique
     * string to identify a session.
     *
     * @returns the session id.
     */
    std::string const&
    get_session_id () const;

    /**
     * Set the session identifier.  The session identifier is a unique
     * string to identify a session.
     *
     * @param session_id the session id.
     */
    void
    set_session_id (std::string const& session_id);

    /**
     * Get the force status of this session.
     *
     * @returns true if operation will be forced, otherwise false.
     */
    bool
    get_force () const;

    /**
     * Set the force status of this session.
     *
     * @param force true to force operation, otherwise false.
     */
    void
    set_force (bool force);

    /**
     * Save terminal state.
     */
    void
    save_termios ();

    /**
     * Restore terminal state.
     */
    void
    restore_termios ();

    /**
     * Get the exit (wait) status of the last child process to run in this
     * session.
     *
     * @returns the exit status.
     */
    int
    get_child_status () const;

  protected:
    /**
     * Check if authentication is required for a single chroot, taking
     * users, groups, root-users and root-groups membership into
     * account.
     */
    virtual auth::status
    get_chroot_auth_status (auth::status status,
			    chroot::ptr const& chroot) const;

  public:
    /**
     * Check if authentication is required, taking users, groups,
     * root-users and root-groups membership of all chroots specified
     * into account.
     */
    virtual sbuild::auth::status
    get_auth_status () const;

    /**
     * Run a session.  The user will be asked for authentication if
     * required, and then the run_impl virtual method will be called.
     *
     * An auth::error will be thrown on failure.
     */
    void
    run ();

  protected:
    /**
     * Run a session.  If a command has been specified, this will be
     * run in each of the specified chroots.  If no command has been
     * specified, a login shell will run in the specified chroot.
     *
     * An error will be thrown on failure.
     */
    virtual void
    run_impl ();

    /**
     * Get a list of directories to change to when running a login
     * shell.  Multiple directories are used as fallbacks.
     *
     * @returns a list of directories
     */
    virtual string_list
    get_login_directories () const;

    /**
     * Get a list of directories to change to when running a command
     * Multiple directories are used as fallbacks.
     *
     * @returns a list of directories
     */
    virtual string_list
    get_command_directories () const;

    /**
     * Get the shell to run.  This finds a suitable shell to run in
     * the chroot, falling back to /bin/sh if necessary.  Note that it
     * assumes it is inside the chroot when called.
     *
     * @returns the shell.
     */
    virtual std::string
    get_shell () const;

    /**
     * Get the command to run.
     *
     * @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_command (chroot::ptr& session_chroot,
		 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:
    /**
     * Setup a chroot.  This runs all of the commands in setup.d or run.d.
     *
     * The environment variables CHROOT_NAME, CHROOT_DESCRIPTION,
     * CHROOT_LOCATION, AUTH_USER and AUTH_VERBOSITY are set for use in
     * setup scripts.  See schroot-setup(5) for a complete list.
     *
     * An error will be thrown on failure.
     *
     * @param session_chroot the chroot to setup.  This must be
     * present in the chroot list and the chroot configuration object.
     * @param setup_type the type of setup to perform.
     */
    void
    setup_chroot (chroot::ptr&       session_chroot,
		  chroot::setup_type setup_type);

    /**
     * Run command or login shell in the specified chroot.
     *
     * An error will be thrown on failure.
     *
     * @param session_chroot the chroot to setup.  This must be
     * present in the chroot list and the chroot configuration object.
     */
    void
    run_chroot (chroot::ptr& session_chroot);

    /**
     * Run a command or login shell as a child process in the
     * specified chroot.  This method is only ever to be run in a
     * child process, and will never return.
     *
     * @param session_chroot the chroot to setup.  This must be
     * present in the chroot list and the chroot configuration object.
     */
    void
    run_child (chroot::ptr& session_chroot);

    /**
     * Wait for a child process to complete, and check its exit status.
     *
     * An error will be thrown on failure.
     *
     * @param pid the pid to wait for.
     * @param child_status the place to store the child exit status.
     */
    void
    wait_for_child (pid_t pid,
		    int&  child_status);

    /**
     * Set the SIGHUP handler.
     *
     * An error will be thrown on failure.
     */
    void
    set_sighup_handler ();

    /**
     * Restore the state of SIGHUP prior to setting the handler.
     */
    void
    clear_sighup_handler ();

    /**
     * Set the SIGTERM handler.
     *
     * An error will be thrown on failure.
     */
    void
    set_sigterm_handler ();

    /**
     * Restore the state of SIGTERM prior to setting the handler.
     */
    void
    clear_sigterm_handler ();

    /**
     * Set a signal handler.
     * An error will be thrown on failure.
     *
     * @param signal the signal number.
     * @param saved_signal the location to save the current handler.
     * @param handler the signal handler to install.
     */
    void
    set_signal_handler (int                signal,
			struct sigaction  *saved_signal,
			void             (*handler)(int));

    /**
     * Restore the state of the signal prior to setting the handler.
     *
     * @param signal the signal number.
     * @param saved_signal the location from which to restore the
     * saved handler.
     */
    void
    clear_signal_handler (int               signal,
			  struct sigaction *saved_signal);

    /// Authentication state.
    auth::ptr        authstat;
    /// The chroot configuration.
    config_ptr       config;
    /// The chroots to run the session operation in.
    string_list      chroots;
    /// The current chroot status.
    int              chroot_status;
    /// Lock status for locks acquired during chroot setup.
    bool lock_status;
    /// The child exit status.
    int              child_status;
    /// The session operation to perform.
    operation        session_operation;
    /// The session identifier.
    std::string      session_id;
    /// The session force status.
    bool             force;
    /// Signal saved while sighup handler is set.
    struct sigaction saved_sighup_signal;
    /// Signal saved while sigterm handler is set.
    struct sigaction saved_sigterm_signal;
    /// Saved terminal settings.
    struct termios saved_termios;
    /// Are the saved terminal settings valid?
    bool termios_ok;

  protected:
    /// Current working directory.
    std::string      cwd;
  };

}

#endif /* SBUILD_SESSION_H */

/*
 * Local Variables:
 * mode:C++
 * End:
 */