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 */
context_menu(char ** list)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 */
query_user_context(char ** list,char ** usercon)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 */
get_field(const char * fieldstr,char * newfield,int newfieldlen)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 */
manual_user_enter_context(const char * user,char ** newcon)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