1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 Monty Taylor <mordred@inaugust.com>
5
* Copyright (C) 2011 Canonical, Ltd.
6
* Author: Clint Byrum <clint.byrum@canonical.com>
8
* Copied from simple_user_policy
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; version 2 of the License.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
#include <drizzled/plugin/authorization.h>
27
#include <drizzled/module/option_map.h>
31
namespace po= boost::program_options;
34
using namespace drizzled;
36
namespace regex_policy
39
static int init(module::Context &context)
41
const module::option_map &vm= context.getOptions();
43
Policy *policy= new (nothrow) Policy(fs::path(vm["policy"].as<string>()));
44
if (policy == NULL or not policy->loadFile())
46
errmsg_printf(error::ERROR, _("Could not load regex policy file: %s\n"),
47
(policy ? policy->getError().str().c_str() : _("Unknown")));
56
context.registerVariable(new sys_var_const_string_val("policy", vm["policy"].as<string>()));
61
static void init_options(drizzled::module::option_context &context)
64
po::value<string>()->default_value(DEFAULT_POLICY_FILE.string()),
65
N_("File to load for regex authorization policies"));
68
bool Policy::loadFile()
70
ifstream file(policy_file.string().c_str());
71
boost::regex *comment_re= NULL;
72
boost::regex *empty_re= NULL;
73
boost::regex *table_matches_re= NULL;
74
boost::regex *process_matches_re= NULL;
75
boost::regex *schema_matches_re= NULL;
79
comment_re= new boost::regex(comment_regex);
80
empty_re= new boost::regex(empty_regex);
81
table_matches_re= new boost::regex(table_match_regex);
82
process_matches_re= new boost::regex(process_match_regex);
83
schema_matches_re= new boost::regex(schema_match_regex);
85
catch (const std::exception &e)
97
delete table_matches_re;
99
if (process_matches_re)
101
delete process_matches_re;
103
if (schema_matches_re)
105
delete schema_matches_re;
111
if (! file.is_open())
113
error << "Unable to open regex policy file: " << policy_file.string();
125
if (boost::regex_match(line, *comment_re))
129
if (boost::regex_match(line, *empty_re))
133
boost::smatch matches;
134
PolicyItemList *policies;
135
if (boost::regex_match(line, matches, *table_matches_re, boost::match_extra))
137
policies= &table_policies;
139
else if (boost::regex_match(line, matches, *process_matches_re, boost::match_extra))
141
policies= &process_policies;
143
else if (boost::regex_match(line, matches, *schema_matches_re, boost::match_extra))
145
policies= &schema_policies;
149
throw std::exception();
154
user_regex= matches[MATCH_REGEX_USER_POS];
155
object_regex= matches[MATCH_REGEX_OBJECT_POS];
156
action= matches[MATCH_REGEX_ACTION_POS];
160
i= new PolicyItem(user_regex, object_regex, action);
162
catch (const std::exception &e)
164
error << "Bad policy item: user=" << user_regex << " object=" << object_regex << " action=" << action;
165
throw std::exception();
167
policies->push_back(i);
171
catch (const std::exception &e)
173
/* On any non-EOF break, unparseable line */
174
error << "Unable to parse line " << lines << " of policy file " << policy_file.string() << ":" << e.what();
179
bool Policy::restrictObject(const drizzled::identifier::User &user_ctx,
180
const string &obj, const PolicyItemList &policies,
181
CheckMap **check_cache)
183
CheckItem c(user_ctx.username(), obj, check_cache);
184
if (!c.hasCachedResult())
186
PolicyItemList::const_iterator m= find_if(policies.begin(), policies.end(), c);
187
if (m != policies.end())
189
c.setCachedResult((*m)->isRestricted());
193
/* TODO: make default action configurable */
194
c.setCachedResult(false);
197
return c.getCachedResult();
200
bool Policy::restrictSchema(const drizzled::identifier::User &user_ctx,
201
drizzled::identifier::Schema::const_reference schema)
203
return restrictObject(user_ctx, schema.getSchemaName(), schema_policies, &schema_check_cache);
206
bool Policy::restrictProcess(const drizzled::identifier::User &user_ctx,
207
const drizzled::identifier::User &session_ctx)
209
return restrictObject(user_ctx, session_ctx.username(), process_policies, &process_check_cache);
212
bool Policy::restrictTable(drizzled::identifier::User::const_reference user_ctx,
213
drizzled::identifier::Table::const_reference table)
215
return restrictObject(user_ctx, table.getTableName(), table_policies, &table_check_cache);
218
bool CheckItem::operator()(PolicyItem *p)
220
if (p->userMatches(user))
222
errmsg_printf(error::INSPECT, _("User %s matches regex\n"), user.c_str());
223
if (p->objectMatches(object))
225
errmsg_printf(error::INSPECT, _("Object %s matches regex %s (%s)\n"),
227
p->getObject().c_str(),
231
errmsg_printf(error::INSPECT, _("Object %s NOT restricted by regex %s (%s)\n"),
233
p->getObject().c_str(),
239
CheckItem::CheckItem(const std::string &user_in, const std::string &obj_in, CheckMap **check_cache_in)
240
: user(user_in), object(obj_in), has_cached_result(false), check_cache(check_cache_in)
242
CheckMap::iterator check_val;
243
std::stringstream keystream;
244
keystream << user << "_" << object;
245
key= keystream.str();
247
/* using RCU to only need to lock when updating the cache */
248
if ((*check_cache) && (check_val= (*check_cache)->find(key)) != (*check_cache)->end())
250
setCachedResult(check_val->second);
254
void CheckItem::setCachedResult(bool result)
256
// TODO: make the mutex per-cache
259
boost::mutex::scoped_lock lock(check_cache_mutex, boost::defer_lock);
262
// Copy the current one
265
new_cache= new CheckMap(**check_cache);
269
new_cache= new CheckMap();
272
(*new_cache)[key]= result;
274
old_cache= *check_cache;
275
*check_cache= new_cache;
278
has_cached_result= true;
279
cached_result= result;
287
} /* namespace regex_policy */
289
DRIZZLE_PLUGIN(regex_policy::init, NULL, regex_policy::init_options);