ldap_auth.c revision 606d2d03833903f00d40f9810d4dccd04a752e76
/*
SSSD
LDAP Backend Module
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2008 Red Hat
Copyright (C) 2010, rhafer@suse.de, Novell Inc.
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/>.
*/
#ifdef WITH_MOZLDAP
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#include <time.h>
#include <errno.h>
#include <strings.h>
#include <shadow.h>
#include <security/pam_modules.h>
#include "util/user_info_msg.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_async.h"
#include "providers/ldap/sdap_async_private.h"
/* MIT Kerberos has the same hardcoded warning interval of 7 days. Due to the
* fact that using the expiration time of a Kerberos password with LDAP
* authentication is presumably a rare case a separate config option is not
* necessary. */
enum pwexpire {
PWEXPIRE_NONE = 0,
};
{
int ret;
return EINVAL;
}
return ENOMEM;
}
}
return EOK;
}
enum sdap_result *result)
{
char *end;
int ret;
return EINVAL;
}
if (*end != '\0') {
expire_date));
return EINVAL;
}
if (expire_time == -1) {
return EINVAL;
}
tzset();
expire_time -= timezone;
"daylight [%d] now [%d] expire_time [%d].\n", tzname[0],
} else {
}
}
}
return EOK;
}
enum sdap_result *result)
{
long today;
long password_age;
long exp;
int ret;
return EOK;
}
if (password_age < 0) {
return EOK;
}
{
return EOK;
}
return EOK;
}
/* add_expired_warning() expects time in seconds */
if (exp == 0) {
/* Seconds until next midnight */
}
}
}
return EOK;
}
struct sdap_ppolicy_data *ppolicy,
enum sdap_result *result)
{
int ret;
return ENOMEM;
}
ptr++;
ptr++;
}
return ret;
}
}
return EOK;
}
const struct ldb_message *msg,
{
const char *mark;
const char *val;
const char *pwd_policy;
int ret;
*type = PWEXPIRE_NONE;
if (pwd_policy == NULL) {
return EINVAL;
}
return EOK;
NULL);
return ENOMEM;
}
return EOK;
}
} else {
"but MIT Kerberos password policy was requested. "
"Access will be denied.\n"));
return EACCES;
}
return ENOMEM;
}
*type = PWEXPIRE_SHADOW;
return EOK;
} else {
"but shadow password policy was requested. "
"Access will be denied.\n"));
return EACCES;
}
}
return EOK;
return ret;
}
/* ==Get-User-DN========================================================== */
struct sdap_options *opts,
const char *username,
char **user_dn,
enum pwexpire *user_pw_expire_type,
void **user_pw_expire_data)
{
enum pwexpire pw_expire_type;
void *pw_expire_data;
struct ldb_result *res;
const char **attrs;
const char *dn;
int ret;
if (!tmpctx) {
return ENOMEM;
}
if (!attrs) {
goto done;
}
attrs[0] = SYSDB_ORIG_DN;
if (ret) {
goto done;
}
case 0:
/* FIXME: not in cache, needs a true search */
break;
case 1:
if (dn) {
} else {
/* TODO: try to search ldap server ? */
/* FIXME: remove once we store originalDN on every call
* NOTE: this is wrong, works only with some DITs */
}
if (!dn) {
break;
}
}
break;
default:
username));
break;
}
done:
if (!*user_dn) {
}
/* pw_expire_data may be NULL */
}
return ret;
}
/* ==Authenticate-User==================================================== */
struct auth_state {
struct tevent_context *ev;
struct sdap_auth_ctx *ctx;
const char *username;
struct dp_opt_blob password;
struct sdap_service *sdap_service;
struct sdap_handle *sh;
enum sdap_result result;
char *dn;
enum pwexpire pw_expire_type;
void *pw_expire_data;
};
struct tevent_context *ev,
struct sdap_auth_ctx *ctx,
const char *username,
struct dp_opt_blob password,
bool try_chpass_service)
{
struct tevent_req *req;
struct auth_state *state;
/* Treat a zero-length password as a failure */
}
} else {
}
return req;
fail:
return NULL;
}
{
struct tevent_req *next_req;
struct auth_state);
/* NOTE: this call may cause service->uri to be refreshed
* with a new valid server. Do not use service->uri before */
if (!next_req) {
return NULL;
}
return next_req;
}
{
struct tevent_req);
struct auth_state);
int ret;
bool use_tls;
if (ret) {
/* all servers have been tried and none
* was found good, go offline */
return;
}
/* Determine whether we need to use TLS */
use_tls = false;
} else {
/* Check for undocumented debugging feature to disable TLS
* for authentication. This should never be used in production
* for obvious reasons.
*/
if (!use_tls) {
"insecure connection. This should be done "
"for debugging purposes only.");
}
}
if (!subreq) {
return;
}
}
{
struct tevent_req);
struct auth_state);
int ret;
if (ret) {
/* mark this server as bad if connection failed */
}
}
return;
}
return;
}
if (ret) {
return;
}
if (!subreq) {
return;
}
}
{
struct tevent_req);
struct auth_state);
int ret;
struct sdap_ppolicy_data *ppolicy;
"assuming LDAP password policies are active.\n"));
}
if (ret) {
return;
}
}
struct sdap_handle **sh,
{
enum tevent_req_state tstate;
switch (tstate) {
case TEVENT_REQ_USER_ERROR:
*result = SDAP_UNAVAIL;
return EOK;
return EOK;
} else {
*result = SDAP_ERROR;
return err;
}
default:
*result = SDAP_ERROR;
return EIO;
}
}
}
}
if (pw_expire_data != NULL) {
}
return EOK;
}
/* ==Perform-Password-Change===================== */
struct sdap_pam_chpass_state {
const char *username;
char *dn;
char *password;
char *new_password;
struct sdap_handle *sh;
struct sdap_auth_ctx *ctx;
};
{
struct sdap_pam_chpass_state *state;
struct sdap_auth_ctx *ctx;
struct tevent_req *subreq;
struct dp_opt_blob authtok;
int dp_err = DP_ERR_FATAL;
struct sdap_auth_ctx);
goto done;
}
pd->authtok_size == 0) {
goto done;
}
goto done;
}
(char *)pd->newauthtok,
}
return;
done:
}
{
struct sdap_pam_chpass_state *state =
struct tevent_req *subreq;
enum sdap_result result;
enum pwexpire pw_expire_type;
void *pw_expire_data;
int dp_err = DP_ERR_FATAL;
int ret;
if (ret) {
goto done;
}
"successful.\n"));
goto done;
}
if (result == SDAP_AUTH_SUCCESS) {
switch (pw_expire_type) {
case PWEXPIRE_SHADOW:
&result);
goto done;
}
break;
case PWEXPIRE_KERBEROS:
&result);
goto done;
}
if (result == SDAP_AUTH_PW_EXPIRED) {
"passwords.\n"));
goto done;
}
break;
case PWEXPIRE_NONE:
break;
default:
goto done;
}
}
switch (result) {
case SDAP_AUTH_SUCCESS:
case SDAP_AUTH_PW_EXPIRED:
if (pw_expire_type == PWEXPIRE_SHADOW) {
/* TODO: implement async ldap modify request */
goto done;
} else {
if (!subreq) {
goto done;
}
return;
}
break;
case SDAP_AUTH_FAILED:
break;
case SDAP_UNAVAIL:
break;
default:
}
done:
}
{
struct sdap_pam_chpass_state *state =
enum sdap_result result;
int dp_err = DP_ERR_FATAL;
int ret;
char *user_error_message = NULL;
char *lastchanged_name;
struct tevent_req *subreq;
goto done;
}
switch (result) {
case SDAP_SUCCESS:
break;
break;
default:
break;
}
} else {
msg);
}
}
}
goto done;
}
return;
}
done:
}
{
struct sdap_pam_chpass_state *state =
int dp_err = DP_ERR_FATAL;
goto done;
}
done:
}
/* ==Perform-User-Authentication-and-Password-Caching===================== */
struct sdap_pam_auth_state {
const char *username;
struct dp_opt_blob password;
};
{
struct sdap_pam_auth_state *state;
struct sdap_auth_ctx *ctx;
struct tevent_req *subreq;
int dp_err = DP_ERR_FATAL;
struct sdap_auth_ctx);
goto done;
}
case SSS_PAM_AUTHENTICATE:
case SSS_PAM_CHAUTHTOK_PRELIM:
return;
case SSS_PAM_CHAUTHTOK:
break;
case SSS_PAM_ACCT_MGMT:
case SSS_PAM_SETCRED:
case SSS_PAM_OPEN_SESSION:
case SSS_PAM_CLOSE_SESSION:
break;
default:
}
done:
}
{
struct sdap_pam_auth_state *state =
enum sdap_result result;
enum pwexpire pw_expire_type;
void *pw_expire_data;
int ret;
goto done;
}
if (result == SDAP_AUTH_SUCCESS) {
switch (pw_expire_type) {
case PWEXPIRE_SHADOW:
goto done;
}
break;
case PWEXPIRE_KERBEROS:
goto done;
}
break;
goto done;
}
break;
case PWEXPIRE_NONE:
break;
default:
goto done;
}
}
switch (result) {
case SDAP_AUTH_SUCCESS:
break;
case SDAP_AUTH_FAILED:
break;
case SDAP_UNAVAIL:
break;
case SDAP_ACCT_EXPIRED:
break;
case SDAP_AUTH_PW_EXPIRED:
break;
default:
}
if (result == SDAP_UNAVAIL) {
goto done;
}
if (result == SDAP_AUTH_SUCCESS &&
/* password caching failures are not fatal errors */
if (!password) {
goto done;
}
/* password caching failures are not fatal errors */
} else {
}
goto done;
}
done:
}
{
}