krb5_renew_tgt.c revision 83bf46f4066e3d5e838a32357c201de9bd6ecdfd
/*
SSSD
Kerberos 5 Backend Module -- Renew a TGT automatically
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 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 <security/pam_modules.h>
#include "providers/krb5/krb5_common.h"
#include "providers/krb5/krb5_auth.h"
#include "providers/krb5/krb5_utils.h"
#define INITIAL_TGT_TABLE_SIZE 10
struct renew_tgt_ctx {
struct tevent_context *ev;
struct tevent_timer *te;
};
struct renew_data {
const char *ccfile;
};
struct auth_data {
struct renew_data *renew_data;
};
{
struct auth_data);
struct tevent_req *req;
/* Give back the pam data to the renewal item to be able to retry at the next
* time the renewals re run. */
return;
}
}
{
struct auth_data);
int ret;
int pam_status = PAM_SYSTEM_ERR;
int dp_err;
if (ret) {
}
} else {
switch (pam_status) {
case PAM_SUCCESS:
"Successfully renewed TGT for user [%s].\n",
/* In general a successful renewal will update the renewal item and free the
* old data. But if the TGT has reached the end of his renewable lifetime it
* will not be put into the list of renewable tickets again. In this case the
* renewal item is not updated and the value from the hash and the one we have
* stored are the same. Since the TGT cannot be renewed anymore we want to
* remove it from the list of renewable tickets. */
if (ret == HASH_SUCCESS) {
struct renew_data)) {
"New TGT was not added for renewal, "
"removing list entry for user [%s].\n",
if (ret != HASH_SUCCESS) {
}
}
}
break;
case PAM_AUTHINFO_UNAVAIL:
case PAM_AUTHTOK_LOCK_BUSY:
"Cannot renewed TGT for user [%s] while offline, "
"will retry later.\n",
}
break;
default:
"Failed to renew TGT for user [%s].\n",
if (ret != HASH_SUCCESS) {
}
}
}
}
{
int ret;
unsigned long count;
size_t c;
struct renew_data *renew_data;
if (ret != HASH_SUCCESS) {
return ENOMEM;
}
for (c = 0; c < count; c++) {
/* If renew_data->pd == NULL a renewal request for this data is
* currently running so we skip it. */
} else {
/* We need to steal the pam_data here, because a successful renewal of the
* ticket might add a new renewal item to the list with the same key (upn).
* This would delete renew_data and all its children. But we cannot be sure
* that adding the new renewal item is the last operation of the renewal
* process with access the pam_data. To be on the safe side we steal the
* pam_data and make it a child of auth_data which is only freed after the
* renewal process is finished. In the case of an error during renewal we
* might want to steal the pam_data back to renew_data before freeing
* auth_data to allow a new renewal attempt. */
} else {
"tevent_add_timer failed.\n");
}
}
}
if (ret != HASH_SUCCESS) {
}
}
}
}
return EOK;
}
static void renew_tgt_offline_callback(void *private_data)
{
struct renew_tgt_ctx);
}
static void renew_tgt_online_callback(void *private_data)
{
struct renew_tgt_ctx);
}
struct tevent_timer *te,
{
struct renew_tgt_ctx);
/* forget the timer event, it will be freed by the tevent timer loop */
}
{
int ret;
return;
}
"Disabling automatic TGT renewal\n");
return;
}
"There is an active renewal timer, doing nothing.\n");
return;
}
0);
}
return;
}
{
struct renew_data *renew_data;
return;
}
}
const char *ccache_file, const char *upn,
const char *user_name)
{
int ret;
const char *filename;
"Missing one of the needed attributes: [%s][%s][%s].\n",
return EINVAL;
}
} else {
}
return EOK;
}
return ret;
}
return ret;
}
"Adding [%s] for automatic renewal.\n", ccache_file);
"automatic renewal not possible.\n");
}
} else {
}
return EOK;
}
{
int ret;
size_t msgs_count = 0;
size_t c;
const char *ccache_file;
char *upn;
const char *user_name;
const struct ldb_val *user_dom_val;
char *user_dom;
return ENOMEM;
}
goto done;
}
&msgs_count, &msgs);
goto done;
}
if (msgs_count == 0) {
"No entries with ccache file found in cache.\n");
goto done;
}
"Found [%zu] entries with ccache file in cache.\n", msgs_count);
for (c = 0; c < msgs_count; c++) {
"No user name found, this is a severe error, "
"but we ignore it here.\n");
continue;
}
/* The DNs of users in sysdb looks like
* name=username,cn=users,cn=domain.name,cn=sysdb
* the value of the third component (index 2) is the domain name. */
if (user_dom_val == NULL) {
goto done;
}
goto done;
}
goto done;
}
NULL);
"Failed to check ccache file [%s].\n", ccache_file);
}
}
done:
return ret;
}
{
int ret;
return ENOMEM;
}
renew_del_cb, NULL);
goto fail;
}
"Failed to read ccache files, continuing ...\n");
}
0);
goto fail;
}
"Adding offline callback to remove renewal timer.\n");
NULL);
goto fail;
}
NULL);
"Failed to add renewal task to online callbacks.\n");
goto fail;
}
return EOK;
fail:
return ret;
}
const char *upn)
{
int ret;
"automatic renewal not available.\n");
return EOK;
}
return EINVAL;
}
return EINVAL;
}
/* hash_enter copies the content of the hash string, so it is safe to use
* discard_const_p here. */
if (renew_data == NULL) {
goto done;
}
if (ccfile[0] == '/') {
goto done;
}
} else {
}
goto done;
}
if (ret) {
goto done;
}
if (ret != HASH_SUCCESS) {
goto done;
}
done:
}
return ret;
}