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 */ 12static 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 */ 38int 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 */ 78static 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 */ 106int 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