2001-11-19 04:50:51 +00:00
|
|
|
/*-
|
2002-03-13 22:55:20 +00:00
|
|
|
* Copyright (c) 2001 Networks Associates Technology, Inc.
|
2001-11-19 04:50:51 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
2001-11-19 22:34:06 +00:00
|
|
|
* This software was developed for the FreeBSD Project by NAI Labs, the
|
|
|
|
* Security Research Division of Network Associates, Inc. under
|
|
|
|
* DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
|
|
|
|
* CHATS research program.
|
|
|
|
*
|
2001-11-19 04:50:51 +00:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2001-11-19 22:34:06 +00:00
|
|
|
* 3. The name of the author may not be used to endorse or promote
|
|
|
|
* products derived from this software without specific prior written
|
|
|
|
* permission.
|
2001-11-19 04:50:51 +00:00
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
2001-11-19 22:34:06 +00:00
|
|
|
* $Id$
|
|
|
|
* $FreeBSD$
|
2001-11-19 04:50:51 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file contains functions that make access control decisions
|
|
|
|
* concerning wether or not given system calls should be allowed
|
|
|
|
* or denied. This activity is called "mediation". These functions
|
|
|
|
* generally consider both the parameters passed to a system call
|
|
|
|
* and the current internal state of LOMAC in the course of making
|
|
|
|
* a decision. However, they do not modify these parameters or
|
|
|
|
* LOMAC's internal state. Functions for modifying LOMAC's internal
|
|
|
|
* state can be found in lomac_monitor.c.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kernel_interface.h"
|
|
|
|
#include "kernel_mediate.h"
|
|
|
|
#if 0
|
|
|
|
#include "lomac_plm.h"
|
|
|
|
#endif
|
|
|
|
#include "kernel_log.h"
|
|
|
|
|
|
|
|
/* mediate_subject_level_subject()
|
|
|
|
*
|
|
|
|
* in: op_s - name of operation to mediate
|
|
|
|
* p_subject_one - subject one (for informational purposes only)
|
|
|
|
* level_one - already-known level of the first subject
|
|
|
|
* p_subject_two - subject two
|
|
|
|
* out: nothing
|
|
|
|
* return: value condition
|
|
|
|
* ----- ---------
|
|
|
|
* 0 caller should deny operation
|
|
|
|
* 1 caller should allow operation
|
|
|
|
*
|
|
|
|
* This function returns 1 if `p_subject_one's level is at least
|
|
|
|
* as great as `p_subject_two's level. Otherwise, it logs a permission
|
|
|
|
* failure on operation `op_s' and returns 0.
|
|
|
|
*
|
|
|
|
* This function is used to mediate pgrp changes.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
mediate_subject_level_subject(const char *op_s,
|
|
|
|
const lomac_subject_t *p_subject_one, level_t level_one,
|
|
|
|
lomac_subject_t *p_subject_two) {
|
|
|
|
|
|
|
|
lattr_t lattr_two; /* lattr of `p_subject_two' */
|
|
|
|
int ret_val; /* result to return to caller */
|
|
|
|
|
|
|
|
#ifdef NO_MEDIATION
|
|
|
|
ret_val = 1; /* no denials, just logging */
|
|
|
|
#else
|
|
|
|
ret_val = 0; /* pessimistically assume deny */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
get_subject_lattr(p_subject_two, &lattr_two);
|
|
|
|
|
|
|
|
if (lattr_two.level <= level_one) {
|
|
|
|
ret_val = 1; /* OK, allow */
|
|
|
|
} else if (lomac_verbose_demote_deny) {
|
|
|
|
lomac_log_t *logmsg = log_start();
|
|
|
|
|
|
|
|
log_append_string(logmsg, "LOMAC: denied level-");
|
|
|
|
log_append_int(logmsg, level_one);
|
|
|
|
log_append_string(logmsg, " proc ");
|
|
|
|
log_append_subject_id(logmsg, p_subject_one);
|
|
|
|
log_append_string(logmsg, " ");
|
|
|
|
log_append_string(logmsg, op_s);
|
|
|
|
log_append_string(logmsg, " to level-");
|
|
|
|
log_append_int(logmsg, lattr_two.level);
|
|
|
|
log_append_string(logmsg, " proc ");
|
|
|
|
log_append_subject_id(logmsg, p_subject_two);
|
|
|
|
log_print(logmsg);
|
|
|
|
}
|
|
|
|
return (ret_val);
|
|
|
|
} /* mediate_subject_subject() */
|
|
|
|
|
|
|
|
/* mediate_subject_object()
|
|
|
|
*
|
|
|
|
* in: op_s - string describing operation, like "write" or "writev"
|
|
|
|
* p_subject - subject trying to operate on `p_object'.
|
|
|
|
* p_object - object that `p_subject' is trying to operate on.
|
|
|
|
* out: nothing
|
|
|
|
* return: value condition
|
|
|
|
* ----- ---------
|
|
|
|
* 0 Caller should prevent operation
|
|
|
|
* 1 Caller should permit operation
|
|
|
|
*
|
|
|
|
* This function returns 1 if the level of `p_object' is less than or
|
|
|
|
* equal to the level of `p_subject'. Otherwise, it returns 0 and
|
|
|
|
* logs a permission denial on `op_s'.
|
|
|
|
*
|
|
|
|
* This function allows LOMAC to mediate write and writev system calls.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
mediate_subject_object(const char *op_s, lomac_subject_t *p_subject,
|
|
|
|
const lomac_object_t *p_object) {
|
|
|
|
lattr_t subject_lattr; /* lattr of `p_subject' */
|
|
|
|
lattr_t object_lattr; /* lattr of `p_object' */
|
|
|
|
int ret_val; /* value to return to caller */
|
|
|
|
|
|
|
|
#ifdef NO_MEDIATION
|
|
|
|
ret_val = 1; /* allow operation regardless of decision */
|
|
|
|
#else
|
|
|
|
ret_val = 0; /* pessimistically assume deny */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Get the lattrs of `p_subject' and `p_object' so we can compare them. */
|
|
|
|
get_subject_lattr(p_subject, &subject_lattr);
|
|
|
|
get_object_lattr(p_object, &object_lattr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If `p_subject's level is less than `p_object's level,
|
|
|
|
* we indicate that the operation must not be allowed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!lomac_must_deny(&subject_lattr, &object_lattr) ||
|
|
|
|
object_lattr.flags & LOMAC_ATTR_LOWWRITE) {
|
|
|
|
ret_val = 1; /* allow operation */
|
|
|
|
} else if (lomac_verbose_demote_deny) {
|
|
|
|
lomac_log_t *logmsg = log_start();
|
|
|
|
log_append_string(logmsg, "LOMAC: level-");
|
|
|
|
log_append_int(logmsg, subject_lattr.level);
|
|
|
|
log_append_string(logmsg, " proc ");
|
|
|
|
log_append_subject_id(logmsg, p_subject);
|
|
|
|
log_append_string(logmsg, " denied ");
|
|
|
|
log_append_string(logmsg, op_s);
|
|
|
|
log_append_string(logmsg, " to level-");
|
|
|
|
log_append_int(logmsg, object_lattr.level);
|
|
|
|
log_append_string(logmsg, " object ");
|
|
|
|
log_append_object_id(logmsg, p_object);
|
|
|
|
log_append_string(logmsg, "\n");
|
|
|
|
log_print(logmsg);
|
|
|
|
}
|
|
|
|
return (ret_val);
|
|
|
|
} /* mediate_subject_object() */
|
|
|
|
|
|
|
|
|
|
|
|
/* mediate_subject_object_open()
|
|
|
|
*
|
|
|
|
* in: p_subject - subject trying to operate on `p_object'.
|
|
|
|
* p_object - object that `p_subject' is trying to operate on.
|
|
|
|
* out: nothing
|
|
|
|
* return: value condition
|
|
|
|
* ----- ---------
|
|
|
|
* 0 Caller should prevent operation
|
|
|
|
* 1 Caller should permit operation
|
|
|
|
*
|
|
|
|
* This function returns 1 if the level of `p_object' is less than or
|
|
|
|
* equal to the level of `p_subject'. Otherwise, it returns 0 and
|
|
|
|
* logs a permission denial on `op_s'.
|
|
|
|
*
|
|
|
|
* This function allows LOMAC to mediate open system calls.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
mediate_subject_object_open(lomac_subject_t *p_subject,
|
|
|
|
const lomac_object_t *p_object) {
|
|
|
|
lattr_t subject_lattr; /* lattr of `p_subject' */
|
|
|
|
lattr_t object_lattr; /* lattr of `p_object' */
|
|
|
|
int ret_val; /* value to return to caller */
|
|
|
|
|
|
|
|
#ifdef NO_MEDIATION
|
|
|
|
ret_val = 1; /* allow operation regardless of decision */
|
|
|
|
#else
|
|
|
|
ret_val = 0; /* pessimistically assume deny */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Get the lattrs of `p_subject' and `p_object' so we can compare them. */
|
|
|
|
get_subject_lattr(p_subject, &subject_lattr);
|
|
|
|
get_object_lattr(p_object, &object_lattr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If `p_subject's level is less than `p_object's level,
|
|
|
|
* we must indicate that the operation should not be allowed.
|
|
|
|
*/
|
|
|
|
if (lomac_must_deny(&subject_lattr, &object_lattr) &&
|
|
|
|
object_lattr.flags & LOMAC_ATTR_LOWNOOPEN) {
|
|
|
|
if (lomac_verbose_demote_deny) {
|
|
|
|
lomac_log_t *logmsg = log_start();
|
|
|
|
|
|
|
|
log_append_string(logmsg, "LOMAC: level-");
|
|
|
|
log_append_int(logmsg, subject_lattr.level);
|
|
|
|
log_append_string(logmsg, " proc ");
|
|
|
|
log_append_subject_id(logmsg, p_subject);
|
|
|
|
log_append_string(logmsg, " denied open to level-");
|
|
|
|
log_append_int(logmsg, object_lattr.level);
|
|
|
|
log_append_string(logmsg, " object ");
|
|
|
|
log_append_object_id(logmsg, p_object);
|
|
|
|
log_append_string(logmsg, "\n");
|
|
|
|
log_print(logmsg);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret_val = 1; /* allow operation */
|
|
|
|
} /* if/else allow/deny */
|
|
|
|
return (ret_val);
|
|
|
|
} /* mediate_subject_object() */
|
|
|
|
|
|
|
|
|
|
|
|
/* mediate_subject_at_level()
|
|
|
|
*
|
|
|
|
* in: op_s - name of operation being mediated
|
|
|
|
* p_subject - subject whose level we want to check
|
|
|
|
* target_level - level to compare to `p_subject's level
|
|
|
|
*
|
|
|
|
* out: nothing
|
|
|
|
* return: value condition
|
|
|
|
* ----- ---------
|
|
|
|
* 0 `p_subject' is not at `target_level'
|
|
|
|
* 1 `p_subject' is at `target_level'
|
|
|
|
*
|
|
|
|
* This function provides a predicate for determining whether or not
|
|
|
|
* `p_subject' is at the level specified by `target_level'. This
|
|
|
|
* function compares `p_subject's level to `target_level'. If the
|
|
|
|
* levels match, it retruns 1. Otherwise, it logs a permission denial
|
|
|
|
* on `op_s' and returns 0.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
mediate_subject_at_level(const char *op_s, lomac_subject_t *p_subject,
|
|
|
|
const level_t target_level) {
|
|
|
|
lattr_t subject_lattr; /* lattr of `p_subject' */
|
|
|
|
int ret_val; /* value returned to caller */
|
|
|
|
|
|
|
|
#ifdef NO_MEDIATION
|
|
|
|
ret_val = 1; /* allow operation regardless of decision */
|
|
|
|
#else
|
|
|
|
ret_val = 0; /* pessimistically assume deny */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Make `subject_lattr' the lattr of `p_subject'. */
|
|
|
|
get_subject_lattr(p_subject, &subject_lattr);
|
|
|
|
|
|
|
|
/* compare with `target_lattr */
|
|
|
|
if (subject_lattr.level == target_level) {
|
|
|
|
ret_val = 1; /* allow operation */
|
|
|
|
} else if (lomac_verbose_demote_deny) {
|
|
|
|
lomac_log_t *logmsg = log_start();
|
|
|
|
|
|
|
|
log_append_string(logmsg, "LOMAC: denied level-");
|
|
|
|
log_append_int(logmsg, subject_lattr.level);
|
|
|
|
log_append_string(logmsg, " proc ");
|
|
|
|
log_append_subject_id(logmsg, p_subject);
|
|
|
|
log_append_string(logmsg, "'s ");
|
|
|
|
log_append_string(logmsg, op_s);
|
|
|
|
log_append_string(logmsg, ".\n");
|
|
|
|
log_print(logmsg);
|
|
|
|
}
|
|
|
|
return (ret_val);
|
|
|
|
} /* mediate_subject_at_level() */
|