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
use crate::_doc::{guide, linklist, stdlinks};
use crate::constants::Result;
#[cfg(doc)]
use crate::handle::{ModuleClient, PamShared};
use std::ffi::{OsStr, OsString};
macro_rules! getter {
($(#[$md:meta])* $getter:ident($item:literal $(, see = $see:path)?)) => {
$(#[$md])*
#[doc = ""]
#[doc = concat!("Gets the `", $item, "` of the PAM handle.")]
$(
#[doc = concat!("See [`", stringify!($see), "`].")]
)?
fn $getter(&self) -> Result<Option<OsString>>;
};
}
pub(crate) use getter;
macro_rules! setter {
($(#[$md:meta])* $setter:ident($item:literal $(, see = $see:path)?)) => {
$(#[$md])*
#[doc = ""]
#[doc = concat!("Sets the `", $item, "` from the PAM handle.")]
$(
#[doc = concat!("See [`", stringify!($see), "`].")]
)?
///
/// Sets the item's value. PAM copies the string's contents.
///
/// # Panics
///
/// If the string contains a nul byte, this will panic.
///
fn $setter(&mut self, value: Option<&OsStr>) -> Result<()>;
};
}
/// Provides access to Items, pieces of data shared by the PAM application,
/// modules, and the framework itself.
///
/// # References
#[doc = linklist!(pam_get_item: mwg, adg, _std)]
///
#[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_get_item")]
#[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_item")]
#[doc = stdlinks!(3 pam_get_item)]
pub trait Items<'a> {
getter!(
/// The identity of the user for whom service is being requested.
///
/// Unlike [`username`](PamShared::username), this will simply get
/// the current state of the user item, and not request the username.
/// While PAM usually sets this automatically in the `username` call,
/// it may be changed by a module during the PAM transaction.
/// Applications should check it after each step of the PAM process.
user("PAM_USER", see = PamShared::username)
);
getter!(
/// If set, the identity of the remote user logging in.
///
/// This is only as trustworthy as the application calling PAM.
remote_user("PAM_RUSER", see = Self::remote_host)
);
getter!(
/// If set, the remote location where the user is coming from.
///
/// This is only as trustworthy as the application calling PAM.
/// This can be combined with [`Self::remote_user`] to identify
/// the account the user is attempting to log in from,
/// with `remote_user@remote_host`.
///
/// If unset, "it is unclear where the authentication request
/// is originating from."
remote_host("PAM_RHOST", see = Self::remote_user)
);
getter!(
/// The service name, which identifies the PAM stack which is used
/// to perform authentication.
service("PAM_SERVICE")
);
getter!(
/// The string used to prompt for a user's name.
/// By default, this is a localized version of `login: `.
user_prompt("PAM_USER_PROMPT")
);
getter!(
/// The device path of the TTY being used to log in.
///
/// This is the terminal the user is logging in on,
/// specified as the full device path (e.g. `/dev/tty0`).
/// Very old applications may use this instead of `PAM_XDISPLAY`.
tty_name("PAM_TTY")
);
}
/// Provides write access to PAM Items, data shared by the PAM application,
/// the framework, and modules.
///
/// # References
#[doc = linklist!(pam_set_item: mwg, adg, _std)]
///
#[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_set_item")]
#[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_set_item")]
#[doc = stdlinks!(3 pam_set_item)]
pub trait ItemsMut<'a>: Items<'a> {
setter!(
/// Sets the identity of the logging-in user.
///
/// Usually this will be set during the course of
/// a [`username`](PamShared::username) call, but you may set it manually
/// or change it during the PAM process.
set_user("PAM_USER", see = Items::user)
);
setter!(
/// Sets the service name. It's probably a bad idea to change this.
set_service("PAM_SERVICE", see = Items::service)
);
setter!(
/// Sets the string used to prompt for a user's name.
set_user_prompt("PAM_USER_PROMPT", see = Items::user_prompt)
);
setter!(
/// Sets the path to the terminal where the user is logging on.
set_tty_name("PAM_TTY", see = Items::tty_name)
);
setter!(
/// Sets the identity of the remote user logging in.
///
/// This may be set by the application before making calls
/// into a PAM transaction.
set_remote_user("PAM_RUSER", see = Items::remote_user)
);
setter!(
/// Sets the location where the user is coming from.
///
/// This may be set by the application before making calls
/// into a PAM transaction.
set_remote_host("PAM_RHOST", see = Items::remote_host)
);
setter!(
/// Gets the user's authentication token (e.g., password).
///
/// This is usually set automatically when
/// [`authtok`](ModuleClient::authtok) is called,
/// but can be manually set.
set_authtok("PAM_AUTHTOK", see = ModuleClient::authtok_item)
);
setter!(
/// Sets the user's "old authentication token" when changing passwords.
///
/// This is usually set automatically by PAM when
/// [`old_authtok`](ModuleClient::old_authtok) is called.
set_old_authtok("PAM_OLDAUTHTOK", see = ModuleClient::old_authtok_item)
);
}