sudo_plugin/
errors.rs

1// Copyright 2018 Square Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12// implied. See the License for the specific language governing
13// permissions and limitations under the License.
14
15//! The collection of `Error` types used by this library.
16
17// TODO: use error types as directly defined by sudo_plugin(8).
18
19// TODO: remove when error_chain is updated to compile cleanly
20#![allow(bare_trait_objects)]
21#![allow(renamed_and_removed_lints)]
22#![allow(single_use_lifetimes)]
23#![allow(variant_size_differences)]
24
25use crate::version::Version;
26
27use std::fmt;
28
29use sudo_plugin_sys as sys;
30use libc::c_int;
31use error_chain::*;
32
33pub use error_chain::bail;
34
35/// The list of supported facilities to communicate with the end-user.
36#[derive(Clone, Copy, Debug)]
37pub enum IoFacility {
38    /// A printf-style function that can be used for one-way communication
39    /// with the invoking user.
40    PluginPrintf,
41
42    /// A more complicated facility that enables two-way communication
43    /// with the invoking user.
44    Conversation,
45}
46
47impl fmt::Display for IoFacility {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        match *self {
50            IoFacility::PluginPrintf => write!(f, "plugin_printf"),
51            IoFacility::Conversation => write!(f, "conversation"),
52        }
53    }
54}
55
56error_chain! {
57    errors {
58        /// An error which can be returned when the requsested plugin API
59        /// version is incompatible with the version implemented by this
60        /// library.
61        UnsupportedApiVersion(cur: Version) {
62            description("sudo doesn't support the minimum plugin API version required by this plugin"),
63            display("sudo called this plugin with an API version of {}, but a minimum of {} is required", cur, Version::minimum()),
64        }
65
66        /// An error which can be returned when there's a general error
67        /// when initiailizing the plugin.
68        Uninitialized {
69            description("the plugin failed to initialize"),
70            display("the plugin failed to initialize"),
71        }
72
73        /// An error which can be returned if the user is not authorized
74        /// to invoke sudo with the provided command and/or options.
75        Unauthorized {
76            description("command unauthorized"),
77            display("command unauthorized"),
78        }
79    }
80}
81
82/// A trait that is implemented by all Error types in this library, which
83/// allows any error to be converted to its corresponding integer error
84/// code as understood by the sudo plugin API.
85///
86/// The sudo plugin API understands the following error codes:
87///
88/// *  1: Success
89/// *  0: Failure
90/// * -1: General error
91/// * -2: Usage error
92pub trait AsSudoPluginRetval {
93    /// Converts the error to its corresponding integer error code for
94    /// the I/O plugin `open` function.
95    fn as_sudo_io_plugin_open_retval(&self) -> c_int;
96
97    /// Converts the error to its corresponding integer error code for
98    /// the I/O plugin `log_*` suite of functions.
99    fn as_sudo_io_plugin_log_retval(&self) -> c_int;
100}
101
102impl<T, E: AsSudoPluginRetval> AsSudoPluginRetval for ::std::result::Result<T, E> {
103    fn as_sudo_io_plugin_open_retval(&self) -> c_int {
104        match *self {
105            Ok(_)      => sys::SUDO_PLUGIN_OPEN_SUCCESS,
106            Err(ref e) => e.as_sudo_io_plugin_open_retval(),
107        }
108    }
109
110    fn as_sudo_io_plugin_log_retval(&self) -> c_int {
111        match *self {
112            Ok(_)      => sys::SUDO_PLUGIN_OPEN_SUCCESS,
113            Err(ref e) => e.as_sudo_io_plugin_log_retval(),
114        }
115    }
116}
117
118impl AsSudoPluginRetval for Error {
119    fn as_sudo_io_plugin_open_retval(&self) -> c_int {
120        match *self {
121            Error(ErrorKind::Unauthorized, _) => sys::SUDO_PLUGIN_OPEN_GENERAL_ERROR,
122            Error(_, _)                       => sys::SUDO_PLUGIN_OPEN_FAILURE,
123        }
124    }
125
126    fn as_sudo_io_plugin_log_retval(&self) -> c_int {
127        match *self {
128            Error(ErrorKind::Unauthorized, _) => sys::SUDO_PLUGIN_OPEN_FAILURE,
129            Error(_, _)                       => sys::SUDO_PLUGIN_OPEN_GENERAL_ERROR,
130        }
131    }
132}