#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(char ** 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(char ** list, char ** 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, char ** 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; }