Read and write users db from file.
authorJarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
Mon, 15 Nov 2010 01:43:12 +0000 (17:43 -0800)
committerJarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
Mon, 15 Nov 2010 02:42:57 +0000 (18:42 -0800)
src/smack.c
src/smack.h
tests/check_smack.c
tests/data/rw_users-excepted.txt [new file with mode: 0644]
tests/data/rw_users-in.txt [new file with mode: 0644]

index 5bab567..3d3b5ee 100644 (file)
@@ -55,9 +55,21 @@ struct smack_ruleset {
        struct smack_subject *subjects;
 };
 
+struct smack_user {
+       char *user;
+       char label[SMACK64_LEN + 1];
+       UT_hash_handle hh;
+};
+
+struct smack_users {
+       struct smack_user *users;
+};
+
 static int update_rule(struct smack_ruleset *handle,
                       const char *subject_str, const char *object_str,
                       unsigned ac);
+static int update_user(struct smack_users *handle,
+                      const char *user, const char *label);
 inline unsigned str_to_ac(const char *str);
 inline void ac_to_str(unsigned ac, char *str, int format);
 
@@ -232,6 +244,88 @@ int smack_have_access_rule(smack_ruleset_t handle, const char *subject,
        return ((o->ac & ac) == ac);
 }
 
