1/* 2 * Generalized labeling frontend for userspace object managers. 3 * 4 * Author : Eamon Walsh <ewalsh@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 19typedef int (*selabel_initfunc)(struct selabel_handle *rec, 20 const struct selinux_opt *opts, 21 unsigned nopts); 22 23static 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 35static 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 45int 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; 58out: 59 return rc; 60} 61 62/* 63 * Public API 64 */ 65 66struct 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 93out: 94 return rec; 95} 96 97static struct selabel_lookup_rec * 98selabel_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 109int 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 122bool 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 134int selabel_lookup_best_match(struct selabel_handle *rec, char **con, 135 const char *key, const char **aliases, int type) 136{ 137 struct selabel_lookup_rec *lr; 138 139 if (!rec->func_lookup_best_match) { 140 errno = ENOTSUP; 141 return -1; 142 } 143 144 lr = rec->func_lookup_best_match(rec, key, aliases, type); 145 if (!lr) 146 return -1; 147 148 *con = strdup(lr->ctx_raw); 149 return *con ? 0 : -1; 150} 151 152void selabel_close(struct selabel_handle *rec) 153{ 154 rec->func_close(rec); 155 free(rec); 156} 157 158void selabel_stats(struct selabel_handle *rec) 159{ 160 rec->func_stats(rec); 161} 162