summaryrefslogtreecommitdiff
path: root/server/providers/krb5
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2009-09-10 14:43:33 +0200
committerSimo Sorce <ssorce@redhat.com>2009-09-14 12:08:58 -0400
commit945e1f1fab935616bde0d1d64d9e16225b44c183 (patch)
tree24f7f54a3457ea982d90ce3cb6b7b0ab4e10efbe /server/providers/krb5
parent4039db6e6b34330fec51bc765f40e85bf7b61141 (diff)
downloadsssd-945e1f1fab935616bde0d1d64d9e16225b44c183.tar.gz
sssd-945e1f1fab935616bde0d1d64d9e16225b44c183.tar.bz2
sssd-945e1f1fab935616bde0d1d64d9e16225b44c183.zip
add krb5ccache_dir and krb5ccname_template option
The configuration options krb5ccache_dir and krb5ccname_template are added to the Kerberos provider to create the user's credential caches the same way as pam_krb5 does. Due to the design of the sssd and the supported ccache types of MIT Kerberos only files are allowed.
Diffstat (limited to 'server/providers/krb5')
-rw-r--r--server/providers/krb5/krb5_auth.c90
-rw-r--r--server/providers/krb5/krb5_auth.h22
-rw-r--r--server/providers/krb5/krb5_child.c116
-rw-r--r--server/providers/krb5/krb5_utils.c141
-rw-r--r--server/providers/krb5/krb5_utils.h37
5 files changed, 356 insertions, 50 deletions
diff --git a/server/providers/krb5/krb5_auth.c b/server/providers/krb5/krb5_auth.c
index 14562760..0fb74ddc 100644
--- a/server/providers/krb5/krb5_auth.c
+++ b/server/providers/krb5/krb5_auth.c
@@ -31,14 +31,16 @@
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
+#include <sys/stat.h>
+
#include <security/pam_modules.h>
#include "util/util.h"
#include "providers/dp_backend.h"
#include "db/sysdb.h"
-#include "krb5_plugin/sssd_krb5_locator_plugin.h"
#include "providers/krb5/krb5_auth.h"
+#include "providers/krb5/krb5_utils.h"
#ifndef SSSD_LIBEXEC_PATH
#error "SSSD_LIBEXEC_PATH not defined"
@@ -46,16 +48,6 @@
#define KRB5_CHILD SSSD_LIBEXEC_PATH"/krb5_child"
#endif
-struct krb5child_req {
- pid_t child_pid;
- int read_from_child_fd;
- int write_to_child_fd;
-
- struct be_req *req;
- struct pam_data *pd;
- struct krb5_ctx *krb5_ctx;
-};
-
static errno_t become_user(uid_t uid, gid_t gid)
{
int ret;
@@ -102,7 +94,8 @@ errno_t create_send_buffer(struct krb5child_req *kr, struct io_buffer **io_buf)
return ENOMEM;
}
- buf->size = 3*sizeof(int) + strlen(kr->pd->upn) + kr->pd->authtok_size;
+ buf->size = 4*sizeof(int) + strlen(kr->pd->upn) + strlen(kr->ccname) +
+ kr->pd->authtok_size;
if (kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
buf->size += sizeof(int) + kr->pd->newauthtok_size;
}
@@ -118,12 +111,18 @@ errno_t create_send_buffer(struct krb5child_req *kr, struct io_buffer **io_buf)
((uint32_t *)(&buf->data[rp]))[0] = kr->pd->cmd;
rp += sizeof(uint32_t);
- ((uint32_t *)(&buf->data[rp]))[0] = strlen(kr->pd->upn);
+ ((uint32_t *)(&buf->data[rp]))[0] = (uint32_t) strlen(kr->pd->upn);
rp += sizeof(uint32_t);
memcpy(&buf->data[rp], kr->pd->upn, strlen(kr->pd->upn));
rp += strlen(kr->pd->upn);
+ ((uint32_t *)(&buf->data[rp]))[0] = (uint32_t) strlen(kr->ccname);
+ rp += sizeof(uint32_t);
+
+ memcpy(&buf->data[rp], kr->ccname, strlen(kr->ccname));
+ rp += strlen(kr->ccname);
+
((uint32_t *)(&buf->data[rp]))[0] = kr->pd->authtok_size;
rp += sizeof(uint32_t);
@@ -168,7 +167,8 @@ static void krb5_cleanup(struct krb5child_req *kr)
talloc_zfree(kr);
}
-static errno_t krb5_setup(struct be_req *req, struct krb5child_req **krb5_req)
+static errno_t krb5_setup(struct be_req *req, struct krb5child_req **krb5_req,
+ const char *homedir)
{
struct krb5child_req *kr = NULL;
struct krb5_ctx *krb5_ctx;
@@ -190,6 +190,14 @@ static errno_t krb5_setup(struct be_req *req, struct krb5child_req **krb5_req)
kr->pd = pd;
kr->req = req;
kr->krb5_ctx = krb5_ctx;
+ kr->homedir = homedir;
+
+ kr->ccname = expand_ccname_template(kr, kr, krb5_ctx->ccname_template);
+ if (kr->ccname == NULL) {
+ DEBUG(1, ("expand_ccname_template failed.\n"));
+ err = EINVAL;
+ goto failed;
+ }
*krb5_req = kr;
@@ -501,13 +509,14 @@ static void krb5_pam_handler(struct be_req *be_req)
goto done;
}
- attrs = talloc_array(be_req, const char *, 2);
+ attrs = talloc_array(be_req, const char *, 3);
if (attrs == NULL) {
goto done;
}
attrs[0] = SYSDB_UPN;
- attrs[1] = NULL;
+ attrs[1] = SYSDB_HOMEDIR;
+ attrs[2] = NULL;
ret = sysdb_get_user_attr(be_req, be_req->be_ctx->sysdb,
be_req->be_ctx->domain, pd->user, attrs,
@@ -534,7 +543,7 @@ static void get_user_upn_done(void *pvt, int err, struct ldb_result *res)
int ret;
struct pam_data *pd;
int pam_status=PAM_SYSTEM_ERR;
- //const char *upn = NULL;
+ const char *homedir = NULL;
pd = talloc_get_type(be_req->req_data, struct pam_data);
krb5_ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
@@ -563,6 +572,12 @@ static void get_user_upn_done(void *pvt, int err, struct ldb_result *res)
DEBUG(9, ("Using simple UPN [%s].\n", pd->upn));
}
}
+
+ homedir = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_HOMEDIR,
+ NULL);
+ if (homedir == NULL) {
+ DEBUG(4, ("Home directory for user [%s] not known.\n", pd->user));
+ }
break;
default:
@@ -576,7 +591,7 @@ static void get_user_upn_done(void *pvt, int err, struct ldb_result *res)
goto failed;
}
- ret = krb5_setup(be_req, &kr);
+ ret = krb5_setup(be_req, &kr, homedir);
if (ret != EOK) {
DEBUG(1, ("krb5_setup failed.\n"));
goto failed;
@@ -665,7 +680,7 @@ static void krb5_pam_handler_done(struct tevent_req *req)
}
if (pd->pam_status == PAM_SUCCESS && pd->cmd == SSS_PAM_AUTHENTICATE) {
- env = talloc_asprintf(pd, "%s=%s", SSSD_REALM, krb5_ctx->realm);
+ env = talloc_asprintf(pd, "%s=%s", SSSD_KRB5_REALM, krb5_ctx->realm);
if (env == NULL) {
DEBUG(1, ("talloc_asprintf failed.\n"));
goto done;
@@ -676,7 +691,7 @@ static void krb5_pam_handler_done(struct tevent_req *req)
goto done;
}
- env = talloc_asprintf(pd, "%s=%s", SSSD_KDC, krb5_ctx->kdcip);
+ env = talloc_asprintf(pd, "%s=%s", SSSD_KRB5_KDC, krb5_ctx->kdcip);
if (env == NULL) {
DEBUG(1, ("talloc_asprintf failed.\n"));
goto done;
@@ -770,6 +785,7 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
bool bool_value;
int ret;
struct tevent_signal *sige;
+ struct stat stat_buf;
ctx = talloc_zero(bectx, struct krb5_ctx);
if (!ctx) {
@@ -785,10 +801,10 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
if (value == NULL) {
DEBUG(2, ("Missing krb5KDCIP, authentication might fail.\n"));
} else {
- ret = setenv(SSSD_KDC, value, 1);
+ ret = setenv(SSSD_KRB5_KDC, value, 1);
if (ret != EOK) {
DEBUG(2, ("setenv %s failed, authentication might fail.\n",
- SSSD_KDC));
+ SSSD_KRB5_KDC));
}
}
ctx->kdcip = value;
@@ -799,14 +815,40 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
if (value == NULL) {
DEBUG(4, ("Missing krb5REALM authentication might fail.\n"));
} else {
- ret = setenv(SSSD_REALM, value, 1);
+ ret = setenv(SSSD_KRB5_REALM, value, 1);
if (ret != EOK) {
DEBUG(2, ("setenv %s failed, authentication might fail.\n",
- SSSD_REALM));
+ SSSD_KRB5_REALM));
}
}
ctx->realm = value;
+ ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path,
+ "krb5ccache_dir", "/tmp", &value);
+ if (ret != EOK) goto fail;
+ ret = lstat(value, &stat_buf);
+ if (ret != EOK) {
+ DEBUG(1, ("lstat for [%s] failed: [%d][%s].\n", value, errno,
+ strerror(errno)));
+ goto fail;
+ }
+ if ( !S_ISDIR(stat_buf.st_mode) ) {
+ DEBUG(1, ("Value of krb5ccache_dir [%s] is not a directory.\n", value));
+ goto fail;
+ }
+ ctx->ccache_dir = value;
+
+ ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path,
+ "krb5ccname_template", "FILE:%d/krb5cc_%U_XXXXXX",
+ &value);
+ if (ret != EOK) goto fail;
+ if (value[0] != '/' && strncmp(value, "FILE:", 5) != 0) {
+ DEBUG(1, ("Currently only file based credential caches are supported "
+ "and krb5ccname_template must start with '/' or 'FILE:'\n"));
+ goto fail;
+ }
+ ctx->ccname_template = value;
+
ret = confdb_get_bool(bectx->cdb, ctx, bectx->conf_path,
"krb5try_simple_upn", false, &bool_value);
if (ret != EOK) goto fail;
diff --git a/server/providers/krb5/krb5_auth.h b/server/providers/krb5/krb5_auth.h
index 123a1895..d238cb63 100644
--- a/server/providers/krb5/krb5_auth.h
+++ b/server/providers/krb5/krb5_auth.h
@@ -26,12 +26,32 @@
#ifndef __KRB5_AUTH_H__
#define __KRB5_AUTH_H__
+#include <stdbool.h>
+#include <krb5/krb5.h>
+
#define MAX_CHILD_MSG_SIZE 255
#define CCACHE_ENV_NAME "KRB5CCNAME"
+
#define SSSD_KRB5_CHANGEPW_PRINCIPLE "SSSD_KRB5_CHANGEPW_PRINCIPLE"
+#define SSSD_KRB5_KDC "SSSD_KRB5_KDC"
+#define SSSD_KRB5_REALM "SSSD_KRB5_REALM"
+
typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
+struct krb5child_req {
+ pid_t child_pid;
+ int read_from_child_fd;
+ int write_to_child_fd;
+
+ struct be_req *req;
+ struct pam_data *pd;
+ struct krb5_ctx *krb5_ctx;
+
+ char *ccname;
+ const char *homedir;
+};
+
struct krb5_ctx {
/* opts taken from kinit */
/* in seconds */
@@ -64,6 +84,8 @@ struct krb5_ctx {
char *realm;
bool try_simple_upn;
char *changepw_principle;
+ char *ccache_dir;
+ char *ccname_template;
};
#endif /* __KRB5_AUTH_H__ */
diff --git a/server/providers/krb5/krb5_child.c b/server/providers/krb5/krb5_child.c
index e272a7f3..578e8227 100644
--- a/server/providers/krb5/krb5_child.c
+++ b/server/providers/krb5/krb5_child.c
@@ -24,12 +24,15 @@
#include <krb5/krb5.h>
#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
#include <security/pam_modules.h>
#include "util/util.h"
#include "providers/dp_backend.h"
#include "providers/krb5/krb5_auth.h"
+#include "providers/krb5/krb5_utils.h"
struct krb5_req {
krb5_context ctx;
@@ -46,6 +49,8 @@ struct krb5_req {
struct pam_data *pd;
struct krb5_ctx *krb5_ctx;
errno_t (*child_req)(int fd, struct krb5_req *kr);
+
+ char *ccname;
};
static krb5_context krb5_error_ctx;
@@ -107,7 +112,6 @@ static errno_t pack_response_packet(struct response *resp, int status, int type,
static struct response *prepare_response_message(struct krb5_req *kr,
krb5_error_code kerr, int pam_status)
{
- const char *cc_name = NULL;
char *msg = NULL;
const char *krb5_msg = NULL;
int ret;
@@ -120,13 +124,12 @@ static struct response *prepare_response_message(struct krb5_req *kr,
}
if (kerr == 0) {
- cc_name = krb5_cc_get_name(kr->ctx, kr->cc);
- if (cc_name == NULL) {
- DEBUG(1, ("krb5_cc_get_name failed.\n"));
+ if (kr->cc == NULL || kr->ccname == NULL) {
+ DEBUG(1, ("Error obtaining ccname.\n"));
return NULL;
}
- msg = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, cc_name);
+ msg = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, kr->ccname);
if (msg == NULL) {
DEBUG(1, ("talloc_asprintf failed.\n"));
return NULL;
@@ -157,6 +160,9 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
char *password)
{
krb5_error_code kerr = 0;
+ int fd = -1;
+ size_t ccname_len = 0;
+ size_t offset = 0;
kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
password, NULL, NULL, 0, NULL,
@@ -166,16 +172,37 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
return kerr;
}
- kerr = krb5_cc_default(kr->ctx, &kr->cc);
+ if (kr->ccname[0] == '/' || strncmp(kr->ccname, "FILE:", 5) == 0) {
+ offset = 0;
+ if (kr->ccname[0] == 'F') {
+ offset = 5;
+ }
+ ccname_len = strlen(kr->ccname + offset);
+ if (ccname_len >= 6 &&
+ strcmp(kr->ccname + (ccname_len-6), "XXXXXX")==0 ) {
+ fd = mkstemp(kr->ccname + offset);
+ if (fd == -1) {
+ DEBUG(1, ("mkstemp failed [%d][%s].\n", errno,
+ strerror(errno)));
+ kerr = KRB5KRB_ERR_GENERIC;
+ goto done;
+ }
+ }
+ }
+
+ kerr = krb5_cc_resolve(kr->ctx, kr->ccname, &kr->cc);
if (kerr != 0) {
KRB5_DEBUG(1, kerr);
- return kerr;
+ goto done;
}
kerr = krb5_cc_initialize(kr->ctx, kr->cc, kr->princ);
+ if (fd != -1) {
+ close(fd);
+ }
if (kerr != 0) {
KRB5_DEBUG(1, kerr);
- return kerr;
+ goto done;
}
kerr = krb5_cc_store_cred(kr->ctx, kr->cc, kr->creds);
@@ -183,12 +210,15 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
KRB5_DEBUG(1, kerr);
krb5_cc_destroy(kr->ctx, kr->cc);
kr->cc = NULL;
- return kerr;
+ goto done;
}
+ kerr = 0;
+
+done:
krb5_free_cred_contents(kr->ctx, kr->creds);
- return 0;
+ return kerr;
}
@@ -205,15 +235,6 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
krb5_data result_code_string;
krb5_data result_string;
- char *changepw_principle = NULL;
-
- changepw_principle = getenv(SSSD_KRB5_CHANGEPW_PRINCIPLE);
- if (changepw_principle == NULL) {
- DEBUG(1, ("Change password principle not available.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto sendresponse;
- }
-
pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
kr->pd->authtok_size);
if (pass_str == NULL) {
@@ -224,7 +245,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
pass_str, NULL, NULL, 0,
- changepw_principle,
+ kr->krb5_ctx->changepw_principle,
kr->options);
if (kerr != 0) {
KRB5_DEBUG(1, kerr);
@@ -362,7 +383,8 @@ sendresponse:
return EOK;
}
-static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd)
+static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
+ char **ccname)
{
size_t p = 0;
uint32_t *len;
@@ -385,6 +407,14 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd)
str = talloc_memdup(pd, buf+p, sizeof(char) * (*len + 1));
if (str == NULL) return ENOMEM;
str[*len] = '\0';
+ *ccname = (char *) str;
+ p += *len;
+
+ len = ((uint32_t *)(buf+p));
+ p += sizeof(uint32_t);
+ str = talloc_memdup(pd, buf+p, sizeof(char) * (*len + 1));
+ if (str == NULL) return ENOMEM;
+ str[*len] = '\0';
pd->authtok = str;
pd->authtok_size = *len + 1;
p += *len;
@@ -411,12 +441,12 @@ static int krb5_cleanup(void *ptr)
struct krb5_req *kr = talloc_get_type(ptr, struct krb5_req);
if (kr == NULL) return EOK;
- /* FIXME: is it safe to drop the "!= NULL" checks? */
if (kr->options != NULL)
krb5_get_init_creds_opt_free(kr->ctx, kr->options);
- if (kr->creds != NULL)
+ if (kr->creds != NULL) {
krb5_free_cred_contents(kr->ctx, kr->creds);
krb5_free_creds(kr->ctx, kr->creds);
+ }
if (kr->name != NULL)
krb5_free_unparsed_name(kr->ctx, kr->name);
if (kr->princ != NULL)
@@ -426,6 +456,9 @@ static int krb5_cleanup(void *ptr)
if (kr->ctx != NULL)
krb5_free_context(kr->ctx);
+ if (kr->krb5_ctx != NULL) {
+ memset(kr->krb5_ctx, 0, sizeof(struct krb5_ctx));
+ }
memset(kr, 0, sizeof(struct krb5_req));
return EOK;
@@ -445,6 +478,27 @@ static int krb5_setup(struct pam_data *pd, const char *user_princ_str,
}
talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup);
+ kr->krb5_ctx = talloc_zero(kr, struct krb5_ctx);
+ if (kr->krb5_ctx == NULL) {
+ DEBUG(1, ("talloc failed.\n"));
+ kerr = ENOMEM;
+ goto failed;
+ }
+
+ kr->krb5_ctx->changepw_principle = getenv(SSSD_KRB5_CHANGEPW_PRINCIPLE);
+ if (kr->krb5_ctx->changepw_principle == NULL) {
+ DEBUG(1, ("Cannot read [%s] from environment.\n",
+ SSSD_KRB5_CHANGEPW_PRINCIPLE));
+ if (pd->cmd == SSS_PAM_CHAUTHTOK) {
+ goto failed;
+ }
+ }
+
+ kr->krb5_ctx->realm = getenv(SSSD_KRB5_REALM);
+ if (kr->krb5_ctx->realm == NULL) {
+ DEBUG(2, ("Cannot read [%s] from environment.\n", SSSD_KRB5_REALM));
+ }
+
kr->pd = pd;
switch(pd->cmd) {
@@ -513,12 +567,15 @@ failed:
return kerr;
}
-int main(void)
+int main(int argc, char *argv[])
{
uint8_t *buf = NULL;
int ret;
struct pam_data *pd = NULL;
struct krb5_req *kr = NULL;
+ char *ccname;
+
+ debug_prg_name = argv[0];
pd = talloc(NULL, struct pam_data);
@@ -536,14 +593,21 @@ int main(void)
}
close(STDIN_FILENO);
- ret = unpack_buffer(buf, ret, pd);
+ ret = unpack_buffer(buf, ret, pd, &ccname);
if (ret != EOK) {
DEBUG(1, ("unpack_buffer failed.\n"));
talloc_free(pd);
exit(-1);
}
- krb5_setup(pd, pd->upn, &kr);
+ ret = krb5_setup(pd, pd->upn, &kr);
+ if (ret != EOK) {
+ DEBUG(1, ("krb5_setup failed.\n"));
+ talloc_free(pd);
+ exit(-1);
+ }
+ kr->ccname = ccname;
+
ret = kr->child_req(STDOUT_FILENO, kr);
if (ret != EOK) {
DEBUG(1, ("Child request failed.\n"));
diff --git a/server/providers/krb5/krb5_utils.c b/server/providers/krb5/krb5_utils.c
new file mode 100644
index 00000000..68254abc
--- /dev/null
+++ b/server/providers/krb5/krb5_utils.c
@@ -0,0 +1,141 @@
+/*
+ SSSD
+
+ Kerberos 5 Backend Module -- Utilities
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2009 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ 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 <string.h>
+#include <stdlib.h>
+
+#include "providers/krb5/krb5_utils.h"
+#include "providers/krb5/krb5_auth.h"
+#include "util/util.h"
+
+char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
+ const char *template)
+{
+ char *copy;
+ char *p;
+ char *n;
+ char *result = NULL;
+
+ copy = talloc_strdup(mem_ctx, template);
+ if (copy == NULL) {
+ DEBUG(1, ("talloc_strdup failed.\n"));
+ return NULL;
+ }
+
+ result = talloc_strdup(mem_ctx, "");
+ if (result == NULL) {
+ DEBUG(1, ("talloc_strdup failed.\n"));
+ return NULL;
+ }
+
+ p = copy;
+ while ( (n = strchr(p, '%')) != NULL) {
+ *n = '\0';
+ n++;
+ if ( *n == '\0' ) {
+ DEBUG(1, ("format error, single %% at the end of the template.\n"));
+ return NULL;
+ }
+
+ switch( *n ) {
+ case 'u':
+ if (kr->pd->user == NULL) {
+ DEBUG(1, ("Cannot expand user name template "
+ "because user name is empty.\n"));
+ return NULL;
+ }
+ result = talloc_asprintf_append(result, "%s%s", p,
+ kr->pd->user);
+ break;
+ case 'U':
+ if (kr->pd->pw_uid <= 0) {
+ DEBUG(1, ("Cannot expand uid template "
+ "because uid is invalid.\n"));
+ return NULL;
+ }
+ result = talloc_asprintf_append(result, "%s%d", p,
+ kr->pd->pw_uid);
+ break;
+ case 'p':
+ if (kr->pd->upn == NULL) {
+ DEBUG(1, ("Cannot expand user principal name template "
+ "because upn is empty.\n"));
+ return NULL;
+ }
+ result = talloc_asprintf_append(result, "%s%s", p, kr->pd->upn);
+ break;
+ case '%':
+ result = talloc_asprintf_append(result, "%s%%", p);
+ break;
+ case 'r':
+ if (kr->krb5_ctx->realm == NULL) {
+ DEBUG(1, ("Cannot expand realm template "
+ "because value is not available.\n"));
+ return NULL;
+ }
+ result = talloc_asprintf_append(result, "%s%s", p,
+ kr->krb5_ctx->realm);
+ break;
+ case 'h':
+ if (kr->homedir == NULL) {
+ DEBUG(1, ("Cannot expand home directory template "
+ "because the path is not available.\n"));
+ return NULL;
+ }
+ result = talloc_asprintf_append(result, "%s%s", p, kr->homedir);
+ break;
+ case 'd':
+ if (kr->krb5_ctx->ccache_dir == NULL) {
+ DEBUG(1, ("Cannot expand ccache directory template "
+ "because value is not available.\n"));
+ return NULL;
+ }
+ result = talloc_asprintf_append(result, "%s%s", p,
+ kr->krb5_ctx->ccache_dir);
+ break;
+ case 'P':
+ if (kr->pd->cli_pid == 0) {
+ DEBUG(1, ("Cannot expand PID template "
+ "because PID is not available.\n"));
+ return NULL;
+ }
+ result = talloc_asprintf_append(result, "%s%d", p,
+ kr->pd->cli_pid);
+ break;
+ default:
+ DEBUG(1, ("format error, unknown template [%%%c].\n", *n));
+ return NULL;
+ }
+
+ if (result == NULL) {
+ DEBUG(1, ("talloc_asprintf_append failed.\n"));
+ return NULL;
+ }
+
+ p = n + 1;
+ }
+
+ result = talloc_asprintf_append(result, "%s", p);
+
+ return result;
+}
diff --git a/server/providers/krb5/krb5_utils.h b/server/providers/krb5/krb5_utils.h
new file mode 100644
index 00000000..dec6f7f2
--- /dev/null
+++ b/server/providers/krb5/krb5_utils.h
@@ -0,0 +1,37 @@
+/*
+ SSSD
+
+ Kerberos Backend, header file for utilities
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2009 Red Hat
+
+
+ This program is free software; you can redistribute it and/or modify
+ 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/>.
+*/
+
+#ifndef __KRB5_UTILS_H__
+#define __KRB5_UTILS_H__
+
+#include <talloc.h>
+
+#include "providers/krb5/krb5_auth.h"
+#include "providers/data_provider.h"
+
+char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
+ const char *template);
+
+#endif /* __KRB5_UTILS_H__ */