2 * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
3 * Copyright (c) 2004-2011 Dag-Erling Smørgrav
6 * This software was developed for the FreeBSD Project by ThinkSec AS and
7 * Network Associates Laboratories, the Security Research Division of
8 * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
9 * ("CBOSS"), as part of the DARPA CHATS research program.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote
20 * products derived from this software without specific prior written
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * $Id: openpam_dispatch.c 501 2011-12-07 01:28:05Z des $
42 #include <sys/param.h>
44 #include <security/pam_appl.h>
46 #include "openpam_impl.h"
48 #if !defined(OPENPAM_RELAX_CHECKS)
49 static void openpam_check_error_code(int, int);
51 #define openpam_check_error_code(a, b)
52 #endif /* !defined(OPENPAM_RELAX_CHECKS) */
57 * Execute a module chain
61 openpam_dispatch(pam_handle_t
*pamh
,
71 RETURNC(PAM_SYSTEM_ERR
);
73 /* prevent recursion */
74 if (pamh
->current
!= NULL
) {
75 openpam_log(PAM_LOG_ERROR
,
76 "%s() called while %s::%s() is in progress",
77 pam_func_name
[primitive
],
78 pamh
->current
->module
->path
,
79 pam_sm_func_name
[pamh
->primitive
]);
85 case PAM_SM_AUTHENTICATE
:
87 chain
= pamh
->chains
[PAM_AUTH
];
89 case PAM_SM_ACCT_MGMT
:
90 chain
= pamh
->chains
[PAM_ACCOUNT
];
92 case PAM_SM_OPEN_SESSION
:
93 case PAM_SM_CLOSE_SESSION
:
94 chain
= pamh
->chains
[PAM_SESSION
];
96 case PAM_SM_CHAUTHTOK
:
97 chain
= pamh
->chains
[PAM_PASSWORD
];
100 RETURNC(PAM_SYSTEM_ERR
);
104 for (err
= fail
= 0; chain
!= NULL
; chain
= chain
->next
) {
105 if (chain
->module
->func
[primitive
] == NULL
) {
106 openpam_log(PAM_LOG_ERROR
, "%s: no %s()",
107 chain
->module
->path
, pam_sm_func_name
[primitive
]);
110 pamh
->primitive
= primitive
;
111 pamh
->current
= chain
;
112 debug
= (openpam_get_option(pamh
, "debug") != NULL
);
115 openpam_log(PAM_LOG_DEBUG
, "calling %s() in %s",
116 pam_sm_func_name
[primitive
], chain
->module
->path
);
117 r
= (chain
->module
->func
[primitive
])(pamh
, flags
,
118 chain
->optc
, (const char **)chain
->optv
);
119 pamh
->current
= NULL
;
120 openpam_log(PAM_LOG_DEBUG
, "%s: %s(): %s",
121 chain
->module
->path
, pam_sm_func_name
[primitive
],
122 pam_strerror(pamh
, r
));
129 if (r
== PAM_SUCCESS
) {
131 * For pam_setcred() and pam_chauthtok() with the
132 * PAM_PRELIM_CHECK flag, treat "sufficient" as
135 if ((chain
->flag
== PAM_SUFFICIENT
||
136 chain
->flag
== PAM_BINDING
) && !fail
&&
137 primitive
!= PAM_SM_SETCRED
&&
138 !(primitive
== PAM_SM_CHAUTHTOK
&&
139 (flags
& PAM_PRELIM_CHECK
)))
144 openpam_check_error_code(primitive
, r
);
147 * Record the return code from the first module to
148 * fail. If a required module fails, record the
149 * return code from the first required module to fail.
153 if ((chain
->flag
== PAM_REQUIRED
||
154 chain
->flag
== PAM_BINDING
) && !fail
) {
155 openpam_log(PAM_LOG_DEBUG
, "required module failed");
161 * If a requisite module fails, terminate the chain
164 if (chain
->flag
== PAM_REQUISITE
) {
165 openpam_log(PAM_LOG_DEBUG
, "requisite module failed");
171 if (!fail
&& err
!= PAM_NEW_AUTHTOK_REQD
)
176 #if !defined(OPENPAM_RELAX_CHECKS)
178 openpam_check_error_code(int primitive
, int r
)
180 /* common error codes */
181 if (r
== PAM_SUCCESS
||
182 r
== PAM_SERVICE_ERR
||
185 r
== PAM_PERM_DENIED
||
189 /* specific error codes */
191 case PAM_SM_AUTHENTICATE
:
192 if (r
== PAM_AUTH_ERR
||
193 r
== PAM_CRED_INSUFFICIENT
||
194 r
== PAM_AUTHINFO_UNAVAIL
||
195 r
== PAM_USER_UNKNOWN
||
200 if (r
== PAM_CRED_UNAVAIL
||
201 r
== PAM_CRED_EXPIRED
||
202 r
== PAM_USER_UNKNOWN
||
206 case PAM_SM_ACCT_MGMT
:
207 if (r
== PAM_USER_UNKNOWN
||
209 r
== PAM_NEW_AUTHTOK_REQD
||
210 r
== PAM_ACCT_EXPIRED
)
213 case PAM_SM_OPEN_SESSION
:
214 case PAM_SM_CLOSE_SESSION
:
215 if (r
== PAM_SESSION_ERR
)
218 case PAM_SM_CHAUTHTOK
:
219 if (r
== PAM_PERM_DENIED
||
220 r
== PAM_AUTHTOK_ERR
||
221 r
== PAM_AUTHTOK_RECOVERY_ERR
||
222 r
== PAM_AUTHTOK_LOCK_BUSY
||
223 r
== PAM_AUTHTOK_DISABLE_AGING
||
229 openpam_log(PAM_LOG_ERROR
, "%s(): unexpected return value %d",
230 pam_sm_func_name
[primitive
], r
);
232 #endif /* !defined(OPENPAM_RELAX_CHECKS) */