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
|
NOTE: the Sudo auth API is subject to change
Purpose: to provide a simple API for authentication methods that
encapsulates things nicely without turning into a maze
of #ifdef's
The sudo_auth struct looks like this:
typedef struct sudo_auth {
short flags; /* various flags, see below */
short status; /* status from verify routine */
char *name; /* name of the method in string form */
void *data; /* method-specific data pointer */
int (*init) __P((struct passwd *pw, char **prompt, sudo_auth *auth));
int (*setup) __P((struct passwd *pw, char **prompt, sudo_auth *auth));
int (*verify) __P((struct passwd *pw, char *p, sudo_auth *auth));
int (*cleanup) __P((struct passwd *pw, sudo_auth *auth));
} sudo_auth;
The variables in the struct are as follows:
flags Bitwise binary flags, see below.
status Contains the return value from the last run of
the "verify" function. Starts out as AUTH_FAILURE.
name The name of the authentication method as a C string.
data A pointer to method-specific data. This is passed to
all the functions of an auth method and is usually
initialized in the "init" or "setup" routines.
Possible values of sudo_auth.flags:
FLAG_USER Whether or not the auth functions should run with
the euid of the invoking user instead of 0.
FLAG_CONFIGURED If set then the auth method is assumed to have been
configured successfully. All auth methods start out
with this set. If an "init" or "setup" function
fails, this bit is cleared.
FLAG_ONEANDONLY If set, this indicates that the method is the
only one in use. Can be used by auth functions
to determine whether to return a fatal or nonfatal
error.
The member functions can return the following values:
AUTH_SUCCESS Function succeeded. For a ``verify'' function
this means the user correctly authenticated.
AUTH_FAILURE Function failed. If this is an ``init'' or
``setup'' routine, the auth method will be
marked as !configured.
AUTH_FATAL A fatal error occurred. The routine should have
written an error message to stderr and optionally
sent mail to the administrator. (If log_error()
is called to do this, the NO_EXIT flag must be used.)
When verify_user() gets AUTH_FATAL from an auth
function it does an exit(1).
The functions in the struct are as follows:
int init(struct passwd *pw, char **prompt, sudo_auth *auth)
Function to do any one-time initialization for the auth
method. All of the "init" functions are run before anything
else. A pointer to the prompt string may be used to add
method-specific info to the prompt.
int setup(struct passwd *pw, char **prompt, sudo_auth *auth)
Function to do method-specific setup. All the "setup"
routines are run before any of the "verify" routines. A
pointer to the prompt string may be used to add method-specific
info to the prompt.
int verify(struct passwd *pw, char *p, sudo_auth *auth)
Function to do user verification for this auth method. For
standalone auth methods ``p'' is the prompt string. For
normal auth methods, ``p'' is the password the user entered.
Note that standalone auth methods are responsible for
rerading the password themselves.
int cleanup(struct passwd *pw, sudo_auth *auth)
Function to do per-auth method cleanup. This is only run
at the end of the authentication process, after the user
has completely failed or succeeded to authenticate.
The ``auth->status'' variable contains the result of the
last authentication attempt which may be interesting.
A note about standalone methods. Some authentication methods can't
coexist with any others. This may be because they encapsulate other
methods (pam, sia) or because they have a special way of interacting
with the user (securid).
Adding a new authentication method:
Each method should live in its own file. Add prototypes for the functions
in sudo_auth.h.
If this is a standalone method, add it to the standalone #if cascade
in sudo_auth.h. For instance, for a method, ``fooauth'', add:
#elif defined(HAVE_FOOAUTH)
# define AUTH_STANDALONE \
AUTH_ENTRY(0, "foo", \
foo_init, foo_setup, foo_verify, foo_cleanup)
If the method needs to run as the user, not root, replace the first
parameter to AUTH_ENTRY (0) with FLAG_USER. If you don't have a
init/setup/cleanup routine, just use a NULL for that field.
For a normal authentication method, add it to the ``auth_switch'' in
sudo_auth.c. If ``fooauth'' is a normal auth method, its entry
would look like:
# ifdef HAVE_FOOAUTH
AUTH_ENTRY(0, "foo", foo_init, foo_setup, foo_verify, foo_cleanup)
# endif
Again, if the method doesn't need to run as root, replace the 0 with
FLAG_USER. Likewise, if you don't have a init/setup/cleanup routine,
just use a NULL for that field.
NOTE: You should not make a method both ``standalone'' and
``normal''. Just use the --without-passwd configure argument
to disable passwd/shadow file checking and then have your
auth routines check the FLAG_ONEANDONLY flag to see if
they are running standalone and act accordingly.
|