2 * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
5 * This software was developed for the FreeBSD Project by ThinkSec AS and
6 * Network Associates Laboratories, the Security Research Division of
7 * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
8 * ("CBOSS"), as part of the DARPA CHATS research program.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote
19 * products derived from this software without specific prior written
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $P4: //depot/projects/openpam/lib/openpam_dispatch.c#21 $
37 #include <sys/param.h>
39 #include <security/pam_appl.h>
41 #include "openpam_impl.h"
43 #if !defined(OPENPAM_RELAX_CHECKS)
44 static void _openpam_check_error_code(int, int);
46 #define _openpam_check_error_code(a, b)
47 #endif /* !defined(OPENPAM_RELAX_CHECKS) */
52 * Execute a module chain
56 openpam_dispatch(pam_handle_t
*pamh
,
68 RETURNC(PAM_SYSTEM_ERR
);
70 /* prevent recursion */
71 if (pamh
->current
!= NULL
) {
72 openpam_log(PAM_LOG_ERROR
,
73 "%s() called while %s::%s() is in progress",
74 _pam_func_name
[primitive
],
75 pamh
->current
->module
->path
,
76 _pam_sm_func_name
[pamh
->primitive
]);
82 case PAM_SM_AUTHENTICATE
:
84 chain
= pamh
->chains
[PAM_AUTH
];
86 case PAM_SM_ACCT_MGMT
:
87 chain
= pamh
->chains
[PAM_ACCOUNT
];
89 case PAM_SM_OPEN_SESSION
:
90 case PAM_SM_CLOSE_SESSION
:
91 chain
= pamh
->chains
[PAM_SESSION
];
93 case PAM_SM_CHAUTHTOK
:
94 chain
= pamh
->chains
[PAM_PASSWORD
];
97 RETURNC(PAM_SYSTEM_ERR
);
101 for (err
= fail
= 0; chain
!= NULL
; chain
= chain
->next
) {
102 if (chain
->module
->func
[primitive
] == NULL
) {
103 openpam_log(PAM_LOG_ERROR
, "%s: no %s()",
104 chain
->module
->path
, _pam_sm_func_name
[primitive
]);
107 pamh
->primitive
= primitive
;
108 pamh
->current
= chain
;
110 debug
= (openpam_get_option(pamh
, "debug") != NULL
);
113 openpam_log(PAM_LOG_DEBUG
, "calling %s() in %s",
114 _pam_sm_func_name
[primitive
], chain
->module
->path
);
116 r
= (chain
->module
->func
[primitive
])(pamh
, flags
,
117 chain
->optc
, (const char **)chain
->optv
);
118 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
));
130 if (r
== PAM_SUCCESS
) {
132 * For pam_setcred() and pam_chauthtok() with the
133 * PAM_PRELIM_CHECK flag, treat "sufficient" as
136 if ((chain
->flag
== PAM_SUFFICIENT
||
137 chain
->flag
== PAM_BINDING
) && !fail
&&
138 primitive
!= PAM_SM_SETCRED
&&
139 !(primitive
== PAM_SM_CHAUTHTOK
&&
140 (flags
& PAM_PRELIM_CHECK
)))
145 _openpam_check_error_code(primitive
, r
);
148 * Record the return code from the first module to
149 * fail. If a required module fails, record the
150 * return code from the first required module to fail.
154 if ((chain
->flag
== PAM_REQUIRED
||
155 chain
->flag
== PAM_BINDING
) && !fail
) {
156 openpam_log(PAM_LOG_DEBUG
, "required module failed");
162 * If a requisite module fails, terminate the chain
165 if (chain
->flag
== PAM_REQUISITE
) {
166 openpam_log(PAM_LOG_DEBUG
, "requisite module failed");
172 if (!fail
&& err
!= PAM_NEW_AUTHTOK_REQD
)
177 #if !defined(OPENPAM_RELAX_CHECKS)
179 _openpam_check_error_code(int primitive
, int r
)
181 /* common error codes */
182 if (r
== PAM_SUCCESS
||
183 r
== PAM_SERVICE_ERR
||
186 r
== PAM_PERM_DENIED
||
190 /* specific error codes */
192 case PAM_SM_AUTHENTICATE
:
193 if (r
== PAM_AUTH_ERR
||
194 r
== PAM_CRED_INSUFFICIENT
||
195 r
== PAM_AUTHINFO_UNAVAIL
||
196 r
== PAM_USER_UNKNOWN
||
201 if (r
== PAM_CRED_UNAVAIL
||
202 r
== PAM_CRED_EXPIRED
||
203 r
== PAM_USER_UNKNOWN
||
207 case PAM_SM_ACCT_MGMT
:
208 if (r
== PAM_USER_UNKNOWN
||
210 r
== PAM_NEW_AUTHTOK_REQD
||
211 r
== PAM_ACCT_EXPIRED
)
214 case PAM_SM_OPEN_SESSION
:
215 case PAM_SM_CLOSE_SESSION
:
216 if (r
== PAM_SESSION_ERR
)
219 case PAM_SM_CHAUTHTOK
:
220 if (r
== PAM_PERM_DENIED
||
221 r
== PAM_AUTHTOK_ERR
||
222 r
== PAM_AUTHTOK_RECOVERY_ERR
||
223 r
== PAM_AUTHTOK_LOCK_BUSY
||
224 r
== PAM_AUTHTOK_DISABLE_AGING
||
230 openpam_log(PAM_LOG_ERROR
, "%s(): unexpected return value %d",
231 _pam_sm_func_name
[primitive
], r
);
233 #endif /* !defined(OPENPAM_RELAX_CHECKS) */