113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "selinux_internal.h"
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "context_internal.h"
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <selinux/get_context_list.h>
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* context_menu - given a list of contexts, presents a menu of security contexts
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *            to the user.  Returns the number (position in the list) of
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *            the user selected context.
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
129eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic int context_menu(char ** list)
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i;			/* array index                        */
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int choice = 0;		/* index of the user's choice         */
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char response[10];	/* string to hold the user's response */
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	printf("\n\n");
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; list[i]; i++)
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		printf("[%d] %s\n", i + 1, list[i]);
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while ((choice < 1) || (choice > i)) {
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		printf("Enter number of choice: ");
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fflush(stdin);
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (fgets(response, sizeof(response), stdin) == NULL)
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fflush(stdin);
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		choice = strtol(response, NULL, 10);
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return (choice - 1);
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* query_user_context - given a list of context, allow the user to choose one.  The
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *                  default is the first context in the list.  Returns 0 on
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *                  success, -1 on failure
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
389eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint query_user_context(char ** list, char ** usercon)
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char response[10];	/* The user's response                        */
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int choice;		/* The index in the list of the sid chosen by
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   the user                                   */
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!list[0])
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	printf("\nYour default context is %s.\n", list[0]);
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (list[1]) {
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		printf("Do you want to choose a different one? [n]");
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fflush(stdin);
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (fgets(response, sizeof(response), stdin) == NULL)
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fflush(stdin);
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((response[0] == 'y') || (response[0] == 'Y')) {
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			choice = context_menu(list);
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*usercon = strdup(list[choice]);
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!(*usercon))
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*usercon = strdup(list[0]);
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!(*usercon))
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} else {
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*usercon = strdup(list[0]);
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!(*usercon))
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* get_field - given fieldstr - the "name" of a field, query the user
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *             and set the new value of the field
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void get_field(const char *fieldstr, char *newfield, int newfieldlen)
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int done = 0;		/* true if a non-empty field has been obtained */
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (!done) {		/* Keep going until we get a value for the field */
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		printf("\tEnter %s ", fieldstr);
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fflush(stdin);
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (fgets(newfield, newfieldlen, stdin) == NULL)
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fflush(stdin);
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (newfield[strlen(newfield) - 1] == '\n')
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			newfield[strlen(newfield) - 1] = '\0';
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (strlen(newfield) == 0) {
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			printf("You must enter a %s\n", fieldstr);
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			done = 1;
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* manual_user_enter_context - provides a way for a user to manually enter a
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *                     context in case the policy doesn't allow a list
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *                     to be obtained.
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *                     given the userid, queries the user and places the
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *                     context chosen by the user into usercon.  Returns 0
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *                     on success.
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
1069eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint manual_user_enter_context(const char *user, char ** newcon)
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char response[10];	/* Used to get yes or no answers from user */
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char role[100];		/* The role requested by the user          */
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rolelen = 100;
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char type[100];		/* The type requested by the user          */
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int typelen = 100;
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char level[100];	/* The level requested by the user         */
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int levellen = 100;
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int mls_enabled = is_selinux_mls_enabled();
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	context_t new_context;	/* The new context chosen by the user     */
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *user_context = NULL;	/* String value of the user's context     */
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int done = 0;		/* true if a valid sid has been obtained  */
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Initialize the context.  How this is done depends on whether
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	   or not MLS is enabled                                        */
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (mls_enabled)
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_context = context_new("user:role:type:level");
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		new_context = context_new("user:role:type");
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!new_context)
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (!done) {
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		printf("Would you like to enter a security context? [y]");
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (fgets(response, sizeof(response), stdin) == NULL
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    || (response[0] == 'n') || (response[0] == 'N')) {
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			context_free(new_context);
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Allow the user to enter each field of the context individually */
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (context_user_set(new_context, user)) {
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			context_free(new_context);
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		get_field("role", role, rolelen);
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (context_role_set(new_context, role)) {
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			context_free(new_context);
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		get_field("type", type, typelen);
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (context_type_set(new_context, type)) {
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			context_free(new_context);
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (mls_enabled) {
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			get_field("level", level, levellen);
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (context_range_set(new_context, level)) {
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				context_free(new_context);
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return -1;
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Get the string value of the context and see if it is valid. */
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		user_context = context_str(new_context);
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!user_context) {
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			context_free(new_context);
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return -1;
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!security_check_context(user_context))
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			done = 1;
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		else
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			printf("Not a valid security context\n");
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*newcon = strdup(user_context);
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	context_free(new_context);
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!(*newcon))
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
181