[SSSD] [PATCH] Support DIR: credential caches
Jakub Hrozek
jhrozek at redhat.com
Thu Jun 14 17:07:55 UTC 2012
On Wed, Jun 13, 2012 at 03:48:50PM -0400, Stephen Gallagher wrote:
> On Wed, 2012-06-13 at 20:32 +0200, Jakub Hrozek wrote:
> > I'm going to combine the replies into one (thanks for sending them
> > separately, though).
> >
> > The unit tests were fixed.
> >
> > > > [PATCH 01/11] Two small krb5_child fixes
> > > > ssia
> > > >
> > >
> > > Nack. You only fixed the errno overwrite in one of the two debug
> > > messages you changed.
> >
> > Actually, one of three :-) Fixed.
>
> Ack.
>
> >
> > > > [PATCH 02/11] Provide more debugging in krb5_child and ldap_child
> > > > I started this patch before Nick did, maybe it would still be useful, at
> > > > least the parts that get rid of level-9 DEBUG messages.
> > > >
> > >
> > > Nack.
> > >
> > > Can we change the debug log message "Created ccache file:" to just
> > > "Created ccache:"? Since we're now printing the whole CCNAME, complete
> > > with type.
> >
> > It's only printed in create_ccache_file() which only created FILE:
> > ccaches.
> >
>
>
> In that case, Ack.
>
> > >
> > > Speling misteak (it was there before, but we should fix it while we're
> > > touching the code:
> > > "successfull" should be "successful" in changepw_child()
> >
> > Done
> >
>
> Ack
>
> > > > [PATCH 03/11] Allow redefining the KRB5_CHILD path
> > > > The krb5-child-test will want to run the child from the build directory.
> > > >
> > >
> > > Ack
> > >
> > > > [PATCH 04/11] Split parse_krb5_child_response so it can be reused
> > > > krb5-child-test will be another consumer. It also makes the code more
> > > > readable by splitting a huge function.
> > > >
> > >
> > > Ack
> > >
> > > > [PATCH 05/11] Add a krb5_child test tool
> > > > https://fedorahosted.org/sssd/ticket/1127
> > > >
> > >
> > > Nack
> > >
> > > Typo in help: secods -> seconds.
> >
> > Fixed
> >
> > >
> > > Typo in DEBUG: unkown -> unknown
> >
> > Sorry, I don't see that?
> >
>
> I can't find it anymore either. My eyes must be playing tricks on you.
>
>
> > > On Wed, 2012-06-13 at 15:48 +0200, Jakub Hrozek wrote:
> > > ...
> > > > [PATCH 06/11] Residual util functions
> > > > Kerberos credential caches can be specified by TYPE:RESIDUAL. This pa
> > > > tch adds a couple of utilities to support parsing if ccache locations,
> > > > checking types etc.
> > > >
> > >
> > > Ack
> > >
> > > > [PATCH 07/11] Handle trailing slash in the ccname template
> > > > With the DIR cache support, it's perfectly legal to specify a ccname
> > > > directory that ends with a slash. The create_dir function did not han dle
> > > > that situation correctly. The unit test is included in the DIR: cache
> > > > patch, because it uses the cc_dir_create() function.
> > > >
> > >
> > > Nack
> > >
> > > Please add comments explaining that you're walking back from the end and
> > > removing any trailing slashes.
> > >
> >
> > Done.
> >
>
> Nack
>
> Your comment needs work:
> we only pass /some/path to find_ccdir_parent_data, not /some/path
>
> That looks like the same thing to me :)
>
> > >
> > > > [PATCH 08/11] Add a credential cache back end structure
> > > > To be able to add support for new credential cache types easily, this
> > > > patch creates a new structure sss_krb5_cc_be that defines common with
> > > > a credential cache, such as create, check if used or remove.
> > > >
> > >
> > > Nack.
> > >
> > > Why did you add a tmp_ctx to safe_remove_old_ccache_file()? You don't
> > > allocate anything atop it.
> > >
> >
> > I used to, then I changed safe_remove_old_ccache_file() and forgot to
> > remove the context. Fixed.
> >
>
> Ack
>
> > > Otherwise I think this looks sane. It's a good approach to modularizing
> > > the approaches.
> > >
> > > > [PATCH 09/11] Add support for storing credential caches in the DIR: back end
> > > > https://fedorahosted.org/sssd/ticket/974
> > > >
> > > > Please note that only the TGTs acquired by the krb5_child have changed,
> > > > the ldap_child still puts its ccache into /var/lib/sss/db.
> > > >
> > >
> > > Yes, this is as it should be. We're unlikely to need multiple TGTs for
> > > GSSAPI.
> > >
> > > > The cc_dir_remove() function is a little odd, I tried to use the krb5
> > > > API directly, but I think I found a bug in libkrb5. For a subsidiary
> > > > cache that does not exist (DIR::/no/such/path), the following code would
> > > > segfault:
> > > >
> > > > krb5_cc_resolve(context, location, &ccache); // returns EOK
> > > > krberr = krb5_cc_destroy(context, ccache); // KRB5_FCC_NOFILE
> > > > if (krberr) {
> > > > if (ccache) krb5_cc_close(context, ccache); // SIGSEGV
> > > > }
> > >
> > > Maybe I'm confused, but shouldn't you be closing the cache before
> > > destroying it?
> > >
> >
> > It was my impression that krb5_cc_destroy() does both destroy and
> > close and the krb5_ccache "object" is invalid after krb5_cc_close().
> >
>
> Ok, Ack.
>
> > >
> > > In general, I don't see anything obviously wrong with this code, so I'm
> > > probably okay with committing it for the beta and fixing any issues as
> > > they come up, provided that the testing I'm doing continues to meet my
> > > expectations.
> > >
> > > I'll continue to test (and retest) until the requested revisions are
> > > complete.
> > >
> >
> > There's one thing I forgot that I'm going to write a separate patch for
> > - we should probably limit the substitutions used in the templates in
> > case DIR is used. I think that if DIR is used, the last template must be
> > "%d", the file-specific substitutions make no sense if DIR is used.
> >
>
> Simo, Jakub and I had a long discussion on #sssd about how to handle
> this. The end result is that we're going to maintain the existing
> expansions (regardless of their usefulness).
>
> We also decided that our plan would be to attempt to mkdir() the
> requested patch and fail if we could not do so. We would also fail if
> the path currently exists but has the wrong ownership and/or
> permissions.
>
>
> > > >
> > > > [PATCH 10/11] Use Kerberos context in KRB5_DEBUG
> > > > Passing Kerberos context to sss_krb5_get_error_message will allow us to
> > > > get better error messages. This patch technically belong earlier, but
> > > > rebasing would be hard at this point.
> > > >
> > >
> > > Ack
> > >
> > > > [PATCH 11/11] Switch Kerberos cache default to DIR
> > > > Just switches the defaults.
> > >
> > > Nack
> > >
> > > Instead of hard-coding the defaults, can we make this into a configure
> > > flag? Not all distributions are yet using systemd, so on those platforms
> > > we'll still want to default to /tmp.
> > >
> >
> > Done, patch #11 is a different one.
> >
> > New patches are attached
>
> Nack
>
> The specfile needs to be conditionalized to only set /run/user by
> default on F17 and higher. This will break our nightlies for F16, RHEL 5
> and RHEL 6.
>
Done
> Building sssd-krb5.5 appears to be broken when building from a parallel
> build directory:
>
> po4a --option doctype=docbook --package-name sssd-docs --variable
> builddir=/home/sgallagh/workspace/sssd/x86_64/src/man --package-version
> 1.8.92 --msgid-bugs-address sssd-devel at redhat.com --copyright-holder
> "Red Hat" --no-backups po/po4a.cfg
> po/po4a.cfg:13: The 'sssd-krb5.5.xml' master file does not exist.
OK, I switched po4a.cfg to using absolute paths and sssd-krb5.xml is now
referenced from builddir because it's generated.
New patches are attached.
-------------- next part --------------
>From 35e20f5e86176347758829c9df36de2122775559 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Mon, 28 May 2012 16:39:15 +0200
Subject: [PATCH 01/12] Two small krb5_child fixes
* Allocation check was missing
* a DEBUG statement overwrote errno
---
src/providers/krb5/krb5_child.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 199ef67bb36c36d632ac6006871a55ebcf88123c..1a9d655220d9a75ec257c600e01787b36212c5d6 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -262,13 +262,18 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
goto done;
}
tmp_ccname = talloc_asprintf_append(tmp_ccname, "/.krb5cc_dummy_XXXXXX");
+ if (tmp_ccname == NULL) {
+ kerr = ENOMEM;
+ goto done;
+ }
old_umask = umask(077);
fd = mkstemp(tmp_ccname);
umask(old_umask);
if (fd == -1) {
- DEBUG(1, ("mkstemp failed [%d][%s].\n", errno, strerror(errno)));
kerr = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("mkstemp failed [%d][%s].\n", kerr, strerror(kerr)));
goto done;
}
@@ -315,15 +320,17 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
if (ccname_len >= 6 && strcmp(cc_file_name + (ccname_len-6), "XXXXXX")==0 ) {
fd = mkstemp(cc_file_name);
if (fd == -1) {
- DEBUG(1, ("mkstemp failed [%d][%s].\n", errno, strerror(errno)));
kerr = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("mkstemp failed [%d][%s].\n", kerr, strerror(kerr)));
goto done;
}
}
kerr = rename(tmp_ccname, cc_file_name);
if (kerr == -1) {
- DEBUG(1, ("rename failed [%d][%s].\n", errno, strerror(errno)));
+ kerr = errno;
+ DEBUG(1, ("rename failed [%d][%s].\n", kerr, strerror(kerr)));
}
DEBUG(SSSDBG_TRACE_LIBS, ("Created ccache file: [%s]\n", cc_file_name));
--
1.7.10.2
-------------- next part --------------
>From 6d1b643ee6244f58e74d4b6448b779c59ea7d514 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Fri, 18 May 2012 18:57:08 +0200
Subject: [PATCH 02/12] Provide more debugging in krb5_child and ldap_child
https://fedorahosted.org/sssd/ticket/1225
---
src/providers/krb5/krb5_child.c | 78 ++++++++++++++++++++++++++++++++-------
src/providers/ldap/ldap_child.c | 9 ++++-
2 files changed, 73 insertions(+), 14 deletions(-)
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 1a9d655220d9a75ec257c600e01787b36212c5d6..195c431af3e933e093e36df7a43cc667c52e94fb 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -163,7 +163,7 @@ static krb5_error_code sss_krb5_prompter(krb5_context context, void *data,
return EOK;
}
- DEBUG(9, ("Prompter called with [%s].\n", banner));
+ DEBUG(SSSDBG_FUNC_DATA, ("Prompter called with [%s].\n", banner));
ret = pam_add_response(kr->pd, SSS_PAM_TEXT_MSG, strlen(banner)+1,
(const uint8_t *) banner);
@@ -236,6 +236,8 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
TALLOC_CTX *tmp_ctx = NULL;
mode_t old_umask;
+ DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
+
if (strncmp(ccname, "FILE:", 5) == 0) {
cc_file_name = ccname + 5;
} else {
@@ -333,7 +335,7 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
DEBUG(1, ("rename failed [%d][%s].\n", kerr, strerror(kerr)));
}
- DEBUG(SSSDBG_TRACE_LIBS, ("Created ccache file: [%s]\n", cc_file_name));
+ DEBUG(SSSDBG_TRACE_LIBS, ("Created ccache file: [%s]\n", ccname));
done:
if (fd != -1) {
@@ -412,6 +414,8 @@ static struct response *prepare_response_message(struct krb5_req *kr,
return NULL;
}
+ DEBUG(SSSDBG_TRACE_FUNC, ("Building response for result [%d]\n", kerr));
+
if (kerr == 0) {
if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
pam_status = PAM_SUCCESS;
@@ -543,7 +547,8 @@ static krb5_error_code validate_tgt(struct krb5_req *kr)
memset(&entry, 0, sizeof(entry));
while ((kt_err = krb5_kt_next_entry(kr->ctx, keytab, &entry, &cursor)) == 0) {
if (krb5_realm_compare(kr->ctx, entry.principal, kr->princ)) {
- DEBUG(9, ("Found keytab entry with the realm of the credential.\n"));
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ ("Found keytab entry with the realm of the credential.\n"));
break;
}
@@ -615,6 +620,8 @@ static void krb5_set_canonicalize(krb5_get_init_creds_opt *opts)
if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) {
canonicalize = 1;
}
+ DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
+ SSSD_KRB5_CANONICALIZE, tmp_str ? tmp_str : "not set"));
sss_krb5_get_init_creds_opt_set_canonicalize(opts, canonicalize);
}
@@ -707,7 +714,7 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
}
} else {
- DEBUG(9, ("TGT validation is disabled.\n"));
+ DEBUG(SSSDBG_CONF_SETTINGS, ("TGT validation is disabled.\n"));
}
if (kr->validate || kr->fast_ccname != NULL) {
@@ -760,6 +767,8 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
char *changepw_princ = NULL;
krb5_prompter_fct prompter = sss_krb5_prompter;
+ DEBUG(SSSDBG_TRACE_LIBS, ("Password change operation\n"));
+
if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_PASSWORD) {
pam_status = PAM_CRED_INSUFFICIENT;
kerr = KRB5KRB_ERR_GENERIC;
@@ -781,6 +790,8 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
kerr = KRB5KRB_ERR_GENERIC;
goto sendresponse;
}
+ DEBUG(SSSDBG_FUNC_DATA,
+ ("Created a changepw principal [%s]\n", changepw_princ));
if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
/* We do not need a password expiration warning here. */
@@ -804,8 +815,9 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
memset(kr->pd->authtok, 0, kr->pd->authtok_size);
if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
- DEBUG(9, ("Initial authentication for change password operation "
- "successfull.\n"));
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("Initial authentication for change password operation "
+ "successful.\n"));
krb5_free_cred_contents(kr->ctx, kr->creds);
pam_status = PAM_SUCCESS;
goto sendresponse;
@@ -906,7 +918,10 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
char *changepw_princ = NULL;
int pam_status = PAM_SYSTEM_ERR;
+ DEBUG(SSSDBG_TRACE_LIBS, ("Attempting to get a TGT\n"));
+
if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_PASSWORD) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Unknown authtok type\n"));
pam_status = PAM_CRED_INSUFFICIENT;
kerr = KRB5KRB_ERR_GENERIC;
goto sendresponse;
@@ -927,6 +942,8 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
kerr = KRB5KRB_ERR_GENERIC;
goto sendresponse;
}
+ DEBUG(SSSDBG_FUNC_DATA,
+ ("Created a changepw principal [%s]\n", changepw_princ));
kerr = get_and_save_tgt(kr, pass_str);
@@ -935,6 +952,7 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
not. In general the password can still be used to get a changepw ticket.
So we validate the password by trying to get a changepw ticket. */
if (kerr == KRB5KDC_ERR_KEY_EXP) {
+ DEBUG(SSSDBG_TRACE_LIBS, ("Password was expired\n"));
kerr = sss_krb5_get_init_creds_opt_set_expire_callback(kr->ctx,
kr->options,
NULL, NULL);
@@ -989,6 +1007,8 @@ static errno_t kuserok_child(int fd, struct krb5_req *kr)
int ret;
krb5_error_code kerr;
+ DEBUG(SSSDBG_TRACE_LIBS, ("Verifying if principal can log in as user\n"));
+
/* krb5_kuserok tries to verify that kr->pd->user is a locally known
* account, so we have to unset _SSS_LOOPS to make getpwnam() work. */
ret = unsetenv("_SSS_LOOPS");
@@ -1004,6 +1024,8 @@ static errno_t kuserok_child(int fd, struct krb5_req *kr)
}
access_allowed = krb5_kuserok(kr->ctx, kr->princ, kr->pd->user);
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("Access was %s\n", access_allowed ? "allowed" : "denied"));
status = access_allowed ? 0 : 1;
@@ -1023,6 +1045,8 @@ static errno_t renew_tgt_child(int fd, struct krb5_req *kr)
char *ccname;
krb5_ccache ccache = NULL;
+ DEBUG(SSSDBG_TRACE_LIBS, ("Renewing a ticket\n"));
+
if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_CCFILE) {
DEBUG(1, ("Unsupported authtok type for TGT renewal [%d].\n",
kr->pd->authtok_type));
@@ -1061,7 +1085,7 @@ static errno_t renew_tgt_child(int fd, struct krb5_req *kr)
}
} else {
- DEBUG(9, ("TGT validation is disabled.\n"));
+ DEBUG(SSSDBG_CONF_SETTINGS, ("TGT validation is disabled.\n"));
}
if (kr->validate || kr->fast_ccname != NULL) {
@@ -1116,6 +1140,8 @@ static errno_t create_empty_ccache(int fd, struct krb5_req *kr)
int ret;
int pam_status = PAM_SUCCESS;
+ DEBUG(SSSDBG_TRACE_LIBS, ("Creating empty ccache\n"));
+
ret = create_ccache_file(kr->ctx, kr->princ, kr->ccname, NULL);
if (ret != 0) {
KRB5_DEBUG(1, ret);
@@ -1146,6 +1172,12 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
kr->validate = (validate == 0) ? false : true;
SAFEALIGN_COPY_UINT32_CHECK(offline, buf + p, size, &p);
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("cmd [%d] uid [%llu] gid [%llu] validate [%s] offline [%s] "
+ "UPN [%s]\n", pd->cmd, kr->uid, kr->gid,
+ kr->validate ? "true" : "false", offline ? "true" : "false",
+ kr->upn ? kr->upn : "none"));
+
SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
if ((p + len ) > size) return EINVAL;
kr->upn = talloc_strndup(pd, (char *)(buf + p), len);
@@ -1174,6 +1206,9 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
if (pd->authtok == NULL) return ENOMEM;
pd->authtok_size = len + 1;
p += len;
+
+ DEBUG(SSSDBG_CONF_SETTINGS, ("ccname: [%s] keytab: [%s]\n",
+ kr->ccname, kr->keytab));
} else {
kr->ccname = NULL;
kr->keytab = NULL;
@@ -1201,6 +1236,7 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
pd->user = talloc_strndup(pd, (char *)(buf + p), len);
if (pd->user == NULL) return ENOMEM;
p += len;
+ DEBUG(SSSDBG_CONF_SETTINGS, ("user: [%s]\n", pd->user));
} else {
pd->user = NULL;
}
@@ -1403,27 +1439,33 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
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));
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("Cannot read [%s] from environment.\n", SSSD_KRB5_REALM));
}
switch(kr->pd->cmd) {
case SSS_PAM_AUTHENTICATE:
/* If we are offline, we need to create an empty ccache file */
if (offline) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Will perform offline auth\n"));
kr->child_req = create_empty_ccache;
} else {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Will perform online auth\n"));
kr->child_req = tgt_req_child;
}
break;
case SSS_PAM_CHAUTHTOK:
case SSS_PAM_CHAUTHTOK_PRELIM:
+ DEBUG(SSSDBG_TRACE_FUNC, ("Will perform password change\n"));
kr->child_req = changepw_child;
break;
case SSS_PAM_ACCT_MGMT:
+ DEBUG(SSSDBG_TRACE_FUNC, ("Will perform account management\n"));
kr->child_req = kuserok_child;
break;
case SSS_CMD_RENEW:
if (!offline) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Will perform ticket renewal\n"));
kr->child_req = renew_tgt_child;
} else {
DEBUG(1, ("Cannot renew TGT while offline.\n"));
@@ -1481,8 +1523,8 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
lifetime_str = getenv(SSSD_KRB5_RENEWABLE_LIFETIME);
if (lifetime_str == NULL) {
- DEBUG(7, ("Cannot read [%s] from environment.\n",
- SSSD_KRB5_RENEWABLE_LIFETIME));
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Cannot read [%s] from environment.\n",
+ SSSD_KRB5_RENEWABLE_LIFETIME));
} else {
kerr = krb5_string_to_deltat(lifetime_str, &lifetime);
if (kerr != 0) {
@@ -1491,13 +1533,15 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
KRB5_DEBUG(1, kerr);
goto failed;
}
+ DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
+ SSSD_KRB5_RENEWABLE_LIFETIME, lifetime_str));
krb5_get_init_creds_opt_set_renew_life(kr->options, lifetime);
}
lifetime_str = getenv(SSSD_KRB5_LIFETIME);
if (lifetime_str == NULL) {
- DEBUG(7, ("Cannot read [%s] from environment.\n",
- SSSD_KRB5_LIFETIME));
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Cannot read [%s] from environment.\n",
+ SSSD_KRB5_LIFETIME));
} else {
kerr = krb5_string_to_deltat(lifetime_str, &lifetime);
if (kerr != 0) {
@@ -1506,6 +1550,8 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
KRB5_DEBUG(1, kerr);
goto failed;
}
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("%s is set to [%s]\n", SSSD_KRB5_LIFETIME, lifetime_str));
krb5_get_init_creds_opt_set_tkt_life(kr->options, lifetime);
}
@@ -1514,15 +1560,19 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
use_fast_str = getenv(SSSD_KRB5_USE_FAST);
if (use_fast_str == NULL || strcasecmp(use_fast_str, "never") == 0) {
- DEBUG(9, ("Not using FAST.\n"));
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Not using FAST.\n"));
} else if (strcasecmp(use_fast_str, "try") == 0 ||
strcasecmp(use_fast_str, "demand") == 0) {
+ DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
+ SSSD_KRB5_LIFETIME, lifetime_str));
tmp_str = getenv(SSSD_KRB5_FAST_PRINCIPAL);
if (!tmp_str) {
fast_principal = NULL;
fast_principal_realm = kr->krb5_ctx->realm;
} else {
+ DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
+ SSSD_KRB5_FAST_PRINCIPAL, lifetime_str));
kerr = krb5_parse_name(kr->ctx, tmp_str, &fast_princ_struct);
if (kerr) {
DEBUG(1, ("krb5_parse_name failed.\n"));
@@ -1712,12 +1762,14 @@ int main(int argc, const char *argv[])
goto fail;
}
+ DEBUG(SSSDBG_TRACE_FUNC, ("krb5_child completed successfully\n"));
close(STDOUT_FILENO);
talloc_free(pd);
return 0;
fail:
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_child failed!\n"));
close(STDOUT_FILENO);
talloc_free(pd);
exit(-1);
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
index 13e12e93c4fb28a2b4ff4eba5db8106249b446f4..83ce468fa9227f7c98e225660d2a803bd9aaf6a6 100644
--- a/src/providers/ldap/ldap_child.c
+++ b/src/providers/ldap/ldap_child.c
@@ -118,6 +118,10 @@ static int pack_buffer(struct response *r, int result, krb5_error_code krberr,
return ENOMEM;
}
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("result [%d] krberr [%d] msgsize [%d] msg [%s]\n",
+ result, krberr, len, msg));
+
/* result */
SAFEALIGN_SET_UINT32(&r->buf[p], result, &p);
@@ -183,7 +187,6 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
krberr = KRB5KRB_ERR_GENERIC;
goto done;
}
-
} else {
realm_name = talloc_strdup(memctx, realm_str);
if (!realm_name) {
@@ -235,6 +238,7 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
} else {
krberr = krb5_kt_default(context, &keytab);
}
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Using keytab [%s]\n", KEYTAB_CLEAN_NAME));
if (krberr) {
DEBUG(SSSDBG_FATAL_FAILURE,
("Failed to read keytab file [%s]: %s\n",
@@ -275,6 +279,7 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
tmp_str = getenv("KRB5_CANONICALIZE");
if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) {
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Will canonicalize principals\n"));
canonicalize = 1;
}
sss_krb5_get_init_creds_opt_set_canonicalize(&options, canonicalize);
@@ -514,11 +519,13 @@ int main(int argc, const char *argv[])
goto fail;
}
+ DEBUG(SSSDBG_TRACE_FUNC, ("ldap_child completed successfully\n"));
close(STDOUT_FILENO);
talloc_free(main_ctx);
_exit(0);
fail:
+ DEBUG(SSSDBG_CRIT_FAILURE, ("ldap_child failed!\n"));
close(STDOUT_FILENO);
talloc_free(main_ctx);
_exit(-1);
--
1.7.10.2
-------------- next part --------------
>From 4f04f470e8aa995443feb6ded4472856749661c1 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 23 May 2012 17:50:21 +0200
Subject: [PATCH 03/12] Allow redefining the KRB5_CHILD path
The krb5-child-test will want to run the child from the current
directory.
---
src/providers/krb5/krb5_child_handler.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
index 990a9eccbb433147bebb324c65ce5c441aeb7f73..87f9d3cab1d36676d07058673a078ee2c6ba907b 100644
--- a/src/providers/krb5/krb5_child_handler.c
+++ b/src/providers/krb5/krb5_child_handler.c
@@ -28,11 +28,15 @@
#include "providers/krb5/krb5_auth.h"
#include "src/providers/krb5/krb5_utils.h"
+#ifndef KRB5_CHILD_DIR
#ifndef SSSD_LIBEXEC_PATH
#error "SSSD_LIBEXEC_PATH not defined"
-#else
-#define KRB5_CHILD SSSD_LIBEXEC_PATH"/krb5_child"
-#endif
+#endif /* SSSD_LIBEXEC_PATH */
+
+#define KRB5_CHILD_DIR SSSD_LIBEXEC_PATH
+#endif /* KRB5_CHILD_DIR */
+
+#define KRB5_CHILD KRB5_CHILD_DIR"/krb5_child"
struct io {
int read_from_child_fd;
--
1.7.10.2
-------------- next part --------------
>From fa36d339518073995ca128677c8d5d0b41568371 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 23 May 2012 17:51:24 +0200
Subject: [PATCH 04/12] Split parse_krb5_child_response so it can be reused
krb5-child-test will be another consumer. It also makes the code more
readable by splitting a huge function.
---
src/providers/krb5/krb5_auth.c | 146 ++++++-------------------------
src/providers/krb5/krb5_auth.h | 11 +++
src/providers/krb5/krb5_child_handler.c | 132 ++++++++++++++++++++++++++++
3 files changed, 170 insertions(+), 119 deletions(-)
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 50028e15d5cf9133b9fac11b45c1adda2e2fceb9..7c622dbea6869f1acf510104498a304f634c21b5 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -39,9 +39,6 @@
#include "providers/krb5/krb5_auth.h"
#include "providers/krb5/krb5_utils.h"
-#define TIME_T_MAX LONG_MAX
-#define int64_to_time_t(val) ((time_t)((val) < TIME_T_MAX ? val : TIME_T_MAX))
-
static errno_t safe_remove_old_ccache_file(const char *old_ccache_file,
const char *new_ccache_file)
{
@@ -727,23 +724,7 @@ static void krb5_child_done(struct tevent_req *subreq)
int ret;
uint8_t *buf = NULL;
ssize_t len = -1;
- ssize_t pref_len;
- size_t p;
- int32_t msg_status;
- int32_t msg_type;
- int32_t msg_len;
- int64_t time_data;
- struct tgt_times tgtt;
- int pwd_exp_warning;
- uint32_t *expiration;
- uint32_t *msg_subtype;
- bool skip;
-
- memset(&tgtt, 0, sizeof(tgtt));
- pwd_exp_warning = state->be_ctx->domain->pwd_expiration_warning;
- if (pwd_exp_warning < 0) {
- pwd_exp_warning = KERBEROS_PWEXPIRE_WARNING_TIME;
- }
+ struct krb5_child_response *res;
ret = handle_child_recv(subreq, pd, &buf, &len);
talloc_zfree(subreq);
@@ -759,114 +740,41 @@ static void krb5_child_done(struct tevent_req *subreq)
return;
}
- /* A buffer with the following structure is expected.
- * int32_t status of the request (required)
- * message (zero or more)
- *
- * A message consists of:
- * int32_t type of the message
- * int32_t length of the following data
- * uint8_t[len] data
- */
-
- if ((size_t) len < sizeof(int32_t)) {
- DEBUG(1, ("message too short.\n"));
- ret = EINVAL;
+ ret = parse_krb5_child_response(state, buf, len, pd,
+ state->be_ctx->domain->pwd_expiration_warning,
+ &res);
+ if (ret) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not parse child response [%d]: %s\n",
+ ret, strerror(ret)));
goto done;
}
- p=0;
- SAFEALIGN_COPY_INT32(&msg_status, buf+p, &p);
-
- while (p < len) {
- skip = false;
- SAFEALIGN_COPY_INT32(&msg_type, buf+p, &p);
- SAFEALIGN_COPY_INT32(&msg_len, buf+p, &p);
-
- DEBUG(9, ("child response [%d][%d][%d].\n", msg_status, msg_type,
- msg_len));
-
- if ((p + msg_len) > len) {
- DEBUG(1, ("message format error [%d] > [%d].\n", p+msg_len, len));
- ret = EINVAL;
- goto done;
- }
-
- /* We need to save the name of the credential cache file. To find it
- * we check if the data part of a message starts with
- * CCACHE_ENV_NAME"=". pref_len also counts the trailing '=' because
- * sizeof() counts the trailing '\0' of a string. */
- pref_len = sizeof(CCACHE_ENV_NAME);
- if (msg_len > pref_len &&
- strncmp((const char *) &buf[p], CCACHE_ENV_NAME"=", pref_len) == 0) {
- kr->ccname = talloc_strndup(kr, (char *) &buf[p+pref_len],
- msg_len-pref_len);
- if (kr->ccname == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- ret = ENOMEM;
- goto done;
- }
- }
-
- if (msg_type == SSS_KRB5_INFO_TGT_LIFETIME &&
- msg_len == 4*sizeof(int64_t)) {
- SAFEALIGN_COPY_INT64(&time_data, buf+p, NULL);
- tgtt.authtime = int64_to_time_t(time_data);
- SAFEALIGN_COPY_INT64(&time_data, buf+p+sizeof(int64_t), NULL);
- tgtt.starttime = int64_to_time_t(time_data);
- SAFEALIGN_COPY_INT64(&time_data, buf+p+2*sizeof(int64_t), NULL);
- tgtt.endtime = int64_to_time_t(time_data);
- SAFEALIGN_COPY_INT64(&time_data, buf+p+3*sizeof(int64_t), NULL);
- tgtt.renew_till = int64_to_time_t(time_data);
- DEBUG(7, ("TGT times are [%d][%d][%d][%d].\n", tgtt.authtime,
- tgtt.starttime, tgtt.endtime, tgtt.renew_till));
- }
-
- if (msg_type == SSS_PAM_USER_INFO) {
- msg_subtype = (uint32_t *)&buf[p];
- if (*msg_subtype == SSS_PAM_USER_INFO_EXPIRE_WARN)
- {
- expiration = (uint32_t *)&buf[p+sizeof(uint32_t)];
- if (pwd_exp_warning > 0 &&
- difftime(pwd_exp_warning, *expiration) < 0.0) {
- skip = true;
- }
- }
- }
-
- if (!skip) {
- ret = pam_add_response(pd, msg_type, msg_len, &buf[p]);
- if (ret != EOK) {
- /* This is not a fatal error */
- DEBUG(1, ("pam_add_response failed.\n"));
- }
- }
- p += msg_len;
-
- if ((p < len) && (p + 2*sizeof(int32_t) >= len)) {
- DEBUG(1, ("The remainder of the message is too short.\n"));
- ret = EINVAL;
+ if (res->ccname) {
+ kr->ccname = talloc_strdup(kr, res->ccname);
+ if (!kr->ccname) {
+ ret = ENOMEM;
goto done;
}
}
/* If the child request failed, but did not return an offline error code,
* return with the status */
- if (msg_status != PAM_SUCCESS && msg_status != PAM_AUTHINFO_UNAVAIL &&
- msg_status != PAM_AUTHTOK_LOCK_BUSY &&
- msg_status != PAM_NEW_AUTHTOK_REQD) {
- state->pam_status = msg_status;
+ if (res->msg_status != PAM_SUCCESS &&
+ res->msg_status != PAM_AUTHINFO_UNAVAIL &&
+ res->msg_status != PAM_AUTHTOK_LOCK_BUSY &&
+ res->msg_status != PAM_NEW_AUTHTOK_REQD) {
+ state->pam_status = res->msg_status;
state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
} else {
- state->pam_status = msg_status;
+ state->pam_status = res->msg_status;
}
/* 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. */
- if (msg_status == PAM_NEW_AUTHTOK_REQD) {
+ if (res->msg_status == PAM_NEW_AUTHTOK_REQD) {
if (pd->cmd == SSS_PAM_AUTHENTICATE && !kr->active_ccache_present) {
if (kr->old_ccname != NULL) {
ret = safe_remove_old_ccache_file(kr->old_ccname, "dummy");
@@ -883,7 +791,7 @@ static void krb5_child_done(struct tevent_req *subreq)
}
}
- state->pam_status = msg_status;
+ state->pam_status = res->msg_status;
state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
@@ -891,7 +799,7 @@ static void krb5_child_done(struct tevent_req *subreq)
/* If the child request was successful and we run the first pass of the
* change password request just return success. */
- if (msg_status == PAM_SUCCESS && pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
+ if (res->msg_status == PAM_SUCCESS && pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
state->pam_status = PAM_SUCCESS;
state->dp_err = DP_ERR_OK;
ret = EOK;
@@ -902,7 +810,7 @@ static void krb5_child_done(struct tevent_req *subreq)
if (kr->kpasswd_srv != NULL &&
(pd->cmd == SSS_PAM_CHAUTHTOK || pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM)) {
/* ..which is unreachable by now.. */
- if (msg_status == PAM_AUTHTOK_LOCK_BUSY) {
+ if (res->msg_status == PAM_AUTHTOK_LOCK_BUSY) {
be_fo_set_port_status(state->be_ctx,
kr->kpasswd_srv, PORT_NOT_WORKING);
/* ..try to resolve next kpasswd server */
@@ -919,8 +827,8 @@ static void krb5_child_done(struct tevent_req *subreq)
/* if the KDC for auth (PAM_AUTHINFO_UNAVAIL) or
* chpass (PAM_AUTHTOK_LOCK_BUSY) was not available while using KDC
* also for chpass operation... */
- if (msg_status == PAM_AUTHINFO_UNAVAIL ||
- (kr->kpasswd_srv == NULL && msg_status == PAM_AUTHTOK_LOCK_BUSY)) {
+ if (res->msg_status == PAM_AUTHINFO_UNAVAIL ||
+ (kr->kpasswd_srv == NULL && res->msg_status == PAM_AUTHTOK_LOCK_BUSY)) {
if (kr->srv != NULL) {
be_fo_set_port_status(state->be_ctx, kr->srv, PORT_NOT_WORKING);
/* ..try to resolve next KDC */
@@ -958,14 +866,14 @@ static void krb5_child_done(struct tevent_req *subreq)
goto done;
}
- if (msg_status == PAM_SUCCESS &&
+ if (res->msg_status == PAM_SUCCESS &&
dp_opt_get_int(kr->krb5_ctx->opts, KRB5_RENEW_INTERVAL) > 0 &&
(pd->cmd == SSS_PAM_AUTHENTICATE || pd->cmd == SSS_CMD_RENEW ||
pd->cmd == SSS_PAM_CHAUTHTOK) &&
- tgtt.renew_till > tgtt.endtime && kr->ccname != NULL) {
+ res->tgtt.renew_till > res->tgtt.endtime && kr->ccname != NULL) {
DEBUG(7, ("Adding [%s] for automatic renewal.\n", kr->ccname));
- ret = add_tgt_to_renew_table(kr->krb5_ctx, kr->ccname, &tgtt, pd,
- kr->upn);
+ ret = add_tgt_to_renew_table(kr->krb5_ctx, kr->ccname, &(res->tgtt),
+ pd, kr->upn);
if (ret != EOK) {
DEBUG(1, ("add_tgt_to_renew_table failed, "
"automatic renewal not possible.\n"));
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index 89b77d3663d2aec8dbf73178ca6827213f94d89d..5cc22dfe8171d1f83a1d6ef63313222f66e302d4 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -74,6 +74,17 @@ struct tevent_req *handle_child_send(TALLOC_CTX *mem_ctx,
int handle_child_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
uint8_t **buf, ssize_t *len);
+struct krb5_child_response {
+ int32_t msg_status;
+ struct tgt_times tgtt;
+ char *ccname;
+};
+
+errno_t
+parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len,
+ struct pam_data *pd, int pwd_exp_warning,
+ struct krb5_child_response **_res);
+
errno_t add_user_to_delayed_online_authentication(struct krb5_ctx *krb5_ctx,
struct pam_data *pd,
uid_t uid);
diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
index 87f9d3cab1d36676d07058673a078ee2c6ba907b..6343f3b5355b62f50b4412a737b81a701538c143 100644
--- a/src/providers/krb5/krb5_child_handler.c
+++ b/src/providers/krb5/krb5_child_handler.c
@@ -38,6 +38,9 @@
#define KRB5_CHILD KRB5_CHILD_DIR"/krb5_child"
+#define TIME_T_MAX LONG_MAX
+#define int64_to_time_t(val) ((time_t)((val) < TIME_T_MAX ? val : TIME_T_MAX))
+
struct io {
int read_from_child_fd;
int write_to_child_fd;
@@ -415,3 +418,132 @@ int handle_child_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
return EOK;
}
+
+errno_t
+parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len,
+ struct pam_data *pd, int pwd_exp_warning,
+ struct krb5_child_response **_res)
+{
+ ssize_t pref_len;
+ size_t p;
+ errno_t ret;
+ bool skip;
+ char *ccname = NULL;
+ size_t ccname_len;
+ int32_t msg_status;
+ int32_t msg_type;
+ int32_t msg_len;
+ int64_t time_data;
+ struct tgt_times tgtt;
+ uint32_t *expiration;
+ uint32_t *msg_subtype;
+ struct krb5_child_response *res;
+
+ if ((size_t) len < sizeof(int32_t)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("message too short.\n"));
+ return EINVAL;
+ }
+
+ if (pwd_exp_warning < 0) {
+ pwd_exp_warning = KERBEROS_PWEXPIRE_WARNING_TIME;
+ }
+
+ /* A buffer with the following structure is expected.
+ * int32_t status of the request (required)
+ * message (zero or more)
+ *
+ * A message consists of:
+ * int32_t type of the message
+ * int32_t length of the following data
+ * uint8_t[len] data
+ */
+
+ p=0;
+ SAFEALIGN_COPY_INT32(&msg_status, buf+p, &p);
+
+ while (p < len) {
+ skip = false;
+ SAFEALIGN_COPY_INT32(&msg_type, buf+p, &p);
+ SAFEALIGN_COPY_INT32(&msg_len, buf+p, &p);
+
+ DEBUG(SSSDBG_TRACE_LIBS, ("child response [%d][%d][%d].\n",
+ msg_status, msg_type, msg_len));
+
+ if ((p + msg_len) > len) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("message format error [%d] > [%d].\n",
+ p+msg_len, len));
+ return EINVAL;
+ }
+
+ /* We need to save the name of the credential cache file. To find it
+ * we check if the data part of a message starts with
+ * CCACHE_ENV_NAME"=". pref_len also counts the trailing '=' because
+ * sizeof() counts the trailing '\0' of a string. */
+ pref_len = sizeof(CCACHE_ENV_NAME);
+ if (msg_len > pref_len &&
+ strncmp((const char *) &buf[p], CCACHE_ENV_NAME"=", pref_len) == 0) {
+ ccname = (char *) &buf[p+pref_len];
+ ccname_len = msg_len-pref_len;
+ }
+
+ if (msg_type == SSS_KRB5_INFO_TGT_LIFETIME &&
+ msg_len == 4*sizeof(int64_t)) {
+ SAFEALIGN_COPY_INT64(&time_data, buf+p, NULL);
+ tgtt.authtime = int64_to_time_t(time_data);
+ SAFEALIGN_COPY_INT64(&time_data, buf+p+sizeof(int64_t), NULL);
+ tgtt.starttime = int64_to_time_t(time_data);
+ SAFEALIGN_COPY_INT64(&time_data, buf+p+2*sizeof(int64_t), NULL);
+ tgtt.endtime = int64_to_time_t(time_data);
+ SAFEALIGN_COPY_INT64(&time_data, buf+p+3*sizeof(int64_t), NULL);
+ tgtt.renew_till = int64_to_time_t(time_data);
+ DEBUG(SSSDBG_TRACE_LIBS, ("TGT times are [%d][%d][%d][%d].\n",
+ tgtt.authtime, tgtt.starttime, tgtt.endtime, tgtt.renew_till));
+ }
+
+ if (msg_type == SSS_PAM_USER_INFO) {
+ msg_subtype = (uint32_t *)&buf[p];
+ if (*msg_subtype == SSS_PAM_USER_INFO_EXPIRE_WARN)
+ {
+ expiration = (uint32_t *)&buf[p+sizeof(uint32_t)];
+ if (pwd_exp_warning > 0 &&
+ difftime(pwd_exp_warning, *expiration) < 0.0) {
+ skip = true;
+ }
+ }
+ }
+
+ if (!skip) {
+ ret = pam_add_response(pd, msg_type, msg_len, &buf[p]);
+ if (ret != EOK) {
+ /* This is not a fatal error */
+ DEBUG(SSSDBG_CRIT_FAILURE, ("pam_add_response failed.\n"));
+ }
+ }
+
+ p += msg_len;
+
+ if ((p < len) && (p + 2*sizeof(int32_t) >= len)) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("The remainder of the message is too short.\n"));
+ return EINVAL;
+ }
+ }
+
+ res = talloc_zero(mem_ctx, struct krb5_child_response);
+ if (!res) return ENOMEM;
+
+ res->msg_status = msg_status;
+ memcpy(&res->tgtt, &tgtt, sizeof(tgtt));
+
+ if (ccname) {
+ res->ccname = talloc_strndup(res, ccname, ccname_len);
+ if (res->ccname == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strndup failed.\n"));
+ talloc_free(res);
+ return ENOMEM;
+ }
+ }
+
+ *_res = res;
+ return EOK;
+}
--
1.7.10.2
-------------- next part --------------
>From 04e8a10f95a879f846a603b2478f2d7bcfc8579c Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Tue, 22 May 2012 00:17:32 +0200
Subject: [PATCH 05/12] Add a krb5_child test tool
https://fedorahosted.org/sssd/ticket/1127
---
Makefile.am | 24 ++
src/tests/krb5_child-test.c | 551 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 575 insertions(+)
create mode 100644 src/tests/krb5_child-test.c
diff --git a/Makefile.am b/Makefile.am
index a6c2f909846011e81270e3f99e771e3f1c11bedb..f5366a36c607a1d2bb75152b64e73e93ba6b7ff9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -120,6 +120,7 @@ endif
check_PROGRAMS = \
stress-tests \
+ krb5-child-test \
$(non_interactive_check_based_tests)
PYTHON_TESTS =
@@ -972,6 +973,29 @@ stress_tests_LDADD = \
libsss_util.la \
libsss_test_common.la
+krb5_child_test_SOURCES = \
+ src/tests/krb5_child-test.c \
+ src/providers/krb5/krb5_utils.c \
+ src/providers/krb5/krb5_child_handler.c \
+ src/providers/krb5/krb5_become_user.c \
+ src/providers/krb5/krb5_common.c \
+ src/util/sss_krb5.c \
+ src/providers/data_provider_fo.c \
+ src/providers/data_provider_opts.c \
+ src/providers/data_provider_callbacks.c \
+ $(SSSD_FAILOVER_OBJ)
+krb5_child_test_CFLAGS = \
+ $(AM_CFLAGS) \
+ -DKRB5_CHILD_DIR=\"$(builddir)\" \
+ $(CHECK_CFLAGS)
+krb5_child_test_LDADD = \
+ $(SSSD_LIBS)\
+ $(CARES_LIBS) \
+ $(KRB5_LIBS) \
+ $(CHECK_LIBS) \
+ libsss_util.la \
+ libsss_test_common.la
+
noinst_PROGRAMS = pam_test_client
if BUILD_SUDO
noinst_PROGRAMS += sss_sudo_cli
diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
new file mode 100644
index 0000000000000000000000000000000000000000..4dde996a00ac7490d7168bda27b391bbabcd7ae5
--- /dev/null
+++ b/src/tests/krb5_child-test.c
@@ -0,0 +1,551 @@
+/*
+ SSSD
+
+ Unit tests - exercise the krb5 child
+
+ Authors:
+ Jakub Hrozek <jhrozek at redhat.com>
+
+ Copyright (C) 2012 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 <stdio.h>
+#include <stdlib.h>
+#include <talloc.h>
+#include <popt.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "util/util.h"
+#include "src/tools/tools_util.h"
+
+/* Interfaces being tested */
+#include "providers/krb5/krb5_auth.h"
+#include "providers/krb5/krb5_common.h"
+#include "providers/krb5/krb5_utils.h"
+
+extern struct dp_option default_krb5_opts[];
+
+static krb5_context krb5_error_ctx;
+#define KRB5_DEBUG(level, krb5_error) do { \
+ const char * __krb5_error_msg; \
+ __krb5_error_msg = sss_krb5_get_error_message(krb5_error_ctx, krb5_error); \
+ DEBUG(level, ("%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg)); \
+ sss_log(SSS_LOG_ERR, "%s", __krb5_error_msg); \
+ sss_krb5_free_error_message(krb5_error_ctx, __krb5_error_msg); \
+} while(0)
+
+#define CHECK_KRET(kret, err) do { \
+ if (kret) { \
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kret); \
+ return err; \
+ } \
+} while(0) \
+
+#define CHECK_KRET_L(kret, err, label) do { \
+ if (kret) { \
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kret); \
+ goto label; \
+ } \
+} while(0) \
+
+struct krb5_child_test_ctx {
+ struct tevent_context *ev;
+ struct krb5child_req *kr;
+
+ bool done;
+ errno_t child_ret;
+
+ uint8_t *buf;
+ ssize_t len;
+ struct krb5_child_response *res;
+};
+
+static errno_t
+setup_krb5_child_test(TALLOC_CTX *mem_ctx, struct krb5_child_test_ctx **_ctx)
+{
+ struct krb5_child_test_ctx *ctx;
+
+ ctx = talloc_zero(mem_ctx, struct krb5_child_test_ctx);
+ if (!ctx) return ENOMEM;
+
+ ctx->ev = tevent_context_init(ctx);
+ if (ctx->ev == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not init tevent context"));
+ talloc_free(ctx);
+ return EFAULT;
+ }
+
+ *_ctx = ctx;
+ return EOK;
+}
+
+int re_destructor(void *memctx)
+{
+ struct krb5_ctx *ctx = (struct krb5_ctx *) memctx;
+
+ if (ctx->illegal_path_re) {
+ pcre_free(ctx->illegal_path_re);
+ ctx->illegal_path_re = NULL;
+ }
+ return 0;
+}
+
+static struct krb5_ctx *
+create_dummy_krb5_ctx(TALLOC_CTX *mem_ctx, const char *realm)
+{
+ struct krb5_ctx *krb5_ctx;
+ const char *errstr;
+ int errval;
+ int errpos;
+ int i;
+ errno_t ret;
+
+ krb5_ctx = talloc_zero(mem_ctx, struct krb5_ctx);
+ if (!krb5_ctx) return NULL;
+
+ krb5_ctx->illegal_path_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0,
+ &errval, &errstr, &errpos, NULL);
+ if (krb5_ctx->illegal_path_re == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Invalid Regular Expression pattern at position %d. "
+ "(Error: %d [%s])\n", errpos, errval, errstr));
+ goto fail;
+ }
+ talloc_set_destructor((TALLOC_CTX *) krb5_ctx, re_destructor);
+
+ /* Kerberos options */
+ krb5_ctx->opts = talloc_zero_array(krb5_ctx, struct dp_option, KRB5_OPTS);
+ if (!krb5_ctx->opts) goto fail;
+ for (i = 0; i < KRB5_OPTS; i++) {
+ krb5_ctx->opts[i].opt_name = default_krb5_opts[i].opt_name;
+ krb5_ctx->opts[i].type = default_krb5_opts[i].type;
+ krb5_ctx->opts[i].def_val = default_krb5_opts[i].def_val;
+ switch (krb5_ctx->opts[i].type) {
+ case DP_OPT_STRING:
+ ret = dp_opt_set_string(krb5_ctx->opts, i,
+ default_krb5_opts[i].def_val.string);
+ break;
+ case DP_OPT_BLOB:
+ ret = dp_opt_set_blob(krb5_ctx->opts, i,
+ default_krb5_opts[i].def_val.blob);
+ break;
+ case DP_OPT_NUMBER:
+ ret = dp_opt_set_int(krb5_ctx->opts, i,
+ default_krb5_opts[i].def_val.number);
+ break;
+ case DP_OPT_BOOL:
+ ret = dp_opt_set_bool(krb5_ctx->opts, i,
+ default_krb5_opts[i].def_val.boolean);
+ break;
+ }
+ if (ret) goto fail;
+ }
+
+ ret = dp_opt_set_string(krb5_ctx->opts, KRB5_REALM, realm);
+ if (ret) goto fail;
+
+ return krb5_ctx;
+
+fail:
+ talloc_free(krb5_ctx);
+ return NULL;
+}
+
+static struct pam_data *
+create_dummy_pam_data(TALLOC_CTX *mem_ctx, const char *user,
+ const char *password)
+{
+ struct pam_data *pd;
+
+ pd = talloc_zero(mem_ctx, struct pam_data);
+ if (!pd) goto fail;
+
+ pd->cmd = SSS_PAM_AUTHENTICATE;
+ pd->user = talloc_strdup(pd, user);
+ if (!pd->user) goto fail;
+
+ pd->authtok = discard_const(talloc_strdup(pd, password));
+ if (!pd->authtok) goto fail;
+ pd->authtok_size = strlen(password);
+ pd->authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
+ DEBUG(SSSDBG_FUNC_DATA, ("Authtok [%s] len [%d]\n",
+ pd->authtok, pd->authtok_size));
+
+ return pd;
+
+fail:
+ talloc_free(pd);
+ return NULL;
+}
+
+static struct krb5child_req *
+create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
+ const char *password, const char *realm,
+ const char *ccname, const char *ccname_template,
+ int timeout)
+{
+ struct krb5child_req *kr;
+ struct passwd *pwd;
+ bool private;
+ errno_t ret;
+
+ /* The top level child request */
+ kr = talloc_zero(mem_ctx, struct krb5child_req);
+ if (!kr) return NULL;
+
+ pwd = getpwnam(user);
+ if (!pwd) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Cannot get info on user [%s]\n", user));
+ goto fail;
+ }
+
+ kr->uid = pwd->pw_uid;
+ kr->gid = pwd->pw_gid;
+
+ /* The Kerberos context */
+ kr->krb5_ctx = create_dummy_krb5_ctx(kr, realm);
+ /* PAM Data structure */
+ kr->pd = create_dummy_pam_data(kr, user, password);
+
+ ret = krb5_get_simple_upn(kr, kr->krb5_ctx, kr->pd->user, &kr->upn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("krb5_get_simple_upn failed.\n"));
+ goto fail;
+ }
+
+ /* Override options with what was provided by the user */
+ if (ccname_template) {
+ ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL,
+ ccname_template);
+ if (ret != EOK) goto fail;
+ }
+
+ if (timeout) {
+ dp_opt_set_int(kr->krb5_ctx->opts, KRB5_AUTH_TIMEOUT, timeout);
+ }
+
+ if (!ccname) {
+ kr->ccname = expand_ccname_template(kr, kr,
+ dp_opt_get_cstring(kr->krb5_ctx->opts,
+ KRB5_CCNAME_TMPL),
+ true, true, &private);
+ if (!kr->ccname) goto fail;
+
+ DEBUG(SSSDBG_FUNC_DATA, ("ccname [%s] uid [%llu] gid [%llu]\n",
+ kr->ccname, kr->uid, kr->gid));
+
+ ret = create_ccache_dir(kr, kr->ccname,
+ kr->krb5_ctx->illegal_path_re,
+ kr->uid, kr->gid, private);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("create_ccache_dir failed.\n"));
+ goto fail;
+ }
+ }
+
+ return kr;
+
+fail:
+ talloc_free(kr);
+ return NULL;
+}
+
+static void
+child_done(struct tevent_req *req)
+{
+ struct krb5_child_test_ctx *ctx = tevent_req_callback_data(req,
+ struct krb5_child_test_ctx);
+ errno_t ret;
+
+ ret = handle_child_recv(req, ctx, &ctx->buf, &ctx->len);
+ talloc_free(req);
+ ctx->done = true;
+ ctx->child_ret = ret;
+}
+
+static void
+printtime(krb5_timestamp ts)
+{
+ krb5_error_code kret;
+ char timestring[BUFSIZ];
+ char fill = '\0';
+
+ kret = krb5_timestamp_to_sfstring(ts, timestring, BUFSIZ, &fill);
+ if (kret) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kret);
+ }
+ printf("%s", timestring);
+}
+
+static void
+print_creds(krb5_context kcontext, krb5_creds *cred, const char *defname)
+{
+ krb5_error_code kret;
+ char *name = NULL;
+ char *sname = NULL;
+
+ kret = krb5_unparse_name(kcontext, cred->client, &name);
+ CHECK_KRET_L(kret, EIO, done);
+
+ kret = krb5_unparse_name(kcontext, cred->server, &sname);
+ CHECK_KRET_L(kret, EIO, done);
+
+ if (!cred->times.starttime) {
+ cred->times.starttime = cred->times.authtime;
+ }
+
+
+ printf("\t\t%s\n", sname);
+ printf("\t\tValid from\t"); printtime(cred->times.starttime);
+ printf("\n\t\tValid until\t"); printtime(cred->times.endtime);
+ printf("\n");
+
+ if (strcmp(name, defname)) {
+ printf("\t\tfor client %s", name);
+ }
+
+done:
+ krb5_free_unparsed_name(kcontext, name);
+ krb5_free_unparsed_name(kcontext, sname);
+}
+
+static errno_t
+print_ccache(const char *cc)
+{
+ krb5_cc_cursor cur;
+ krb5_ccache cache = NULL;
+ krb5_error_code kret;
+ krb5_context kcontext = NULL;
+ krb5_principal_data *princ = NULL;
+ krb5_creds creds;
+ char *defname = NULL;
+ int i = 1;
+ errno_t ret;
+
+ kret = krb5_init_context(&kcontext);
+ CHECK_KRET_L(kret, EIO, done);
+
+ kret = krb5_cc_resolve(kcontext, cc, &cache);
+ CHECK_KRET_L(kret, EIO, done);
+
+ kret = krb5_cc_get_principal(kcontext, cache, &princ);
+ CHECK_KRET_L(kret, EIO, done);
+
+ kret = krb5_unparse_name(kcontext, princ, &defname);
+ CHECK_KRET_L(kret, EIO, done);
+
+ printf("\nTicket cache: %s:%s\nDefault principal: %s\n\n",
+ krb5_cc_get_type(kcontext, cache),
+ krb5_cc_get_name(kcontext, cache), defname);
+
+ kret = krb5_cc_start_seq_get(kcontext, cache, &cur);
+ CHECK_KRET_L(kret, EIO, done);
+
+ while (!(kret = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
+ printf("Ticket #%d:\n", i);
+ print_creds(kcontext, &creds, defname);
+ krb5_free_cred_contents(kcontext, &creds);
+ }
+
+ krb5_cc_end_seq_get(kcontext, cache, &cur);
+ CHECK_KRET_L(kret, EIO, done);
+
+ ret = EOK;
+done:
+ krb5_cc_close(kcontext, cache);
+ krb5_free_unparsed_name(kcontext, defname);
+ krb5_free_principal(kcontext, princ);
+ krb5_free_context(kcontext);
+ return ret;
+}
+
+static void
+remove_ccache(const char *cc)
+{
+ size_t offset = 0;
+ errno_t ret;
+
+ if (strncmp(cc, "FILE:", 5) == 0) {
+ offset = 5;
+ }
+ if (cc[offset] != '/') {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("ccname [%s] does not contain absolute path?\n", cc));
+ }
+
+ errno = 0;
+ ret = unlink(cc+offset);
+ if (ret == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("unlink [%s] failed [%d]: %s\n", cc, ret, strerror(ret)));
+ }
+}
+
+int
+main(int argc, const char *argv[])
+{
+ int opt;
+ errno_t ret;
+ struct krb5_child_test_ctx *ctx = NULL;
+ struct tevent_req *req;
+
+ int pc_debug = 0;
+ int pc_timeout = 0;
+ const char *pc_user = NULL;;
+ const char *pc_passwd = NULL;;
+ const char *pc_realm = NULL;;
+ const char *pc_ccname = NULL;;
+ const char *pc_ccname_tp = NULL;;
+ char *password = NULL;
+ bool rm_ccache = true;
+
+ poptContext pc;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, 0,
+ "The debug level to run with", NULL },
+ { "user", 'u', POPT_ARG_STRING, &pc_user, 0,
+ "The user to log in as", NULL },
+ { "password", 'w', POPT_ARG_STRING, &pc_passwd, 0,
+ "The authtok to use", NULL },
+ { "ask-password", 'W', POPT_ARG_NONE, NULL, 'W',
+ "Ask interactively for authtok", NULL },
+ { "ccname", 'c', POPT_ARG_STRING, &pc_ccname, 0,
+ "Force usage of a certain credential cache", NULL },
+ { "ccname-template", 't', POPT_ARG_STRING, &pc_ccname_tp, 0,
+ "Specify the credential cache template", NULL },
+ { "realm", 'r', POPT_ARG_STRING, &pc_realm, 0,
+ "The Kerberos realm to use", NULL },
+ { "keep-ccache", 'k', POPT_ARG_NONE, NULL, 'k',
+ "Do not delete the ccache when the tool finishes", NULL },
+ { "timeout", '\0', POPT_ARG_INT, &pc_timeout, 0,
+ "The timeout for the child, in seconds", NULL },
+ POPT_TABLEEND
+ };
+
+ debug_prg_name = argv[0];
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+
+ while ((opt = poptGetNextOpt(pc)) > 0) {
+ switch(opt) {
+ case 'W':
+ errno = 0;
+ password = getpass("Enter password:");
+ if (!password) {
+ return 1;
+ }
+ break;
+ case 'k':
+ rm_ccache = false;
+ break;
+ default:
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Unexpected option\n"));
+ return 1;
+ }
+ }
+
+ debug_level = debug_convert_old_level(pc_debug);
+
+ if (opt != -1) {
+ poptPrintUsage(pc, stderr, 0);
+ fprintf(stderr, "%s", poptStrerror(opt));
+ return 1;
+ }
+
+ if (!pc_user) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Please specify the user\n"));
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+
+ if (!pc_realm) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Please specify the realm\n"));
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+
+ if (!password && !pc_passwd) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Password was not provided or asked for\n"));
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+
+ if (pc_ccname && pc_ccname_tp) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("Both ccname and ccname template specified, "
+ "will prefer ccname\n"));
+ }
+
+ ret = setup_krb5_child_test(NULL, &ctx);
+ if (ret != EOK) {
+ poptPrintUsage(pc, stderr, 0);
+ fprintf(stderr, "%s", poptStrerror(opt));
+ return 3;
+ }
+
+ ctx->kr = create_dummy_req(ctx, pc_user, password ? password : pc_passwd,
+ pc_realm, pc_ccname, pc_ccname_tp, pc_timeout);
+ if (!ctx->kr) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Cannot create Kerberos request\n"));
+ ret = 4;
+ goto done;
+ }
+
+ req = handle_child_send(ctx, ctx->ev, ctx->kr);
+ if (!req) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Cannot create child request\n"));
+ ret = 4;
+ goto done;
+ }
+ tevent_req_set_callback(req, child_done, ctx);
+
+ while (ctx->done == false) {
+ tevent_loop_once(ctx->ev);
+ }
+
+ printf("Child returned %d\n", ctx->child_ret);
+
+ ret = parse_krb5_child_response(ctx, ctx->buf, ctx->len,
+ ctx->kr->pd, 0, &ctx->res);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Could not parse child response\n"));
+ ret = 5;
+ goto done;
+ }
+
+ if (!ctx->res->ccname) {
+ fprintf(stderr, "No ccname returned\n");
+ ret = 6;
+ goto done;
+ }
+
+ print_ccache(ctx->res->ccname);
+
+ ret = 0;
+done:
+ if (rm_ccache && ctx->res && ctx->res->ccname) {
+ remove_ccache(ctx->res->ccname);
+ }
+ free(password);
+ talloc_free(ctx);
+ poptFreeContext(pc);
+ return ret;
+}
--
1.7.10.2
-------------- next part --------------
>From b5daaeacecac32e81a49167ef64c36e5cd91c67b Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Thu, 17 May 2012 13:49:30 +0200
Subject: [PATCH 06/12] Residual util functions
Kerberos credential caches can be specified by TYPE:RESIDUAL. This patch
adds a couple of utilities to support parsing if ccache locations,
checking types etc.
---
src/util/sss_krb5.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/util/sss_krb5.h | 16 ++++++++++
2 files changed, 102 insertions(+)
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index 81a1623ef9df340d7618bdf55c1707ce4cfb1a6a..5bc1140d0778882aa001a4a4504ddca42a63a4f8 100644
--- a/src/util/sss_krb5.c
+++ b/src/util/sss_krb5.c
@@ -1124,3 +1124,89 @@ sss_krb5_read_etypes_for_keytab(TALLOC_CTX *mem_ctx,
talloc_free(tmp_ctx);
return ret;
}
+
+#define SSS_KRB5_FILE "FILE:"
+#define SSS_KRB5_DIR "DIR:"
+
+enum sss_krb5_cc_type
+sss_krb5_get_type(const char *full_location)
+{
+ if (!full_location) {
+ return SSS_KRB5_TYPE_UNKNOWN;
+ }
+
+ if (strncmp(full_location, SSS_KRB5_FILE,
+ sizeof(SSS_KRB5_FILE)-1) == 0) {
+ return SSS_KRB5_TYPE_FILE;
+ } else if (strncmp(full_location, SSS_KRB5_DIR,
+ sizeof(SSS_KRB5_DIR)-1) == 0) {
+ return SSS_KRB5_TYPE_DIR;
+ } else if (full_location[0] == '/') {
+ return SSS_KRB5_TYPE_FILE;
+ }
+
+ return SSS_KRB5_TYPE_UNKNOWN;
+}
+
+const char *
+sss_krb5_residual_by_type(const char *full_location,
+ enum sss_krb5_cc_type type)
+{
+ size_t offset;
+
+ if (full_location == NULL) return NULL;
+
+ switch (type) {
+ case SSS_KRB5_TYPE_FILE:
+ if (full_location[0] == '/') {
+ offset = 0;
+ } else {
+ offset = sizeof(SSS_KRB5_FILE)-1;
+ }
+ break;
+ case SSS_KRB5_TYPE_DIR:
+ offset = sizeof(SSS_KRB5_DIR)-1;
+ break;
+ default:
+ return NULL;
+ }
+
+ return full_location + offset;
+}
+
+const char *
+sss_krb5_cc_file_path(const char *full_location)
+{
+ enum sss_krb5_cc_type cc_type;
+ const char *residual;
+
+ cc_type = sss_krb5_get_type(full_location);
+ residual = sss_krb5_residual_by_type(full_location, cc_type);
+
+ switch(cc_type) {
+ case SSS_KRB5_TYPE_FILE:
+ return residual;
+ case SSS_KRB5_TYPE_DIR:
+ /* DIR::/run/user/tkt_foo */
+ if (residual[0] == ':') return residual+1;
+ case SSS_KRB5_TYPE_UNKNOWN:
+ break;
+ }
+
+ return NULL;
+}
+
+const char *
+sss_krb5_residual_check_type(const char *full_location,
+ enum sss_krb5_cc_type expected_type)
+{
+ enum sss_krb5_cc_type type;
+
+ type = sss_krb5_get_type(full_location);
+ if (type != expected_type) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Unexpected ccache type\n"));
+ return NULL;
+ }
+
+ return sss_krb5_residual_by_type(full_location, type);
+}
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index 12412585f516cd72726faf2de18ccd60c2c2fd84..bba2a7eda38b2da9fa3d875b327026de7cbe50cf 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -122,6 +122,22 @@ sss_krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal
void sss_krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt *opts,
int canonicalize);
+enum sss_krb5_cc_type {
+ SSS_KRB5_TYPE_FILE,
+ SSS_KRB5_TYPE_DIR,
+ SSS_KRB5_TYPE_UNKNOWN
+};
+
+enum sss_krb5_cc_type
+sss_krb5_get_type(const char *full_location);
+const char *
+sss_krb5_residual_by_type(const char *full_location, enum sss_krb5_cc_type type);
+const char *
+sss_krb5_cc_file_path(const char *full_location);
+const char *
+sss_krb5_residual_check_type(const char *full_location,
+ enum sss_krb5_cc_type expected_type);
+
/* === Compatibility routines for the Heimdal Kerberos implementation === */
void sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
--
1.7.10.2
-------------- next part --------------
>From 90a1de66766cde2f00d06385847099c7e4860b1a Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Thu, 31 May 2012 19:28:29 +0200
Subject: [PATCH 07/12] Handle trailing slash in the ccname template
With the DIR cache support, it's perfectly legal to specify a ccname
directory that ends with a slash. The create_dir function did not handle
that situation correctly.
---
src/providers/krb5/krb5_utils.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index c97d58e7c7cfb80b3fd34eaf18a5371669871272..9d199e1f5ad3f97aeed7a2d7fd5360d10d957ec3 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -285,14 +285,20 @@ static errno_t find_ccdir_parent_data(TALLOC_CTX *mem_ctx, const char *dirname,
DEBUG(1, ("talloc_strdup failed.\n"));
return ENOMEM;
}
- end = strrchr(parent, '/');
- if (end == NULL || end == parent) {
- DEBUG(1, ("Cannot find parent directory of [%s], / is not allowed.\n",
- dirname));
- ret = EINVAL;
- goto done;
- }
- *end = '\0';
+
+ /* We'll remove all trailing slashes from the back so that
+ * we only pass /some/path to find_ccdir_parent_data, not
+ * /some/path */
+ do {
+ end = strrchr(parent, '/');
+ if (end == NULL || end == parent) {
+ DEBUG(1, ("Cannot find parent directory of [%s], / is not allowed.\n",
+ dirname));
+ ret = EINVAL;
+ goto done;
+ }
+ *end = '\0';
+ } while (*(end+1) == '\0');
ret = find_ccdir_parent_data(mem_ctx, parent, parent_stat, missing_parents);
--
1.7.10.2
-------------- next part --------------
>From 91a8beb5e7d1218a27711c89d96c82b5e51ddf06 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Thu, 17 May 2012 18:06:34 +0200
Subject: [PATCH 08/12] Add a credential cache back end structure
To be able to add support for new credential cache types easily, this
patch creates a new structure sss_krb5_cc_be that defines common
operations with a credential cache, such as create, check if used or remove.
---
Makefile.am | 3 +
src/providers/krb5/krb5_auth.c | 199 +++++++++++------------
src/providers/krb5/krb5_auth.h | 1 +
src/providers/krb5/krb5_become_user.c | 2 +-
src/providers/krb5/krb5_common.c | 12 +-
src/providers/krb5/krb5_common.h | 3 +
src/providers/krb5/krb5_utils.c | 286 ++++++++++++++++++++++++++++-----
src/providers/krb5/krb5_utils.h | 33 +++-
src/tests/krb5_child-test.c | 38 ++---
src/tests/krb5_utils-tests.c | 44 ++---
10 files changed, 420 insertions(+), 201 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index f5366a36c607a1d2bb75152b64e73e93ba6b7ff9..3783100e6d74f4982652d8280aa4d7305da9ad3f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -758,6 +758,7 @@ krb5_utils_tests_SOURCES = \
src/providers/krb5/krb5_utils.c \
src/providers/krb5/krb5_common.c \
src/util/sss_krb5.c \
+ src/util/find_uid.c \
src/providers/data_provider_fo.c \
src/providers/data_provider_opts.c \
src/providers/data_provider_callbacks.c \
@@ -980,6 +981,7 @@ krb5_child_test_SOURCES = \
src/providers/krb5/krb5_become_user.c \
src/providers/krb5/krb5_common.c \
src/util/sss_krb5.c \
+ src/util/find_uid.c \
src/providers/data_provider_fo.c \
src/providers/data_provider_opts.c \
src/providers/data_provider_callbacks.c \
@@ -1157,6 +1159,7 @@ libsss_ldap_la_SOURCES = \
src/util/find_uid.c \
src/providers/ldap/ldap_init.c \
src/providers/krb5/krb5_common.c \
+ src/providers/krb5/krb5_utils.c \
src/util/user_info_msg.c \
src/util/sss_ldap.c \
src/util/sss_krb5.c
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 7c622dbea6869f1acf510104498a304f634c21b5..9b503f47a14acb5cab09b4855066546ca0996ac3 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -39,107 +39,76 @@
#include "providers/krb5/krb5_auth.h"
#include "providers/krb5/krb5_utils.h"
-static errno_t safe_remove_old_ccache_file(const char *old_ccache_file,
- const char *new_ccache_file)
+static errno_t safe_remove_old_ccache_file(struct sss_krb5_cc_be *cc_be,
+ const char *princ,
+ const char *old_ccache,
+ const char *new_ccache)
{
int ret;
- size_t old_offset = 0;
- size_t new_offset = 0;
+ enum sss_krb5_cc_type old_type;
+ struct sss_krb5_cc_be *old_cc_ops;
- if (new_ccache_file == NULL) {
- DEBUG(1, ("Missing new ccache file, "
- "old ccache file is not deleted.\n"));
+ if (old_ccache == NULL) {
+ DEBUG(SSSDBG_FUNC_DATA, ("No old ccache, nothing to do\n"));
+ return EOK;
+ }
+
+ if (new_ccache == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Missing new ccache file, old ccache file is not deleted.\n"));
return EINVAL;
}
- if (old_ccache_file != NULL) {
- if (strncmp(old_ccache_file, "FILE:", 5) == 0) {
- old_offset = 5;
- }
- if (strncmp(new_ccache_file, "FILE:", 5) == 0) {
- new_offset = 5;
- }
- if (strcmp(old_ccache_file + old_offset,
- new_ccache_file + new_offset) == 0) {
- DEBUG(7, ("New and old ccache file are the same, "
- "no one will be deleted.\n"));
- return EOK;
- }
- if (old_ccache_file[old_offset] != '/') {
- DEBUG(1, ("Ccache file name [%s] is not an absolute path.\n",
- old_ccache_file + old_offset));
- return EINVAL;
- }
- ret = unlink(old_ccache_file + old_offset);
- if (ret == -1 && errno != ENOENT) {
- ret = errno;
- DEBUG(1, ("unlink [%s] failed [%d][%s].\n", old_ccache_file, ret,
- strerror(ret)));
- return ret;
- }
+ old_type = sss_krb5_get_type(old_ccache);
+ old_cc_ops = get_cc_be_ops(old_type);
+ if (!old_cc_ops) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get ccache operations\n"));
+ return EINVAL;
+ }
+
+ if (cc_be->type == old_type &&
+ strcmp(old_ccache, new_ccache) == 0) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("New and old ccache file are the same, "
+ "no one will be deleted.\n"));
+ return EOK;
+ }
+
+ ret = old_cc_ops->remove(old_ccache);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Cannot remove ccache [%s]\n", old_ccache));
+ return EIO;
}
return EOK;
}
-static errno_t check_if_ccache_file_is_used(uid_t uid, const char *ccname,
- bool *result)
+static errno_t
+check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
+ const char *realm, bool *active, bool *valid)
{
- int ret;
- size_t offset = 0;
- struct stat stat_buf;
- const char *filename;
- bool active;
-
- *result = false;
-
- if (ccname == NULL || *ccname == '\0') {
- return EINVAL;
- }
-
- if (strncmp(ccname, "FILE:", 5) == 0) {
- offset = 5;
- }
-
- filename = ccname + offset;
-
- if (filename[0] != '/') {
- DEBUG(1, ("Only absolute path names are allowed.\n"));
+ struct sss_krb5_cc_be *old_cc_ops;
+ errno_t ret;
+
+ /* ccache file might be of a different type if the user changed
+ * configuration
+ */
+ old_cc_ops = get_cc_be_ops_ccache(old_ccache);
+ if (old_cc_ops == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Cannot get operations on saved ccache %s\n", old_ccache));
return EINVAL;
}
- ret = lstat(filename, &stat_buf);
-
- if (ret == -1 && errno != ENOENT) {
- DEBUG(1, ("stat failed [%d][%s].\n", errno, strerror(errno)));
- return errno;
- } else if (ret == EOK) {
- if (stat_buf.st_uid != uid) {
- DEBUG(1, ("Cache file [%s] exists, but is owned by [%d] instead of "
- "[%d].\n", filename, stat_buf.st_uid, uid));
- return EINVAL;
- }
-
- if (!S_ISREG(stat_buf.st_mode)) {
- DEBUG(1, ("Cache file [%s] exists, but is not a regular file.\n",
- filename));
- return EINVAL;
- }
- }
-
- ret = check_if_uid_is_active(uid, &active);
+ ret = old_cc_ops->check_existing(old_ccache, kr->uid, realm,
+ kr->upn, active, valid);
if (ret != EOK) {
- DEBUG(1, ("check_if_uid_is_active failed.\n"));
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Cannot check if saved ccache %s is active and valid\n",
+ old_ccache));
return ret;
}
- if (!active) {
- DEBUG(5, ("User [%d] is not active\n", uid));
- } else {
- DEBUG(9, ("User [%d] is still active, reusing ccache file [%s].\n",
- uid, filename));
- *result = true;
- }
return EOK;
}
@@ -332,7 +301,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
struct krb5child_req *kr = NULL;
const char *ccache_file = NULL;
const char *realm;
- krb5_error_code kerr;
struct tevent_req *req;
struct tevent_req *subreq;
int ret;
@@ -457,22 +425,20 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* The type of the ccache might change during the request if we
+ * end up reusing an old ccache */
+ kr->cc_be = krb5_ctx->cc_be;
+
ccache_file = ldb_msg_find_attr_as_string(res->msgs[0],
SYSDB_CCACHE_FILE,
NULL);
if (ccache_file != NULL) {
- ret = check_if_ccache_file_is_used(kr->uid, ccache_file,
- &kr->active_ccache_present);
+ ret = check_old_ccache(ccache_file, kr, realm,
+ &kr->active_ccache_present,
+ &kr->valid_tgt_present);
if (ret != EOK) {
- DEBUG(1, ("check_if_ccache_file_is_used failed.\n"));
- goto done;
- }
-
- kerr = check_for_valid_tgt(ccache_file, realm, kr->upn,
- &kr->valid_tgt_present);
- if (kerr != 0) {
- DEBUG(1, ("check_for_valid_tgt failed.\n"));
- ret = kerr;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("check_if_ccache_file_is_used failed.\n"));
goto done;
}
} else {
@@ -639,13 +605,27 @@ static void krb5_find_ccache_step(struct tevent_req *req)
goto done;
}
- ret = create_ccache_dir(kr, kr->ccname,
+ ret = kr->cc_be->create(kr->ccname,
kr->krb5_ctx->illegal_path_re,
kr->uid, kr->gid, private_path);
if (ret != EOK) {
- DEBUG(1, ("create_ccache_dir failed.\n"));
+ DEBUG(SSSDBG_OP_FAILURE, ("ccache creation failed.\n"));
goto done;
}
+ } else {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("Saved ccache %s if of different type than ccache in "
+ "configuration file, reusing the old ccache\n"));
+
+ kr->cc_be = get_cc_be_ops_ccache(kr->old_ccname);
+ if (kr->cc_be == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Cannot get operations on saved ccache %s\n",
+ kr->old_ccname));
+ ret = EINVAL;
+ goto done;
+ }
+
}
if (kr->is_offline) {
@@ -725,6 +705,7 @@ static void krb5_child_done(struct tevent_req *subreq)
uint8_t *buf = NULL;
ssize_t len = -1;
struct krb5_child_response *res;
+ const char *store_ccname;
ret = handle_child_recv(subreq, pd, &buf, &len);
talloc_zfree(subreq);
@@ -777,7 +758,8 @@ static void krb5_child_done(struct tevent_req *subreq)
if (res->msg_status == PAM_NEW_AUTHTOK_REQD) {
if (pd->cmd == SSS_PAM_AUTHENTICATE && !kr->active_ccache_present) {
if (kr->old_ccname != NULL) {
- ret = safe_remove_old_ccache_file(kr->old_ccname, "dummy");
+ ret = safe_remove_old_ccache_file(kr->cc_be, kr->upn,
+ kr->old_ccname, "dummy");
if (ret != EOK) {
DEBUG(1, ("Failed to remove old ccache file [%s], "
"please remove it manually.\n", kr->old_ccname));
@@ -851,16 +833,25 @@ static void krb5_child_done(struct tevent_req *subreq)
goto done;
}
- if (kr->old_ccname != NULL) {
- ret = safe_remove_old_ccache_file(kr->old_ccname, kr->ccname);
- if (ret != EOK) {
- DEBUG(1, ("Failed to remove old ccache file [%s], "
- "please remove it manually.\n", kr->old_ccname));
- }
+ store_ccname = kr->cc_be->ccache_for_princ(kr, kr->ccname,
+ kr->upn);
+ if (store_ccname == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("No ccache for %s in %s?\n", kr->upn, kr->ccname));
+ ret = EIO;
+ goto done;
+ }
+
+ ret = safe_remove_old_ccache_file(kr->cc_be, kr->upn,
+ kr->old_ccname, store_ccname);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("Failed to remove old ccache file [%s], "
+ "please remove it manually.\n", kr->old_ccname));
}
ret = krb5_save_ccname(state, state->be_ctx->sysdb,
- pd->user, kr->ccname);
+ pd->user, store_ccname);
if (ret) {
DEBUG(1, ("krb5_save_ccname failed.\n"));
goto done;
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index 5cc22dfe8171d1f83a1d6ef63313222f66e302d4..cc079ba9352092a2b2dbcfe46ab4538bd120b567 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -41,6 +41,7 @@ struct krb5child_req {
struct pam_data *pd;
struct krb5_ctx *krb5_ctx;
+ struct sss_krb5_cc_be *cc_be;
const char *ccname;
const char *old_ccname;
const char *homedir;
diff --git a/src/providers/krb5/krb5_become_user.c b/src/providers/krb5/krb5_become_user.c
index 351f539a32e3e0cad56dd0bdde2ab67d9223ebc5..cc4e6a58a3fe84ffb1d2c0c8773f880e5f912e43 100644
--- a/src/providers/krb5/krb5_become_user.c
+++ b/src/providers/krb5/krb5_become_user.c
@@ -31,7 +31,7 @@ errno_t become_user(uid_t uid, gid_t gid)
{
int ret;
- DEBUG(9, ("Trying to become user [%d][%d].\n", uid, gid));
+ DEBUG(SSSDBG_FUNC_DATA, ("Trying to become user [%d][%d].\n", uid, gid));
ret = setgid(gid);
if (ret == -1) {
DEBUG(1, ("setgid failed [%d][%s].\n", errno, strerror(errno)));
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index 022745d6153c524cf30dbf787c3343d874cde90a..91816662b8a694fbf31933eae05db2793e3a9dbc 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -31,6 +31,7 @@
#include "providers/dp_backend.h"
#include "providers/krb5/krb5_common.h"
#include "providers/krb5/krb5_opts.h"
+#include "providers/krb5/krb5_utils.h"
errno_t check_and_export_lifetime(struct dp_option *opts, const int opt_id,
const char *env_name)
@@ -95,6 +96,7 @@ errno_t check_and_export_options(struct dp_option *opts,
const char *dummy;
char *use_fast_str;
char *fast_principal;
+ enum sss_krb5_cc_type cc_be;
realm = dp_opt_get_cstring(opts, KRB5_REALM);
if (realm == NULL) {
@@ -178,11 +180,15 @@ errno_t check_and_export_options(struct dp_option *opts,
DEBUG(1, ("Missing credential cache name template.\n"));
return EINVAL;
}
- if (dummy[0] != '/' && strncmp(dummy, "FILE:", 5) != 0) {
- DEBUG(1, ("Currently only file based credential caches are supported "
- "and krb5ccname_template must start with '/' or 'FILE:'\n"));
+
+ cc_be = sss_krb5_get_type(dummy);
+ if (cc_be != SSS_KRB5_TYPE_FILE || dummy[0] != '/') {
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("Currently only file based credential caches are supported "
+ "and krb5ccname_template must start with '/' or 'FILE:'\n"));
return EINVAL;
}
+ krb5_ctx->cc_be = &file_cc;
return EOK;
}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 950505f1208f164f9267aacbf49da136b3cc0073..029ebf6ed07e6ee3f6af892eb7fe2f3741ab6350 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -84,6 +84,7 @@ struct krb5_service {
struct fo_service;
struct deferred_auth_ctx;
struct renew_tgt_ctx;
+struct sss_krb5_cc_be;
struct krb5_ctx {
/* opts taken from kinit */
@@ -115,6 +116,7 @@ struct krb5_ctx {
struct krb5_service *kpasswd_service;
int child_debug_fd;
+ struct sss_krb5_cc_be *cc_be;
pcre *illegal_path_re;
struct deferred_auth_ctx *deferred_auth_ctx;
@@ -171,4 +173,5 @@ errno_t remove_krb5_info_files(TALLOC_CTX *mem_ctx, const char *realm);
errno_t krb5_get_simple_upn(TALLOC_CTX *mem_ctx, struct krb5_ctx *krb5_ctx,
const char *username, const char **_upn);
+
#endif /* __KRB5_COMMON_H__ */
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 9d199e1f5ad3f97aeed7a2d7fd5360d10d957ec3..9f02fe3328c938470d243fed5d4fff7f6f2dfda0 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -26,6 +26,7 @@
#include "providers/krb5/krb5_utils.h"
#include "providers/krb5/krb5_auth.h"
+#include "src/util/find_uid.h"
#include "util/util.h"
char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
@@ -307,38 +308,46 @@ done:
return ret;
}
-errno_t create_ccache_dir(TALLOC_CTX *mem_ctx, const char *filename,
- pcre *illegal_re, uid_t uid, gid_t gid,
- bool private_path)
+static errno_t
+check_ccache_re(const char *filename, pcre *illegal_re)
+{
+ errno_t ret;
+
+ ret = pcre_exec(illegal_re, NULL, filename, strlen(filename),
+ 0, 0, NULL, 0);
+ if (ret == 0) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Illegal pattern in ccache directory name [%s].\n", filename));
+ return EINVAL;
+ } else if (ret == PCRE_ERROR_NOMATCH) {
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("Ccache directory name [%s] does not contain "
+ "illegal patterns.\n", filename));
+ return EOK;
+ }
+
+ DEBUG(SSSDBG_CRIT_FAILURE, ("pcre_exec failed [%d].\n", ret));
+ return EFAULT;
+}
+
+static errno_t
+create_ccache_dir(const char *dirname, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path)
{
int ret = EFAULT;
- char *dirname;
- char *end;
struct stat parent_stat;
struct string_list *missing_parents = NULL;
struct string_list *li = NULL;
mode_t old_umask;
mode_t new_dir_mode;
- size_t offset = 0;
TALLOC_CTX *tmp_ctx = NULL;
- tmp_ctx = talloc_new(mem_ctx);
+ tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(1, ("talloc_new failed.\n"));
return ENOMEM;
}
- if (strncmp(filename, "FILE:", 5) == 0) {
- offset = 5;
- }
-
- dirname = talloc_strdup(tmp_ctx, filename + offset);
- if (dirname == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
if (*dirname != '/') {
DEBUG(1, ("Only absolute paths are allowed, not [%s] .\n", dirname));
ret = EINVAL;
@@ -346,31 +355,12 @@ errno_t create_ccache_dir(TALLOC_CTX *mem_ctx, const char *filename,
}
if (illegal_re != NULL) {
- ret = pcre_exec(illegal_re, NULL, dirname, strlen(dirname),
- 0, 0, NULL, 0);
- if (ret == 0) {
- DEBUG(1, ("Illegal pattern in ccache directory name [%s].\n",
- dirname));
- ret = EINVAL;
- goto done;
- } else if ( ret == PCRE_ERROR_NOMATCH) {
- DEBUG(9, ("Ccache directory name [%s] does not contain "
- "illegal patterns.\n", dirname));
- } else {
- DEBUG(1, ("pcre_exec failed [%d].\n", ret));
- ret = EFAULT;
+ ret = check_ccache_re(dirname, illegal_re);
+ if (ret != EOK) {
goto done;
}
}
- end = strrchr(dirname, '/');
- if (end == NULL || end == dirname) {
- DEBUG(1, ("Missing filename in [%s].\n", dirname));
- ret = EINVAL;
- goto done;
- }
- *end = '\0';
-
ret = find_ccdir_parent_data(tmp_ctx, dirname, &parent_stat,
&missing_parents);
if (ret != EOK) {
@@ -527,3 +517,221 @@ done:
return EOK;
}
+
+/*======== ccache back end utilities ========*/
+struct sss_krb5_cc_be *
+get_cc_be_ops(enum sss_krb5_cc_type type)
+{
+ struct sss_krb5_cc_be *be;
+
+ switch (type) {
+ case SSS_KRB5_TYPE_FILE:
+ be = &file_cc;
+ break;
+ case SSS_KRB5_TYPE_UNKNOWN:
+ be = NULL;
+ break;
+ }
+
+ return be;
+}
+
+struct sss_krb5_cc_be *
+get_cc_be_ops_ccache(const char *ccache)
+{
+ enum sss_krb5_cc_type type;
+
+ type = sss_krb5_get_type(ccache);
+ return get_cc_be_ops(type);
+}
+
+/*======== Operations on the FILE: back end ========*/
+errno_t
+cc_file_create(const char *location, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path)
+{
+ const char *filename;
+ char *dirname;
+ char *end;
+ TALLOC_CTX *tmp_ctx = NULL;
+ errno_t ret;
+
+ filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
+ if (filename == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Bad ccache type %s\n", location));
+ return EINVAL;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n"));
+ return ENOMEM;
+ }
+
+ dirname = talloc_strdup(tmp_ctx, filename);
+ if (dirname == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ end = strrchr(dirname, '/');
+ if (end == NULL || end == dirname) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Missing filename in [%s].\n", dirname));
+ ret = EINVAL;
+ goto done;
+ }
+ *end = '\0';
+
+ ret = create_ccache_dir(dirname, illegal_re, uid, gid, private_path);
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static errno_t
+cc_residual_is_used(uid_t uid, const char *ccname,
+ enum sss_krb5_cc_type type, bool *result)
+{
+ int ret;
+ struct stat stat_buf;
+ bool active;
+
+ *result = false;
+
+ if (ccname == NULL || *ccname == '\0') {
+ return EINVAL;
+ }
+
+ ret = lstat(ccname, &stat_buf);
+
+ if (ret == -1 && errno != ENOENT) {
+ ret = errno;
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("stat failed [%d][%s].\n", ret, strerror(ret)));
+ return ret;
+ } else if (ret == EOK) {
+ if (stat_buf.st_uid != uid) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Cache file [%s] exists, but is owned by [%d] instead of "
+ "[%d].\n", ccname, stat_buf.st_uid, uid));
+ return EINVAL;
+ }
+
+ switch (type) {
+ case SSS_KRB5_TYPE_FILE:
+ ret = S_ISREG(stat_buf.st_mode);
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unsupported ccache type\n"));
+ return EINVAL;
+ }
+
+ if (ret == 0) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Cache file [%s] exists, but is not the expected type\n",
+ ccname));
+ return EINVAL;
+ }
+ }
+
+ ret = check_if_uid_is_active(uid, &active);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("check_if_uid_is_active failed.\n"));
+ return ret;
+ }
+
+ if (!active) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("User [%d] is not active\n", uid));
+ } else {
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("User [%d] is still active, reusing ccache [%s].\n",
+ uid, ccname));
+ *result = true;
+ }
+ return EOK;
+}
+
+errno_t
+cc_file_check_existing(const char *location, uid_t uid,
+ const char *realm, const char *princ,
+ bool *_active, bool *_valid)
+{
+ errno_t ret;
+ bool active;
+ bool valid;
+ const char *filename;
+
+ filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
+ if (!filename) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type FILE:\n"));
+ return EINVAL;
+ }
+
+ if (filename[0] != '/') {
+ DEBUG(SSSDBG_OP_FAILURE, ("Only absolute path names are allowed.\n"));
+ return EINVAL;
+ }
+
+ ret = cc_residual_is_used(uid, filename, SSS_KRB5_TYPE_FILE, &active);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not check if ccache is active\n"));
+ return ret;
+ }
+
+ ret = check_for_valid_tgt(location, realm, princ, &valid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Could not check if ccache contains a valid principal\n"));
+ return ret;
+ }
+
+ *_active = active;
+ *_valid = valid;
+ return EOK;
+}
+
+const char *
+cc_file_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
+ const char *princ)
+{
+ return talloc_strdup(mem_ctx, location);
+}
+
+errno_t
+cc_file_remove(const char *location)
+{
+ errno_t ret;
+ const char *filename;
+
+ filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
+ if (!filename) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type FILE:\n"));
+ return EINVAL;
+ }
+
+ if (filename[0] != '/') {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Ccache file name [%s] is not an absolute path.\n", filename));
+ return EINVAL;
+ }
+
+ errno = 0;
+ ret = unlink(filename);
+ if (ret == -1 && errno != ENOENT) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("unlink [%s] failed [%d][%s].\n", filename, ret,
+ strerror(ret)));
+ return ret;
+ }
+ return EOK;
+}
+
+struct sss_krb5_cc_be file_cc = {
+ .type = SSS_KRB5_TYPE_FILE,
+ .create = cc_file_create,
+ .check_existing = cc_file_check_existing,
+ .ccache_for_princ = cc_file_cache_for_princ,
+ .remove = cc_file_remove,
+};
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index 7cc57d42f460380a97d4c7d149cbedc8e516e977..87bba2bae403b1271f45a7cea685a9bcf02207f8 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -31,16 +31,41 @@
#include "providers/krb5/krb5_auth.h"
#include "providers/data_provider.h"
+/* Operations on a credential cache */
+typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path);
+typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
+ const char *realm, const char *princ,
+ bool *active, bool *valid);
+typedef const char * (*cc_be_ccache_for_princ)(TALLOC_CTX *mem_ctx,
+ const char *location,
+ const char *princ);
+typedef errno_t (*cc_be_remove)(const char *location);
+
+/* A ccache back end */
+struct sss_krb5_cc_be {
+ enum sss_krb5_cc_type type;
+
+ cc_be_create_fn create;
+ cc_be_check_existing check_existing;
+ cc_be_ccache_for_princ ccache_for_princ;
+ cc_be_remove remove;
+};
+
+struct sss_krb5_cc_be file_cc;
+
+errno_t cc_file_create(const char *filename, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path);
+
+struct sss_krb5_cc_be *get_cc_be_ops(enum sss_krb5_cc_type type);
+struct sss_krb5_cc_be *get_cc_be_ops_ccache(const char *ccache);
+
char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
const char *template, bool file_mode,
bool case_sensitive, bool *private_path);
errno_t become_user(uid_t uid, gid_t gid);
-errno_t create_ccache_dir(TALLOC_CTX *mem_ctx, const char *filename,
- pcre *illegal_re, uid_t uid, gid_t gid,
- bool private_path);
-
errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
struct tgt_times *tgtt);
#endif /* __KRB5_UTILS_H__ */
diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
index 4dde996a00ac7490d7168bda27b391bbabcd7ae5..2ca655310aebc0cbadaa2bf2e8dd14fef706b7c6 100644
--- a/src/tests/krb5_child-test.c
+++ b/src/tests/krb5_child-test.c
@@ -39,6 +39,7 @@
#include "providers/krb5/krb5_utils.h"
extern struct dp_option default_krb5_opts[];
+extern struct sss_krb5_cc_be file_cc;
static krb5_context krb5_error_ctx;
#define KRB5_DEBUG(level, krb5_error) do { \
@@ -118,6 +119,8 @@ create_dummy_krb5_ctx(TALLOC_CTX *mem_ctx, const char *realm)
krb5_ctx = talloc_zero(mem_ctx, struct krb5_ctx);
if (!krb5_ctx) return NULL;
+ krb5_ctx->cc_be = &file_cc;
+
krb5_ctx->illegal_path_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0,
&errval, &errstr, &errpos, NULL);
if (krb5_ctx->illegal_path_re == NULL) {
@@ -250,14 +253,16 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
DEBUG(SSSDBG_FUNC_DATA, ("ccname [%s] uid [%llu] gid [%llu]\n",
kr->ccname, kr->uid, kr->gid));
- ret = create_ccache_dir(kr, kr->ccname,
- kr->krb5_ctx->illegal_path_re,
- kr->uid, kr->gid, private);
+ ret = kr->krb5_ctx->cc_be->create(kr->ccname,
+ kr->krb5_ctx->illegal_path_re,
+ kr->uid, kr->gid, private);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("create_ccache_dir failed.\n"));
- goto fail;
}
+ } else {
+ kr->ccname = talloc_strdup(kr, ccname);
}
+ if (!kr->ccname) goto fail;
return kr;
@@ -375,29 +380,6 @@ done:
return ret;
}
-static void
-remove_ccache(const char *cc)
-{
- size_t offset = 0;
- errno_t ret;
-
- if (strncmp(cc, "FILE:", 5) == 0) {
- offset = 5;
- }
- if (cc[offset] != '/') {
- DEBUG(SSSDBG_FATAL_FAILURE,
- ("ccname [%s] does not contain absolute path?\n", cc));
- }
-
- errno = 0;
- ret = unlink(cc+offset);
- if (ret == -1) {
- ret = errno;
- DEBUG(SSSDBG_FATAL_FAILURE,
- ("unlink [%s] failed [%d]: %s\n", cc, ret, strerror(ret)));
- }
-}
-
int
main(int argc, const char *argv[])
{
@@ -542,7 +524,7 @@ main(int argc, const char *argv[])
ret = 0;
done:
if (rm_ccache && ctx->res && ctx->res->ccname) {
- remove_ccache(ctx->res->ccname);
+ ctx->kr->krb5_ctx->cc_be->remove(ctx->res->ccname);
}
free(password);
talloc_free(ctx);
diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
index aacc384de2e0113fdaed861cf007b10f41b7aa6c..4a572488f0dfc3e8bae59813d646ee0791b1f428 100644
--- a/src/tests/krb5_utils-tests.c
+++ b/src/tests/krb5_utils-tests.c
@@ -117,14 +117,14 @@ START_TEST(test_pub_ccache_dir)
ret = chmod(testpath, 0754);
fail_unless(ret == EOK, "chmod failed.");
- ret = create_ccache_dir(tmp_ctx, filename, NULL, 12345, 12345, false);
- fail_unless(ret == EINVAL, "create_ccache_dir does not return EINVAL "
+ ret = cc_file_create(filename, NULL, 12345, 12345, false);
+ fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
"while x-bit is missing.");
ret = chmod(testpath, 0755);
fail_unless(ret == EOK, "chmod failed.");
- ret = create_ccache_dir(tmp_ctx, filename, NULL, 12345, 12345, false);
- fail_unless(ret == EOK, "create_ccache_dir failed.");
+ ret = cc_file_create(filename, NULL, 12345, 12345, false);
+ fail_unless(ret == EOK, "cc_file_create failed.");
check_dir(subdirname, 0, 0, 01777);
RMDIR(subdirname);
@@ -158,7 +158,7 @@ START_TEST(test_pub_ccache_dir_in_user_dir)
filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = create_ccache_dir(tmp_ctx, filename, NULL, 12345, 12345, false);
+ ret = cc_file_create(filename, NULL, 12345, 12345, false);
fail_unless(ret == EINVAL, "Creating public ccache dir in user dir "
"does not failed with EINVAL.");
@@ -193,14 +193,14 @@ START_TEST(test_priv_ccache_dir)
ret = chmod(testpath, 0754);
fail_unless(ret == EOK, "chmod failed.");
- ret = create_ccache_dir(tmp_ctx, filename, NULL, uid, gid, true);
- fail_unless(ret == EINVAL, "create_ccache_dir does not return EINVAL "
+ ret = cc_file_create(filename, NULL, uid, gid, true);
+ fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
"while x-bit is missing.");
ret = chmod(testpath, 0755);
fail_unless(ret == EOK, "chmod failed.");
- ret = create_ccache_dir(tmp_ctx, filename, NULL, uid, gid, true);
- fail_unless(ret == EOK, "create_ccache_dir failed.");
+ ret = cc_file_create(filename, NULL, uid, gid, true);
+ fail_unless(ret == EOK, "cc_file_create failed.");
check_dir(subdir, uid, gid, 0700);
RMDIR(subdir);
@@ -248,14 +248,14 @@ START_TEST(test_private_ccache_dir_in_user_dir)
ret = chmod(user_dir, 0600);
fail_unless(ret == EOK, "chmod failed.");
- ret = create_ccache_dir(tmp_ctx, filename, NULL, uid, gid, true);
- fail_unless(ret == EINVAL, "create_ccache_dir does not return EINVAL "
+ ret = cc_file_create(filename, NULL, uid, gid, true);
+ fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
"while x-bit is missing.");
ret = chmod(user_dir, 0700);
fail_unless(ret == EOK, "chmod failed.");
- ret = create_ccache_dir(tmp_ctx, filename, NULL, uid, gid, true);
- fail_unless(ret == EOK, "create_ccache_dir failed.");
+ ret = cc_file_create(filename, NULL, uid, gid, true);
+ fail_unless(ret == EOK, "cc_file_create failed.");
check_dir(dn3, uid, gid, 0700);
RMDIR(dn3);
@@ -292,7 +292,7 @@ START_TEST(test_private_ccache_dir_in_wrong_user_dir)
filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = create_ccache_dir(tmp_ctx, filename, NULL, 12345, 12345, true);
+ ret = cc_file_create(filename, NULL, 12345, 12345, true);
fail_unless(ret == EINVAL, "Creating private ccache dir in wrong user "
"dir does not failed with EINVAL.");
@@ -329,28 +329,28 @@ START_TEST(test_illegal_patterns)
filename = talloc_asprintf(tmp_ctx, "abc/./ccfile");
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = create_ccache_dir(tmp_ctx, filename, illegal_re, uid, gid, true);
- fail_unless(ret == EINVAL, "create_ccache_dir allowed relative path [%s].",
+ ret = cc_file_create(filename, illegal_re, uid, gid, true);
+ fail_unless(ret == EINVAL, "cc_file_create allowed relative path [%s].",
filename);
filename = talloc_asprintf(tmp_ctx, "%s/abc/./ccfile", dirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = create_ccache_dir(tmp_ctx, filename, illegal_re, uid, gid, true);
- fail_unless(ret == EINVAL, "create_ccache_dir allowed "
+ ret = cc_file_create(filename, illegal_re, uid, gid, true);
+ fail_unless(ret == EINVAL, "cc_file_create allowed "
"illegal pattern '/./' in filename [%s].",
filename);
filename = talloc_asprintf(tmp_ctx, "%s/abc/../ccfile", dirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = create_ccache_dir(tmp_ctx, filename, illegal_re, uid, gid, true);
- fail_unless(ret == EINVAL, "create_ccache_dir allowed "
+ ret = cc_file_create(filename, illegal_re, uid, gid, true);
+ fail_unless(ret == EINVAL, "cc_file_create allowed "
"illegal pattern '/../' in filename [%s].",
filename);
filename = talloc_asprintf(tmp_ctx, "%s/abc//ccfile", dirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = create_ccache_dir(tmp_ctx, filename, illegal_re, uid, gid, true);
- fail_unless(ret == EINVAL, "create_ccache_dir allowed "
+ ret = cc_file_create(filename, illegal_re, uid, gid, true);
+ fail_unless(ret == EINVAL, "cc_file_create allowed "
"illegal pattern '//' in filename [%s].",
filename);
--
1.7.10.2
-------------- next part --------------
>From 2759fa46973fadf5b9262e47e0a6c6dd1c91dfa0 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Tue, 5 Jun 2012 23:41:12 +0200
Subject: [PATCH 09/12] Add support for storing credential caches in the DIR:
back end
https://fedorahosted.org/sssd/ticket/974
---
src/man/sssd-krb5.5.xml | 10 +-
src/providers/krb5/krb5_child.c | 230 ++++++++++++++++++++++++----
src/providers/krb5/krb5_common.c | 34 ++++-
src/providers/krb5/krb5_opts.h | 4 +-
src/providers/krb5/krb5_utils.c | 307 ++++++++++++++++++++++++++++++++++----
src/providers/krb5/krb5_utils.h | 4 +
src/tests/krb5_child-test.c | 46 ++++--
src/tests/krb5_utils-tests.c | 66 +++++++-
src/util/sss_krb5.c | 21 +--
src/util/sss_krb5.h | 3 +-
10 files changed, 613 insertions(+), 112 deletions(-)
diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml
index 247337a90a80b078d0395b27a02e5ea2c72a5ce8..1baee36e9b0ade76de2990fd4f06bc655b5ce06c 100644
--- a/src/man/sssd-krb5.5.xml
+++ b/src/man/sssd-krb5.5.xml
@@ -157,10 +157,12 @@
<term>krb5_ccname_template (string)</term>
<listitem>
<para>
- Location of the user's credential cache. Currently
- only file based credential caches are supported. In
- the template the following sequences are
- substituted:
+ Location of the user's credential cache. Two credential
+ cache types are currently supported - <quote>FILE</quote>
+ and <quote>DIR</quote>. The cache can either be specified
+ as <replaceable>TYPE:RESIDUAL</replaceable>, or an absolute
+ path, which implies the <quote>FILE</quote> type. In the
+ template the following sequences are substituted:
<variablelist>
<varlistentry>
<term>%u</term>
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 195c431af3e933e093e36df7a43cc667c52e94fb..6b8722a8a159644e1e601cdc5cb21e3f06f9e1b3 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -221,6 +221,51 @@ done:
return kerr;
}
+static krb5_error_code
+store_creds_in_ccache(krb5_context ctx, krb5_principal princ,
+ krb5_ccache cc, krb5_creds *creds)
+{
+ krb5_error_code kerr;
+ krb5_creds *l_cred;
+
+ kerr = krb5_cc_initialize(ctx, cc, princ);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+
+ if (creds == NULL) {
+ kerr = create_empty_cred(ctx, princ, &l_cred);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+ } else {
+ l_cred = creds;
+ }
+
+ kerr = krb5_cc_store_cred(ctx, cc, l_cred);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+
+ kerr = krb5_cc_switch(ctx, cc);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+
+ kerr = krb5_cc_close(ctx, cc);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+
+done:
+ return kerr;
+}
+
static krb5_error_code create_ccache_file(krb5_context ctx,
krb5_principal princ,
char *ccname, krb5_creds *creds)
@@ -232,7 +277,6 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
size_t ccname_len;
char *dummy;
char *tmp_ccname;
- krb5_creds *l_cred;
TALLOC_CTX *tmp_ctx = NULL;
mode_t old_umask;
@@ -285,38 +329,16 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
goto done;
}
- kerr = krb5_cc_initialize(ctx, tmp_cc, princ);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
+ kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
if (fd != -1) {
close(fd);
fd = -1;
}
-
- if (creds == NULL) {
- kerr = create_empty_cred(ctx, princ, &l_cred);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
- } else {
- l_cred = creds;
- }
-
- kerr = krb5_cc_store_cred(ctx, tmp_cc, l_cred);
if (kerr != 0) {
KRB5_DEBUG(1, kerr);
goto done;
}
- kerr = krb5_cc_close(ctx, tmp_cc);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
- tmp_cc = NULL;
ccname_len = strlen(cc_file_name);
if (ccname_len >= 6 && strcmp(cc_file_name + (ccname_len-6), "XXXXXX")==0 ) {
@@ -338,18 +360,163 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
DEBUG(SSSDBG_TRACE_LIBS, ("Created ccache file: [%s]\n", ccname));
done:
+ if (kerr != 0 && tmp_cc != NULL) {
+ krb5_cc_destroy(ctx, tmp_cc);
+ }
+
if (fd != -1) {
close(fd);
}
- if (kerr != 0 && tmp_cc != NULL) {
- krb5_cc_destroy(ctx, tmp_cc);
- }
talloc_free(tmp_ctx);
+ return kerr;
+}
+
+static errno_t
+create_ccdir(const char *dirname, uid_t uid, gid_t gid)
+{
+ mode_t old_umask;
+ struct stat statbuf;
+ errno_t ret;
+
+ old_umask = umask(0000);
+ ret = mkdir(dirname, 0700);
+ umask(old_umask);
+ if (ret == -1) {
+ /* Failing the mkdir is only OK if the directory already
+ * exists AND it is owned by the same user and group and
+ * has the correct permissions.
+ */
+ ret = errno;
+ if (ret == EEXIST) {
+ errno = 0;
+ ret = stat(dirname, &statbuf);
+ if (ret == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("stat failed [%d]: %s\n", ret, strerror(ret)));
+ return EIO;
+ }
+
+ if (statbuf.st_uid != uid || statbuf.st_gid != gid) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("The directory %s is owned by %d/%d, expected %d/%d\n",
+ dirname, statbuf.st_uid, statbuf.st_gid, uid, gid));
+ return EACCES;
+ }
+
+ if ((statbuf.st_mode & ~S_IFMT) != 0700) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("The directory %s has wrong permissions %o, expected 0700\n",
+ dirname, (statbuf.st_mode & ~S_IFMT)));
+ return EACCES;
+ }
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("mkdir [%s] failed [%d]: %s\n",
+ dirname, ret, strerror(ret)));
+ return ret;
+ }
+ }
+
+ return EOK;
+}
+
+static krb5_error_code
+create_ccache_in_dir(uid_t uid, gid_t gid,
+ krb5_context ctx,
+ krb5_principal princ,
+ char *ccname, krb5_creds *creds)
+{
+ krb5_error_code kerr;
+ krb5_ccache tmp_cc = NULL;
+ const char *dirname;
+
+ DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
+
+ dirname = sss_krb5_residual_check_type(ccname, SSS_KRB5_TYPE_DIR);
+ if (dirname == NULL) {
+ return EIO;
+ }
+ kerr = become_user(uid, gid);
+ if (kerr != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("become_user failed.\n"));
+ goto done;
+ }
+
+ if (dirname[0] == ':') {
+ /* Cache name in the form of DIR::filepath represents a single
+ * ccache in a collection that we are trying to reuse.
+ * See src/lib/krb5/ccache/cc_dir.c in the MIT Kerberos tree.
+ */
+ kerr = krb5_cc_resolve(ctx, ccname, &tmp_cc);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+ } else if (dirname[0] == '/') {
+ /* An absolute path denotes that krb5_child should create a new
+ * ccache. We can afford to just call mkdir(dirname) because we
+ * only want the last component to be created.
+ */
+
+ kerr = create_ccdir(dirname, uid, gid);
+ if (kerr) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Cannot create directory %s\n", dirname));
+ goto done;
+ }
+
+ kerr = krb5_cc_set_default_name(ctx, ccname);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+
+ kerr = krb5_cc_new_unique(ctx, "DIR", NULL, &tmp_cc);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Wrong residual format for DIR in ccache %s\n", ccname));
+ return EIO;
+ }
+
+ kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
+ if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ goto done;
+ }
+
+done:
+ if (kerr != 0 && tmp_cc != NULL) {
+ krb5_cc_destroy(ctx, tmp_cc);
+ }
return kerr;
}
+static krb5_error_code
+create_ccache(uid_t uid, gid_t gid, krb5_context ctx,
+ krb5_principal princ, char *ccname, krb5_creds *creds)
+{
+ enum sss_krb5_cc_type cctype;
+
+ cctype = sss_krb5_get_type(ccname);
+ switch (cctype) {
+ case SSS_KRB5_TYPE_FILE:
+ return create_ccache_file(ctx, princ, ccname, creds);
+ case SSS_KRB5_TYPE_DIR:
+ return create_ccache_in_dir(uid, gid, ctx, princ, ccname, creds);
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unknown cache type\n"));
+ return EINVAL;
+ }
+
+ return EINVAL; /* Should never get here */
+}
+
static errno_t pack_response_packet(struct response *resp, int status,
struct pam_data *pd)
{
@@ -729,9 +896,9 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
}
/* Use the updated principal in the creds in case canonicalized */
- kerr = create_ccache_file(kr->ctx,
- kr->creds ? kr->creds->client : kr->princ,
- kr->ccname, kr->creds);
+ kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
+ kr->creds ? kr->creds->client : kr->princ,
+ kr->ccname, kr->creds);
if (kerr != 0) {
KRB5_DEBUG(1, kerr);
goto done;
@@ -1142,7 +1309,8 @@ static errno_t create_empty_ccache(int fd, struct krb5_req *kr)
DEBUG(SSSDBG_TRACE_LIBS, ("Creating empty ccache\n"));
- ret = create_ccache_file(kr->ctx, kr->princ, kr->ccname, NULL);
+ ret = create_ccache(kr->uid, kr->gid, kr->ctx,
+ kr->princ, kr->ccname, NULL);
if (ret != 0) {
KRB5_DEBUG(1, ret);
pam_status = PAM_SYSTEM_ERR;
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index 91816662b8a694fbf31933eae05db2793e3a9dbc..f4033d29597661d1a9b4ff66e0ee02b4bf649f21 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -182,13 +182,37 @@ errno_t check_and_export_options(struct dp_option *opts,
}
cc_be = sss_krb5_get_type(dummy);
- if (cc_be != SSS_KRB5_TYPE_FILE || dummy[0] != '/') {
- DEBUG(SSSDBG_CONF_SETTINGS,
- ("Currently only file based credential caches are supported "
- "and krb5ccname_template must start with '/' or 'FILE:'\n"));
+ switch (cc_be) {
+ case SSS_KRB5_TYPE_FILE:
+ DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type FILE\n"));
+ krb5_ctx->cc_be = &file_cc;
+ if (dummy[0] != '/') {
+ /* FILE:/path/to/cc */
+ break;
+ }
+
+ DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was "
+ "missing an explicit type, but is an absolute "
+ "path specifier. Assuming FILE:\n"));
+
+ dummy = talloc_asprintf(opts, "FILE:%s", dummy);
+ if (!dummy) return ENOMEM;
+
+ ret = dp_opt_set_string(opts, KRB5_CCNAME_TMPL, dummy);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n"));
+ return ret;
+ }
+ break;
+ case SSS_KRB5_TYPE_DIR:
+ DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type DIR\n"));
+ krb5_ctx->cc_be = &dir_cc;
+ break;
+ default:
+ DEBUG(SSSDBG_OP_FAILURE, ("Unkown ccname database\n"));
return EINVAL;
+ break;
}
- krb5_ctx->cc_be = &file_cc;
return EOK;
}
diff --git a/src/providers/krb5/krb5_opts.h b/src/providers/krb5/krb5_opts.h
index 7f47290c961ce6455e0d123e9ec14c7add39d28d..45dfec544f6d5261df313649658a1432f763ce5b 100644
--- a/src/providers/krb5/krb5_opts.h
+++ b/src/providers/krb5/krb5_opts.h
@@ -28,8 +28,8 @@
struct dp_option default_krb5_opts[] = {
{ "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "krb5_ccachedir", DP_OPT_STRING, { "/tmp" }, NULL_STRING },
- { "krb5_ccname_template", DP_OPT_STRING, { "FILE:%d/krb5cc_%U_XXXXXX" }, NULL_STRING},
+ { "krb5_ccachedir", DP_OPT_STRING, { "/run/user/%u" }, NULL_STRING },
+ { "krb5_ccname_template", DP_OPT_STRING, { "DIR:%d" }, NULL_STRING},
{ "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER },
{ "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
{ "krb5_validate", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 9f02fe3328c938470d243fed5d4fff7f6f2dfda0..35ece8117f20ac015771b4a0b6877ca068de7153 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -23,6 +23,7 @@
*/
#include <string.h>
#include <stdlib.h>
+#include <libgen.h>
#include "providers/krb5/krb5_utils.h"
#include "providers/krb5/krb5_auth.h"
@@ -330,7 +331,7 @@ check_ccache_re(const char *filename, pcre *illegal_re)
return EFAULT;
}
-static errno_t
+errno_t
create_ccache_dir(const char *dirname, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path)
{
@@ -518,6 +519,42 @@ done:
return EOK;
}
+static errno_t
+create_ccache_dir_head(const char *parent, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path)
+{
+ char *dirname;
+ TALLOC_CTX *tmp_ctx = NULL;
+ char *end;
+ errno_t ret;
+
+ dirname = talloc_strdup(tmp_ctx, parent);
+ if (dirname == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* We'll remove all trailing slashes from the back so that
+ * we only pass /some/path to find_ccdir_parent_data, not
+ * /some/path/ */
+ do {
+ end = strrchr(dirname, '/');
+ if (end == NULL || end == dirname) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot find parent directory of [%s], "
+ "/ is not allowed.\n", dirname));
+ ret = EINVAL;
+ goto done;
+ }
+ *end = '\0';
+ } while (*(end+1) == '\0');
+
+ ret = create_ccache_dir(dirname, illegal_re, uid, gid, private_path);
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
/*======== ccache back end utilities ========*/
struct sss_krb5_cc_be *
get_cc_be_ops(enum sss_krb5_cc_type type)
@@ -528,6 +565,9 @@ get_cc_be_ops(enum sss_krb5_cc_type type)
case SSS_KRB5_TYPE_FILE:
be = &file_cc;
break;
+ case SSS_KRB5_TYPE_DIR:
+ be = &dir_cc;
+ break;
case SSS_KRB5_TYPE_UNKNOWN:
be = NULL;
break;
@@ -551,10 +591,6 @@ cc_file_create(const char *location, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path)
{
const char *filename;
- char *dirname;
- char *end;
- TALLOC_CTX *tmp_ctx = NULL;
- errno_t ret;
filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
if (filename == NULL) {
@@ -562,31 +598,7 @@ cc_file_create(const char *location, pcre *illegal_re,
return EINVAL;
}
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- dirname = talloc_strdup(tmp_ctx, filename);
- if (dirname == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- end = strrchr(dirname, '/');
- if (end == NULL || end == dirname) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Missing filename in [%s].\n", dirname));
- ret = EINVAL;
- goto done;
- }
- *end = '\0';
-
- ret = create_ccache_dir(dirname, illegal_re, uid, gid, private_path);
-done:
- talloc_free(tmp_ctx);
- return ret;
+ return create_ccache_dir_head(filename, illegal_re, uid, gid, private_path);
}
static errno_t
@@ -619,6 +631,9 @@ cc_residual_is_used(uid_t uid, const char *ccname,
}
switch (type) {
+ case SSS_KRB5_TYPE_DIR:
+ ret = S_ISDIR(stat_buf.st_mode);
+ break;
case SSS_KRB5_TYPE_FILE:
ret = S_ISREG(stat_buf.st_mode);
break;
@@ -661,6 +676,9 @@ cc_file_check_existing(const char *location, uid_t uid,
bool active;
bool valid;
const char *filename;
+ krb5_ccache ccache = NULL;
+ krb5_context context = NULL;
+ krb5_error_code kerr;
filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
if (!filename) {
@@ -679,11 +697,26 @@ cc_file_check_existing(const char *location, uid_t uid,
return ret;
}
- ret = check_for_valid_tgt(location, realm, princ, &valid);
- if (ret != EOK) {
+ kerr = krb5_init_context(&context);
+ if (kerr != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to init kerberos context\n"));
+ return EIO;
+ }
+
+ kerr = krb5_cc_resolve(context, location, &ccache);
+ if (kerr != 0) {
+ krb5_free_context(context);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
+ return EIO;
+ }
+
+ kerr = check_for_valid_tgt(context, ccache, realm, princ, &valid);
+ krb5_free_context(context);
+ krb5_cc_close(context, ccache);
+ if (kerr != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
("Could not check if ccache contains a valid principal\n"));
- return ret;
+ return EIO;
}
*_active = active;
@@ -735,3 +768,211 @@ struct sss_krb5_cc_be file_cc = {
.ccache_for_princ = cc_file_cache_for_princ,
.remove = cc_file_remove,
};
+
+/*======== Operations on the DIR: back end ========*/
+errno_t
+cc_dir_create(const char *location, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path)
+{
+ const char *dirname;
+
+ dirname = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_DIR);
+ if (dirname == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Bad residual type\n"));
+ return EINVAL;
+ }
+
+ return create_ccache_dir_head(dirname, illegal_re, uid, gid, private_path);
+}
+
+static krb5_error_code
+get_ccache_for_princ(krb5_context context, const char *location,
+ const char *princ, krb5_ccache *_ccache)
+{
+ krb5_error_code krberr;
+ krb5_principal client_principal = NULL;
+
+ krberr = krb5_cc_set_default_name(context, location);
+ if (krberr != 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("krb5_cc_resolve failed.\n"));
+ return krberr;
+ }
+
+ krberr = krb5_parse_name(context, princ, &client_principal);
+ if (krberr != 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("krb5_parse_name failed.\n"));
+ return krberr;
+ }
+
+ krberr = krb5_cc_cache_match(context, client_principal, _ccache);
+ krb5_free_principal(context, client_principal);
+ return krberr;
+}
+
+errno_t
+cc_dir_check_existing(const char *location, uid_t uid,
+ const char *realm, const char *princ,
+ bool *_active, bool *_valid)
+{
+ bool active = false;
+ bool valid = false;
+ krb5_ccache ccache = NULL;
+ krb5_context context = NULL;
+ krb5_error_code krberr;
+ enum sss_krb5_cc_type type;
+ const char *filename;
+ const char *dir;
+ char *tmp;
+ errno_t ret;
+
+ type = sss_krb5_get_type(location);
+ if (type != SSS_KRB5_TYPE_DIR) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type DIR:\n", location));
+ return EINVAL;
+ }
+
+ filename = sss_krb5_cc_file_path(location);
+ if (!filename) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Existing ccname does not contain path into the collection"));
+ return EINVAL;
+ }
+
+ if (filename[0] != '/') {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Only absolute path names are allowed.\n"));
+ return EINVAL;
+ }
+
+ tmp = talloc_strdup(NULL, filename);
+ if (!tmp) return ENOMEM;
+
+ dir = dirname(tmp);
+ if (!dir) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Cannot base get directory of %s\n", location));
+ return EINVAL;
+ }
+
+ ret = cc_residual_is_used(uid, dir, SSS_KRB5_TYPE_DIR, &active);
+ talloc_free(tmp);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not check if ccache is active\n"));
+ return ret;
+ }
+
+ krberr = krb5_init_context(&context);
+ if (krberr) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to init kerberos context\n"));
+ return EIO;
+ }
+
+ krberr = krb5_cc_resolve(context, location, &ccache);
+ if (krberr == KRB5_FCC_NOFILE || ccache == NULL) {
+ /* KRB5_FCC_NOFILE would be returned if the directory components
+ * of the DIR cache do not exist, which is the case in /run
+ * after a reboot
+ */
+ DEBUG(SSSDBG_TRACE_FUNC,
+ ("ccache %s is missing or empty\n", location));
+ valid = false;
+ ret = EOK;
+ goto done;
+ } else if (krberr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
+ ret = EIO;
+ goto done;
+ }
+
+ krberr = check_for_valid_tgt(context, ccache, realm, princ, &valid);
+ if (krberr != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Could not check if ccache contains a valid principal\n"));
+ ret = EIO;
+ goto done;
+ }
+
+ ret = EOK;
+done:
+ if (ccache) krb5_cc_close(context, ccache);
+ krb5_free_context(context);
+ *_active = active;
+ *_valid = valid;
+ return ret;
+}
+
+const char *
+cc_dir_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
+ const char *princ)
+{
+ krb5_context context = NULL;
+ krb5_error_code krberr;
+ krb5_ccache ccache = NULL;
+ char *name;
+ const char *ccname;
+
+ ccname = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_DIR);
+ if (!ccname) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get ccname file from %s\n",
+ location));
+ return NULL;
+ }
+
+ /* ccname already points to a subsidiary cache */
+ if (ccname[0] == ':' && ccname[1] && ccname[1] == '/') {
+ return talloc_strdup(mem_ctx, location);
+ }
+
+ krberr = krb5_init_context(&context);
+ if (krberr) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to init kerberos context\n"));
+ return NULL;
+ }
+
+ krberr = get_ccache_for_princ(context, location, princ, &ccache);
+ if (krberr) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("No principal for %s in %s\n",
+ princ, location));
+ krb5_free_context(context);
+ return NULL;
+ }
+
+ krberr = krb5_cc_get_full_name(context, ccache, &name);
+ if (ccache) krb5_cc_close(context, ccache);
+ krb5_free_context(context);
+ if (krberr) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Could not get full name of ccache\n"));
+ return NULL;
+ }
+
+ return talloc_strdup(mem_ctx, name);
+}
+
+errno_t
+cc_dir_remove(const char *location)
+{
+ const char *subsidiary;
+
+ if (sss_krb5_get_type(location) != SSS_KRB5_TYPE_DIR) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type DIR\n", location));
+ return EINVAL;
+ }
+
+ subsidiary = sss_krb5_cc_file_path(location);
+ if (!subsidiary) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get subsidiary cache from %s\n",
+ location));
+ return EINVAL;
+ }
+
+ return cc_file_remove(subsidiary);
+}
+
+struct sss_krb5_cc_be dir_cc = {
+ .type = SSS_KRB5_TYPE_DIR,
+ .create = cc_dir_create,
+ .check_existing = cc_dir_check_existing,
+ .ccache_for_princ = cc_dir_cache_for_princ,
+ .remove = cc_dir_remove
+};
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index 87bba2bae403b1271f45a7cea685a9bcf02207f8..684c520151831eb7fbe619a1b14be38a6092e56a 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -53,10 +53,14 @@ struct sss_krb5_cc_be {
};
struct sss_krb5_cc_be file_cc;
+struct sss_krb5_cc_be dir_cc;
errno_t cc_file_create(const char *filename, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path);
+errno_t cc_dir_create(const char *location, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path);
+
struct sss_krb5_cc_be *get_cc_be_ops(enum sss_krb5_cc_type type);
struct sss_krb5_cc_be *get_cc_be_ops_ccache(const char *ccache);
diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
index 2ca655310aebc0cbadaa2bf2e8dd14fef706b7c6..015bd39aef480cb3f52b0d453ee094818ffcbcbb 100644
--- a/src/tests/krb5_child-test.c
+++ b/src/tests/krb5_child-test.c
@@ -40,6 +40,7 @@
extern struct dp_option default_krb5_opts[];
extern struct sss_krb5_cc_be file_cc;
+extern struct sss_krb5_cc_be dir_cc;
static krb5_context krb5_error_ctx;
#define KRB5_DEBUG(level, krb5_error) do { \
@@ -119,8 +120,6 @@ create_dummy_krb5_ctx(TALLOC_CTX *mem_ctx, const char *realm)
krb5_ctx = talloc_zero(mem_ctx, struct krb5_ctx);
if (!krb5_ctx) return NULL;
- krb5_ctx->cc_be = &file_cc;
-
krb5_ctx->illegal_path_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0,
&errval, &errstr, &errpos, NULL);
if (krb5_ctx->illegal_path_re == NULL) {
@@ -202,10 +201,12 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
const char *ccname, const char *ccname_template,
int timeout)
{
+ enum sss_krb5_cc_type cc_be;
struct krb5child_req *kr;
struct passwd *pwd;
bool private;
errno_t ret;
+ const char *tmpl;
/* The top level child request */
kr = talloc_zero(mem_ctx, struct krb5child_req);
@@ -237,6 +238,9 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL,
ccname_template);
if (ret != EOK) goto fail;
+ tmpl = ccname_template;
+ } else {
+ tmpl = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL);
}
if (timeout) {
@@ -252,18 +256,42 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
DEBUG(SSSDBG_FUNC_DATA, ("ccname [%s] uid [%llu] gid [%llu]\n",
kr->ccname, kr->uid, kr->gid));
-
- ret = kr->krb5_ctx->cc_be->create(kr->ccname,
- kr->krb5_ctx->illegal_path_re,
- kr->uid, kr->gid, private);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("create_ccache_dir failed.\n"));
- }
} else {
kr->ccname = talloc_strdup(kr, ccname);
}
if (!kr->ccname) goto fail;
+ cc_be = sss_krb5_get_type(kr->ccname);
+ switch (cc_be) {
+ case SSS_KRB5_TYPE_FILE:
+ kr->krb5_ctx->cc_be = &file_cc;
+ break;
+ case SSS_KRB5_TYPE_DIR:
+ kr->krb5_ctx->cc_be = &dir_cc;
+ break;
+ default:
+ if (tmpl[0] != '/') {
+ DEBUG(SSSDBG_OP_FAILURE, ("Unkown ccname database\n"));
+ ret = EINVAL;
+ goto fail;
+ }
+ DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was "
+ "missing an explicit type, but looks like an absolute "
+ "path specifier. Assuming FILE:\n"));
+ kr->krb5_ctx->cc_be = &file_cc;
+ break;
+ }
+ DEBUG(SSSDBG_FUNC_DATA, ("ccname [%s] uid [%llu] gid [%llu]\n",
+ kr->ccname, kr->uid, kr->gid));
+
+ ret = kr->krb5_ctx->cc_be->create(kr->ccname,
+ kr->krb5_ctx->illegal_path_re,
+ kr->uid, kr->gid, private);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("create_ccache_dir failed.\n"));
+ goto fail;
+ }
+
return kr;
fail:
diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
index 4a572488f0dfc3e8bae59813d646ee0791b1f428..bcd9acb193ec9ba5187f9775002adc7bbe970c23 100644
--- a/src/tests/krb5_utils-tests.c
+++ b/src/tests/krb5_utils-tests.c
@@ -329,34 +329,83 @@ START_TEST(test_illegal_patterns)
filename = talloc_asprintf(tmp_ctx, "abc/./ccfile");
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = cc_file_create(filename, illegal_re, uid, gid, true);
- fail_unless(ret == EINVAL, "cc_file_create allowed relative path [%s].",
+ ret = create_ccache_dir(filename, illegal_re, uid, gid, true);
+ fail_unless(ret == EINVAL, "create_ccache_dir allowed relative path [%s].",
filename);
filename = talloc_asprintf(tmp_ctx, "%s/abc/./ccfile", dirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = cc_file_create(filename, illegal_re, uid, gid, true);
- fail_unless(ret == EINVAL, "cc_file_create allowed "
+ ret = create_ccache_dir(filename, illegal_re, uid, gid, true);
+ fail_unless(ret == EINVAL, "create_ccache_dir allowed "
"illegal pattern '/./' in filename [%s].",
filename);
filename = talloc_asprintf(tmp_ctx, "%s/abc/../ccfile", dirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = cc_file_create(filename, illegal_re, uid, gid, true);
- fail_unless(ret == EINVAL, "cc_file_create allowed "
+ ret = create_ccache_dir(filename, illegal_re, uid, gid, true);
+ fail_unless(ret == EINVAL, "create_ccache_dir allowed "
"illegal pattern '/../' in filename [%s].",
filename);
filename = talloc_asprintf(tmp_ctx, "%s/abc//ccfile", dirname);
fail_unless(filename != NULL, "talloc_asprintf failed.");
- ret = cc_file_create(filename, illegal_re, uid, gid, true);
- fail_unless(ret == EINVAL, "cc_file_create allowed "
+ ret = create_ccache_dir(filename, illegal_re, uid, gid, true);
+ fail_unless(ret == EINVAL, "create_ccache_dir allowed "
"illegal pattern '//' in filename [%s].",
filename);
}
END_TEST
+START_TEST(test_cc_dir_create)
+{
+ char *residual;
+ char *dirname;
+ char *cwd;
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+ pcre *illegal_re;
+ errno_t ret;
+ const char *errstr;
+ int errval;
+ int errpos;
+
+ illegal_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0,
+ &errval, &errstr, &errpos, NULL);
+ fail_unless(illegal_re != NULL, "Invalid Regular Expression pattern at "
+ " position %d. (Error: %d [%s])\n",
+ errpos, errval, errstr);
+
+ cwd = getcwd(NULL, 0);
+ fail_unless(cwd != NULL, "getcwd failed.");
+
+ dirname = talloc_asprintf(tmp_ctx, "%s/%s/user_dir",
+ cwd, TESTS_PATH);
+ fail_unless(dirname != NULL, "talloc_asprintf failed.");
+ residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir");
+ fail_unless(residual != NULL, "talloc_asprintf failed.");
+
+ ret = cc_dir_create(residual, illegal_re, uid, gid, true);
+ fail_unless(ret == EOK, "cc_dir_create failed\n");
+ ret = rmdir(dirname);
+ fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
+ talloc_free(residual);
+
+ dirname = talloc_asprintf(tmp_ctx, "%s/%s/user_dir2",
+ cwd, TESTS_PATH);
+ fail_unless(dirname != NULL, "talloc_asprintf failed.");
+ residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir/");
+ fail_unless(residual != NULL, "talloc_asprintf failed.");
+
+ ret = cc_dir_create(residual, illegal_re, uid, gid, true);
+ fail_unless(ret == EOK, "cc_dir_create failed\n");
+ ret = rmdir(dirname);
+ fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
+ talloc_free(residual);
+ free(cwd);
+}
+END_TEST
+
void setup_talloc_context(void)
{
int ret;
@@ -645,6 +694,7 @@ Suite *krb5_utils_suite (void)
tcase_add_checked_fixture (tc_create_dir, setup_create_dir,
teardown_create_dir);
tcase_add_test (tc_create_dir, test_illegal_patterns);
+ tcase_add_test (tc_create_dir, test_cc_dir_create);
if (getuid() == 0) {
tcase_add_test (tc_create_dir, test_priv_ccache_dir);
tcase_add_test (tc_create_dir, test_private_ccache_dir_in_user_dir);
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index 5bc1140d0778882aa001a4a4504ddca42a63a4f8..8a6bfe2dc471e346b94069b2f7c04a671b8f4d37 100644
--- a/src/util/sss_krb5.c
+++ b/src/util/sss_krb5.c
@@ -604,11 +604,10 @@ void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name)
}
-krb5_error_code check_for_valid_tgt(const char *ccname, const char *realm,
+krb5_error_code check_for_valid_tgt(krb5_context context,
+ krb5_ccache ccache, const char *realm,
const char *client_princ_str, bool *result)
{
- krb5_context context = NULL;
- krb5_ccache ccache = NULL;
krb5_error_code krberr;
TALLOC_CTX *tmp_ctx = NULL;
krb5_creds mcred;
@@ -625,18 +624,6 @@ krb5_error_code check_for_valid_tgt(const char *ccname, const char *realm,
return ENOMEM;
}
- krberr = krb5_init_context(&context);
- if (krberr) {
- DEBUG(1, ("Failed to init kerberos context\n"));
- goto done;
- }
-
- krberr = krb5_cc_resolve(context, ccname, &ccache);
- if (krberr != 0) {
- DEBUG(1, ("krb5_cc_resolve failed.\n"));
- goto done;
- }
-
server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
if (server_name == NULL) {
DEBUG(1, ("talloc_asprintf failed.\n"));
@@ -685,10 +672,6 @@ done:
if (server_principal != NULL) {
krb5_free_principal(context, server_principal);
}
- if (ccache != NULL) {
- krb5_cc_close(context, ccache);
- }
- if (context != NULL) krb5_free_context(context);
talloc_free(tmp_ctx);
return krberr;
}
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index bba2a7eda38b2da9fa3d875b327026de7cbe50cf..89ec00021f09333e94b6fbf1b0bcc1394f9523df 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -55,7 +55,8 @@ void KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name);
-krb5_error_code check_for_valid_tgt(const char *ccname, const char *realm,
+krb5_error_code check_for_valid_tgt(krb5_context context,
+ krb5_ccache ccache, const char *realm,
const char *client_princ_str, bool *result);
int sss_krb5_verify_keytab(const char *principal,
--
1.7.10.2
-------------- next part --------------
>From 60815409c642663621cfbf60665ba0e4ac0741a2 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Mon, 11 Jun 2012 14:35:35 +0200
Subject: [PATCH 10/12] Use Kerberos context in KRB5_DEBUG
Passing Kerberos context to sss_krb5_get_error_message will allow us to
get better error messages.
---
src/providers/krb5/krb5_child.c | 85 ++++++++++++++++++---------------------
src/providers/krb5/krb5_utils.c | 31 +++++++++-----
src/tests/krb5_child-test.c | 14 ++-----
src/util/sss_krb5.h | 8 ++++
4 files changed, 73 insertions(+), 65 deletions(-)
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 6b8722a8a159644e1e601cdc5cb21e3f06f9e1b3..bfec956b672045e7be98c4c002f5889c7817130d 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -99,13 +99,7 @@ struct krb5_req {
};
static krb5_context krb5_error_ctx;
-static const char *__krb5_error_msg;
-#define KRB5_DEBUG(level, krb5_error) do { \
- __krb5_error_msg = sss_krb5_get_error_message(krb5_error_ctx, krb5_error); \
- DEBUG(level, ("%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg)); \
- sss_log(SSS_LOG_ERR, "%s", __krb5_error_msg); \
- sss_krb5_free_error_message(krb5_error_ctx, __krb5_error_msg); \
-} while(0)
+#define KRB5_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error)
static void sss_krb5_expire_callback_func(krb5_context context, void *data,
krb5_timestamp password_expiration,
@@ -230,14 +224,14 @@ store_creds_in_ccache(krb5_context ctx, krb5_principal princ,
kerr = krb5_cc_initialize(ctx, cc, princ);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
if (creds == NULL) {
kerr = create_empty_cred(ctx, princ, &l_cred);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
} else {
@@ -246,19 +240,19 @@ store_creds_in_ccache(krb5_context ctx, krb5_principal princ,
kerr = krb5_cc_store_cred(ctx, cc, l_cred);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
kerr = krb5_cc_switch(ctx, cc);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
kerr = krb5_cc_close(ctx, cc);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
@@ -325,7 +319,7 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
kerr = krb5_cc_resolve(ctx, tmp_ccname, &tmp_cc);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
@@ -335,7 +329,7 @@ static krb5_error_code create_ccache_file(krb5_context ctx,
fd = -1;
}
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
@@ -451,7 +445,7 @@ create_ccache_in_dir(uid_t uid, gid_t gid,
*/
kerr = krb5_cc_resolve(ctx, ccname, &tmp_cc);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
} else if (dirname[0] == '/') {
@@ -469,13 +463,13 @@ create_ccache_in_dir(uid_t uid, gid_t gid,
kerr = krb5_cc_set_default_name(ctx, ccname);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
kerr = krb5_cc_new_unique(ctx, "DIR", NULL, &tmp_cc);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
} else {
@@ -486,7 +480,7 @@ create_ccache_in_dir(uid_t uid, gid_t gid,
kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
if (kerr != 0) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
goto done;
}
@@ -832,14 +826,14 @@ static krb5_error_code get_and_save_tgt_with_keytab(krb5_context ctx,
kerr = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL,
&options);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
/* Use the updated principal in the creds in case canonicalized */
kerr = create_ccache_file(ctx, creds.client, ccname, &creds);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
kerr = 0;
@@ -862,21 +856,21 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
sss_krb5_expire_callback_func,
kr);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
DEBUG(1, ("Failed to set expire callback, continue without.\n"));
}
kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
password, sss_krb5_prompter, kr, 0,
NULL, kr->options);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
if (kr->validate) {
kerr = validate_tgt(kr);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
return kerr;
}
@@ -900,7 +894,7 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
kr->creds ? kr->creds->client : kr->princ,
kr->ccname, kr->creds);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
@@ -970,7 +964,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
changepw_princ,
kr->options);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
if (kerr == KRB5_KDC_UNREACH) {
pam_status = PAM_AUTHINFO_UNAVAIL;
}
@@ -1010,7 +1004,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
if (kerr != 0 || result_code != 0) {
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
} else {
kerr = KRB5KRB_ERR_GENERIC;
}
@@ -1062,7 +1056,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
memset(kr->pd->newauthtok, 0, kr->pd->newauthtok_size);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
if (kerr == KRB5_KDC_UNREACH) {
pam_status = PAM_AUTHINFO_UNAVAIL;
}
@@ -1124,7 +1118,7 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
kr->options,
NULL, NULL);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
DEBUG(1, ("Failed to unset expire callback, continue ...\n"));
}
kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
@@ -1142,7 +1136,7 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
memset(kr->pd->authtok, 0, kr->pd->authtok_size);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
switch (kerr) {
case KRB5_KDC_UNREACH:
pam_status = PAM_AUTHINFO_UNAVAIL;
@@ -1230,13 +1224,13 @@ static errno_t renew_tgt_child(int fd, struct krb5_req *kr)
kerr = krb5_cc_resolve(kr->ctx, ccname, &ccache);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
kerr = krb5_get_renewed_creds(kr->ctx, kr->creds, kr->princ, ccache, NULL);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
if (kerr == KRB5_KDC_UNREACH) {
status = PAM_AUTHINFO_UNAVAIL;
DEBUG(SSSDBG_TRACE_ALL, ("kdc unreachable for renewed creds.\n"));
@@ -1247,7 +1241,7 @@ static errno_t renew_tgt_child(int fd, struct krb5_req *kr)
if (kr->validate) {
kerr = validate_tgt(kr);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
@@ -1269,13 +1263,13 @@ static errno_t renew_tgt_child(int fd, struct krb5_req *kr)
kerr = krb5_cc_initialize(kr->ctx, ccache, kr->princ);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
kerr = krb5_cc_store_cred(kr->ctx, ccache, kr->creds);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto done;
}
@@ -1312,7 +1306,7 @@ static errno_t create_empty_ccache(int fd, struct krb5_req *kr)
ret = create_ccache(kr->uid, kr->gid, kr->ctx,
kr->princ, kr->ccname, NULL);
if (ret != 0) {
- KRB5_DEBUG(1, ret);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, ret);
pam_status = PAM_SYSTEM_ERR;
}
@@ -1649,19 +1643,20 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
kerr = krb5_init_context(&kr->ctx);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
+ krb5_error_ctx = kr->ctx;
kerr = krb5_parse_name(kr->ctx, kr->upn, &kr->princ);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
kerr = krb5_unparse_name(kr->ctx, kr->princ, &kr->name);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
@@ -1674,7 +1669,7 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
kerr = sss_krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
@@ -1684,7 +1679,7 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
* but shall return KRB5KDC_ERR_KEY_EXP. */
krb5_get_init_creds_opt_set_change_password_prompt(kr->options, 0);
if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
#endif
@@ -1698,7 +1693,7 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
if (kerr != 0) {
DEBUG(1, ("krb5_string_to_deltat failed for [%s].\n",
lifetime_str));
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n",
@@ -1715,7 +1710,7 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
if (kerr != 0) {
DEBUG(1, ("krb5_string_to_deltat failed for [%s].\n",
lifetime_str));
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
DEBUG(SSSDBG_CONF_SETTINGS,
@@ -1772,7 +1767,7 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
kr, &kr->fast_ccname);
if (kerr != 0) {
DEBUG(1, ("check_fast_ccache failed.\n"));
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
@@ -1782,7 +1777,7 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
if (kerr != 0) {
DEBUG(1, ("sss_krb5_get_init_creds_opt_set_fast_ccache_name "
"failed.\n"));
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
@@ -1793,7 +1788,7 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
if (kerr != 0) {
DEBUG(1, ("sss_krb5_get_init_creds_opt_set_fast_flags "
"failed.\n"));
- KRB5_DEBUG(1, kerr);
+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
goto failed;
}
}
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 35ece8117f20ac015771b4a0b6877ca068de7153..e6987014fe83860f8a61a9ded43ed0dd9309aae5 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -439,7 +439,8 @@ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
kerr = krb5_parse_name(ctx, client_name, &client_princ);
if (kerr != 0) {
- DEBUG(1, ("krb5_parse_name failed.\n"));
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
goto done;
}
@@ -457,13 +458,15 @@ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
kerr = krb5_parse_name(ctx, server_name, &server_princ);
talloc_free(server_name);
if (kerr != 0) {
- DEBUG(1, ("krb5_parse_name failed.\n"));
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
goto done;
}
kerr = krb5_cc_resolve(ctx, ccache_file, &cc);
if (kerr != 0) {
- DEBUG(1, ("krb5_cc_resolve failed.\n"));
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
goto done;
}
@@ -475,7 +478,8 @@ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
kerr = krb5_cc_retrieve_cred(ctx, cc, 0, &mcred, &cred);
if (kerr != 0) {
- DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_retrieve_cred failed.\n"));
goto done;
}
@@ -488,7 +492,8 @@ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
kerr = krb5_cc_close(ctx, cc);
if (kerr != 0) {
- DEBUG(1, ("krb5_cc_close failed.\n"));
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_close failed.\n"));
goto done;
}
cc = NULL;
@@ -705,6 +710,7 @@ cc_file_check_existing(const char *location, uid_t uid,
kerr = krb5_cc_resolve(context, location, &ccache);
if (kerr != 0) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, context, kerr);
krb5_free_context(context);
DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
return EIO;
@@ -714,7 +720,8 @@ cc_file_check_existing(const char *location, uid_t uid,
krb5_free_context(context);
krb5_cc_close(context, ccache);
if (kerr != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, context, kerr);
+ DEBUG(SSSDBG_CRIT_FAILURE,
("Could not check if ccache contains a valid principal\n"));
return EIO;
}
@@ -794,13 +801,15 @@ get_ccache_for_princ(krb5_context context, const char *location,
krberr = krb5_cc_set_default_name(context, location);
if (krberr != 0) {
- DEBUG(SSSDBG_OP_FAILURE, ("krb5_cc_resolve failed.\n"));
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
return krberr;
}
krberr = krb5_parse_name(context, princ, &client_principal);
if (krberr != 0) {
- DEBUG(SSSDBG_OP_FAILURE, ("krb5_parse_name failed.\n"));
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
return krberr;
}
@@ -857,7 +866,7 @@ cc_dir_check_existing(const char *location, uid_t uid,
ret = cc_residual_is_used(uid, dir, SSS_KRB5_TYPE_DIR, &active);
talloc_free(tmp);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("Could not check if ccache is active\n"));
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not check if ccache is active\n"));
return ret;
}
@@ -887,6 +896,7 @@ cc_dir_check_existing(const char *location, uid_t uid,
krberr = check_for_valid_tgt(context, ccache, realm, princ, &valid);
if (krberr != EOK) {
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
DEBUG(SSSDBG_CRIT_FAILURE,
("Could not check if ccache contains a valid principal\n"));
ret = EIO;
@@ -942,7 +952,8 @@ cc_dir_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
if (ccache) krb5_cc_close(context, ccache);
krb5_free_context(context);
if (krberr) {
- DEBUG(SSSDBG_TRACE_FUNC, ("Could not get full name of ccache\n"));
+ KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not get full name of ccache\n"));
return NULL;
}
diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
index 015bd39aef480cb3f52b0d453ee094818ffcbcbb..fa9374c2ded59abf3ead2c86e4583e368493642e 100644
--- a/src/tests/krb5_child-test.c
+++ b/src/tests/krb5_child-test.c
@@ -43,24 +43,18 @@ extern struct sss_krb5_cc_be file_cc;
extern struct sss_krb5_cc_be dir_cc;
static krb5_context krb5_error_ctx;
-#define KRB5_DEBUG(level, krb5_error) do { \
- const char * __krb5_error_msg; \
- __krb5_error_msg = sss_krb5_get_error_message(krb5_error_ctx, krb5_error); \
- DEBUG(level, ("%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg)); \
- sss_log(SSS_LOG_ERR, "%s", __krb5_error_msg); \
- sss_krb5_free_error_message(krb5_error_ctx, __krb5_error_msg); \
-} while(0)
+#define KRB5_CHILD_TEST_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error)
#define CHECK_KRET(kret, err) do { \
if (kret) { \
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kret); \
+ KRB5_CHILD_TEST_DEBUG(SSSDBG_OP_FAILURE, kret); \
return err; \
} \
} while(0) \
#define CHECK_KRET_L(kret, err, label) do { \
if (kret) { \
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kret); \
+ KRB5_CHILD_TEST_DEBUG(SSSDBG_OP_FAILURE, kret); \
goto label; \
} \
} while(0) \
@@ -321,7 +315,7 @@ printtime(krb5_timestamp ts)
kret = krb5_timestamp_to_sfstring(ts, timestring, BUFSIZ, &fill);
if (kret) {
- KRB5_DEBUG(SSSDBG_OP_FAILURE, kret);
+ KRB5_CHILD_TEST_DEBUG(SSSDBG_OP_FAILURE, kret);
}
printf("%s", timestring);
}
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index 89ec00021f09333e94b6fbf1b0bcc1394f9523df..34fdc495056d7c43293fd57e2c618cfc65b1186e 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -46,6 +46,14 @@ const char * KRB5_CALLCONV sss_krb5_get_error_message (krb5_context,
void KRB5_CALLCONV sss_krb5_free_error_message(krb5_context, const char *);
+#define KRB5_DEBUG(level, errctx, krb5_error) do { \
+ const char *__krb5_error_msg; \
+ __krb5_error_msg = sss_krb5_get_error_message(errctx, krb5_error); \
+ DEBUG(level, ("%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg)); \
+ sss_log(SSS_LOG_ERR, "%s", __krb5_error_msg); \
+ sss_krb5_free_error_message(errctx, __krb5_error_msg); \
+} while(0)
+
krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_alloc(
krb5_context context,
krb5_get_init_creds_opt **opt);
--
1.7.10.2
-------------- next part --------------
>From 35c79b2b9b870796806df4b58df4df5d4ea4ce45 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Thu, 14 Jun 2012 18:40:58 +0200
Subject: [PATCH 11/12] Use absolute path for building manpages
---
src/man/Makefile.am | 1 +
src/man/po/po4a.cfg | 56 +++++++++++++++++++++++++--------------------------
2 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/src/man/Makefile.am b/src/man/Makefile.am
index c15844e82378bf5b9abd835cdde25a3a70cf1a37..5c6520dde61b0125147cac0babf45860f2356c32 100644
--- a/src/man/Makefile.am
+++ b/src/man/Makefile.am
@@ -83,6 +83,7 @@ LINGUAS ?= $(LINGUAS_DIST)
PO4A_COMMON_OPTS = --option doctype=docbook \
--package-name $(PACKAGE_DOC) \
--variable builddir=$(CURDIR) \
+ --variable srcdir=$(srcdir) \
--package-version $(PACKAGE_VERSION) \
--msgid-bugs-address sssd-devel at redhat.com \
--copyright-holder "Red Hat"
diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg
index 6d2a4db7c51bb6dbb646fd8f2511250920a14449..e574047d52c2acd7e393d20150f21becbfc2f906 100644
--- a/src/man/po/po4a.cfg
+++ b/src/man/po/po4a.cfg
@@ -1,30 +1,30 @@
[po4a_langs] cs es fr ja nl pt ru tg uk
[po4a_paths] po/sssd-docs.pot $lang:po/$lang.po
-[type:docbook] sss_groupmod.8.xml $lang:$(builddir)/$lang/sss_groupmod.8.xml
-[type:docbook] sssd.conf.5.xml $lang:$(builddir)/$lang/sssd.conf.5.xml
-[type:docbook] sssd-ldap.5.xml $lang:$(builddir)/$lang/sssd-ldap.5.xml
-[type:docbook] pam_sss.8.xml $lang:$(builddir)/$lang/pam_sss.8.xml
-[type:docbook] sssd_krb5_locator_plugin.8.xml $lang:$(builddir)/$lang/sssd_krb5_locator_plugin.8.xml
-[type:docbook] sssd-simple.5.xml $lang:$(builddir)/$lang/sssd-simple.5.xml
-[type:docbook] sssd-ipa.5.xml $lang:$(builddir)/$lang/sssd-ipa.5.xml
-[type:docbook] sssd.8.xml $lang:$(builddir)/$lang/sssd.8.xml
-[type:docbook] sss_obfuscate.8.xml $lang:$(builddir)/$lang/sss_obfuscate.8.xml
-[type:docbook] sss_useradd.8.xml $lang:$(builddir)/$lang/sss_useradd.8.xml
-[type:docbook] sssd-krb5.5.xml $lang:$(builddir)/$lang/sssd-krb5.5.xml
-[type:docbook] sss_groupadd.8.xml $lang:$(builddir)/$lang/sss_groupadd.8.xml
-[type:docbook] sss_userdel.8.xml $lang:$(builddir)/$lang/sss_userdel.8.xml
-[type:docbook] sss_groupdel.8.xml $lang:$(builddir)/$lang/sss_groupdel.8.xml
-[type:docbook] sss_groupshow.8.xml $lang:$(builddir)/$lang/sss_groupshow.8.xml
-[type:docbook] sss_usermod.8.xml $lang:$(builddir)/$lang/sss_usermod.8.xml
-[type:docbook] sss_cache.8.xml $lang:$(builddir)/$lang/sss_cache.8.xml
-[type:docbook] sss_debuglevel.8.xml $lang:$(builddir)/$lang/sss_debuglevel.8.xml
-[type:docbook] sss_ssh_authorizedkeys.1.xml $lang:$(builddir)/$lang/sss_ssh_authorizedkeys.1.xml
-[type:docbook] sss_ssh_knownhostsproxy.1.xml $lang:$(builddir)/$lang/sss_ssh_knownhostsproxy.1.xml
-[type:docbook] include/service_discovery.xml $lang:$(builddir)/$lang/include/service_discovery.xml opt:"-k 0"
-[type:docbook] include/upstream.xml $lang:$(builddir)/$lang/include/upstream.xml opt:"-k 0"
-[type:docbook] include/failover.xml $lang:$(builddir)/$lang/include/failover.xml opt:"-k 0"
-[type:docbook] include/ldap_id_mapping.xml $lang:$(builddir)/$lang/include/ldap_id_mapping.xml opt:"-k 0"
-[type:docbook] include/param_help.xml $lang:$(builddir)/$lang/include/param_help.xml opt:"-k 0"
-[type:docbook] include/debug_levels.xml $lang:$(builddir)/$lang/include/debug_levels.xml opt:"-k 0"
-[type:docbook] include/experimental.xml $lang:$(builddir)/$lang/include/experimental.xml opt:"-k 0"
-[type:docbook] include/local.xml $lang:$(builddir)/$lang/include/local.xml opt:"-k 0"
+[type:docbook] $(srcdir)/sss_groupmod.8.xml $lang:$(builddir)/$lang/sss_groupmod.8.xml
+[type:docbook] $(srcdir)/sssd.conf.5.xml $lang:$(builddir)/$lang/sssd.conf.5.xml
+[type:docbook] $(srcdir)/sssd-ldap.5.xml $lang:$(builddir)/$lang/sssd-ldap.5.xml
+[type:docbook] $(srcdir)/pam_sss.8.xml $lang:$(builddir)/$lang/pam_sss.8.xml
+[type:docbook] $(srcdir)/sssd_krb5_locator_plugin.8.xml $lang:$(builddir)/$lang/sssd_krb5_locator_plugin.8.xml
+[type:docbook] $(srcdir)/sssd-simple.5.xml $lang:$(builddir)/$lang/sssd-simple.5.xml
+[type:docbook] $(srcdir)/sssd-ipa.5.xml $lang:$(builddir)/$lang/sssd-ipa.5.xml
+[type:docbook] $(srcdir)/sssd.8.xml $lang:$(builddir)/$lang/sssd.8.xml
+[type:docbook] $(srcdir)/sss_obfuscate.8.xml $lang:$(builddir)/$lang/sss_obfuscate.8.xml
+[type:docbook] $(srcdir)/sss_useradd.8.xml $lang:$(builddir)/$lang/sss_useradd.8.xml
+[type:docbook] $(srcdir)/sssd-krb5.5.xml $lang:$(builddir)/$lang/sssd-krb5.5.xml
+[type:docbook] $(srcdir)/sss_groupadd.8.xml $lang:$(builddir)/$lang/sss_groupadd.8.xml
+[type:docbook] $(srcdir)/sss_userdel.8.xml $lang:$(builddir)/$lang/sss_userdel.8.xml
+[type:docbook] $(srcdir)/sss_groupdel.8.xml $lang:$(builddir)/$lang/sss_groupdel.8.xml
+[type:docbook] $(srcdir)/sss_groupshow.8.xml $lang:$(builddir)/$lang/sss_groupshow.8.xml
+[type:docbook] $(srcdir)/sss_usermod.8.xml $lang:$(builddir)/$lang/sss_usermod.8.xml
+[type:docbook] $(srcdir)/sss_cache.8.xml $lang:$(builddir)/$lang/sss_cache.8.xml
+[type:docbook] $(srcdir)/sss_debuglevel.8.xml $lang:$(builddir)/$lang/sss_debuglevel.8.xml
+[type:docbook] $(srcdir)/sss_ssh_authorizedkeys.1.xml $lang:$(builddir)/$lang/sss_ssh_authorizedkeys.1.xml
+[type:docbook] $(srcdir)/sss_ssh_knownhostsproxy.1.xml $lang:$(builddir)/$lang/sss_ssh_knownhostsproxy.1.xml
+[type:docbook] $(srcdir)/include/service_discovery.xml $lang:$(builddir)/$lang/include/service_discovery.xml opt:"-k 0"
+[type:docbook] $(srcdir)/include/upstream.xml $lang:$(builddir)/$lang/include/upstream.xml opt:"-k 0"
+[type:docbook] $(srcdir)/include/failover.xml $lang:$(builddir)/$lang/include/failover.xml opt:"-k 0"
+[type:docbook] $(srcdir)/include/ldap_id_mapping.xml $lang:$(builddir)/$lang/include/ldap_id_mapping.xml opt:"-k 0"
+[type:docbook] $(srcdir)/include/param_help.xml $lang:$(builddir)/$lang/include/param_help.xml opt:"-k 0"
+[type:docbook] $(srcdir)/include/debug_levels.xml $lang:$(builddir)/$lang/include/debug_levels.xml opt:"-k 0"
+[type:docbook] $(srcdir)/include/experimental.xml $lang:$(builddir)/$lang/include/experimental.xml opt:"-k 0"
+[type:docbook] $(srcdir)/include/local.xml $lang:$(builddir)/$lang/include/local.xml opt:"-k 0"
--
1.7.10.2
-------------- next part --------------
>From 7f7b5d69d3141c766d5be0ae43c027c0fc503983 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 13 Jun 2012 17:52:38 +0200
Subject: [PATCH 12/12] Make krb5_ccname_template and krb5_ccachedir
configurable
Provide a configure-time options to specify the default values for
krb5_ccname_template and krb5_ccachedir.
---
configure.ac | 5 +++-
contrib/sssd.spec.in | 5 ++++
src/conf_macros.m4 | 30 +++++++++++++++++++++++
src/man/Makefile.am | 2 +-
src/man/po/po4a.cfg | 2 +-
src/man/{sssd-krb5.5.xml => sssd-krb5.5.xml.in} | 10 ++++----
src/providers/ipa/ipa_opts.h | 4 +--
src/providers/krb5/krb5_opts.h | 4 +--
src/providers/krb5/krb5_utils.h | 3 +++
9 files changed, 53 insertions(+), 12 deletions(-)
rename src/man/{sssd-krb5.5.xml => sssd-krb5.5.xml.in} (98%)
diff --git a/configure.ac b/configure.ac
index d4647d8a0ad8e7e2555b97b13acee114e9a81a65..70ad4e72e67e1a207882217c7b0687667c7b23e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,6 +82,8 @@ WITH_LOG_PATH
WITH_PUBCONF_PATH
WITH_PIPE_PATH
WITH_MCACHE_PATH
+WITH_DEFAULT_CCACHE_DIR
+WITH_DEFAULT_CCNAME_TEMPLATE
WITH_INIT_DIR
WITH_TEST_DIR
WITH_MANPAGES
@@ -252,5 +254,6 @@ AC_CONFIG_FILES([Makefile contrib/sssd.spec src/examples/rwtab src/doxy.config
src/sss_client/sudo/libsss_sudo.pc
src/sss_client/sudo/sss_sudo.doxy
src/config/setup.py
- src/config/SSSDConfig/__init__.py])
+ src/config/SSSDConfig/__init__.py
+ src/man/sssd-krb5.5.xml])
AC_OUTPUT
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
index 8d7a8d5a831628793372dd1efe56a41302b99866..871fbda4c4254cbe846a5e44a45ffaba9f9a0d8e 100644
--- a/contrib/sssd.spec.in
+++ b/contrib/sssd.spec.in
@@ -19,6 +19,10 @@
%define __provides_exclude_from %{python_sitearch}/.*\.so$
%endif
+%if (0%{?fedora} >= 17)
+ %global with_ccache --with-default-ccache-dir='/run/user/%U' --with-default-ccname-template="DIR:%d/ccdir"
+%endif
+
%global enable_experimental 1
%if (0%{?enable_experimental} == 1)
@@ -233,6 +237,7 @@ autoreconf -ivf
--disable-static \
--disable-rpath \
%{with_unicode_lib} \
+ %{with_ccache} \
%{experimental}
make %{?_smp_mflags} all
diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
index 8c13e5dba71a98f25c42acaeccd3b01233f77210..2e98b84c24c2249603b258b12c5a044622fb6985 100644
--- a/src/conf_macros.m4
+++ b/src/conf_macros.m4
@@ -247,6 +247,36 @@ AC_DEFUN([WITH_KRB5_RCACHE_DIR],
AC_DEFINE_UNQUOTED(KRB5_RCACHE_DIR, "$krb5rcachedir", [Directory used for storing Kerberos replay caches])
])
+AC_DEFUN([WITH_DEFAULT_CCACHE_DIR],
+ [ AC_ARG_WITH([default-ccache-dir],
+ [AC_HELP_STRING([--with-default-ccache-dir=CCACHEDIR],
+ [The default value of krb5_ccachedir [/tmp]]
+ )
+ ]
+ )
+ config_def_ccache_dir="/tmp"
+ if test x"$with_default_ccache_dir" != x; then
+ config_def_ccache_dir=$with_default_ccache_dir
+ fi
+ AC_SUBST(config_def_ccache_dir)
+ AC_DEFINE_UNQUOTED(DEFAULT_CCACHE_DIR, "$config_def_ccache_dir", [The default value of krb5_ccachedir])
+ ])
+
+AC_DEFUN([WITH_DEFAULT_CCNAME_TEMPLATE],
+ [ AC_ARG_WITH([default-ccname-template],
+ [AC_HELP_STRING([--with-default-ccname-template=CCACHE],
+ [The default value of krb5_ccname_template [FILE:%d/krb5cc_%U_XXXXXX]]
+ )
+ ]
+ )
+ config_def_ccname_template="FILE:%d/krb5cc_%U_XXXXXX"
+ if test x"$with_default_ccname_template" != x; then
+ config_def_ccname_template=$with_default_ccname_template
+ fi
+ AC_SUBST(config_def_ccname_template)
+ AC_DEFINE_UNQUOTED(DEFAULT_CCNAME_TEMPLATE, "$config_def_ccname_template", [The default value of krb5_ccname_template])
+ ])
+
AC_DEFUN([WITH_PYTHON_BINDINGS],
[ AC_ARG_WITH([python-bindings],
[AC_HELP_STRING([--with-python-bindings],
diff --git a/src/man/Makefile.am b/src/man/Makefile.am
index 5c6520dde61b0125147cac0babf45860f2356c32..8015ccf895d34834a99aeac8ae031afc046cab49 100644
--- a/src/man/Makefile.am
+++ b/src/man/Makefile.am
@@ -32,7 +32,7 @@ if HAVE_PROFILE_CATALOGS
XSLTPROC_FLAGS += --stringparam profile.condition "$(CONDS)"
endif
-EXTRA_DIST = $(wildcard $(srcdir)/*.xml) $(wildcard $(srcdir)/include/*.xml)
+EXTRA_DIST = $(wildcard $(srcdir)/*.xml) $(wildcard $(srcdir)/include/*.xml.in) $(wildcard $(srcdir)/include/*.xml)
man_MANS = \
sss_useradd.8 sss_userdel.8 sss_usermod.8 \
sss_groupadd.8 sss_groupdel.8 sss_groupmod.8 \
diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg
index e574047d52c2acd7e393d20150f21becbfc2f906..b016a3c1eb29bc9b5e1860b881e213cc6f3ff3b1 100644
--- a/src/man/po/po4a.cfg
+++ b/src/man/po/po4a.cfg
@@ -10,7 +10,7 @@
[type:docbook] $(srcdir)/sssd.8.xml $lang:$(builddir)/$lang/sssd.8.xml
[type:docbook] $(srcdir)/sss_obfuscate.8.xml $lang:$(builddir)/$lang/sss_obfuscate.8.xml
[type:docbook] $(srcdir)/sss_useradd.8.xml $lang:$(builddir)/$lang/sss_useradd.8.xml
-[type:docbook] $(srcdir)/sssd-krb5.5.xml $lang:$(builddir)/$lang/sssd-krb5.5.xml
+[type:docbook] $(builddir)/sssd-krb5.5.xml $lang:$(builddir)/$lang/sssd-krb5.5.xml
[type:docbook] $(srcdir)/sss_groupadd.8.xml $lang:$(builddir)/$lang/sss_groupadd.8.xml
[type:docbook] $(srcdir)/sss_userdel.8.xml $lang:$(builddir)/$lang/sss_userdel.8.xml
[type:docbook] $(srcdir)/sss_groupdel.8.xml $lang:$(builddir)/$lang/sss_groupdel.8.xml
diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml.in
similarity index 98%
rename from src/man/sssd-krb5.5.xml
rename to src/man/sssd-krb5.5.xml.in
index 1baee36e9b0ade76de2990fd4f06bc655b5ce06c..760ee2e502d711d6894904c4201d660006c766c6 100644
--- a/src/man/sssd-krb5.5.xml
+++ b/src/man/sssd-krb5.5.xml.in
@@ -4,7 +4,7 @@
<reference>
<title>SSSD Manual pages</title>
<refentry>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/upstream.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="@srcdir@/include/upstream.xml" />
<refmeta>
<refentrytitle>sssd-krb5</refentrytitle>
@@ -148,7 +148,7 @@
</citerefentry> for details) is created.
</para>
<para>
- Default: /tmp
+ Default: @config_def_ccache_dir@
</para>
</listitem>
</varlistentry>
@@ -208,7 +208,7 @@
used to create a unique filename in a safe way.
</para>
<para>
- Default: FILE:%d/krb5cc_%U_XXXXXX
+ Default: @config_def_ccname_template@
</para>
</listitem>
</varlistentry>
@@ -426,9 +426,9 @@
</para>
</refsect1>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/failover.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="@srcdir@/include/failover.xml" />
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/service_discovery.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="@srcdir@/include/service_discovery.xml" />
<refsect1 id='example'>
<title>EXAMPLE</title>
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index 770406cfebe67ba5104163986a29f4a1a9f34869..501f2e18b7db893f61c2e123450b7e156ac91d43 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -232,8 +232,8 @@ struct sdap_attr_map ipa_selinux_user_map[] = {
struct dp_option ipa_def_krb5_opts[] = {
{ "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "krb5_ccachedir", DP_OPT_STRING, { "/tmp" }, NULL_STRING },
- { "krb5_ccname_template", DP_OPT_STRING, { "FILE:%d/krb5cc_%U_XXXXXX" }, NULL_STRING},
+ { "krb5_ccachedir", DP_OPT_STRING, { DEFAULT_CCACHE_DIR }, NULL_STRING },
+ { "krb5_ccname_template", DP_OPT_STRING, { DEFAULT_CCNAME_TEMPLATE }, NULL_STRING},
{ "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER },
{ "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
{ "krb5_validate", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
diff --git a/src/providers/krb5/krb5_opts.h b/src/providers/krb5/krb5_opts.h
index 45dfec544f6d5261df313649658a1432f763ce5b..9de93b0cd725b15210263b282514af94f9dd9473 100644
--- a/src/providers/krb5/krb5_opts.h
+++ b/src/providers/krb5/krb5_opts.h
@@ -28,8 +28,8 @@
struct dp_option default_krb5_opts[] = {
{ "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "krb5_ccachedir", DP_OPT_STRING, { "/run/user/%u" }, NULL_STRING },
- { "krb5_ccname_template", DP_OPT_STRING, { "DIR:%d" }, NULL_STRING},
+ { "krb5_ccachedir", DP_OPT_STRING, { DEFAULT_CCACHE_DIR }, NULL_STRING },
+ { "krb5_ccname_template", DP_OPT_STRING, { DEFAULT_CCNAME_TEMPLATE }, NULL_STRING},
{ "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER },
{ "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
{ "krb5_validate", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index 684c520151831eb7fbe619a1b14be38a6092e56a..5f677cae284b8bf22127b171715c07413fee1bb9 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -55,6 +55,9 @@ struct sss_krb5_cc_be {
struct sss_krb5_cc_be file_cc;
struct sss_krb5_cc_be dir_cc;
+errno_t create_ccache_dir(const char *dirname, pcre *illegal_re,
+ uid_t uid, gid_t gid, bool private_path);
+
errno_t cc_file_create(const char *filename, pcre *illegal_re,
uid_t uid, gid_t gid, bool private_path);
--
1.7.10.2
More information about the sssd-devel
mailing list