/*
SSSD
Kerberos 5 Backend Module
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2009-2010 Red Hat
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <pwd.h>
#include <security/pam_modules.h>
#include "util/find_uid.h"
#include "util/auth_utils.h"
#include "util/sss_utf8.h"
#include "util/child_common.h"
#include "providers/krb5/krb5_auth.h"
#include "providers/krb5/krb5_utils.h"
#include "providers/krb5/krb5_ccache.h"
struct sss_domain_info *domain,
const char *name,
const char *ccname,
int mod_op)
{
int ret;
bool in_transaction = false;
return EINVAL;
}
return EINVAL;
}
if (!tmpctx) {
return ENOMEM;
}
if (!attrs) {
goto done;
}
goto done;
}
goto done;
}
in_transaction = true;
goto done;
}
goto done;
}
in_transaction = false;
done:
if (in_transaction) {
}
}
return ret;
}
struct sss_domain_info *domain,
const char *name,
const char *ccname)
{
}
struct sss_domain_info *domain,
const char *name,
const char *ccname)
{
}
{
return EOK;
}
static errno_t
{
int i = 0;
while(name_to_primary != NULL &&
goto done;
}
i++;
}
/* Handle also the case of name_to_primary being NULL */
done:
return ret;
}
struct sss_domain_info *dom,
struct krb5child_req **_krb5_req)
{
const char *mapped_name;
return ENOMEM;
}
goto done;
}
kr->is_offline = false;
dom->case_sensitive, 0);
goto done;
}
dom->case_sensitive, 0);
goto done;
}
} else {
goto done;
}
done:
}
return ret;
}
struct sss_domain_info *domain,
struct confdb_ctx *cdb,
int *pam_status, int *dp_err)
{
"Delayed authentication is only available for password "
"authentication (single factor).\n");
return;
}
return;
}
return;
}
/* This error is not fatal */
"add_user_to_delayed_online_authentication failed.\n");
}
*dp_err = DP_ERR_OFFLINE;
}
struct ldb_message *user_msg,
{
const char *ccname_template;
return ENOMEM;
}
}
return EOK;
}
{
const char *fa2;
case SSS_CMD_RENEW:
/* The authtok is set to the credential cache
* during renewal. We don't want to save this
* as the cached password.
*/
break;
case SSS_PAM_PREAUTH:
/* There are no credentials available during pre-authentication,
* nothing to do. */
break;
case SSS_PAM_AUTHENTICATE:
case SSS_PAM_CHAUTHTOK_PRELIM:
"First factor is too short to be cache, "
"minimum length is [%u].\n",
}
} else {
}
break;
case SSS_PAM_CHAUTHTOK:
break;
default:
}
/* password caching failures are not fatal errors */
return;
}
"password not available, offline auth may not work.\n");
/* password caching failures are not fatal errors */
}
return;
}
if (ret) {
"Failed to cache password, offline auth may not work."
/* password caching failures are not fatal errors */
}
}
{
size_t i;
return false;
}
for (i = 0; i < el->num_values; i++) {
return true;
}
}
return false;
}
/* krb5_auth request */
struct krb5_auth_state {
bool search_kpasswd;
int pam_status;
int dp_err;
};
struct tevent_context *ev,
{
const char **attrs;
const char *realm;
int ret;
bool otp;
return NULL;
}
goto done;
}
case SSS_PAM_AUTHENTICATE:
case SSS_PAM_CHAUTHTOK:
&& authtok_type != SSS_AUTHTOK_TYPE_2FA) {
/* handle empty password gracefully */
if (authtok_type == SSS_AUTHTOK_TYPE_EMPTY) {
"Illegal zero-length authtok for user [%s]\n",
goto done;
}
"Wrong authtok type for user [%s]. " \
goto done;
}
break;
case SSS_PAM_CHAUTHTOK_PRELIM:
"Password reset by root is not supported.\n");
goto done;
}
break;
case SSS_CMD_RENEW:
if (authtok_type != SSS_AUTHTOK_TYPE_CCFILE) {
"Wrong authtok type for user [%s]. " \
goto done;
}
break;
case SSS_PAM_PREAUTH:
break;
default:
goto done;
}
if (be_is_offline(be_ctx) &&
"Password changes and ticket renewal are not possible "
"while offline.\n");
goto done;
}
goto done;
}
goto done;
}
if (ret) {
goto done;
}
goto done;
}
case 0:
goto done;
break;
case 1:
goto done;
}
if (ret != 0) {
goto done;
}
NULL);
}
SYSDB_UIDNUM, 0);
goto done;
}
SYSDB_GIDNUM, 0);
goto done;
}
goto done;
}
break;
default:
goto done;
break;
}
/* To avoid consuming the OTP */
"Skipping password checks for OTP-enabled user\n");
goto done;
}
state->search_kpasswd = false;
if (!subreq) {
goto done;
}
return req;
done:
} else {
}
return req;
}
{
int ret;
if (!state->search_kpasswd) {
} else {
}
if (state->search_kpasswd) {
/* all kpasswd servers have been tried and none was found good,
* but the kdc seems ok. Password changes are not possible but
* authentication is. We return an PAM error here, but do not
* mark the backend offline. */
goto done;
}
} else {
/* all servers have been tried and none
* was found good, setting offline,
* but we still have to call the child to setup
* the ccache file if we are performing auth */
kr->is_offline = true;
"No KDC suitable for password change is available\n");
goto done;
}
} else {
state->search_kpasswd = true;
goto done;
}
return;
}
}
}
if (!kr->is_offline) {
}
if (!kr->is_offline
"Subdomain %s is inactive, will proceed offline\n",
kr->is_offline = true;
}
if (kr->is_offline
KRB5_REALM))) {
"Resetting offline status, KDC proxy is in use\n");
kr->is_offline = false;
}
goto done;
}
return;
done:
} else {
}
}
{
int ret;
char *renew_interval_str;
bool use_enterprise_principal;
case SSS_PAM_AUTHENTICATE:
case SSS_CMD_RENEW:
state->search_kpasswd = false;
break;
case SSS_PAM_CHAUTHTOK:
case SSS_PAM_CHAUTHTOK_PRELIM:
state->search_kpasswd = true;
break;
} else {
state->search_kpasswd = false;
break;
}
case SSS_PAM_PREAUTH:
goto done;
default:
goto done;
}
search_srv == NULL ? true : false);
goto done;
}
return;
goto done;
}
/* EOK */
&res);
if (ret) {
goto done;
}
goto done;
}
}
/* Check if the cases of our upn are correct and update it if needed.
* Fail if the upn differs by more than just the case for non-enterprise
* principals. */
use_enterprise_principal == true) {
goto done;
}
"check_if_cached_upn_needs_update failed.\n");
goto done;
}
} else {
"returned UPN [%s] differ by more " \
"than just the case.\n",
goto done;
}
}
/* If the child request failed, but did not return an offline error code,
* return with the status */
switch (res->msg_status) {
case ERR_OK:
/* If the child request was successful and we run the first pass of the
* change password request just return success. */
goto done;
}
break;
case ERR_NETWORK_IO:
/* if using a dedicated kpasswd server for a chpass operation... */
/* ..try to resolve next kpasswd server */
state->search_kpasswd = true;
goto done;
}
return;
/* failed to use the KDC... */
/* ..try to resolve next KDC */
state->search_kpasswd = false;
goto done;
}
return;
}
break;
case ERR_CREDS_EXPIRED_CCACHE:
}
/* FALLTHROUGH */
case ERR_CREDS_EXPIRED:
/* If the password is expired we can safely remove the ccache from the
* cache and disk if it is not actively used anymore. This will allow
* to create a new random ccache if sshd with privilege separation is
* used. */
}
}
}
goto done;
case ERR_CREDS_INVALID:
goto done;
case ERR_ACCOUNT_EXPIRED:
goto done;
case ERR_ACCOUNT_LOCKED:
goto done;
case ERR_NO_CREDS:
goto done;
case ERR_AUTH_FAILED:
goto done;
case ERR_CHPASS_FAILED:
goto done;
default:
goto done;
}
/* found a dedicated kpasswd server for a chpass operation */
/* found a KDC */
}
/* Now only a successful authentication or password change is left.
*
* We expect that one of the messages in the received buffer contains
* the name of the credential cache file. */
goto done;
}
if (ret) {
goto done;
}
if (renew_interval_str != NULL) {
"Reading krb5_renew_interval failed.\n");
renew_interval_delta = 0;
}
}
"automatic renewal not possible.\n");
}
}
if (kr->is_offline) {
} else {
"Backend is marked offline, retry later!\n");
}
goto done;
}
SSS_AUTHTOK_TYPE_2FA))) {
}
/* The SSS_OTP message will prevent pam_sss from putting the entered
* password on the PAM stack for other modules to use. This is not needed
* when both factors were entered separately because here the first factor
* (long term password) can be passed to the other modules. */
"pam_add_response failed: %d (%s).\n",
goto done;
}
}
done:
} else {
}
}
{
return EOK;
}
struct krb5_pam_handler_state {
};
struct tevent_req *
struct dp_req_params *params)
{
struct krb5_pam_handler_state);
return NULL;
}
case SSS_PAM_AUTHENTICATE:
case SSS_CMD_RENEW:
case SSS_PAM_CHAUTHTOK_PRELIM:
case SSS_PAM_CHAUTHTOK:
goto immediately;
}
break;
case SSS_PAM_ACCT_MGMT:
goto immediately;
}
break;
case SSS_PAM_SETCRED:
case SSS_PAM_OPEN_SESSION:
case SSS_PAM_CLOSE_SESSION:
goto immediately;
break;
default:
goto immediately;
}
return req;
/* TODO For backward compatibility we always return EOK to DP now. */
return req;
}
{
}
/* TODO For backward compatibility we always return EOK to DP now. */
}
{
bool access_allowed;
}
/* TODO For backward compatibility we always return EOK to DP now. */
}
struct tevent_req *req,
{
return EOK;
}