+smack_users_t smack_create_users()
+{
+
+       struct smack_users *result =
+               calloc(1, sizeof(struct smack_users));
+       return result;
+}
+
+void smack_destroy_users(smack_users_t handle)
+{
+       struct smack_user *u, *tmp;
+
+       HASH_ITER(hh, handle->users, u, tmp) {
+               HASH_DEL(handle->users, u);
+               free(u->user);
+               free(u);
+       }
+}
+
+int smack_read_users(smack_users_t handle, const char *path)
+{
+       FILE *file;
+       char *buf = NULL;
+       size_t size;
+       char *user;
+       char *label;
+       int ret = 0;
+
+       file = fopen(path, "r");
+       if (file == NULL)
+               return -1;
+
+       while (getline(&buf, &size, file) != -1) {
+               user = strtok(buf, " ");
+               if (user == NULL || user[0] == '#')
+                       continue;
+
+               label = strtok(NULL, " \n");
+               if (label == NULL)
+                       ret = -1;
+               else
+                       ret = update_user(handle, user, label);
+
+               free(buf);
+               buf = NULL;
+
+               if (ret != 0)
+                       break;
+       }
+
+       if (ferror(file))
+               ret = -1;
+
+       free(buf);
+       fclose(file);
+       return 0;
+}
+
+int smack_write_users(smack_users_t handle, const char *path)
+{
+       struct smack_user *u, *tmp;
+       FILE *file;
+       char str[6];
+       int err;
+
+       file = fopen(path, "w+");
+       if (!file)
+               return -1;
+
+       HASH_ITER(hh, handle->users, u, tmp) {
+               err = fprintf(file, "%s %s\n",
+                             u->user, u->label);
+               if (err < 0) {
+                       fclose(file);
+                       return errno;
+               }
+       }
+
+       fclose(file);
+       return 0;
+}
+
 int smack_set_file_smack(const char *path, const char *smack, int flags)
 {
        size_t size;
@@ -308,6 +402,10 @@ static int update_rule(struct smack_ruleset *handle,
        struct smack_subject *s = NULL;
        struct smack_object *o = NULL;
 
+       if (strlen(subject_str) > SMACK64_LEN &&
+           strlen(object_str) > SMACK64_LEN)
+               return -ERANGE;
+
        HASH_FIND_STR(handle->subjects, subject_str, s);
        if (s == NULL) {
                s = calloc(1, sizeof(struct smack_subject));
@@ -326,6 +424,25 @@ static int update_rule(struct smack_ruleset *handle,
        return 0;
 }
 
+static int update_user(struct smack_users *handle,
+                      const char *user, const char *label)
+{
+       struct smack_user *u = NULL;
+
+       if (strlen(label) > SMACK64_LEN)
+               return -ERANGE;
+
+       HASH_FIND_STR(handle->users, user, u);
+       if (u == NULL) {
+               u = calloc(1, sizeof(struct smack_subject));
+               u->user = strdup(user);
+               HASH_ADD_STR(handle->users, user, u);
+       }
+
+       strcpy(u->label, label);
+       return 0;
+}
+
 inline unsigned str_to_ac(const char *str)
 {
        int i, count;
index 33cadf5..7f5784e 100644 (file)
@@ -37,6 +37,8 @@
  */
 typedef struct smack_ruleset *smack_ruleset_t;
 
+typedef struct smack_users *smack_users_t;
+
 #define SMACK_FORMAT_CONFIG 0
 #define SMACK_FORMAT_KERNEL 1
 
@@ -136,6 +138,38 @@ extern void smack_remove_object_rules(smack_ruleset_t handle,
  */
 extern int smack_have_access_rule(smack_ruleset_t handle, const char *subject,
                                  const char *object, const char *access);
+/*!
+ * Create users database. The returned rule set must be freed with
+ * smack_destroy_ruleset().
+ *
+ * @return handle to the users db. Returns NULL if creation fails.
+ */
+extern smack_users_t smack_create_users();
+
+/*!
+ * Free users database.
+ *
+ * @param handle handle to a ruleset
+ */
+extern void smack_destroy_users(smack_users_t handle);
+
+/*!
+ * Read users from a given file.
+ *
+ * @param handle handle to a users db
+ * @param path path to the file containing users
+ * @return 0 on success
+ */
+extern int smack_read_users(smack_users_t handle, const char *path);
+
+/*!
+ * Write users to a given file.
+ *
+ * @param handle handle to a users db
+ * @param path path to the users file
+ * @return 0 on success
+ */
+extern int smack_write_users(smack_users_t handle, const char *path);
 
 /*!
  * Set SMACK64 security attribute for a given path.
index fd93390..ee06f98 100644 (file)
@@ -166,6 +166,21 @@ START_TEST(test_have_access_removed_rule)
 }
 END_TEST
 
+START_TEST(test_rw_users)
+{
+       int rc;
+       smack_users_t users = smack_create_users();
+       fail_unless(users != NULL, "Users creation failed");
+       rc = smack_read_users(users, "data/rw_users-in.txt");
+       fail_unless(rc == 0, "Failed to read users");
+       rc = smack_write_users(users, "rw_users-result.txt");
+       fail_unless(rc == 0, "Failed to write ruleset");
+       rc = files_equal("rw_users-result.txt", "data/rw_users-excepted.txt");
+       fail_unless(rc == 1, "Unexcepted result");
+       smack_destroy_users(users);
+}
+END_TEST
+
 START_TEST(test_set_file_smack)
 {
        FILE *file;
@@ -227,6 +242,7 @@ Suite *ruleset_suite (void)
        tcase_add_test(tc_core, test_remove_object_rules);
        tcase_add_test(tc_core, test_have_access_rule);
        tcase_add_test(tc_core, test_have_access_removed_rule);
+       tcase_add_test(tc_core, test_rw_users);
        suite_add_tcase(s, tc_core);
 
        tc_core = tcase_create("Security attributes");
diff --git a/tests/data/rw_users-excepted.txt b/tests/data/rw_users-excepted.txt
new file mode 100644 (file)
index 0000000..f25a925
--- /dev/null
@@ -0,0 +1,2 @@
+foo Apple
+bar Orange
diff --git a/tests/data/rw_users-in.txt b/tests/data/rw_users-in.txt
new file mode 100644 (file)
index 0000000..f25a925
--- /dev/null
@@ -0,0 +1,2 @@
+foo Apple
+bar Orange