00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "policy-query-internal.h"
00026
00027 #include <assert.h>
00028 #include <errno.h>
00029 #include <stdbool.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 #include <apol/render.h>
00034
00035 struct apol_context
00036 {
00037 char *user, *role, *type;
00038 apol_mls_range_t *range;
00039 };
00040
00041 apol_context_t *apol_context_create(void)
00042 {
00043 return calloc(1, sizeof(apol_context_t));
00044 }
00045
00046 apol_context_t *apol_context_create_from_qpol_context(const apol_policy_t * p, const qpol_context_t * context)
00047 {
00048 apol_context_t *c = NULL;
00049 const qpol_user_t *user;
00050 const qpol_role_t *role;
00051 const qpol_type_t *type;
00052 const qpol_mls_range_t *range;
00053 const char *user_name, *role_name, *type_name;
00054 apol_mls_range_t *apol_range = NULL;
00055 if ((c = apol_context_create()) == NULL) {
00056 ERR(p, "%s", strerror(ENOMEM));
00057 goto err;
00058 }
00059 if (qpol_context_get_user(p->p, context, &user) < 0 ||
00060 qpol_context_get_role(p->p, context, &role) < 0 ||
00061 qpol_context_get_type(p->p, context, &type) < 0 || qpol_context_get_range(p->p, context, &range) < 0) {
00062 goto err;
00063 }
00064 if (qpol_user_get_name(p->p, user, &user_name) < 0 ||
00065 qpol_role_get_name(p->p, role, &role_name) < 0 || qpol_type_get_name(p->p, type, &type_name) < 0) {
00066 goto err;
00067 }
00068 if (qpol_policy_has_capability(p->p, QPOL_CAP_MLS)) {
00069
00070
00071 if ((apol_range = apol_mls_range_create_from_qpol_mls_range(p, range)) == NULL) {
00072 goto err;
00073 }
00074 }
00075 if (apol_context_set_user(p, c, user_name) < 0 ||
00076 apol_context_set_role(p, c, role_name) < 0 ||
00077 apol_context_set_type(p, c, type_name) < 0 || apol_context_set_range(p, c, apol_range) < 0) {
00078 goto err;
00079 }
00080 return c;
00081 err:
00082 apol_mls_range_destroy(&apol_range);
00083 apol_context_destroy(&c);
00084 return NULL;
00085 }
00086
00087 apol_context_t *apol_context_create_from_literal(const char *context_string)
00088 {
00089 apol_context_t *c = NULL;
00090 bool is_context_compiled = false;
00091 regex_t context_regex;
00092 const size_t nmatch = 5;
00093 regmatch_t pmatch[nmatch];
00094
00095 if ((c = apol_context_create()) == NULL) {
00096 goto err;
00097 }
00098
00099 if (regcomp(&context_regex, "^([^:]*):([^:]*):([^:]*):?(.*)$", REG_EXTENDED) != 0) {
00100 goto err;
00101 }
00102 is_context_compiled = true;
00103
00104 if (regexec(&context_regex, context_string, nmatch, pmatch, 0) != 0) {
00105 errno = EIO;
00106 goto err;
00107 }
00108
00109 const char *s;
00110 size_t len;
00111
00112 assert(pmatch[1].rm_so == 0);
00113 s = context_string + pmatch[1].rm_so;
00114 len = pmatch[1].rm_eo - pmatch[1].rm_so;
00115 if (len != 0 && *s != '*' && (c->user = strndup(s, len)) == NULL) {
00116 goto err;
00117 }
00118
00119 assert(pmatch[2].rm_so != -1);
00120 s = context_string + pmatch[2].rm_so;
00121 len = pmatch[2].rm_eo - pmatch[2].rm_so;
00122 if (len != 0 && *s != '*' && (c->role = strndup(s, len)) == NULL) {
00123 goto err;
00124 }
00125
00126 assert(pmatch[3].rm_so != -1);
00127 s = context_string + pmatch[3].rm_so;
00128 len = pmatch[3].rm_eo - pmatch[3].rm_so;
00129 if (len != 0 && *s != '*' && (c->type = strndup(s, len)) == NULL) {
00130 goto err;
00131 }
00132
00133 if (pmatch[4].rm_so != -1) {
00134 s = context_string + pmatch[4].rm_so;
00135 len = pmatch[4].rm_eo - pmatch[4].rm_so;
00136 if (len != 0 && *s != '*' && (c->range = apol_mls_range_create_from_literal(s)) == NULL) {
00137 goto err;
00138 }
00139 }
00140
00141 regfree(&context_regex);
00142 return c;
00143
00144 err:
00145 apol_context_destroy(&c);
00146 if (is_context_compiled) {
00147 regfree(&context_regex);
00148 }
00149 return NULL;
00150 }
00151
00152 void apol_context_destroy(apol_context_t ** context)
00153 {
00154 if (*context != NULL) {
00155 free((*context)->user);
00156 free((*context)->role);
00157 free((*context)->type);
00158 apol_mls_range_destroy(&((*context)->range));
00159 free(*context);
00160 *context = NULL;
00161 }
00162 }
00163
00164 int apol_context_set_user(const apol_policy_t * p, apol_context_t * context, const char *user)
00165 {
00166 if (context == NULL) {
00167 ERR(p, "%s", strerror(EINVAL));
00168 errno = EINVAL;
00169 return -1;
00170 }
00171 if (user != context->user) {
00172 free(context->user);
00173 context->user = NULL;
00174 if (user != NULL && (context->user = strdup(user)) == NULL) {
00175 ERR(p, "%s", strerror(errno));
00176 return -1;
00177 }
00178 }
00179 return 0;
00180 }
00181
00182 int apol_context_set_role(const apol_policy_t * p, apol_context_t * context, const char *role)
00183 {
00184 if (context == NULL) {
00185 ERR(p, "%s", strerror(EINVAL));
00186 errno = EINVAL;
00187 return -1;
00188 }
00189 if (role != context->role) {
00190 free(context->role);
00191 context->role = NULL;
00192 if (role != NULL && (context->role = strdup(role)) == NULL) {
00193 ERR(p, "%s", strerror(errno));
00194 return -1;
00195 }
00196 }
00197 return 0;
00198 }
00199
00200 int apol_context_set_type(const apol_policy_t * p, apol_context_t * context, const char *type)
00201 {
00202 if (context == NULL) {
00203 ERR(p, "%s", strerror(EINVAL));
00204 errno = EINVAL;
00205 return -1;
00206 }
00207 if (type != context->type) {
00208 free(context->type);
00209 context->type = NULL;
00210 if (type != NULL && (context->type = strdup(type)) == NULL) {
00211 ERR(p, "%s", strerror(errno));
00212 return -1;
00213 }
00214 }
00215 return 0;
00216 }
00217
00218 int apol_context_set_range(const apol_policy_t * p, apol_context_t * context, apol_mls_range_t * range)
00219 {
00220 if (context == NULL) {
00221 ERR(p, "%s", strerror(EINVAL));
00222 errno = EINVAL;
00223 return -1;
00224 }
00225 if (range != context->range) {
00226 apol_mls_range_destroy(&(context->range));
00227 context->range = range;
00228 }
00229 return 0;
00230 }
00231
00232 const char *apol_context_get_user(const apol_context_t * context)
00233 {
00234 if (context == NULL) {
00235 errno = EINVAL;
00236 return NULL;
00237 }
00238 return context->user;
00239 }
00240
00241 const char *apol_context_get_role(const apol_context_t * context)
00242 {
00243 if (context == NULL) {
00244 errno = EINVAL;
00245 return NULL;
00246 }
00247 return context->role;
00248 }
00249
00250 const char *apol_context_get_type(const apol_context_t * context)
00251 {
00252 if (context == NULL) {
00253 errno = EINVAL;
00254 return NULL;
00255 }
00256 return context->type;
00257 }
00258
00259 const apol_mls_range_t *apol_context_get_range(const apol_context_t * context)
00260 {
00261 if (context == NULL) {
00262 errno = EINVAL;
00263 return NULL;
00264 }
00265 return context->range;
00266 }
00267
00268 int apol_context_compare(const apol_policy_t * p, const apol_context_t * target, const apol_context_t * search,
00269 unsigned int range_compare_type)
00270 {
00271 uint32_t value0, value1;
00272 if (p == NULL || target == NULL || search == NULL) {
00273 ERR(p, "%s", strerror(EINVAL));
00274 errno = EINVAL;
00275 return -1;
00276 }
00277 if (target->user != NULL && search->user != NULL) {
00278 const qpol_user_t *user0, *user1;
00279 if (qpol_policy_get_user_by_name(p->p,
00280 target->user, &user0) < 0 ||
00281 qpol_policy_get_user_by_name(p->p,
00282 search->user, &user1) < 0 ||
00283 qpol_user_get_value(p->p, user0, &value0) < 0 || qpol_user_get_value(p->p, user1, &value1) < 0) {
00284 return -1;
00285 }
00286 if (value0 != value1) {
00287 return 0;
00288 }
00289 }
00290 if (target->role != NULL && search->role != NULL) {
00291 const qpol_role_t *role0, *role1;
00292 if (qpol_policy_get_role_by_name(p->p,
00293 target->role, &role0) < 0 ||
00294 qpol_policy_get_role_by_name(p->p,
00295 search->role, &role1) < 0 ||
00296 qpol_role_get_value(p->p, role0, &value0) < 0 || qpol_role_get_value(p->p, role1, &value1) < 0) {
00297 return -1;
00298 }
00299 if (value0 != value1) {
00300 return 0;
00301 }
00302 }
00303 if (target->type != NULL && search->type != NULL) {
00304 const qpol_type_t *type0, *type1;
00305 if (qpol_policy_get_type_by_name(p->p,
00306 target->type, &type0) < 0 ||
00307 qpol_policy_get_type_by_name(p->p,
00308 search->type, &type1) < 0 ||
00309 qpol_type_get_value(p->p, type0, &value0) < 0 || qpol_type_get_value(p->p, type1, &value1) < 0) {
00310 return -1;
00311 }
00312 if (value0 != value1) {
00313 return 0;
00314 }
00315 }
00316 if (target->range != NULL && search->range != NULL) {
00317 return apol_mls_range_compare(p, target->range, search->range, range_compare_type);
00318 }
00319 return 1;
00320 }
00321
00322 int apol_context_validate(const apol_policy_t * p, const apol_context_t * context)
00323 {
00324 if (context == NULL ||
00325 context->user == NULL ||
00326 context->role == NULL || context->type == NULL || (apol_policy_is_mls(p) && context->range == NULL)) {
00327 ERR(p, "%s", strerror(EINVAL));
00328 errno = EINVAL;
00329 return -1;
00330 }
00331 return apol_context_validate_partial(p, context);
00332 }
00333
00334 int apol_context_validate_partial(const apol_policy_t * p, const apol_context_t * context)
00335 {
00336 apol_user_query_t *user_query = NULL;
00337 apol_role_query_t *role_query = NULL;
00338 apol_vector_t *user_v = NULL, *role_v = NULL;
00339 const qpol_user_t *user;
00340 const qpol_type_t *type;
00341 const qpol_mls_range_t *user_range;
00342 apol_mls_range_t *user_apol_range = NULL;
00343 int retval = -1, retval2;
00344
00345 if (context == NULL) {
00346 return 1;
00347 }
00348 if (context->user != NULL) {
00349 if ((user_query = apol_user_query_create()) == NULL) {
00350 ERR(p, "%s", strerror(ENOMEM));
00351 }
00352 if (apol_user_query_set_user(p, user_query, context->user) < 0 ||
00353 (context->role != NULL && apol_user_query_set_role(p, user_query, context->role) < 0) ||
00354 apol_user_get_by_query(p, user_query, &user_v) < 0) {
00355 goto cleanup;
00356 }
00357 if (apol_vector_get_size(user_v) == 0) {
00358 retval = 0;
00359 goto cleanup;
00360 }
00361 }
00362 if (context->role != NULL) {
00363 if ((role_query = apol_role_query_create()) == NULL) {
00364 ERR(p, "%s", strerror(ENOMEM));
00365 }
00366 if (apol_role_query_set_role(p, role_query, context->role) < 0 ||
00367 (context->type != NULL && apol_role_query_set_type(p, role_query, context->type) < 0) ||
00368 apol_role_get_by_query(p, role_query, &role_v) < 0) {
00369 goto cleanup;
00370 }
00371 if (apol_vector_get_size(role_v) == 0) {
00372 retval = 0;
00373 goto cleanup;
00374 }
00375 }
00376 if (context->type != NULL) {
00377 if (qpol_policy_get_type_by_name(p->p, context->type, &type) < 0) {
00378 retval = 0;
00379 goto cleanup;
00380 }
00381 }
00382 if (apol_policy_is_mls(p) && context->range != NULL) {
00383 retval2 = apol_mls_range_validate(p, context->range);
00384 if (retval2 != 1) {
00385 retval = retval2;
00386 goto cleanup;
00387 }
00388
00389 if (context->user != NULL) {
00390 if (qpol_policy_get_user_by_name(p->p, context->user, &user) < 0 ||
00391 qpol_user_get_range(p->p, user, &user_range) < 0) {
00392 goto cleanup;
00393 }
00394 user_apol_range = apol_mls_range_create_from_qpol_mls_range(p, user_range);
00395 if (user_apol_range == NULL) {
00396 ERR(p, "%s", strerror(ENOMEM));
00397 goto cleanup;
00398 }
00399 retval2 = apol_mls_range_compare(p, user_apol_range, context->range, APOL_QUERY_SUB);
00400 if (retval2 != 1) {
00401 retval = retval2;
00402 goto cleanup;
00403 }
00404 }
00405 }
00406 retval = 1;
00407 cleanup:
00408 apol_user_query_destroy(&user_query);
00409 apol_role_query_destroy(&role_query);
00410 apol_vector_destroy(&user_v);
00411 apol_vector_destroy(&role_v);
00412 apol_mls_range_destroy(&user_apol_range);
00413 return retval;
00414 }
00415
00416 char *apol_context_render(const apol_policy_t * p, const apol_context_t * context)
00417 {
00418 char *buf = NULL, *range_str = NULL;
00419 size_t buf_sz = 0;
00420
00421 if (context == NULL) {
00422 ERR(p, "%s", strerror(EINVAL));
00423 errno = EINVAL;
00424 return NULL;
00425 }
00426 if (p == NULL && !apol_mls_range_is_literal(context->range)) {
00427 ERR(p, "%s", strerror(EINVAL));
00428 errno = EINVAL;
00429 return NULL;
00430 }
00431 if (apol_str_appendf(&buf, &buf_sz, "%s:", (context->user != NULL ? context->user : "*")) != 0) {
00432 ERR(p, "%s", strerror(errno));
00433 goto err_return;
00434 }
00435 if (apol_str_appendf(&buf, &buf_sz, "%s:", (context->role != NULL ? context->role : "*")) != 0) {
00436 ERR(p, "%s", strerror(errno));
00437 goto err_return;
00438 }
00439 if (apol_str_append(&buf, &buf_sz, (context->type != NULL ? context->type : "*")) != 0) {
00440 ERR(p, "%s", strerror(errno));
00441 goto err_return;
00442 }
00443 if ((p != NULL && apol_policy_is_mls(p)) || (p == NULL)) {
00444 if (context->range == NULL) {
00445 range_str = strdup("*");
00446 } else {
00447 range_str = apol_mls_range_render(p, context->range);
00448 }
00449 if (range_str == NULL) {
00450 goto err_return;
00451 }
00452 if (apol_str_appendf(&buf, &buf_sz, ":%s", range_str) != 0) {
00453 ERR(p, "%s", strerror(errno));
00454 goto err_return;
00455 }
00456 free(range_str);
00457 }
00458 return buf;
00459
00460 err_return:
00461 free(buf);
00462 free(range_str);
00463 return NULL;
00464 }
00465
00466 int apol_context_convert(const apol_policy_t * p, apol_context_t * context)
00467 {
00468 if (p == NULL || context == NULL) {
00469 ERR(p, "%s", strerror(EINVAL));
00470 errno = EINVAL;
00471 return -1;
00472 }
00473 if (context->range != NULL) {
00474 return apol_mls_range_convert(p, context->range);
00475 }
00476 return 0;
00477 }