]> Kevux Git Server - fll/commitdiff
Update: capability.
authorKevin Day <thekevinday@gmail.com>
Thu, 18 Mar 2021 22:43:51 +0000 (17:43 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 18 Mar 2021 22:54:30 +0000 (17:54 -0500)
Add missing typedefs and cleanup ordering of typedefs.

Add several more functions.
I found more functions than what are implemented now.
The problem is my current systems manpages don't easily find them (such as cap_new_launcher, cap_iab_init, cap_iab_get_vector, etc..).
I will not implement this for now and will need to do some research to see what they are.
Some functions are documented in the manpages as deprecated or obsolete.
I would rather not want to implement any of the deprecated or obsolete functions.

Make sure all "implemented not" functions still do parameter checking.

Use "clone" instead of "duplicate" to be more consistent with the terminology used in this project.

Add additional documentation.

level_0/f_capability/c/capability-common.h
level_0/f_capability/c/capability.c
level_0/f_capability/c/capability.h

index 0af5f38a0dfe44c28f5bcc165612528e236c8739..098cd7878e9e45d940ae4c895b8760b69b698b70 100644 (file)
@@ -35,20 +35,25 @@ extern "C" {
   // provide stubs in the event that libcap is disabled.
   #ifdef _di_libcap_
     typedef void * cap_t;
-    typedef int cap_value_t;
     typedef int cap_flag_t;
     typedef int cap_flag_value_t;
+    typedef unsigned int cap_mode_t;
+    typedef int cap_value_t;
   #endif // _di_libcap_
 
   typedef cap_t f_capability_t;
-  typedef cap_value_t f_capability_value_t;
+  typedef unsigned int f_capability_bits_t;
   typedef cap_flag_t f_capability_flag_t;
   typedef cap_flag_value_t f_capability_flag_value_t;
+  typedef cap_mode_t f_capability_mode_t;
+  typedef cap_value_t f_capability_value_t;
 
   #define f_capability_t_initialize 0
-  #define f_capability_value_t_initialize 0
+  #define f_capability_bits_t_initialize 0
   #define f_capability_flag_t_initialize 0
   #define f_capability_flag_value_t_initialize 0
+  #define f_capability_mode_t_initialize 0
+  #define f_capability_value_t_initialize 0
 #endif // _di_f_capability_t_
 
 #ifdef __cplusplus
index b7c0c6e1bd44ba700c8f44e3741bd41b77d1c586..ca95b0693419ca5b7a59b94c8e08f0a343e6670e 100644 (file)
@@ -6,87 +6,234 @@ extern "C" {
 
 #ifdef _di_libcap_
 
+  #ifndef _di_f_capability_ambient_get_
+    f_status_t f_capability_ambient_get(const f_capability_value_t value, int *ambient) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!ambient) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_ambient_get_
+
+  #ifndef _di_f_capability_ambient_reset_
+    f_status_t f_capability_ambient_reset() {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_ambient_reset_
+
+  #ifndef _di_f_capability_ambient_set_
+    f_status_t f_capability_ambient_set(const f_capability_value_t value, const f_capability_flag_value_t value_flag) {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_ambient_set_
+
+  #ifndef _di_f_capability_groups_set_
+    f_status_t f_capability_groups_set(const gid_t id_group, const size_t total, const gid_t id_groups[]) {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_groups_set_
+
   #ifndef _di_f_capability_clear_
     f_status_t f_capability_clear(f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_clear_
 
   #ifndef _di_f_capability_clear_flag_
     f_status_t f_capability_clear_flag(const f_capability_flag_t flag, f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_clear_flag_
 
+  #ifndef _di_f_capability_clone_
+    f_status_t f_capability_clone(const f_capability_t source, f_capability_t *destination) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!destination) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_clone_
+
   #ifndef _di_f_capability_compare_
     f_status_t f_capability_compare(const f_capability_t capability1, const f_capability_t capability2, int *flags) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!flags) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_compare_
 
   #ifndef _di_f_capability_copy_external_
     f_status_t f_capability_copy_external(const f_capability_t capability, const ssize_t max, void *external, ssize_t *size) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!external) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_copy_external_
 
   #ifndef _di_f_capability_copy_internal_
     f_status_t f_capability_copy_internal(const void *external, f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!external) return F_status_set_error(F_parameter);
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_copy_internal_
 
   #ifndef _di_f_capability_delete_
     f_status_t f_capability_delete(f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_delete_
 
-  #ifndef _di_f_capability_duplicate_
-    f_status_t f_capability_duplicate(const f_capability_t source, f_capability_t *destination) {
+  #ifndef _di_f_capability_file_descriptor_get_
+    f_status_t f_capability_file_descriptor_get(const int descriptor, f_capability_t *capability) {
       #ifndef _di_level_0_parameter_checking_
-        if (!destination) return F_status_set_error(F_parameter);
+        if (!capability) return F_status_set_error(F_parameter);
       #endif // _di_level_0_parameter_checking_
 
       return F_status_set_error(F_implemented_not);
     }
-  #endif // _di_f_capability_duplicate_
+  #endif // _di_f_capability_file_descriptor_get_
+
+  #ifndef _di_f_capability_file_descriptor_set_
+    f_status_t f_capability_file_descriptor_set(const int descriptor, const f_capability_t capability) {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_file_descriptor_set_
+
+  #ifndef _di_f_capability_file_get_
+    f_status_t f_capability_file_get(const f_string_t path, f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_file_get_
+
+  #ifndef _di_f_capability_file_set_
+    f_status_t f_capability_file_set(const f_string_t path, const f_capability_t capability) {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_file_set_
 
   #ifndef _di_f_capability_flag_get_
     f_status_t f_capability_flag_get(const f_capability_t capability, const f_capability_value_t code, const f_capability_flag_t flag, f_capability_flag_value_t *enabled) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!enabled) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_flag_get_
 
   #ifndef _di_f_capability_flag_set_
     f_status_t f_capability_flag_set(const f_capability_flag_t flag, const f_capability_flag_value_t enabled, const f_int32s_t codes, f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_flag_set_
 
   #ifndef _di_f_capability_from_name_
     f_status_t f_capability_from_name(const f_string_t name, f_capability_value_t *code) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!code) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_from_name_
 
   #ifndef _di_f_capability_from_text_
     f_status_t f_capability_from_text(const f_string_t text, f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_from_text_
 
-  #ifndef _di_f_capability_get_file_
-    f_status_t f_capability_get_file(const f_string_t path, f_capability_t *capability) {
+  #ifndef f_capability_groups_id_set
+    f_status_t f_capability_groups_id_set(const gid_t id_group, const size_t total, const gid_t id_groups[]) {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // f_capability_groups_id_set
+
+  #ifndef _di_f_capability_initialize_
+    f_status_t f_capability_initialize(f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_initialize_
+
+  #ifndef _di_f_capability_mode_get_
+    f_status_t f_capability_mode_get(f_capability_mode_t *mode) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!mode) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
-  #endif // _di_f_capability_get_file_
+  #endif // _di_f_capability_mode_get_
+
+  #ifndef _di_f_capability_mode_get_name_
+    f_status_t f_capability_mode_get_name(const f_capability_mode_t mode, f_string_constant_t *name) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!name) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
 
-  #ifndef _di_f_capability_get_file_descriptor_
-    f_status_t f_capability_get_file_descriptor(const int descriptor, f_capability_t *capability) {
       return F_status_set_error(F_implemented_not);
     }
-  #endif // _di_f_capability_get_file_descriptor_
+  #endif // _di_f_capability_mode_get_name_
+
+  #ifndef _di_f_capability_mode_set_
+    f_status_t f_capability_mode_set(const f_capability_mode_t mode) {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_mode_set_
+
+  #ifndef _di_f_capability_owner_get_
+    f_status_t f_capability_owner_get(const f_capability_t capability, uid_t *id_user) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!id_user) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_owner_get_
+
+  #ifndef _di_f_capability_owner_set_
+    f_status_t f_capability_owner_set(const f_capability_t capability, const uid_t id_user) {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // _di_f_capability_owner_set_
 
   #ifndef _di_f_capability_process_bound_drop_
     f_status_t f_capability_process_bound_drop(f_capability_value_t code, int *bound) {
@@ -108,16 +255,6 @@ extern "C" {
     }
   #endif // _di_f_capability_process_bound_get_
 
-  #ifndef _di_f_capability_initialize_
-    f_status_t f_capability_initialize(f_capability_t *capability) {
-      #ifndef _di_level_0_parameter_checking_
-        if (!capability) return F_status_set_error(F_parameter);
-      #endif // _di_level_0_parameter_checking_
-
-      return F_status_set_error(F_implemented_not);
-    }
-  #endif // _di_f_capability_initialize_
-
   #ifndef _di_f_capability_process_get_
     f_status_t f_capability_process_get(f_capability_t *capability) {
       #ifndef _di_level_0_parameter_checking_
@@ -144,20 +281,28 @@ extern "C" {
     }
   #endif // _di_f_capability_process_set_
 
-  #ifndef _di_f_capability_set_file_
-    f_status_t f_capability_set_file(const f_string_t path, const f_capability_t capability) {
+  #ifndef _di_f_capability_security_bits_get_
+    f_status_t f_capability_security_bits_get(f_capability_bits_t *bits) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!bits) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
-  #endif // _di_f_capability_set_file_
+  #endif // _di_f_capability_security_bits_get_
 
-  #ifndef _di_f_capability_set_file_descriptor_
-    f_status_t f_capability_set_file_descriptor(const int descriptor, const f_capability_t capability) {
+  #ifndef _di_f_capability_security_bits_set_
+    f_status_t f_capability_security_bits_set(const f_capability_bits_t bits) {
       return F_status_set_error(F_implemented_not);
     }
-  #endif // _di_f_capability_set_file_descriptor_
+  #endif // _di_f_capability_security_bits_set_
 
   #ifndef _di_f_capability_size_
     f_status_t f_capability_size(const f_capability_t capability, ssize_t *size) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!size) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_size_
@@ -192,12 +337,87 @@ extern "C" {
 
   #ifndef _di_f_capability_to_text_
     f_status_t f_capability_to_text(const f_capability_t capability, f_string_dynamic_t *text) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!text) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
       return F_status_set_error(F_implemented_not);
     }
   #endif // _di_f_capability_to_text_
 
+  #ifndef f_capability_user_id_set
+    f_status_t f_capability_user_id_set(const uid_t id_user) {
+      return F_status_set_error(F_implemented_not);
+    }
+  #endif // f_capability_user_id_set
+
 #else // _di_libcap_
 
+  #ifndef _di_f_capability_ambient_get_
+    f_status_t f_capability_ambient_get(const f_capability_value_t value, int *ambient) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!ambient) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      *ambient = cap_get_ambient(value);
+
+      if (*ambient == -1) {
+        return F_status_set_error(F_supported_not);
+      }
+
+      return F_none;
+    }
+  #endif // _di_f_capability_ambient_get_
+
+  #ifndef _di_f_capability_ambient_reset_
+    f_status_t f_capability_ambient_reset() {
+
+      if (cap_reset_ambient() == -1) {
+        // The documentation doesn't explicitly describe this for "reset" but it can be implicitly inferred because they say "..all of the setting functions..".
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
+    }
+  #endif // _di_f_capability_ambient_reset_
+
+  #ifndef _di_f_capability_ambient_set_
+    f_status_t f_capability_ambient_set(const f_capability_value_t value, const f_capability_flag_value_t value_flag) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!value_flag) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      if (cap_set_ambient(value, value_flag) == -1) {
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
+    }
+  #endif // _di_f_capability_ambient_set_
+
+  #ifndef _di_f_capability_groups_set_
+    f_status_t f_capability_groups_set(const gid_t id_group, const size_t total, const gid_t id_groups[]) {
+
+      if (cap_setgroups(id_group, total, id_groups) == -1) {
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == ERANGE) return F_status_set_error(F_range_not);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
+    }
+  #endif // _di_f_capability_groups_set_
+
   #ifndef _di_f_capability_clear_
     f_status_t f_capability_clear(f_capability_t *capability) {
       #ifndef _di_level_0_parameter_checking_
@@ -232,6 +452,25 @@ extern "C" {
     }
   #endif // _di_f_capability_clear_flag_
 
+  #ifndef _di_f_capability_clone_
+    f_status_t f_capability_clone(const f_capability_t source, f_capability_t *destination) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!destination) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      *destination = cap_dup(source);
+
+      if (*destination) {
+        return F_none;
+      }
+
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+
+      return F_status_set_error(F_failure);
+    }
+  #endif // _di_f_capability_clone_
+
   #ifndef _di_f_capability_compare_
     f_status_t f_capability_compare(const f_capability_t capability1, const f_capability_t capability2, int *flags) {
       if (*flags) {
@@ -320,24 +559,99 @@ extern "C" {
     }
   #endif // _di_f_capability_delete_
 
-  #ifndef _di_f_capability_duplicate_
-    f_status_t f_capability_duplicate(const f_capability_t source, f_capability_t *destination) {
+  #ifndef _di_f_capability_file_descriptor_get_
+    f_status_t f_capability_file_descriptor_get(const int descriptor, f_capability_t *capability) {
       #ifndef _di_level_0_parameter_checking_
-        if (!destination) return F_status_set_error(F_parameter);
+        if (!capability) return F_status_set_error(F_parameter);
       #endif // _di_level_0_parameter_checking_
 
-      *destination = cap_dup(source);
+      *capability = cap_get_fd(descriptor);
 
-      if (*destination) {
+      if (*capability) {
         return F_none;
       }
 
-      if (errno == EINVAL) return F_status_set_error(F_parameter);
+      if (errno == EACCES) return F_status_set_error(F_access_denied);
+      if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
+      if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
+      if (errno == ENOENT) return F_status_set_error(F_file_found_not);
       if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+      if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
+      if (errno == EPERM) return F_status_set_error(F_prohibited);
+      if (errno == EROFS) return F_status_set_error(F_supported_not);
 
       return F_status_set_error(F_failure);
     }
-  #endif // _di_f_capability_duplicate_
+  #endif // _di_f_capability_file_descriptor_get_
+
+  #ifndef _di_f_capability_file_descriptor_set_
+    f_status_t f_capability_file_descriptor_set(const int descriptor, const f_capability_t capability) {
+
+      const int result = cap_set_fd(descriptor, capability);
+
+      if (result == -1) {
+        if (errno == EACCES) return F_status_set_error(F_access_denied);
+        if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
+        if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
+        if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+        if (errno == EROFS) return F_status_set_error(F_supported_not);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
+    }
+  #endif // _di_f_capability_file_descriptor_set_
+
+  #ifndef _di_f_capability_file_get_
+    f_status_t f_capability_file_get(const f_string_t path, f_capability_t *capability) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!capability) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
+
+      *capability = cap_get_file(path);
+
+      if (*capability) {
+        return F_none;
+      }
+
+      if (errno == EACCES) return F_status_set_error(F_access_denied);
+      if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
+      if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
+      if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+      if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
+      if (errno == EPERM) return F_status_set_error(F_prohibited);
+      if (errno == EROFS) return F_status_set_error(F_supported_not);
+
+      return F_status_set_error(F_failure);
+    }
+  #endif // _di_f_capability_file_get_
+
+  #ifndef _di_f_capability_file_set_
+    f_status_t f_capability_file_set(const f_string_t path, const f_capability_t capability) {
+
+      const int result = cap_set_file(path, capability);
+
+      if (result == -1) {
+        if (errno == EACCES) return F_status_set_error(F_access_denied);
+        if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
+        if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
+        if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+        if (errno == EROFS) return F_status_set_error(F_supported_not);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
+    }
+  #endif // _di_f_capability_file_set_
 
   #ifndef _di_f_capability_flag_get_
     f_status_t f_capability_flag_get(const f_capability_t capability, const f_capability_value_t code, const f_capability_flag_t flag, f_capability_flag_value_t *enabled) {
@@ -407,74 +721,111 @@ extern "C" {
     }
   #endif // _di_f_capability_from_text_
 
-  #ifndef _di_f_capability_get_file_
-    f_status_t f_capability_get_file(const f_string_t path, f_capability_t *capability) {
+  #ifndef f_capability_groups_id_set
+    f_status_t f_capability_groups_id_set(const gid_t id_group, const size_t total, const gid_t id_groups[]) {
+
+      if (cap_setgroups(id_group, total, id_groups) == -1) {
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
+    }
+  #endif // f_capability_groups_id_set
+
+  #ifndef _di_f_capability_initialize_
+    f_status_t f_capability_initialize(f_capability_t *capability) {
       #ifndef _di_level_0_parameter_checking_
         if (!capability) return F_status_set_error(F_parameter);
       #endif // _di_level_0_parameter_checking_
 
-      *capability = cap_get_file(path);
+      *capability = cap_init();
 
       if (*capability) {
         return F_none;
       }
 
-      if (errno == EACCES) return F_status_set_error(F_access_denied);
-      if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
-      if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
-      if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
       if (errno == ENOMEM) return F_status_set_error(F_memory_not);
-      if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
-      if (errno == EPERM) return F_status_set_error(F_prohibited);
-      if (errno == EROFS) return F_status_set_error(F_supported_not);
 
       return F_status_set_error(F_failure);
     }
-  #endif // _di_f_capability_get_file_
+  #endif // _di_f_capability_initialize_
 
-  #ifndef _di_f_capability_get_file_descriptor_
-    f_status_t f_capability_get_file_descriptor(const int descriptor, f_capability_t *capability) {
+  #ifndef _di_f_capability_mode_get_
+    f_status_t f_capability_mode_get(f_capability_mode_t *mode) {
       #ifndef _di_level_0_parameter_checking_
-        if (!capability) return F_status_set_error(F_parameter);
+        if (!mode) return F_status_set_error(F_parameter);
       #endif // _di_level_0_parameter_checking_
 
-      *capability = cap_get_fd(descriptor);
+      *mode = cap_get_mode();
 
-      if (*capability) {
-        return F_none;
-      }
+      return F_none;
+    }
+  #endif // _di_f_capability_mode_get_
 
-      if (errno == EACCES) return F_status_set_error(F_access_denied);
-      if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
-      if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
-      if (errno == ENOENT) return F_status_set_error(F_file_found_not);
-      if (errno == ENOMEM) return F_status_set_error(F_memory_not);
-      if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
-      if (errno == EPERM) return F_status_set_error(F_prohibited);
-      if (errno == EROFS) return F_status_set_error(F_supported_not);
+  #ifndef _di_f_capability_mode_get_name_
+    f_status_t f_capability_mode_get_name(const f_capability_mode_t mode, f_string_constant_t *name) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!mode) return F_status_set_error(F_parameter);
+        if (!name) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
 
-      return F_status_set_error(F_failure);
+      *name = cap_mode_name(mode);
+
+      return F_none;
     }
-  #endif // _di_f_capability_get_file_descriptor_
+  #endif // _di_f_capability_mode_get_name_
 
-  #ifndef _di_f_capability_initialize_
-    f_status_t f_capability_initialize(f_capability_t *capability) {
+  #ifndef _di_f_capability_mode_set_
+    f_status_t f_capability_mode_set(const f_capability_mode_t mode) {
+
+      if (cap_set_mode(mode) == -1) {
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
+    }
+  #endif // _di_f_capability_mode_set_
+
+  #ifndef _di_f_capability_owner_get_
+    f_status_t f_capability_owner_get(const f_capability_t capability, uid_t *id_user) {
       #ifndef _di_level_0_parameter_checking_
-        if (!capability) return F_status_set_error(F_parameter);
+        if (!id_user) return F_status_set_error(F_parameter);
       #endif // _di_level_0_parameter_checking_
 
-      *capability = cap_init();
+      *id_user = cap_get_nsowner(capability);
 
-      if (*capability) {
-        return F_none;
-      }
+      return F_none;
+    }
+  #endif // _di_f_capability_owner_get_
 
-      if (errno == EINVAL) return F_status_set_error(F_parameter);
-      if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+  #ifndef _di_f_capability_owner_set_
+    f_status_t f_capability_owner_set(const f_capability_t capability, const uid_t id_user) {
 
-      return F_status_set_error(F_failure);
+      if (cap_set_nsowner(capability, id_user) == -1) {
+        if (errno == EACCES) return F_status_set_error(F_access_denied);
+        if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
+        if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
+        if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+        if (errno == EROFS) return F_status_set_error(F_supported_not);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
     }
-  #endif // _di_f_capability_initialize_
+  #endif // _di_f_capability_owner_set_
 
   #ifndef _di_f_capability_process_bound_drop_
     f_status_t f_capability_process_bound_drop(f_capability_value_t code, int *bound) {
@@ -562,49 +913,32 @@ extern "C" {
     }
   #endif // _di_f_capability_process_set_
 
-  #ifndef _di_f_capability_set_file_
-    f_status_t f_capability_set_file(const f_string_t path, const f_capability_t capability) {
-
-      const int result = cap_set_file(path, capability);
-
-      if (result == -1) {
-        if (errno == EACCES) return F_status_set_error(F_access_denied);
-        if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
-        if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
-        if (errno == ENOENT) return F_status_set_error(F_file_found_not);
-        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
-        if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
-        if (errno == EPERM) return F_status_set_error(F_prohibited);
-        if (errno == EROFS) return F_status_set_error(F_supported_not);
+  #ifndef _di_f_capability_security_bits_get_
+    f_status_t f_capability_security_bits_get(f_capability_bits_t *bits) {
+      #ifndef _di_level_0_parameter_checking_
+        if (!bits) return F_status_set_error(F_parameter);
+      #endif // _di_level_0_parameter_checking_
 
-        return F_status_set_error(F_failure);
-      }
+      *bits = cap_get_secbits();
 
       return F_none;
     }
-  #endif // _di_f_capability_set_file_
+  #endif // _di_f_capability_security_bits_get_
 
-  #ifndef _di_f_capability_set_file_descriptor_
-    f_status_t f_capability_set_file_descriptor(const int descriptor, const f_capability_t capability) {
+  #ifndef _di_f_capability_security_bits_set_
+    f_status_t f_capability_security_bits_set(const f_capability_bits_t bits) {
 
-      const int result = cap_set_fd(descriptor, capability);
-
-      if (result == -1) {
-        if (errno == EACCES) return F_status_set_error(F_access_denied);
-        if (errno == EBADFD) return F_status_set_error(F_descriptor_not);
-        if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not);
-        if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+      if (cap_set_secbits(bits) == -1) {
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
         if (errno == ENOMEM) return F_status_set_error(F_memory_not);
-        if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
         if (errno == EPERM) return F_status_set_error(F_prohibited);
-        if (errno == EROFS) return F_status_set_error(F_supported_not);
 
         return F_status_set_error(F_failure);
       }
 
       return F_none;
     }
-  #endif // _di_f_capability_set_file_descriptor_
+  #endif // _di_f_capability_security_bits_set_
 
   #ifndef _di_f_capability_size_
     f_status_t f_capability_size(const f_capability_t capability, ssize_t *size) {
@@ -726,6 +1060,21 @@ extern "C" {
     }
   #endif // _di_f_capability_to_text_
 
+  #ifndef _di_f_capability_user_id_set_
+    f_status_t f_capability_user_id_set(const uid_t id_user) {
+
+      if (cap_setuid(id_user) == -1) {
+        if (errno == EINVAL) return F_status_set_error(F_parameter);
+        if (errno == ENOMEM) return F_status_set_error(F_memory_not);
+        if (errno == EPERM) return F_status_set_error(F_prohibited);
+
+        return F_status_set_error(F_failure);
+      }
+
+      return F_none;
+    }
+  #endif // _di_f_capability_user_id_set_
+
 #endif // _di_libcap_
 
 #ifdef __cplusplus
index 027f74808ca4ed983422bd8b0dd2583e6b307857..57581a2c423fbb1deab50724de29c4f94a3ba2a6 100644 (file)
  *
  * When _di_libcap_ is defined (-D_di_libcap_) then many of the structures and functions provided here are stubs.
  * Compilations with _di_libcap_ will not be binary compatible with compilations without _di_libcap_.
+ *
+ * The libcap documentation claims that the Linux kernel fails to honor the  POSIX semantics for setting capabilities and securebits in the presence of pthreads.
+ * This is because changing capability sets, by default, only affects the running thread.
+ * The libcap documentation further claims that "To be meaningfully secure, however, the capability sets should be mirrored by all threads...".
+ * This is untrue and should be considered with caution (for example, a init program (like sysvinit) may want to run different threads with different capabilities).
+ * The libcap povides a separate libray "libpsx", for threads and then suggests linking with "-lcap -lpsx -lpthread --wrap=pthread_create" to "work-around" the perceived limitation.
+ * Use such a work-around with caution.
+ * This project makes no assumptions that all threads must share capabilities.
+ * This project instead recommends explicitly setting the capabilities for each thread (when capabilities change, then change all appropriate threads).
  */
 #ifndef _F_capability_h
 #define _F_capability_h
@@ -40,6 +49,72 @@ extern "C" {
 #endif
 
 /**
+ * Set the ambient capability.
+ *
+ * @param value
+ *   The capability value.
+ * @param ambient
+ *   The retrieved ambient value.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_supported_not (with error bit) if the system does not support ambient capabilities.
+ *
+ *   F_failure (with error bit) on any other failure.
+ *
+ * @see cap_set_ambient()
+ */
+#ifndef _di_f_capability_ambient_get_
+  extern f_status_t f_capability_ambient_get(const f_capability_value_t value, int *ambient);
+#endif // _di_f_capability_ambient_get_
+
+/**
+ * Reset the ambient capability.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_memory_not (with error bit) if a out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the filesystem does not permit this operation.
+ *
+ *   F_failure (with error bit) on any other failure.
+ *
+ * @see cap_reset_ambient()
+ */
+#ifndef _di_f_capability_ambient_reset_
+  extern f_status_t f_capability_ambient_reset();
+#endif // _di_f_capability_ambient_reset_
+
+/**
+ * Set the ambient capability.
+ *
+ * @param value
+ *   The capability value.
+ * @param value_flag
+ *   The capability flag value.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_memory_not (with error bit) if a out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the filesystem does not permit this operation.
+ *
+ *   F_failure (with error bit) on any other failure.
+ *
+ * @see cap_set_ambient()
+ */
+#ifndef _di_f_capability_ambient_set_
+  extern f_status_t f_capability_ambient_set(const f_capability_value_t value, const f_capability_flag_value_t value_flag);
+#endif // _di_f_capability_ambient_set_
+
+/**
  * Clear the capability structure.
  *
  * @param capability
@@ -83,6 +158,30 @@ extern "C" {
 #endif // _di_f_capability_clear_flag_
 
 /**
+ * Clone (copy) the capability structure.
+ *
+ * @param source
+ *   The capability to clone.
+ * @param destination
+ *   The capability to copy to.
+ *   This must be freed via f_capability_delete() when finished with.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_memory_not (with error bit) if a out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   F_failure (with error bit) on any other failure.
+ *
+ * @see cap_dup()
+ */
+#ifndef _di_f_capability_clone_
+  extern f_status_t f_capability_clone(const f_capability_t source, f_capability_t *destination);
+#endif // _di_f_capability_clone_
+
+/**
  * Compare two capability structures.
  *
  * @param capability1
@@ -184,28 +283,126 @@ extern "C" {
 #endif // _di_f_capability_delete_
 
 /**
- * Duplicate (copy) the capability structure.
+ * Get the capability of a file represented by a file descriptor.
  *
- * @param source
- *   The capability to duplicate.
- * @param destination
- *   The capability to copy to.
+ * @param descriptor
+ *   The file descriptor.
+ * @param capability
+ *   The retrieved capability.
  *   This must be freed via f_capability_delete() when finished with.
  *
  * @return
  *   F_none on success.
  *
+ *   F_access_denied (with error bit) on access denied.
+ *   F_descriptor_not (with error bit) if the file descriptor is invalid.
+ *   F_directory_not (with error bit) if a directory containing the file does not exist.
+ *   F_file_found_not (with error bit) if file was not found.
  *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
  *   F_memory_not (with error bit) if a out of memory.
+ *   F_name_not (with error bit) if the file name is too long.
  *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the filesystem does not permit this operation.
+ *   F_supported_not (with error bit) if the filesystem does not support this operation.
  *
  *   F_failure (with error bit) on any other failure.
  *
- * @see cap_dup()
+ * @see cap_get_fd()
+ */
+#ifndef _di_f_capability_file_descriptor_get_
+  extern f_status_t f_capability_file_descriptor_get(const int descriptor, f_capability_t *capability);
+#endif // _di_f_capability_file_descriptor_get_
+
+/**
+ * Set the capability of a file represented by a file descriptor.
+ *
+ * @param descriptor
+ *   The file descriptor.
+ * @param capability
+ *   The capability to set.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_access_denied (with error bit) on access denied.
+ *   F_descriptor_not (with error bit) if the file descriptor is invalid.
+ *   F_directory_not (with error bit) if a directory containing the file does not exist.
+ *   F_file_found_not (with error bit) if file was not found.
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_memory_not (with error bit) if a out of memory.
+ *   F_name_not (with error bit) if the file name is too long.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the filesystem does not permit this operation.
+ *   F_supported_not (with error bit) if the filesystem does not support this operation.
+ *
+ *   F_failure (with error bit) on any other failure.
+ *
+ * @see cap_set_fd()
+ */
+#ifndef _di_f_capability_file_descriptor_set_
+  extern f_status_t f_capability_file_descriptor_set(const int descriptor, const f_capability_t capability);
+#endif // _di_f_capability_file_descriptor_set_
+
+/**
+ * Get the capability of a file represented by a file path.
+ *
+ * @param path
+ *   The file path.
+ * @param capability
+ *   The retrieved capability.
+ *   This must be freed via f_capability_delete() when finished with.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_access_denied (with error bit) on access denied.
+ *   F_descriptor_not (with error bit) if the file descriptor is invalid.
+ *   F_directory_not (with error bit) if a directory containing the file does not exist.
+ *   F_file_found_not (with error bit) if file was not found.
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_memory_not (with error bit) if a out of memory.
+ *   F_name_not (with error bit) if the file name is too long.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the filesystem does not permit this operation.
+ *   F_supported_not (with error bit) if the filesystem does not support this operation.
+ *
+ *   F_failure (with error bit) on any other failure.
+ *
+ * @see cap_get_file()
+ */
+#ifndef _di_f_capability_file_get_
+  extern f_status_t f_capability_file_get(const f_string_t path, f_capability_t *capability);
+#endif // _di_f_capability_file_get_
+
+/**
+ * Set the capability of a file represented by a file path.
+ *
+ * @param path
+ *   The file path.
+ * @param capability
+ *   The capability to set.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_access_denied (with error bit) on access denied.
+ *   F_descriptor_not (with error bit) if the file descriptor is invalid.
+ *   F_directory_not (with error bit) if a directory containing the file does not exist.
+ *   F_file_found_not (with error bit) if file was not found.
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_memory_not (with error bit) if a out of memory.
+ *   F_name_not (with error bit) if the file name is too long.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the filesystem does not permit this operation.
+ *   F_supported_not (with error bit) if the filesystem does not support this operation.
+ *
+ *   F_failure (with error bit) on any other failure.
+ *
+ * @see cap_set_file()
  */
-#ifndef _di_f_capability_duplicate_
-  extern f_status_t f_capability_duplicate(const f_capability_t source, f_capability_t *destination);
-#endif // _di_f_capability_duplicate_
+#ifndef _di_f_capability_file_set_
+  extern f_status_t f_capability_file_set(const f_string_t path, const f_capability_t capability);
+#endif // _di_f_capability_file_set_
 
 /**
  * Get the value of a flag from the capability structure.
@@ -310,88 +507,178 @@ extern "C" {
 #endif // _di_f_capability_from_text_
 
 /**
- * Get the capability of a file represented by a file path.
+ * Set the group IDs.
  *
- * @param path
- *   The file path.
- * @param capability
- *   The retrieved capability.
- *   This must be freed via f_capability_delete() when finished with.
+ * This is the same as setuid(), except:
+ * 1) Helps ensure the correct effective capability is used to perform the operation.
+ * 2) All "effective" capabilities are lowered after this call.
+ *
+ * @param id_group
+ *   The group ID (as in setgid()).
+ * @param total
+ *   The total number of groups in id_groups.
+ * @param id_groups
+ *   The array of supplementary group IDs (as in setgroups()).
  *
  * @return
  *   F_none on success.
  *
- *   F_access_denied (with error bit) on access denied.
- *   F_descriptor_not (with error bit) if the file descriptor is invalid.
- *   F_directory_not (with error bit) if a directory containing the file does not exist.
- *   F_file_found_not (with error bit) if file was not found.
  *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
  *   F_memory_not (with error bit) if a out of memory.
- *   F_name_not (with error bit) if the file name is too long.
  *   F_parameter (with error bit) if a parameter is invalid.
  *   F_prohibited (with error bit) if the filesystem does not permit this operation.
- *   F_supported_not (with error bit) if the filesystem does not support this operation.
  *
- *   F_failure (with error bit) on any other failure.
+ *   F_failure (with error bit) on any other error.
  *
- * @see cap_get_file()
+ * @see cap_setgroups()
+ * @see setgid()
+ * @see setgroups()
  */
-#ifndef _di_f_capability_get_file_
-  extern f_status_t f_capability_get_file(const f_string_t path, f_capability_t *capability);
-#endif // _di_f_capability_get_file_
+#ifndef _di_f_capability_groups_set_
+  extern f_status_t f_capability_groups_set(const gid_t id_group, const size_t total, const gid_t id_groups[]);
+#endif // _di_f_capability_groups_set_
 
 /**
- * Get the capability of a file represented by a file descriptor.
+ * Initialize the capability structure.
  *
- * @param descriptor
- *   The file descriptor.
  * @param capability
- *   The retrieved capability.
+ *   The capability to initialize.
  *   This must be freed via f_capability_delete() when finished with.
  *
  * @return
  *   F_none on success.
  *
- *   F_access_denied (with error bit) on access denied.
- *   F_descriptor_not (with error bit) if the file descriptor is invalid.
- *   F_directory_not (with error bit) if a directory containing the file does not exist.
- *   F_file_found_not (with error bit) if file was not found.
  *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
  *   F_memory_not (with error bit) if a out of memory.
- *   F_name_not (with error bit) if the file name is too long.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   F_failure (with error bit) on failure to initialize.
+ *
+ * @see cap_init()
+ */
+#ifndef _di_f_capability_initialize_
+  extern f_status_t f_capability_initialize(f_capability_t *capability);
+#endif // _di_f_capability_initialize_
+
+/**
+ * Get the mode for the current process.
+ *
+ * @param mode
+ *   The capability mode.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *
+ *   F_failure (with error bit) on any other error.
+ *
+ * @see cap_get_mode()
+ */
+#ifndef _di_f_capability_mode_get_
+  extern f_status_t f_capability_mode_get(f_capability_mode_t *mode);
+#endif // _di_f_capability_mode_get_
+
+/**
+ * Get the name of the mode.
+ *
+ * @param mode
+ *   The capability mode.
+ * @param name
+ *   The name of the mode.
+ *   This is a NULL terminated string.
+ *   This is not an allocated string.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *
+ *   F_failure (with error bit) on any other error.
+ *
+ * @see cap_get_mode()
+ */
+#ifndef _di_f_capability_mode_get_name_
+  extern f_status_t f_capability_mode_get_name(const f_capability_mode_t mode, f_string_constant_t *name);
+#endif // _di_f_capability_mode_get_name_
+
+/**
+ * Set the mode for the current process.
+ *
+ * @param mode
+ *   The capability mode.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_memory_not (with error bit) if a out of memory.
  *   F_parameter (with error bit) if a parameter is invalid.
  *   F_prohibited (with error bit) if the filesystem does not permit this operation.
- *   F_supported_not (with error bit) if the filesystem does not support this operation.
  *
- *   F_failure (with error bit) on any other failure.
+ *   F_failure (with error bit) on any other error.
  *
- * @see cap_get_fd()
+ * @see cap_set_mode()
  */
-#ifndef _di_f_capability_get_file_descriptor_
-  extern f_status_t f_capability_get_file_descriptor(const int descriptor, f_capability_t *capability);
-#endif // _di_f_capability_get_file_descriptor_
+#ifndef _di_f_capability_mode_set_
+  extern f_status_t f_capability_mode_set(const f_capability_mode_t mode);
+#endif // _di_f_capability_mode_set_
 
 /**
- * Initialize the capability structure.
+ * Get the namespace owner for the current process.
  *
  * @param capability
- *   The capability to initialize.
- *   This must be freed via f_capability_delete() when finished with.
+ *   The capability.
+ * @param id_user
+ *   The ID of the user.
  *
  * @return
  *   F_none on success.
  *
  *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *
+ *   F_failure (with error bit) on any other error.
+ *
+ * @see cap_get_owner()
+ */
+#ifndef _di_f_capability_owner_get_
+  extern f_status_t f_capability_owner_get(const f_capability_t capability, uid_t *id_user);
+#endif // _di_f_capability_owner_get_
+
+/**
+ * Set the namespace owner for the current process.
+ *
+ * @param capability
+ *   The capability.
+ * @param id_user
+ *   The ID of the user.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_access_denied (with error bit) on access denied.
+ *   F_descriptor_not (with error bit) if the file descriptor is invalid.
+ *   F_directory_not (with error bit) if a directory containing the file does not exist.
+ *   F_file_found_not (with error bit) if file was not found.
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
  *   F_memory_not (with error bit) if a out of memory.
+ *   F_name_not (with error bit) if the file name is too long.
  *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the filesystem does not permit this operation.
+ *   F_supported_not (with error bit) if the filesystem does not support this operation.
  *
- *   F_failure (with error bit) on failure to initialize.
+ *   F_failure (with error bit) on any other error.
  *
- * @see cap_init()
+ *   Note: the return codes may not make sense.
+ *         the documentation for cap_set_owner() designates them as the return codes.
+ *         however, it is suspected that this is not the case.
+ *         For consistency with the documentation, return the codes anyway.
+ *
+ * @see cap_set_owner()
  */
-#ifndef _di_f_capability_initialize_
-  extern f_status_t f_capability_initialize(f_capability_t *capability);
-#endif // _di_f_capability_initialize_
+#ifndef _di_f_capability_owner_set_
+  extern f_status_t f_capability_owner_set(const f_capability_t capability, const uid_t id_user);
+#endif // _di_f_capability_owner_set_
 
 /**
  * Drop the bound for the process.
@@ -510,64 +797,45 @@ extern "C" {
 #endif // _di_f_capability_process_set_
 
 /**
- * Set the capability of a file represented by a file path.
+ * Get the security bits for the current process.
  *
- * @param path
- *   The file path.
- * @param capability
- *   The capability to set.
+ * @param bits
+ *   The security bits.
  *
  * @return
  *   F_none on success.
  *
- *   F_access_denied (with error bit) on access denied.
- *   F_descriptor_not (with error bit) if the file descriptor is invalid.
- *   F_directory_not (with error bit) if a directory containing the file does not exist.
- *   F_file_found_not (with error bit) if file was not found.
  *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
- *   F_memory_not (with error bit) if a out of memory.
- *   F_name_not (with error bit) if the file name is too long.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_prohibited (with error bit) if the filesystem does not permit this operation.
- *   F_supported_not (with error bit) if the filesystem does not support this operation.
  *
- *   F_failure (with error bit) on any other failure.
+ *   F_failure (with error bit) on any other error.
  *
- * @see cap_set_file()
+ * @see cap_get_secbits()
  */
-#ifndef _di_f_capability_set_file_
-  extern f_status_t f_capability_set_file(const f_string_t path, const f_capability_t capability);
-#endif // _di_f_capability_set_file_
+#ifndef _di_f_capability_security_bits_get_
+  extern f_status_t f_capability_security_bits_get(f_capability_bits_t *bits);
+#endif // _di_f_capability_security_bits_get_
 
 /**
- * Set the capability of a file represented by a file descriptor.
+ * Set the security bits for the current process.
  *
- * @param descriptor
- *   The file descriptor.
- * @param capability
- *   The capability to set.
+ * @param bits
+ *   The security bits.
  *
  * @return
  *   F_none on success.
  *
- *   F_access_denied (with error bit) on access denied.
- *   F_descriptor_not (with error bit) if the file descriptor is invalid.
- *   F_directory_not (with error bit) if a directory containing the file does not exist.
- *   F_file_found_not (with error bit) if file was not found.
  *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
  *   F_memory_not (with error bit) if a out of memory.
- *   F_name_not (with error bit) if the file name is too long.
  *   F_parameter (with error bit) if a parameter is invalid.
  *   F_prohibited (with error bit) if the filesystem does not permit this operation.
- *   F_supported_not (with error bit) if the filesystem does not support this operation.
  *
- *   F_failure (with error bit) on any other failure.
+ *   F_failure (with error bit) on any other error.
  *
- * @see cap_set_fd()
+ * @see cap_set_secbits()
  */
-#ifndef _di_f_capability_set_file_descriptor_
-  extern f_status_t f_capability_set_file_descriptor(const int descriptor, const f_capability_t capability);
-#endif // _di_f_capability_set_file_descriptor_
+#ifndef _di_f_capability_security_bits_set_
+  extern f_status_t f_capability_security_bits_set(const f_capability_bits_t bits);
+#endif // _di_f_capability_security_bits_set_
 
 /**
  * Get the total length (in bytes) the capability would take up when converted to external representation.
@@ -698,6 +966,34 @@ extern "C" {
   extern f_status_t f_capability_to_text(const f_capability_t capability, f_string_dynamic_t *text);
 #endif // _di_f_capability_to_text_
 
+/**
+ * Set the user ID.
+ *
+ * This is the same as setuid(), except:
+ * 1) Helps ensure the correct effective capability is used to perform the operation.
+ * 2) Preserves availability of permitted capabilities after the user ID changes.
+ * 3) All "effective" capabilities are lowered after this call.
+ *
+ * @param id_user
+ *   The ID of the user.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_implemented_not (with error bit) if this function is not available (due to not having libcap support compiled in).
+ *   F_memory_not (with error bit) if a out of memory.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if the filesystem does not permit this operation.
+ *
+ *   F_failure (with error bit) on any other error.
+ *
+ * @see cap_setuid()
+ * @see setuid()
+ */
+#ifndef _di_f_capability_user_id_set_
+  extern f_status_t f_capability_user_id_set(const uid_t id_user);
+#endif // _di_f_capability_user_id_set_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif