Hi,

this patch should fix #406.

bye,
Sumit
From ac0a2de24a0400dc08acf375184d20673872415c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Tue, 23 Feb 2010 09:43:51 +0100
Subject: [PATCH] Add expandable sequences to krb5_ccachedir

As with krb5_ccname_template sequences like %u can be used in the
krb5_ccachedir parameter which are expanded at runtime. If the directory
does not exist, it will be created. Depending on the used sequences it
is created as a public or private directory.
---
 src/man/sssd-krb5.5.xml          |    8 +-
 src/providers/krb5/krb5_auth.c   |   13 ++-
 src/providers/krb5/krb5_common.c |   13 --
 src/providers/krb5/krb5_utils.c  |  134 ++++++++++++++-
 src/providers/krb5/krb5_utils.h  |    7 +-
 src/tests/krb5_utils-tests.c     |  350 ++++++++++++++++++++++++++++----------
 6 files changed, 409 insertions(+), 116 deletions(-)

diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml
index 32b6c29..921d17c 100644
--- a/src/man/sssd-krb5.5.xml
+++ b/src/man/sssd-krb5.5.xml
@@ -102,7 +102,13 @@
                     <term>krb5_ccachedir (string)</term>
                     <listitem>
                         <para>
-                            Directory to store credential caches.
+                            Directory to store credential caches. All the
+                            substitution sequences of krb5_ccname_template can
+                            be used here, too, expect %d. If the directory does
+                            not exist it will be created. If %u, %U, %p or %h
+                            are used a private directory belonging to the user
+                            is created. Otherwise a public directory with
+                            restricted deletion flag is created.
                         </para>
                         <para>
                             Default: /tmp
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 0e5230c..3419838 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -915,12 +915,21 @@ static void krb5_resolve_done(struct tevent_req *req)
             }
             kr->ccname = expand_ccname_template(kr, kr,
                                           
dp_opt_get_cstring(kr->krb5_ctx->opts,
-                                                             KRB5_CCNAME_TMPL)
-                                    );
+                                                             KRB5_CCNAME_TMPL),
+                                                true);
             if (kr->ccname == NULL) {
                 DEBUG(1, ("expand_ccname_template failed.\n"));
                 goto done;
             }
