diff options
Diffstat (limited to 'libselinux/src/query_user_context.c')
-rw-r--r-- | libselinux/src/query_user_context.c | 180 |
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; +} |