Home | History | Annotate | Download | only in src
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include "selinux_internal.h"
      5 #include "context_internal.h"
      6 #include <selinux/get_context_list.h>
      7 
      8 /* context_menu - given a list of contexts, presents a menu of security contexts
      9  *            to the user.  Returns the number (position in the list) of
     10  *            the user selected context.
     11  */
     12 static int context_menu(char ** list)
     13 {
     14 	int i;			/* array index                        */
     15 	int choice = 0;		/* index of the user's choice         */
     16 	char response[10];	/* string to hold the user's response */
     17 
     18 	printf("\n\n");
     19 	for (i = 0; list[i]; i++)
     20 		printf("[%d] %s\n", i + 1, list[i]);
     21 
     22 	while ((choice < 1) || (choice > i)) {
     23 		printf("Enter number of choice: ");
     24 		fflush(stdin);
     25 		if (fgets(response, sizeof(response), stdin) == NULL)
     26 			continue;
     27 		fflush(stdin);
     28 		choice = strtol(response, NULL, 10);
     29 	}
     30 
     31 	return (choice - 1);
     32 }
     33 
     34 /* query_user_context - given a list of context, allow the user to choose one.  The
     35  *                  default is the first context in the list.  Returns 0 on
     36  *                  success, -1 on failure
     37  */
     38 int query_user_context(char ** list, char ** usercon)
     39 {
     40 	char response[10];	/* The user's response                        */
     41 	int choice;		/* The index in the list of the sid chosen by
     42 				   the user                                   */
     43 
     44 	if (!list[0])
     45 		return -1;
     46 
     47 	printf("\nYour default context is %s.\n", list[0]);
     48 	if (list[1]) {
     49 		printf("Do you want to choose a different one? [n]");
     50 		fflush(stdin);
     51 		if (fgets(response, sizeof(response), stdin) == NULL)
     52 			return -1;
     53 		fflush(stdin);
     54 
     55 		if ((response[0] == 'y') || (response[0] == 'Y')) {
     56 			choice = context_menu(list);
     57 			*usercon = strdup(list[choice]);
     58 			if (!(*usercon))
     59 				return -1;
     60 			return 0;
     61 		}
     62 
     63 		*usercon = strdup(list[0]);
     64 		if (!(*usercon))
     65 			return -1;
     66 	} else {
     67 		*usercon = strdup(list[0]);
     68 		if (!(*usercon))
     69 			return -1;
     70 	}
     71 
     72 	return 0;
     73 }
     74 
     75 /* get_field - given fieldstr - the "name" of a field, query the user
     76  *             and set the new value of the field
     77  */
     78 static void get_field(const char *fieldstr, char *newfield, int newfieldlen)
     79 {
     80 	int done = 0;		/* true if a non-empty field has been obtained */
     81 
     82 	while (!done) {		/* Keep going until we get a value for the field */
     83 		printf("\tEnter %s ", fieldstr);
     84 		fflush(stdin);
     85 		if (fgets(newfield, newfieldlen, stdin) == NULL)
     86 			continue;
     87 		fflush(stdin);
     88 		if (newfield[strlen(newfield) - 1] == '\n')
     89 			newfield[strlen(newfield) - 1] = '\0';
     90 
     91 		if (strlen(newfield) == 0) {
     92 			printf("You must enter a %s\n", fieldstr);
     93 		} else {
     94 			done = 1;
     95 		}
     96 	}
     97 }
     98 
     99 /* manual_user_enter_context - provides a way for a user to manually enter a
    100  *                     context in case the policy doesn't allow a list
    101  *                     to be obtained.
    102  *                     given the userid, queries the user and places the
    103  *                     context chosen by the user into usercon.  Returns 0
    104  *                     on success.
    105  */
    106 int manual_user_enter_context(const char *user, char ** newcon)
    107 {
    108 	char response[10];	/* Used to get yes or no answers from user */
    109 	char role[100];		/* The role requested by the user          */
    110 	int rolelen = 100;
    111 	char type[100];		/* The type requested by the user          */
    112 	int typelen = 100;
    113 	char level[100];	/* The level requested by the user         */
    114 	int levellen = 100;
    115 	int mls_enabled = is_selinux_mls_enabled();
    116 
    117 	context_t new_context;	/* The new context chosen by the user     */
    118 	char *user_context = NULL;	/* String value of the user's context     */
    119 	int done = 0;		/* true if a valid sid has been obtained  */
    120 
    121 	/* Initialize the context.  How this is done depends on whether
    122 	   or not MLS is enabled                                        */
    123 	if (mls_enabled)
    124 		new_context = context_new("user:role:type:level");
    125 	else
    126 		new_context = context_new("user:role:type");
    127 
    128 	if (!new_context)
    129 		return -1;
    130 
    131 	while (!done) {
    132 		printf("Would you like to enter a security context? [y]");
    133 		if (fgets(response, sizeof(response), stdin) == NULL
    134 		    || (response[0] == 'n') || (response[0] == 'N')) {
    135 			context_free(new_context);
    136 			return -1;
    137 		}
    138 
    139 		/* Allow the user to enter each field of the context individually */
    140 		if (context_user_set(new_context, user)) {
    141 			context_free(new_context);
    142 			return -1;
    143 		}
    144 		get_field("role", role, rolelen);
    145 		if (context_role_set(new_context, role)) {
    146 			context_free(new_context);
    147 			return -1;
    148 		}
    149 		get_field("type", type, typelen);
    150 		if (context_type_set(new_context, type)) {
    151 			context_free(new_context);
    152 			return -1;
    153 		}
    154 
    155 		if (mls_enabled) {
    156 			get_field("level", level, levellen);
    157 			if (context_range_set(new_context, level)) {
    158 				context_free(new_context);
    159 				return -1;
    160 			}
    161 		}
    162 
    163 		/* Get the string value of the context and see if it is valid. */
    164 		user_context = context_str(new_context);
    165 		if (!user_context) {
    166 			context_free(new_context);
    167 			return -1;
    168 		}
    169 		if (!security_check_context(user_context))
    170 			done = 1;
    171 		else
    172 			printf("Not a valid security context\n");
    173 	}
    174 
    175 	*newcon = strdup(user_context);
    176 	context_free(new_context);
    177 	if (!(*newcon))
    178 		return -1;
    179 	return 0;
    180 }
    181