+
+            ret = create_ccache_dir(kr, kr->ccname,
+                                    dp_opt_get_cstring(kr->krb5_ctx->opts,
+                                                                
KRB5_CCACHEDIR),
+                                    kr->uid, kr->gid);
+            if (ret != EOK) {
+                DEBUG(1, ("create_ccache_dir failed.\n"));
+                goto done;
+            }
     }
 
     if (be_is_offline(be_req->be_ctx)) {
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index 86676f4..7619e6a 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -47,7 +47,6 @@ errno_t check_and_export_options(struct dp_option *opts,
     char *value;
     const char *realm;
     const char *dummy;
-    struct stat stat_buf;
     char **list;
 
     realm = dp_opt_get_cstring(opts, KRB5_REALM);
@@ -83,18 +82,6 @@ errno_t check_and_export_options(struct dp_option *opts,
         talloc_free(list);
     }
 
-    dummy = dp_opt_get_cstring(opts, KRB5_CCACHEDIR);
-    ret = lstat(dummy, &stat_buf);
-    if (ret != EOK) {
-        DEBUG(1, ("lstat for [%s] failed: [%d][%s].\n", dummy, errno,
-                  strerror(errno)));
-        return ret;
-    }
-    if ( !S_ISDIR(stat_buf.st_mode) ) {
-        DEBUG(1, ("Value of krb5ccache_dir [%s] is not a directory.\n", 
dummy));
-        return EINVAL;
-    }
-
     dummy = dp_opt_get_cstring(opts, KRB5_CCNAME_TMPL);
     if (dummy == NULL) {
         DEBUG(1, ("Missing credential cache name template.\n"));
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index a75ad78..6a893f6 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -29,13 +29,14 @@
 #include "util/util.h"
 
 char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
-                             const char *template)
+                             const char *template, bool expand_ccache_dir)
 {
     char *copy;
     char *p;
     char *n;
     char *result = NULL;
     const char *dummy;
+    const char *cache_dir_tmpl;
 
     if (template == NULL) {
         DEBUG(1, ("Missing template.\n"));
@@ -110,12 +111,26 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct 
krb5child_req *kr,
                 result = talloc_asprintf_append(result, "%s%s", p, 
kr->homedir);
                 break;
             case 'd':
-                dummy = dp_opt_get_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR);
-                if (dummy == NULL) {
-                    DEBUG(1, ("Missing credential cache directory.\n"));
+                if (expand_ccache_dir) {
+                    cache_dir_tmpl = dp_opt_get_string(kr->krb5_ctx->opts,
+                                                       KRB5_CCACHEDIR);
+                    if (cache_dir_tmpl == NULL) {
+                        DEBUG(1, ("Missing credential cache directory.\n"));
+                        return NULL;
+                    }
+
+                    dummy = expand_ccname_template(mem_ctx, kr, cache_dir_tmpl,
+                                                   false);
+                    if (dummy == NULL) {
+                        DEBUG(1, ("Expanding credential cache directory "
+                                  "template failed.\n"));
+                        return NULL;
+                    }
+                    result = talloc_asprintf_append(result, "%s%s", p, dummy);
+                } else {
+                    DEBUG(1, ("'%%d' is not allowed in this template.\n"));
                     return NULL;
                 }
-                result = talloc_asprintf_append(result, "%s%s", p, dummy);
                 break;
             case 'P':
                 if (kr->pd->cli_pid == 0) {
@@ -143,3 +158,112 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct 
krb5child_req *kr,
 
     return result;
 }
+
+errno_t create_dir_with_parents(TALLOC_CTX *mem_ctx, const char *dirname)
+{
+    int ret;
+    struct stat stat_buf;
+    char *parent;
+    char *end;
+    mode_t old_umask;
+
+    ret = lstat(dirname, &stat_buf);
+    if (ret == EOK) {
+        if ( !S_ISDIR(stat_buf.st_mode) ) {
+            DEBUG(1, ("[%s] is not a directory.\n", dirname));
+            return EINVAL;
+        }
+        return EOK;
+    } else {
+        if (errno != ENOENT) {
+            DEBUG(1, ("lstat for [%s] failed: [%d][%s].\n", dirname, errno,
+                      strerror(errno)));
+            return errno;
+        }
+    }
+
+    parent = talloc_strdup(mem_ctx, dirname);
+    end = strrchr(parent, '/');
+    if (end == NULL || end == parent) {
+        DEBUG(1, ("Cannot find parent directory of [%s], / is not allowed.\n",
+                   dirname));
+        return EINVAL;
+    }
+    *end = '\0';
+
+    ret = create_dir_with_parents(mem_ctx, parent);
+    if (ret != EOK) {
+        DEBUG(7, ("create_dir_with_parents failed.\n"));
+        return ret;
+    }
+
+    old_umask = umask(0000);
+    ret = mkdir(dirname, 01777);
+    umask(old_umask);
+    if (ret != EOK) {
+        DEBUG(1, ("mkdir [%s] failed: [%d][%s].\n", dirname, errno,
+                  strerror(errno)));
+        return errno;
+    }
+
+    return EOK;
+}
+
+errno_t create_ccache_dir(TALLOC_CTX *mem_ctx, const char *filename,
+                          const char *ccache_dir_tmpl, uid_t priv_uid,
+                          gid_t priv_gid)
+{
+    int ret;
+    char *dirname;
+    char *end;
+    const char *c;
+
+    dirname = talloc_strdup(mem_ctx, filename);
+    if (dirname == NULL) {
+        DEBUG(1, ("talloc_strndup failed.\n"));
+        return ENOMEM;
+    }
+
+    if (strncmp(dirname, "FILE:", 5) == 0) {
+        dirname = dirname + 5;
+    }
+
+    if (*dirname != '/') {
+        DEBUG(1, ("Only absolute paths are allowed, not [%s] .\n", dirname));
+        return EINVAL;
+    }
+
+    end = strrchr(dirname, '/');
+    if (end == NULL || end == dirname) {
+        DEBUG(1, ("Not allowed filename [%s].\n"));
+        return EINVAL;
+    }
+    *end = '\0';
+
+    ret = create_dir_with_parents(mem_ctx, dirname);
+    if (ret != EOK) {
+        DEBUG(1, ("create_dir_with_parents failed.\n"));
+        return ret;
+    }
+
+    c = ccache_dir_tmpl;
+    while((c = strchr(c, '%')) != NULL) {
+        ++c;
+        if ( *c == 'u' || *c == 'U' || *c == 'p' || *c == 'h') {
+            ret = chmod(dirname, 0700);
+            if (ret != EOK) {
+                DEBUG(1, ("chmod failed [%d][%s].\n", errno, strerror(errno)));
+                return errno;
+            }
+
+            ret = chown(dirname, priv_uid, priv_gid);
+            if (ret != EOK) {
+                DEBUG(1, ("chown failed [%d][%s].\n", errno, strerror(errno)));
+                return errno;
+            }
+            break;
+        }
+    }
+
+    return EOK;
+}
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index 7637041..ce407ec 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -32,8 +32,13 @@
 #include "providers/data_provider.h"
 
 char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
-                             const char *template);
+                             const char *template, bool expand_ccache_dir);
 
 errno_t become_user(uid_t uid, gid_t gid);
 
+errno_t create_dir_with_parents(TALLOC_CTX *mem_ctx, const char *dirname);
+
+errno_t create_ccache_dir(TALLOC_CTX *mem_ctx, const char *filename,
+                          const char *ccache_dir_tmpl, uid_t priv_uid,
+                          gid_t priv_gid);
 #endif /* __KRB5_UTILS_H__ */
diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
index 362daf4..58f04fe 100644
--- a/src/tests/krb5_utils-tests.c
+++ b/src/tests/krb5_utils-tests.c
@@ -23,12 +23,16 @@
 */
 
 #include <stdlib.h>
+#include <popt.h>
 #include <check.h>
 
 #include "providers/krb5/krb5_utils.h"
 #include "providers/krb5/krb5_auth.h"
 
+#define TESTS_PATH "tests_krb5_utils"
+
 #define BASE "/abc/def"
+#define FILENAME "ghi"
 
 #define USERNAME "testuser"
 #define UID "12345"
@@ -43,6 +47,144 @@ extern struct dp_option default_krb5_opts[];
 TALLOC_CTX *tmp_ctx = NULL;
 struct krb5child_req *kr;
 
+#define RMDIR(__dir__) do { \
+    ret = rmdir(__dir__); \
+    fail_unless(ret == EOK, "rmdir [%s] failed, [%d][%s].", __dir__, \
+                errno, strerror(errno)); \
+} while(0);
+
+void setup_create_dir(void)
+{
+    fail_unless(tmp_ctx == NULL, "Talloc context already initialized.");
+    tmp_ctx = talloc_new(NULL);
+    fail_unless(tmp_ctx != NULL, "Cannot create talloc context.");
+}
+
+void teardown_create_dir(void)
+{
+    int ret;
+    fail_unless(tmp_ctx != NULL, "Talloc context already freed.");
+    ret = talloc_free(tmp_ctx);
+    tmp_ctx = NULL;
+    fail_unless(ret == 0, "Connot free talloc context.");
+}
+
+static void check_dir(const char *dirname, uid_t uid, gid_t gid, mode_t mode)
+{
+    struct stat stat_buf;
+    int ret;
+
+    ret = stat(dirname, &stat_buf);
+    fail_unless(ret == EOK, "stat failed [%d][%s].", errno, strerror(errno));
+
+    fail_unless(S_ISDIR(stat_buf.st_mode), "[%s] is not a directory.", 
dirname);
+    fail_unless(stat_buf.st_uid == uid, "uid does not match, "
+                                        "expected [%d], got [%d].",
+                                        uid, stat_buf.st_uid);
+    fail_unless(stat_buf.st_gid == gid, "gid does not match, "
+                                        "expected [%d], got [%d].",
+                                        gid, stat_buf.st_gid);
+    fail_unless((stat_buf.st_mode & ~S_IFMT) == mode, "mode does not match, "
+                                           "expected [%o], got [%o].",
+                                            mode, (stat_buf.st_mode & 
~S_IFMT));
+}
+
+START_TEST(test_mkdir_simple)
+{
+    int ret;
+
+    ret = create_dir_with_parents(tmp_ctx, TESTS_PATH"/abc");
+    fail_unless(ret == EOK, "create_dir_with_parents failed.");
+    check_dir(TESTS_PATH"/abc", getuid(), getgid(), 01777);
+
+    RMDIR(TESTS_PATH"/abc");
+}
+END_TEST
+
+START_TEST(test_mkdir_parents)
+{
+    int ret;
+
+    ret = create_dir_with_parents(tmp_ctx, TESTS_PATH"/a/b/c");
+    fail_unless(ret == EOK, "create_dir_with_parents failed.");
+    check_dir(TESTS_PATH"/a/b/c", getuid(), getgid(), 01777);
+    RMDIR(TESTS_PATH"/a/b/c");
+    RMDIR(TESTS_PATH"/a/b");
+    RMDIR(TESTS_PATH"/a");
+}
+END_TEST
+
+START_TEST(test_mkdir_nonexisting_parent)
+{
+    int ret;
+
+    ret = create_dir_with_parents(tmp_ctx, "/a/b/c");
+    fail_unless(ret == EINVAL, "create_dir_with_parents did not return 
EINVAL.");
+}
+END_TEST
+
+START_TEST(test_priv_ccache_dir)
+{
+    int ret;
+    char *cwd;
+    char *dirname;
+    char *filename;
+    uid_t uid = getuid();
+    gid_t gid = getgid();
+
+    if (uid == 0) {
+        uid = 12345;
+        gid = 12345;
+    }
+
+    cwd = getcwd(NULL, 0);
+    fail_unless(cwd != NULL, "getcwd failed.");
+
+    dirname = talloc_asprintf(tmp_ctx, "%s/%s/priv_ccdir", cwd, TESTS_PATH);
+    free(cwd);
+    fail_unless(dirname != NULL, "talloc_asprintf failed.");
+    filename = talloc_asprintf(tmp_ctx, "%s/ccfile", dirname);
+    fail_unless(filename != NULL, "talloc_asprintf failed.");
+
+    ret = create_ccache_dir(tmp_ctx, filename, "/abc_%u_abc", uid, gid);
+    fail_unless(ret == EOK, "create_ccache_dir failed.");
+
+    check_dir(dirname, uid, gid, 0700);
+    RMDIR(dirname);
+}
+END_TEST
+
+START_TEST(test_pub_ccache_dir)
+{
+    int ret;
+    char *cwd;
+    char *dirname;
+    char *filename;
+    uid_t uid = getuid();
+    gid_t gid = getgid();
+
+    if (uid == 0) {
+        uid = 12345;
+        gid = 12345;
+    }
+
+    cwd = getcwd(NULL, 0);
+    fail_unless(cwd != NULL, "getcwd failed.");
+
+    dirname = talloc_asprintf(tmp_ctx, "%s/%s/pub_ccdir", cwd, TESTS_PATH);
+    free(cwd);
+    fail_unless(dirname != NULL, "talloc_asprintf failed.");
+    filename = talloc_asprintf(tmp_ctx, "%s/ccfile", dirname);
+    fail_unless(filename != NULL, "talloc_asprintf failed.");
+
+    ret = create_ccache_dir(tmp_ctx, filename, "/abc_%%_abc", uid, gid);
+    fail_unless(ret == EOK, "create_ccache_dir failed.");
+
+    check_dir(dirname, getuid(), getgid(), 01777);
+    RMDIR(dirname);
+}
+END_TEST
+
 void setup_talloc_context(void)
 {
     int ret;
@@ -96,138 +238,93 @@ void free_talloc_context(void)
     fail_unless(ret == 0, "Connot free talloc context.");
 }
 
-START_TEST(test_multiple_substitutions)
+static void do_test(const char *file_template, const char *dir_template,
+                    const char *expected)
 {
-    const char *test_template = BASE"_%u_%U_%u";
-    const char *expected = BASE"_"USERNAME"_"UID"_"USERNAME;
     char *result;
+    int ret;
 
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
+    ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, dir_template);
+    fail_unless(ret == EOK, "Failed to set Ccache dir");
 
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
+    result = expand_ccname_template(tmp_ctx, kr, file_template, true);
+
+    fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
     fail_unless(strcmp(result, expected) == 0,
                 "Expansion failed, result [%s], expected [%s].",
                 result, expected);
 }
