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