Home | History | Annotate | Download | only in src
      1 /*
      2  * Generalized labeling frontend for userspace object managers.
      3  *
      4  * Author : Eamon Walsh <ewalsh (at) epoch.ncsc.mil>
      5  */
      6 
      7 #include <sys/types.h>
      8 #include <ctype.h>
      9 #include <errno.h>
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 #include <selinux/selinux.h>
     14 #include "callbacks.h"
     15 #include "label_internal.h"
     16 
     17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
     18 
     19 typedef int (*selabel_initfunc)(struct selabel_handle *rec,
     20 				const struct selinux_opt *opts,
     21 				unsigned nopts);
     22 
     23 static selabel_initfunc initfuncs[] = {
     24 	&selabel_file_init,
     25 	NULL,
     26 	NULL,
     27 	NULL,
     28 	&selabel_property_init,
     29 };
     30 
     31 /*
     32  * Validation functions
     33  */
     34 
     35 static inline int selabel_is_validate_set(const struct selinux_opt *opts,
     36 					  unsigned n)
     37 {
     38 	while (n--)
     39 		if (opts[n].type == SELABEL_OPT_VALIDATE)
     40 			return !!opts[n].value;
     41 
     42 	return 0;
     43 }
     44 
     45 int selabel_validate(struct selabel_handle *rec,
     46 		     struct selabel_lookup_rec *contexts)
     47 {
     48 	int rc = 0;
     49 
     50 	if (!rec->validating || contexts->validated)
     51 		goto out;
     52 
     53 	rc = selinux_validate(&contexts->ctx_raw);
     54 	if (rc < 0)
     55 		goto out;
     56 
     57 	contexts->validated = 1;
     58 out:
     59 	return rc;
     60 }
     61 
     62 /*
     63  * Public API
     64  */
     65 
     66 struct selabel_handle *selabel_open(unsigned int backend,
     67 				    const struct selinux_opt *opts,
     68 				    unsigned nopts)
     69 {
     70 	struct selabel_handle *rec = NULL;
     71 
     72 	if (backend >= ARRAY_SIZE(initfuncs)) {
     73 		errno = EINVAL;
     74 		goto out;
     75 	}
     76 
     77 	if (initfuncs[backend] == NULL)
     78 		goto out;
     79 
     80 	rec = (struct selabel_handle *)malloc(sizeof(*rec));
     81 	if (!rec)
     82 		goto out;
     83 
     84 	memset(rec, 0, sizeof(*rec));
     85 	rec->backend = backend;
     86 	rec->validating = selabel_is_validate_set(opts, nopts);
     87 
     88 	if ((*initfuncs[backend])(rec, opts, nopts)) {
     89 		free(rec);
     90 		rec = NULL;
     91 	}
     92 
     93 out:
     94 	return rec;
     95 }
     96 
     97 static struct selabel_lookup_rec *
     98 selabel_lookup_common(struct selabel_handle *rec,
     99 		      const char *key, int type)
    100 {
    101 	struct selabel_lookup_rec *lr;
    102 	lr = rec->func_lookup(rec, key, type);
    103 	if (!lr)
    104 		return NULL;
    105 
    106 	return lr;
    107 }
    108 
    109 int selabel_lookup(struct selabel_handle *rec, char **con,
    110 		   const char *key, int type)
    111 {
    112 	struct selabel_lookup_rec *lr;
    113 
    114 	lr = selabel_lookup_common(rec, key, type);
    115 	if (!lr)
    116 		return -1;
    117 
    118 	*con = strdup(lr->ctx_raw);
    119 	return *con ? 0 : -1;
    120 }
    121 
    122 bool selabel_partial_match(struct selabel_handle *rec, const char *key)
    123 {
    124 	if (!rec->func_partial_match) {
    125 		/*
    126 		 * If the label backend does not support partial matching,
    127 		 * then assume a match is possible.
    128 		 */
    129 		return true;
    130 	}
    131 	return rec->func_partial_match(rec, key);
    132 }
    133 
    134 void selabel_close(struct selabel_handle *rec)
    135 {
    136 	rec->func_close(rec);
    137 	free(rec);
    138 }
    139 
    140 void selabel_stats(struct selabel_handle *rec)
    141 {
    142 	rec->func_stats(rec);
    143 }
    144