+
+START_TEST(test_multiple_substitutions)
+{
+    do_test(BASE"_%u_%U_%u", CCACHE_DIR, BASE"_"USERNAME"_"UID"_"USERNAME);
+    do_test("%d/"FILENAME, BASE"_%u_%U_%u",
+            BASE"_"USERNAME"_"UID"_"USERNAME"/"FILENAME);
+}
 END_TEST
 
 START_TEST(test_username)
 {
-    const char *test_template = BASE"_%u";
-    const char *expected = BASE"_"USERNAME;
-    char *result;
-
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
-
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-    fail_unless(strcmp(result, expected) == 0,
-                "Expansion failed, result [%s], expected [%s].",
-                result, expected);
+    do_test(BASE"_%u", CCACHE_DIR, BASE"_"USERNAME);
+    do_test("%d/"FILENAME, BASE"_%u", BASE"_"USERNAME"/"FILENAME);
 }
 END_TEST
 
 START_TEST(test_uid)
 {
-    const char *test_template = BASE"_%U";
-    const char *expected = BASE"_"UID;
-    char *result;
-
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
-
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-    fail_unless(strcmp(result, expected) == 0,
-                "Expansion failed, result [%s], expected [%s].",
-                result, expected);
+    do_test(BASE"_%U", CCACHE_DIR, BASE"_"UID);
+    do_test("%d/"FILENAME, BASE"_%U", BASE"_"UID"/"FILENAME);
 }
 END_TEST
 
 START_TEST(test_upn)
 {
-    const char *test_template = BASE"_%p";
-    const char *expected = BASE"_"PRINCIPLE_NAME;
-    char *result;
-
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
-
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-    fail_unless(strcmp(result, expected) == 0,
-                "Expansion failed, result [%s], expected [%s].",
-                result, expected);
+    do_test(BASE"_%p", CCACHE_DIR, BASE"_"PRINCIPLE_NAME);
+    do_test("%d/"FILENAME, BASE"_%p", BASE"_"PRINCIPLE_NAME"/"FILENAME);
 }
 END_TEST
 
 START_TEST(test_realm)
 {
-    const char *test_template = BASE"_%r";
-    const char *expected = BASE"_"REALM;
-    char *result;
-
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
-
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-    fail_unless(strcmp(result, expected) == 0,
-                "Expansion failed, result [%s], expected [%s].",
-                result, expected);
+    do_test(BASE"_%r", CCACHE_DIR, BASE"_"REALM);
+    do_test("%d/"FILENAME, BASE"_%r", BASE"_"REALM"/"FILENAME);
 }
 END_TEST
 
 START_TEST(test_home)
 {
-    const char *test_template = BASE"_%h";
-    const char *expected = BASE"_"HOME_DIRECTORY;
-    char *result;
-
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
-
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-    fail_unless(strcmp(result, expected) == 0,
-                "Expansion failed, result [%s], expected [%s].",
-                result, expected);
+    do_test(BASE"_%h", CCACHE_DIR, BASE"_"HOME_DIRECTORY);
+    do_test("%d/"FILENAME, BASE"_%h", BASE"_"HOME_DIRECTORY"/"FILENAME);
 }
 END_TEST
 
 START_TEST(test_ccache_dir)
 {
-    const char *test_template = BASE"_%d";
-    const char *expected = BASE"_"CCACHE_DIR;
     char *result;
+    int ret;
 
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
+    do_test(BASE"_%d", CCACHE_DIR, BASE"_"CCACHE_DIR);
 
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-    fail_unless(strcmp(result, expected) == 0,
-                "Expansion failed, result [%s], expected [%s].",
-                result, expected);
+    ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%d");
+    fail_unless(ret == EOK, "Failed to set Ccache dir");
+
+    result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, true);
+
+    fail_unless(result == NULL, "Using %%d in ccache dir should fail.");
 }
 END_TEST
 
 START_TEST(test_pid)
 {
-    const char *test_template = BASE"_%P";
-    const char *expected = BASE"_"PID;
-    char *result;
-
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
-
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-    fail_unless(strcmp(result, expected) == 0,
-                "Expansion failed, result [%s], expected [%s].",
-                result, expected);
+    do_test(BASE"_%P", CCACHE_DIR, BASE"_"PID);
+    do_test("%d/"FILENAME, BASE"_%P", BASE"_"PID"/"FILENAME);
 }
 END_TEST
 
 START_TEST(test_percent)
 {
-    const char *test_template = BASE"_%%";
-    const char *expected = BASE"_%";
-    char *result;
-
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
-
-    fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-    fail_unless(strcmp(result, expected) == 0,
-                "Expansion failed, result [%s], expected [%s].",
-                result, expected);
+    do_test(BASE"_%%", CCACHE_DIR, BASE"_%");
+    do_test("%d/"FILENAME, BASE"_%%", BASE"_%/"FILENAME);
 }
 END_TEST
 
