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