aboutsummaryrefslogtreecommitdiffstats
path: root/libselinux/src/query_user_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'libselinux/src/query_user_context.c')
-rw-r--r--libselinux/src/query_user_context.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/libselinux/src/query_user_context.c b/libselinux/src/query_user_context.c
new file mode 100644
index 00000000..dcfc1b0f
--- /dev/null
+++ b/libselinux/src/query_user_context.c
@@ -0,0 +1,180 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "selinux_internal.h"
+#include "context_internal.h"
+#include <selinux/get_context_list.h>
+
+/* context_menu - given a list of contexts, presents a menu of security contexts
+ * to the user. Returns the number (position in the list) of
+ * the user selected context.
+ */
+static int context_menu(security_context_t * list)
+{
+ int i; /* array index */
+ int choice = 0; /* index of the user's choice */
+ char response[10]; /* string to hold the user's response */
+
+ printf("\n\n");
+ for (i = 0; list[i]; i++)
+ printf("[%d] %s\n", i + 1, list[i]);
+
+ while ((choice < 1) || (choice > i)) {
+ printf("Enter number of choice: ");
+ fflush(stdin);
+ if (fgets(response, sizeof(response), stdin) == NULL)
+ continue;
+ fflush(stdin);
+ choice = strtol(response, NULL, 10);
+ }
+
+ return (choice - 1);
+}
+
+/* query_user_context - given a list of context, allow the user to choose one. The
+ * default is the first context in the list. Returns 0 on
+ * success, -1 on failure
+ */
+int query_user_context(security_context_t * list, security_context_t * usercon)
+{
+ char response[10]; /* The user's response */
+ int choice; /* The index in the list of the sid chosen by
+ the user */
+
+ if (!list[0])
+ return -1;
+
+ printf("\nYour default context is %s.\n", list[0]);
+ if (list[1]) {
+ printf("Do you want to choose a different one? [n]");
+ fflush(stdin);
+ if (fgets(response, sizeof(response), stdin) == NULL)
+ return -1;
+ fflush(stdin);
+
+ if ((response[0] == 'y') || (response[0] == 'Y')) {
+ choice = context_menu(list);
+ *usercon = strdup(list[choice]);
+ if (!(*usercon))
+ return -1;
+ return 0;
+ }
+
+ *usercon = strdup(list[0]);
+ if (!(*usercon))
+ return -1;
+ } else {
+ *usercon = strdup(list[0]);
+ if (!(*usercon))
+ return -1;
+ }
+
+ return 0;
+}
+
+/* get_field - given fieldstr - the "name" of a field, query the user
+ * and set the new value of the field
+ */
+static void get_field(const char *fieldstr, char *newfield, int newfieldlen)
+{
+ int done = 0; /* true if a non-empty field has been obtained */
+
+ while (!done) { /* Keep going until we get a value for the field */
+ printf("\tEnter %s ", fieldstr);
+ fflush(stdin);
+ if (fgets(newfield, newfieldlen, stdin) == NULL)
+ continue;
+ fflush(stdin);
+ if (newfield[strlen(newfield) - 1] == '\n')
+ newfield[strlen(newfield) - 1] = '\0';
+
+ if (strlen(newfield) == 0) {
+ printf("You must enter a %s\n", fieldstr);
+ } else {
+ done = 1;
+ }
+ }
+}
+
+/* manual_user_enter_context - provides a way for a user to manually enter a
+ * context in case the policy doesn't allow a list
+ * to be obtained.
+ * given the userid, queries the user and places the
+ * context chosen by the user into usercon. Returns 0
+ * on success.
+ */
+int manual_user_enter_context(const char *user, security_context_t * newcon)
+{
+ char response[10]; /* Used to get yes or no answers from user */
+ char role[100]; /* The role requested by the user */
+ int rolelen = 100;
+ char type[100]; /* The type requested by the user */
+ int typelen = 100;
+ char level[100]; /* The level requested by the user */
+ int levellen = 100;
+ int mls_enabled = is_selinux_mls_enabled();
+
+ context_t new_context; /* The new context chosen by the user */
+ char *user_context = NULL; /* String value of the user's context */
+ int done = 0; /* true if a valid sid has been obtained */
+
+ /* Initialize the context. How this is done depends on whether
+ or not MLS is enabled */
+ if (mls_enabled)
+ new_context = context_new("user:role:type:level");
+ else
+ new_context = context_new("user:role:type");
+
+ if (!new_context)
+ return -1;
+
+ while (!done) {
+ printf("Would you like to enter a security context? [y]");
+ if (fgets(response, sizeof(response), stdin) == NULL
+ || (response[0] == 'n') || (response[0] == 'N')) {
+ context_free(new_context);
+ return -1;
+ }
+
+ /* Allow the user to enter each field of the context individually */
+ if (context_user_set(new_context, user)) {
+ context_free(new_context);
+ return -1;
+ }
+ get_field("role", role, rolelen);
+ if (context_role_set(new_context, role)) {
+ context_free(new_context);
+ return -1;
+ }
+ get_field("type", type, typelen);
+ if (context_type_set(new_context, type)) {
+ context_free(new_context);
+ return -1;
+ }
+
+ if (mls_enabled) {
+ get_field("level", level, levellen);
+ if (context_range_set(new_context, level)) {
+ context_free(new_context);
+ return -1;
+ }
+ }
+
+ /* Get the string value of the context and see if it is valid. */
+ user_context = context_str(new_context);
+ if (!user_context) {
+ context_free(new_context);
+ return -1;
+ }
+ if (!security_check_context(user_context))
+ done = 1;
+ else
+ printf("Not a valid security context\n");
+ }
+
+ *newcon = strdup(user_context);
+ context_free(new_context);
+ if (!(*newcon))
+ return -1;
+ return 0;
+}