@@ -235,8 +332,17 @@ START_TEST(test_unknow_template)
 {
     const char *test_template = BASE"_%X";
     char *result;
+    int ret;
 
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
+    result = expand_ccname_template(tmp_ctx, kr, test_template, true);
+
+    fail_unless(result == NULL, "Unknown template [%s] should fail.",
+                test_template);
+
+    ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%X");
+    fail_unless(ret == EOK, "Failed to set Ccache dir");
+    test_template = "%d/"FILENAME;
+    result = expand_ccname_template(tmp_ctx, kr, test_template, true);
 
     fail_unless(result == NULL, "Unknown template [%s] should fail.",
                 test_template);
@@ -248,7 +354,7 @@ START_TEST(test_NULL)
     char *test_template = NULL;
     char *result;
 
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
+    result = expand_ccname_template(tmp_ctx, kr, test_template, true);
 
     fail_unless(result == NULL, "Expected NULL as a result for an empty 
input.",
                 test_template);
@@ -260,7 +366,7 @@ START_TEST(test_no_substitution)
     const char *test_template = BASE;
     char *result;
 
-    result = expand_ccname_template(tmp_ctx, kr, test_template);
+    result = expand_ccname_template(tmp_ctx, kr, test_template, true);
 
     fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
     fail_unless(strcmp(result, test_template) == 0,
@@ -290,18 +396,74 @@ Suite *krb5_utils_suite (void)
     tcase_add_test (tc_ccname_template, test_multiple_substitutions);
     suite_add_tcase (s, tc_ccname_template);
 
+    TCase *tc_create_dir = tcase_create("create_dir");
+    tcase_add_checked_fixture (tc_create_dir, setup_create_dir,
+                               teardown_create_dir);
+    tcase_add_test (tc_create_dir, test_mkdir_simple);
+    tcase_add_test (tc_create_dir, test_mkdir_parents);
+    tcase_add_test (tc_create_dir, test_mkdir_nonexisting_parent);
+    tcase_add_test (tc_create_dir, test_priv_ccache_dir);
+    tcase_add_test (tc_create_dir, test_pub_ccache_dir);
+    suite_add_tcase (s, tc_create_dir);
+
     return s;
 }
 
-int main(void)
+int main(int argc, const char *argv[])
 {
-  int number_failed;
-  Suite *s = krb5_utils_suite ();
-  SRunner *sr = srunner_create (s);
-  /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
-  srunner_run_all(sr, CK_ENV);
-  number_failed = srunner_ntests_failed (sr);
-  srunner_free (sr);
-  return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    int ret;
+    int opt;
+    poptContext pc;
+    int number_failed;
+
+    struct poptOption long_options[] = {
+        POPT_AUTOHELP
+        SSSD_MAIN_OPTS
+        { NULL }
+    };
+
+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+    while((opt = poptGetNextOpt(pc)) != -1) {
+        switch(opt) {
+        default:
+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
+                    poptBadOption(pc, 0), poptStrerror(opt));
+            poptPrintUsage(pc, stderr, 0);
+            return 1;
+        }
+    }
+    poptFreeContext(pc);
+
+
+    ret = mkdir(TESTS_PATH, 0775);
+    if (ret != EOK) {
+        fprintf(stderr, "Could not create empty directory [%s]. ", TESTS_PATH);
+        if (errno == EEXIST) {
+            fprintf(stderr, "Please remove [%s].\n", TESTS_PATH);
+        } else {
+            fprintf(stderr, "[%d][%s].\n", errno, strerror(errno));
+        }
+
+        return 1;
+    }
+
+    Suite *s = krb5_utils_suite ();
+    SRunner *sr = srunner_create (s);
+    /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
+    srunner_run_all(sr, CK_ENV);
+    number_failed = srunner_ntests_failed (sr);
+    srunner_free (sr);
+    if (number_failed == 0) {
+        ret = rmdir(TESTS_PATH);
+        if (ret != EOK) {
+            fprintf(stderr, "Cannot remove [%s]: [%d][%s].\n", TESTS_PATH,
+                            errno, strerror(errno));
+            return EXIT_FAILURE;
+        }
+
+        return EXIT_SUCCESS;
+    }
+
+    return EXIT_FAILURE;
 }
 
-- 
1.6.6

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to