15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generalized labeling frontend for userspace object managers.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdlib.h>
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <selinux/selinux.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "callbacks.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "label_internal.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int (*selabel_initfunc)(struct selabel_handle *rec,
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				const struct selinux_opt *opts,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned nopts);
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static selabel_initfunc initfuncs[] = {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	&selabel_file_init,
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu	NULL,
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	NULL,
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	NULL,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	&selabel_property_init,
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Validation functions
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int selabel_is_validate_set(const struct selinux_opt *opts,
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  unsigned n)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (n--)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (opts[n].type == SELABEL_OPT_VALIDATE)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return !!opts[n].value;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int selabel_validate(struct selabel_handle *rec,
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		     struct selabel_lookup_rec *contexts)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int rc = 0;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!rec->validating || contexts->validated)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto out;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rc = selinux_validate(&contexts->ctx_raw);
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	if (rc < 0)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto out;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	contexts->validated = 1;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)out:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return rc;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Public API
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) */
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct selabel_handle *selabel_open(unsigned int backend,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    const struct selinux_opt *opts,
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				    unsigned nopts)
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct selabel_handle *rec = NULL;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (backend >= ARRAY_SIZE(initfuncs)) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		errno = EINVAL;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto out;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (initfuncs[backend] == NULL)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto out;
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	rec = (struct selabel_handle *)malloc(sizeof(*rec));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!rec)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto out;
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(rec, 0, sizeof(*rec));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rec->backend = backend;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rec->validating = selabel_is_validate_set(opts, nopts);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((*initfuncs[backend])(rec, opts, nopts)) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(rec);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rec = NULL;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)out:
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	return rec;
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct selabel_lookup_rec *
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)selabel_lookup_common(struct selabel_handle *rec,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      const char *key, int type)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct selabel_lookup_rec *lr;
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	lr = rec->func_lookup(rec, key, type);
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if (!lr)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		return NULL;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	return lr;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int selabel_lookup(struct selabel_handle *rec, char **con,
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		   const char *key, int type)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	struct selabel_lookup_rec *lr;
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	lr = selabel_lookup_common(rec, key, type);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!lr)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return -1;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*con = strdup(lr->ctx_raw);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return *con ? 0 : -1;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool selabel_partial_match(struct selabel_handle *rec, const char *key)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (!rec->func_partial_match) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		/*
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * If the label backend does not support partial matching,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * then assume a match is possible.
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		 */
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return true;
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return rec->func_partial_match(rec, key);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void selabel_close(struct selabel_handle *rec)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rec->func_close(rec);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	free(rec);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void selabel_stats(struct selabel_handle *rec)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rec->func_stats(rec);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)