Commit 6fbcf13b authored by Yathindra Naik's avatar Yathindra Naik

- Nodes in xenstore have capabilities by default with this change.

- Some cleaning up.
- Needs to be reviewed.
parent f4ebcb5b
/******************************************************************************
* flask.c
*
* Authors: George Coker, <gscoker@alpha.ncsc.mil>
* Michael LeMay, <mdlemay@epoch.ncsc.mil>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*/
#include <Python.h>
#include <xenctrl.h>
#define PKG "xen.lowlevel.flask"
#define CLS "flask"
#define CTX_LEN 1024
static PyObject *xc_error_obj;
typedef struct {
PyObject_HEAD;
xc_interface *xc_handle;
} XcObject;
static PyObject *pyflask_context_to_sid(PyObject *self, PyObject *args,
PyObject *kwds)
{
xc_interface *xc_handle;
char *ctx;
char *buf;
uint32_t len;
uint32_t sid;
int ret;
static char *kwd_list[] = { "context", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list,
&ctx) )
return NULL;
len = strlen(ctx);
buf = malloc(len);
if (!buf) {
errno = -ENOMEM;
PyErr_SetFromErrno(xc_error_obj);
}
memcpy(buf, ctx, len);
xc_handle = xc_interface_open(0,0,0);
if (!xc_handle) {
free(buf);
return PyErr_SetFromErrno(xc_error_obj);
}
ret = xc_flask_context_to_sid(xc_handle, buf, len, &sid);
xc_interface_close(xc_handle);
free(buf);
if ( ret != 0 ) {
errno = -ret;
return PyErr_SetFromErrno(xc_error_obj);
}
return PyInt_FromLong(sid);
}
static PyObject *pyflask_sid_to_context(PyObject *self, PyObject *args,
PyObject *kwds)
{
xc_interface *xc_handle;
uint32_t sid;
char ctx[CTX_LEN];
uint32_t ctx_len = CTX_LEN;
int ret;
static char *kwd_list[] = { "sid", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
&sid) )
return NULL;
xc_handle = xc_interface_open(0,0,0);
if (!xc_handle) {
return PyErr_SetFromErrno(xc_error_obj);
}
ret = xc_flask_sid_to_context(xc_handle, sid, ctx, ctx_len);
xc_interface_close(xc_handle);
if ( ret != 0 ) {
errno = -ret;
return PyErr_SetFromErrno(xc_error_obj);
}
return Py_BuildValue("s", ctx, ctx_len);
}
static PyObject *pyflask_load(PyObject *self, PyObject *args, PyObject *kwds)
{
xc_interface *xc_handle;
char *policy;
uint32_t len;
int ret;
static char *kwd_list[] = { "policy", NULL };
if( !PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwd_list, &policy, &len) )
return NULL;
xc_handle = xc_interface_open(0,0,0);
if (!xc_handle) {
return PyErr_SetFromErrno(xc_error_obj);
}
ret = xc_flask_load(xc_handle, policy, len);
xc_interface_close(xc_handle);
if ( ret != 0 ) {
errno = -ret;
return PyErr_SetFromErrno(xc_error_obj);
}
return Py_BuildValue("i", ret);
}
static PyObject *pyflask_getenforce(PyObject *self)
{
xc_interface *xc_handle;
int ret;
xc_handle = xc_interface_open(0,0,0);
if (!xc_handle) {
return PyErr_SetFromErrno(xc_error_obj);
}
ret = xc_flask_getenforce(xc_handle);
xc_interface_close(xc_handle);
if ( ret < 0 ) {
errno = -ret;
return PyErr_SetFromErrno(xc_error_obj);
}
return Py_BuildValue("i", ret);
}
static PyObject *pyflask_setenforce(PyObject *self, PyObject *args,
PyObject *kwds)
{
xc_interface *xc_handle;
int mode;
int ret;
static char *kwd_list[] = { "mode", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
&mode) )
return NULL;
xc_handle = xc_interface_open(0,0,0);
if (!xc_handle) {
return PyErr_SetFromErrno(xc_error_obj);
}
ret = xc_flask_setenforce(xc_handle, mode);
xc_interface_close(xc_handle);
if ( ret != 0 ) {
errno = -ret;
return PyErr_SetFromErrno(xc_error_obj);
}
return Py_BuildValue("i", ret);
}
static PyObject *pyflask_access(PyObject *self, PyObject *args,
PyObject *kwds)
{
xc_interface *xc_handle;
char *tcon, *scon;
uint16_t tclass;
uint32_t req, allowed, decided, auditallow, auditdeny, seqno;
int ret;
static char *kwd_list[] = { "src_context", "tar_context",
"tar_class", "req_permissions",
"decided", "auditallow","auditdeny",
"seqno", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ssil|llll", kwd_list,
&scon, &tcon, &tclass, &req, &decided,
&auditallow, &auditdeny, &seqno) )
return NULL;
xc_handle = xc_interface_open(0,0,0);
if (!xc_handle) {
return PyErr_SetFromErrno(xc_error_obj);
}
ret = xc_flask_access(xc_handle, scon, tcon, tclass, req, &allowed, &decided,
&auditallow, &auditdeny, &seqno);
xc_interface_close(xc_handle);
if ( ret != 0 ) {
errno = -ret;
return PyErr_SetFromErrno(xc_error_obj);
}
return Py_BuildValue("i",ret);
}
static PyMethodDef pyflask_methods[] = {
{ "flask_context_to_sid",
(PyCFunction)pyflask_context_to_sid,
METH_KEYWORDS, "\n"
"Convert a context string to a dynamic SID.\n"
" context [str]: String specifying context to be converted\n"
"Returns: [int]: Numeric SID on success; -1 on error.\n" },
{ "flask_sid_to_context",
(PyCFunction)pyflask_sid_to_context,
METH_KEYWORDS, "\n"
"Convert a dynamic SID to context string.\n"
" context [int]: SID to be converted\n"
"Returns: [str]: Numeric SID on success; -1 on error.\n" },
{ "flask_load",
(PyCFunction)pyflask_load,
METH_KEYWORDS, "\n"
"Loads a policy into the hypervisor.\n"
" policy [str]: policy to be load\n"
"Returns: [int]: 0 on success; -1 on failure.\n" },
{ "flask_getenforce",
(PyCFunction)pyflask_getenforce,
METH_NOARGS, "\n"
"Returns the current mode of the Flask XSM module.\n"
"Returns: [int]: 0 for permissive; 1 for enforcing; -1 on failure.\n" },
{ "flask_setenforce",
(PyCFunction)pyflask_setenforce,
METH_KEYWORDS, "\n"
"Modifies the current mode for the Flask XSM module.\n"
" mode [int]: mode to change to\n"
"Returns: [int]: 0 on success; -1 on failure.\n" },
{ "flask_access",
(PyCFunction)pyflask_access,
METH_KEYWORDS, "\n"
"Returns whether a source context has access to target context based on \
class and permissions requested.\n"
" scon [str]: source context\n"
" tcon [str]: target context\n"
" tclass [int]: target security class\n"
" req [int] requested permissions\n"
" allowed [int] permissions allow for the target class between the source \
and target context\n"
" decided [int] the permissions that were returned in the allowed \
parameter\n"
" auditallow [int] permissions set to audit on allow\n"
" auditdeny [int] permissions set to audit on deny\n"
" seqno [int] not used\n"
"Returns: [int]: 0 on all permission granted; -1 if any permissions are \
denied\n" },
{ NULL, NULL, 0, NULL }
};
PyMODINIT_FUNC initflask(void)
{
Py_InitModule("flask", pyflask_methods);
}
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/
......@@ -396,9 +396,10 @@ static struct node *read_node(struct connection *conn, const char *name)
talloc_steal(node, data.dptr);
#ifdef CONFIG_XENCAP
if ((!strncmp("/",node->name,1) || !strncmp("/tool",node->name,5)
|| !strncmp("/tool/xenstored",node->name,15)) ||
(conn != NULL && conn->cap_flag)) {
// if ((!strncmp("/",node->name,1) || !strncmp("/tool",node->name,5)
// || !strncmp("/tool/xenstored",node->name,15)) ||
// (conn != NULL && conn->cap_flag))
// {
/* Datalen, childlen, number of permissions */
p = (uint32_t *)data.dptr;
node->num_perms = p[0];
......@@ -414,22 +415,22 @@ static struct node *read_node(struct connection *conn, const char *name)
node->data = node->caps + node->num_caps;
/* Children is strings, nul separated. */
node->children = node->data + node->datalen;
}
else
{
/* Datalen, childlen, number of permissions */
p = (uint32_t *)data.dptr;
node->num_perms = p[0];
node->datalen = p[1];
node->childlen = p[2];
/* Permissions are struct xs_permissions. */
node->perms = (void *)&p[3];
/* Data is binary blob (usually ascii, no nul). */
node->data = node->perms + node->num_perms;
/* Children is strings, nul separated. */
node->children = node->data + node->datalen;
}
// } else
#else
// {
/* Datalen, childlen, number of permissions */
p = (uint32_t *)data.dptr;
node->num_perms = p[0];
node->datalen = p[1];
node->childlen = p[2];
/* Permissions are struct xs_permissions. */
node->perms = (void *)&p[3];
/* Data is binary blob (usually ascii, no nul). */
node->data = node->perms + node->num_perms;
/* Children is strings, nul separated. */
node->children = node->data + node->datalen;
// }
#endif
log("read_node: %s returning node %p\n",name, node);
return node;
......@@ -483,9 +484,9 @@ static bool write_node(struct connection *conn, const struct node *node)
log("write_node: %s\n",node->name);
#ifdef CONFIG_XENCAP
if ((!strncmp("/",node->name,1) || !strncmp("/tool",node->name,5)
|| !strncmp("/tool/xenstored",node->name,15)) ||
(conn != NULL && conn->cap_flag)) {
// if ((!strncmp("/",node->name,1) || !strncmp("/tool",node->name,5)
// || !strncmp("/tool/xenstored",node->name,15)) ||
// (conn != NULL && conn->cap_flag)) {
data.dsize = 4*sizeof(uint32_t)
+ node->num_perms*sizeof(node->perms[0])
......@@ -507,9 +508,10 @@ static bool write_node(struct connection *conn, const struct node *node)
p += node->datalen;
memcpy(p, node->children, node->childlen);
debug_xencap(key,data,node);
}
else
{
#else
// }
// else
// {
data.dsize = 3*sizeof(uint32_t)
+ node->num_perms*sizeof(node->perms[0])
+ node->datalen + node->childlen;
......@@ -526,7 +528,7 @@ static bool write_node(struct connection *conn, const struct node *node)
p += node->datalen;
memcpy(p, node->children, node->childlen);
}
// }
#endif
if (domain_is_unprivileged(conn) && data.dsize >= quota_max_entry_size)
{
......@@ -680,12 +682,17 @@ static enum xs_perm_type ask_parents(struct connection *conn, const char *name)
log("checking write cap\n");
if (caps_for_conn(conn, node->caps, XS_PERM_WRITE))
xs_perms |= XS_PERM_WRITE;
log("ask_parents: Returning %d\n",xs_perms);
if(xs_perms == 3)
log("ask_parents: read and write caps\n");
if(xs_perms == 2)
log("ask_parents: only write caps\n");
if(xs_perms == 1)
log("ask_parents: only read caps\n");
return xs_perms;
}
else
return perm_for_conn(conn, node->perms, node->num_perms);
#endif
return perm_for_conn(conn, node->perms, node->num_perms);
}
/* We have a weird permissions system. You can allow someone into a
......@@ -718,7 +725,7 @@ struct node *get_node(struct connection *conn,
}
node = read_node(conn, name);
log("get_node: node->name %s node %p\n",name,node);
log("get_node: node: %s\n",name);
#ifdef CONFIG_XENCAP
if ( conn != NULL && conn->cap_flag ) {
if (node) {
......@@ -728,7 +735,9 @@ struct node *get_node(struct connection *conn,
}
}
}
else {
else
#endif
{
/* If we don't have permission, we don't have node. */
if (node) {
log("get_node: calling perm_for_conn.\n");
......@@ -740,7 +749,7 @@ struct node *get_node(struct connection *conn,
}
}
}
#endif
/* Clean up errno if they weren't supposed to know. */
if (!node)
errno = errno_from_parents(conn, name, errno, perm);
......@@ -856,7 +865,6 @@ static bool valid_chars(const char *node)
bool is_valid_nodename(const char *node)
{
log("in is_valid_nodename.\n");
/* Must start in /. */
if (!strstarts(node, "/"))
return false;
......@@ -1151,7 +1159,9 @@ char *canonicalize(struct connection *conn, const char *node)
bool check_event_node(const char *node)
{
if (!node || !strstarts(node, "@")) {
#ifdef CONFIG_XENCAP
log("check_event_node: node:%p not found\n",node);
#endif
errno = EINVAL;
return false;
}
......@@ -1177,9 +1187,13 @@ static void do_read(struct connection *conn, const char *name)
struct node *node;
name = canonicalize(conn, name);
#ifdef CONFIG_XENCAP
log("do_read: node %s\n",name);
#endif
node = get_node(conn, name, XS_PERM_READ);
#ifdef CONFIG_XENCAP
log("do_read: got back node %p\n",node);
#endif
if (!node) {
send_error(conn, errno);
return;
......@@ -1297,6 +1311,9 @@ static struct node *construct_node(struct connection *conn, const char *name)
node->parent = parent;
domain_entry_inc(conn, node);
log("construct_node: returning node %p\n",node);
#ifdef CONFIG_XENCAP
xc_interface_close(xch);
#endif
return node;
#ifdef CONFIG_XENCAP
out:
......@@ -1401,21 +1418,29 @@ static void do_mkdir(struct connection *conn, const char *name)
struct node *node;
name = canonicalize(conn, name);
#ifdef CONFIG_XENCAP
log("do_mkdir: making dir %s\n",name);
#endif
node = get_node(conn, name, XS_PERM_WRITE);
/* If it already exists, fine. */
if (!node) {
#ifdef CONFIG_XENCAP
log("do_mkdir: node %s not found\n",name);
#endif
/* No permissions? */
if (errno != ENOENT) {
send_error(conn, errno);
return;
}
#ifdef CONFIG_XENCAP
log("do_mkdir: creating a new node for %s\n",name);
#endif
node = create_node(conn, name, NULL, 0);
if (!node) {
#ifdef CONFIG_XENCAP
log("do_mkdir: new node for %s failed!\n",name);
#endif
send_error(conn, errno);
return;
}
......@@ -1492,13 +1517,17 @@ static int _rm(struct connection *conn, struct node *node, const char *name)
otherwise be unreachable. */
struct node *parent = read_node(conn, get_parent(name));
if (!parent) {
#ifdef CONFIG_XENCAP
log("_rm: Parent for %s not found\n",name);
#endif
send_error(conn, EINVAL);
return 0;
}
if (!delete_child(conn, parent, basename(name))) {
#ifdef CONFIG_XENCAP
log("_rm: delete_child failed\n");
#endif
send_error(conn, EINVAL);
return 0;
}
......@@ -1524,10 +1553,14 @@ static void do_rm(struct connection *conn, const char *name)
struct node *node;
name = canonicalize(conn, name);
#ifdef CONFIG_XENCAP
log("do_rm: Removing node %s\n",name);
#endif
node = get_node(conn, name, XS_PERM_WRITE);
if (!node) {
#ifdef CONFIG_XENCAP
log("do_rm: did not get node: %s\n",name);
#endif
/* Didn't exist already? Fine, if parent exists. */
if (errno == ENOENT) {
node = read_node(conn, get_parent(name));
......@@ -1535,7 +1568,9 @@ static void do_rm(struct connection *conn, const char *name)
send_ack(conn, XS_RM);
return;
}
#ifdef CONFIG_XENCAP
log("do_rm: even parent does not exist for %s\n",name);
#endif
/* Restore errno, just in case. */
errno = ENOENT;
}
......@@ -1637,7 +1672,9 @@ static void do_get_perms(struct connection *conn, const char *name)
unsigned int len = 0;
name = canonicalize(conn, name);
#ifdef CONFIG_XENCAP
log("do_get_perms: getting perms for node %s\n",name);
#endif
node = get_node(conn, name, XS_PERM_READ);
if (!node) {
send_error(conn, errno);
......@@ -1653,8 +1690,8 @@ static void do_get_perms(struct connection *conn, const char *name)
send_error(conn, errno);
}
else
#endif
strings = perms_to_strings(node, node->perms, node->num_perms, &len);
#endif
if (!strings)
send_error(conn, errno);
else
......@@ -2537,14 +2574,10 @@ int main(int argc, char *argv[])
/* Setup the database */
setup_structure();
log("xenstored setup_structure is done.\n");
/* Listen to hypervisor. */
if (!no_domain_init)
domain_init();
log("xenstored domain_init is done.\n");
/* Restore existing connections. */
restore_existing_connections();
......@@ -2568,8 +2601,6 @@ int main(int argc, char *argv[])
/* Tell the kernel we're up and running. */
xenbus_notify_running();
log("xenstored xenbus_notify_running.\n");
/* Main loop. */
for (;;) {
struct connection *conn, *next;
......
/**
* This file is a part of the Flux Xen Capabilities infrastructure.
*
* Capabilities Support for Xen
*
* Author: Yathindra Naik
* Date: September 2012
*/
#ifndef __CAP_H__
#define __CAP_H__
/* This is a simple structure for capabilities. */
/* It is on a list for now. Later I'll consider a more efficient structure. */
struct capability
{
uint32_t magic;
/* We may need to encode the rights here too ? */
/* CAP_READ, CAP_WRITE, CAP_SHARE etc */
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment