#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;
}