aboutsummaryrefslogtreecommitdiffstats
path: root/libselinux/src/query_user_context.c
blob: dcfc1b0f35ee3251770c04d219372e14e032940b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "selinux_internal.h"
#include "context_internal.h"
#include <selinux/get_context_list.h>

/* context_menu - given a list of contexts, presents a menu of security contexts
 *            to the user.  Returns the number (position in the list) of
 *            the user selected context.
 */
static int context_menu(security_context_t * list)
{
	int i;			/* array index                        */
	int choice = 0;		/* index of the user's choice         */
	char response[10];	/* string to hold the user's response */

	printf("\n\n");
	for (i = 0; list[i]; i++)
		printf("[%d] %s\n", i + 1, list[i]);

	while ((choice < 1) || (choice > i)) {
		printf("Enter number of choice: ");
		fflush(stdin);
		if (fgets(response, sizeof(response), stdin) == NULL)
			continue;
		fflush(stdin);
		choice = strtol(response, NULL, 10);
	}

	return (choice - 1);
}

/* query_user_context - given a list of context, allow the user to choose one.  The 
 *                  default is the first context in the list.  Returns 0 on
 *                  success, -1 on failure
 */
int query_user_context(security_context_t * list, security_context_t * usercon)
{
	char response[10];	/* The user's response                        */
	int choice;		/* The index in the list of the sid chosen by
				   the user                                   */

	if (!list[0])
		return -1;

	printf("\nYour default context is %s.\n", list[0]);
	if (list[1]) {
		printf("Do you want to choose a different one? [n]");
		fflush(stdin);
		if (fgets(response, sizeof(response), stdin) == NULL)
			return -1;
		fflush(stdin);

		if ((response[0] == 'y') || (response[0] == 'Y')) {
			choice = context_menu(list);
			*usercon = strdup(list[choice]);
			if (!(*usercon))
				return -1;
			return 0;
		}

		*usercon = strdup(list[0]);
		if (!(*usercon))
			return -1;
	} else {
		*usercon = strdup(list[0]);
		if (!(*usercon))
			return -1;
	}

	return 0;
}

/* get_field - given fieldstr - the "name" of a field, query the user 
 *             and set the new value of the field
 */
static void get_field(const char *fieldstr, char *newfield, int newfieldlen)
{
	int done = 0;		/* true if a non-empty field has been obtained */

	while (!done) {		/* Keep going until we get a value for the field */
		printf("\tEnter %s ", fieldstr);
		fflush(stdin);
		if (fgets(newfield, newfieldlen, stdin) == NULL)
			continue;
		fflush(stdin);
		if (newfield[strlen(newfield) - 1] == '\n')
			newfield[strlen(newfield) - 1] = '\0';

		if (strlen(newfield) == 0) {
			printf("You must enter a %s\n", fieldstr);
		} else {
			done = 1;
		}
	}
}

/* manual_user_enter_context - provides a way for a user to manually enter a
 *                     context in case the policy doesn't allow a list
 *                     to be obtained.
 *                     given the userid, queries the user and places the
 *                     context chosen by the user into usercon.  Returns 0
 *                     on success.
 */
int manual_user_enter_context(const char *user, security_context_t * newcon)
{
	char response[10];	/* Used to get yes or no answers from user */
	char role[100];		/* The role requested by the user          */
	int rolelen = 100;
	char type[100];		/* The type requested by the user          */
	int typelen = 100;
	char level[100];	/* The level requested by the user         */
	int levellen = 100;
	int mls_enabled = is_selinux_mls_enabled();

	context_t new_context;	/* The new context chosen by the user     */
	char *user_context = NULL;	/* String value of the user's context     */
	int done = 0;		/* true if a valid sid has been obtained  */

	/* Initialize the context.  How this is done depends on whether
	   or not MLS is enabled                                        */
	if (mls_enabled)
		new_context = context_new("user:role:type:level");
	else
		new_context = context_new("user:role:type");

	if (!new_context)
		return -1;

	while (!done) {
		printf("Would you like to enter a security context? [y]");
		if (fgets(response, sizeof(response), stdin) == NULL
		    || (response[0] == 'n') || (response[0] == 'N')) {
			context_free(new_context);
			return -1;
		}

		/* Allow the user to enter each field of the context individually */
		if (context_user_set(new_context, user)) {
			context_free(new_context);
			return -1;
		}
		get_field("role", role, rolelen);
		if (context_role_set(new_context, role)) {
			context_free(new_context);
			return -1;
		}
		get_field("type", type, typelen);
		if (context_type_set(new_context, type)) {
			context_free(new_context);
			return -1;
		}

		if (mls_enabled) {
			get_field("level", level, levellen);
			if (context_range_set(new_context, level)) {
				context_free(new_context);
				return -1;
			}
		}

		/* Get the string value of the context and see if it is valid. */
		user_context = context_str(new_context);
		if (!user_context) {
			context_free(new_context);
			return -1;
		}
		if (!security_check_context(user_context))
			done = 1;
		else
			printf("Not a valid security context\n");
	}

	*newcon = strdup(user_context);
	context_free(new_context);
	if (!(*newcon))
		return -1;
	return 0;
}