/*
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
#endif
#include "config.h"
#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"
#include "providers/ldap/ldap_auth.h"
#include "providers/ldap/sdap_access.h"
#define LDAP_PWEXPIRE_WARNING_TIME 0
{
int ret;
return EINVAL;
}
return ENOMEM;
}
}
return EOK;
}
int pwd_exp_warning)
{
int expiration_warning;
&expire_time);
return ret;
}
"Time info: tzname[0] [%s] tzname[1] [%s] timezone [%ld] "
"daylight [%d] now [%ld] expire_time [%ld].\n", tzname[0],
} else {
if (pwd_exp_warning >= 0) {
} else {
}
expiration_warning == 0)) {
}
}
}
return ret;
}
{
long today;
long password_age;
long exp;
int ret;
"Last change day is not set, new password needed.\n");
return ERR_PASSWORD_EXPIRED;
}
if (password_age < 0) {
"The last password change time is in the future!.\n");
return EOK;
}
{
return ERR_ACCOUNT_EXPIRED;
}
return ERR_PASSWORD_EXPIRED;
}
/* add_expired_warning() expects time in seconds */
if (exp == 0) {
/* Seconds until next midnight */
}
}
}
return EOK;
}
struct sdap_ppolicy_data *ppolicy,
int pwd_exp_warning)
{
if (pwd_exp_warning < 0) {
pwd_exp_warning = 0;
}
return ENOMEM;
}
ptr++;
/* do not warn */
goto done;
}
/* send warning */
ptr++;
}
}
}
done:
return ret;
}
void *pw_expire_data,
{
switch (pw_expire_type) {
case PWEXPIRE_SHADOW:
break;
case PWEXPIRE_KERBEROS:
break;
break;
case PWEXPIRE_NONE:
break;
default:
}
return ret;
}
static errno_t
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;
"Found Kerberos password expiration attributes.\n");
NULL);
return ENOMEM;
}
return EOK;
}
} else {
"No Kerberos password expiration attributes found, "
"but MIT Kerberos password policy was requested. "
"Access will be denied.\n");
return EACCES;
}
"Found shadow password expiration attributes.\n");
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 get_user_dn_state {
char *username;
char *orig_dn;
};
struct tevent_context *ev,
struct sss_domain_info *domain,
struct sdap_handle *sh,
struct sdap_options *opts,
const char *username)
{
char *clean_name;
char *filter;
const char **attrs;
goto done;
}
goto done;
}
goto done;
}
/* We're mostly interested in the DN anyway */
goto done;
}
attrs[0] = "objectclass";
if (!subreq) {
goto done;
}
return req;
done:
} else {
}
return req;
}
{
struct tevent_req);
struct get_user_dn_state);
return;
}
if (count == 0) {
return;
} else if (count > 1) {
return;
}
/* exactly one user. Get the originalDN */
return;
}
return;
}
}
char **orig_dn)
{
struct get_user_dn_state);
if (orig_dn) {
}
return EOK;
}
struct sss_domain_info *domain,
struct sdap_options *opts,
const char *username,
char **user_dn,
enum pwexpire *user_pw_expire_type,
void **user_pw_expire_data)
{
void *pw_expire_data;
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:
/* No such user entry? Look it up */
break;
case 1:
/* The user entry has no original DN. This is the case when the ID
* provider is not LDAP-based (proxy perhaps) */
break;
}
if (!dn) {
break;
}
"find_password_expiration_attributes failed.\n");
}
break;
default:
"User search by name (%s) returned > 1 results!\n",
username);
break;
}
done:
if (!*user_dn) {
}
/* pw_expire_data may be NULL */
}
return ret;
}
/* ==Authenticate-User==================================================== */
struct auth_state {
const char *username;
char *dn;
void *pw_expire_data;
};
struct tevent_context *ev,
struct sdap_auth_ctx *ctx,
const char *username,
struct sss_auth_token *authtok,
bool try_chpass_service)
{
/* The token must be a password token */
}
} else {
}
return req;
fail:
return NULL;
}
{
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 */
"[%s] is a secure channel. No need to run START_TLS\n",
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;
}
/* In case the ID provider is set to proxy, this might be the first
* LDAP operation at all, so we need to set the connection status
*/
if (ret) {
return;
}
}
/* All required user data was pre-cached during an identity lookup.
* We can proceed with the bind */
return;
/* The cached user entry was missing the bind DN. Need to look
* it up based on user name in order to perform the bind */
return;
}
return;
}
return;
}
{
struct tevent_req);
return;
}
/* The DN was found with an LDAP lookup
* We can proceed with the bind */
return auth_do_bind(req);
}
{
if (!subreq) {
return;
}
}
{
struct tevent_req);
struct auth_state);
int ret;
"assuming LDAP password policies are active.\n");
}
switch (ret) {
case EOK:
break;
case ETIMEDOUT:
case ERR_NETWORK_IO:
}
return;
default:
return;
}
}
{
}
}
if (pw_expire_data != NULL) {
}
return EOK;
}
struct sdap_pam_auth_handler_state {
};
struct tevent_req *
struct sdap_auth_ctx *auth_ctx,
struct dp_req_params *params)
{
struct sdap_pam_auth_handler_state);
return NULL;
}
case SSS_PAM_AUTHENTICATE:
goto immediately;
}
break;
case SSS_PAM_CHAUTHTOK_PRELIM:
goto immediately;
}
break;
case SSS_PAM_CHAUTHTOK:
goto immediately;
case SSS_PAM_ACCT_MGMT:
case SSS_PAM_SETCRED:
case SSS_PAM_OPEN_SESSION:
case SSS_PAM_CLOSE_SESSION:
goto immediately;
default:
goto immediately;
}
return req;
/* TODO For backward compatibility we always return EOK to DP now. */
return req;
}
{
void *pw_expire_data;
const char *password;
/* Unknown password expiration type. */
goto done;
}
}
switch (ret) {
case EOK:
break;
case ERR_AUTH_DENIED:
break;
case ERR_AUTH_FAILED:
break;
case ETIMEDOUT:
case ERR_NETWORK_IO:
break;
case ERR_ACCOUNT_EXPIRED:
break;
case ERR_PASSWORD_EXPIRED:
break;
case ERR_ACCOUNT_LOCKED:
break;
default:
break;
}
password);
}
/* password caching failures are not fatal errors */
} else {
}
}
done:
/* TODO For backward compatibility we always return EOK to DP now. */
}
struct tevent_req *req,
{
return EOK;
}
struct sdap_pam_chpass_handler_state {
char *dn;
};
struct tevent_req *
struct sdap_auth_ctx *auth_ctx,
struct dp_req_params *params)
{
struct sdap_pam_chpass_handler_state);
return NULL;
}
goto immediately;
}
"Password reset by root is not supported.\n");
goto immediately;
}
"chpass target was called by wrong pam command.\n");
goto immediately;
}
goto immediately;
}
return req;
/* TODO For backward compatibility we always return EOK to DP now. */
return req;
}
{
void *pw_expire_data;
"password operation successful.\n");
goto done;
}
switch (pw_expire_type) {
case PWEXPIRE_SHADOW:
break;
case PWEXPIRE_KERBEROS:
if (ret == ERR_PASSWORD_EXPIRED) {
"kerberos passwords.\n");
goto done;
}
break;
case PWEXPIRE_NONE:
break;
default:
goto done;
}
}
switch (ret) {
case EOK:
case ERR_PASSWORD_EXPIRED:
if (pw_expire_type == PWEXPIRE_SHADOW) {
/* TODO: implement async ldap modify request */
"Changing shadow password attributes not implemented.\n");
goto done;
} else {
const char *password;
const char *new_password;
int timeout;
if (ret) {
goto done;
}
&new_password, NULL);
if (ret) {
goto done;
}
timeout);
goto done;
}
req);
return;
}
break;
case ERR_AUTH_DENIED:
case ERR_AUTH_FAILED:
"pack_user_info_chpass_error failed.\n");
} else {
}
}
break;
case ETIMEDOUT:
case ERR_NETWORK_IO:
break;
default:
break;
}
done:
/* TODO For backward compatibility we always return EOK to DP now. */
}
{
char *lastchanged_name;
switch (ret) {
case EOK:
break;
case ERR_CHPASS_DENIED:
break;
case ERR_NETWORK_IO:
break;
default:
break;
}
} else {
}
}
}
goto done;
}
return;
}
done:
/* TODO For backward compatibility we always return EOK to DP now. */
}
{
goto done;
}
done:
/* TODO For backward compatibility we always return EOK to DP now. */
}
struct tevent_req *req,
{
return EOK;
}