Skip to content
Snippets Groups Projects
Commit dcedb1ad authored by Michal Kostenec's avatar Michal Kostenec
Browse files

SQL features

Authorization
Authentication
parent b8da1998
Branches
Tags
No related merge requests found
*.pem
......@@ -155,7 +155,7 @@ class NoAuthenticator(Object):
return "anybody" # or None
def authorize(self, env, client, method, args):
def authorize(self, env, client, method, event, args):
return (client is not None)
......@@ -192,10 +192,29 @@ class X509Authenticator(NoAuthenticator):
return self.db.get_client_by_name(names)
def authorize(self, env, client, method, args):
return (client is not None) and client["rights"]=="whatever"
def authorize(self, env, client, method, event, args):
cl = None
service = event['Node'][0]['Name']
for i in range(len(client)):
if client[i]['service'] == service:
cl = client[i]
break
if cl is None:
return None
# logging.debug(cl)
# logging.debug(method)
# logging.debug(service)
# return True if (method == 'getEvents' and cl['read'])
if ((method == 'sendEvents' and cl['write'] == 1) or
(method == 'getDebug' and cl['debug'] == 1) or
(method == 'sendEvents' and cl['test'] == 1 and service == 'Test')):
return cl
return None
class NoValidator(Object):
......@@ -203,7 +222,6 @@ class NoValidator(Object):
return []
class JSONSchemaValidator(NoValidator):
def __init__(self, filename=None):
......@@ -256,14 +274,15 @@ class MySQL(Object):
def get_client_by_name(self, name):
return {
"name": name[0] if name else None,
"rights": "whatever"
}
format_strings = ','.join(['%s'] * len(name))
self.crs.execute("SELECT `id`, `hostname`, `service`, `identity`, `read`, `write`, `debug`, `test` FROM `clients2` WHERE `valid` = 1 AND `hostname` IN (%s)" % format_strings, tuple(name))
row = self.crs.fetchall()
return row if row else None
def get_debug(self):
self.crs.execute("SELECT VERSION() AS VER");
self.crs.execute("SELECT VERSION() AS VER")
row = self.crs.fetchone()
return {
"db": "MySQL",
......@@ -296,16 +315,176 @@ class MySQL(Object):
cat=None, nocat=None,
tag=None, notag=None,
group=None, nogroup=None):
sqlwhere = []
sqltemp = {}
if cat is not None and nocat is not None:
raise Error("Unrealizable conditions. Choose cat or nocat option.", 500, method='getEvents',
exc=sys.exc_info(), detail={'cat': cat, 'nocat' : nocat})
if cat is not None or nocat is not None:
if cat is not None:
sqltemp['cat'] = generateDynamicQuery(self, "Category", "category_id IN (%s)", json.loads(cat))
if nocat is not None:
sqltemp['cat'] = generateDynamicQuery(self, "Category", "category_id NOT IN (%s)", json.loads(nocat))
sqlwhere.append("e.id IN (SELECT event_id FROM event_category_mapping4 WHERE %s)" % sqltemp['cat'])
if tag is not None and notag is not None:
raise Error("Unrealizable conditions. Choose tag or notag option.", 500, method='getEvents',
exc=sys.exc_info(), detail={'tag': cat, 'notag' : nocat})
if tag is not None or notag is not None:
if tag is not None:
sqltemp['tag'] = generateDynamicQuery(self, "Tag", "tag_id IN (%s)", json.loads(tag))
if notag is not None:
sqltemp['tag'] = generateDynamicQuery(self, "Tag", "tag_id NOT IN (%s)", json.loads(notag))
sqlwhere.append("e.id IN (SELECT event_id FROM event_tag_mapping4 WHERE %s)" % sqltemp['tag'])
if group is not None and nogroup is not None:
raise Error("Unrealizable conditions. Choose group or nogroup option.", 500, method='getEvents',
exc=sys.exc_info(), detail={'tag': cat, 'notag' : nocat})
if group is not None or nogroup is not None:
sqltemp['group'] = ""
if group is not None:
for identity in json.loads(group):
sqltemp['group'] += ("cl.identity LIKE '%s' AND " % (identity))
if nogroup is not None:
for identity in json.loads(nogroup):
sqltemp['group'] += ("cl.identity NOT LIKE '%s' AND " % (identity))
# logging.debug(sqltemp['group'][:-4])
sqlwhere.append(sqltemp['group'][:-4])
sqlwhere_string = (" AND " . join(sqlwhere))
# logging.debug(sqlwhere_string)
# logging.debug(' AND ' . join(sqlwhere))
#sqlwhere = sqlwhere[:-4]
and_op = "" if not sqlwhere_string else "AND"
# logging.debug("SELECT e.id, e.data FROM clients2 cl RIGHT JOIN events4 e ON cl.id = e.client_id WHERE e.id > %s AND %s %s e.valid = 1 LIMIT %s" % (str(id), sqlwhere_string, and_op, str(count)))
self.crs.execute("SELECT e.id, e.data FROM clients2 cl RIGHT JOIN events4 e ON cl.id = e.client_id WHERE e.id > %s AND %s %s e.valid = 1 LIMIT %s" % (str(id), sqlwhere_string, and_op, str(count)))
row = self.crs.fetchall()
return {
"lastid": (id or 0)+count,
"events": [self.gen_random_idea() for i in range(count)]
"lastid": row[-1]['id'] if row else str(id),
"events": [row[i]['data'] for i in range(len(row))]
}
def store_events(self, client, events):
errs = [] # See sendEvents and validation, should return something similar
for event in events:
try:
# logging.debug("INSERT INTO events5 (detected,received,client_id,data) VALUES ('%s', NOW(), '%s', '%s')" % (event['DetectTime'], client['id'], self.con.escape_string(str(event))))
self.crs.execute("INSERT INTO events5 (detected,received,client_id,data) VALUES ('%s', NOW(), '%s', '%s')" % (event['DetectTime'], client['id'], self.con.escape_string(str(event))))
lastid = self.crs.lastrowid
# logging.debug(str(lastid))
for cat in event['Category']:
# logging.debug({'cat': cat})
cat_id = self.map_id('Category', cat) if self.map_id('Category', cat) else self.map_id('Category', 'Other.Other')
# logging.debug({'cat_id': cat_id})
# logging.debug("INSERT INTO event_category_mapping5 (event_id,category_id) VALUES ('%s', '%s')" % (str(lastid), str(cat_id)))
self.crs.execute("INSERT INTO event_category_mapping5 (event_id,category_id) VALUES ('%s', '%s')" % (str(lastid), str(cat_id)))
for tag in event['Node'][0]['Tags']:
tag_id = self.map_id('Tag', tag) if self.map_id('Tag', tag) else self.map_id('Tag', 'Other')
# logging.debug({'tag_id': tag_id})
# logging.debug("INSERT INTO event_tag_mapping5 (event_id,tag_id) VALUES ('%s', '%s')" % (str(lastid), tag_id))
self.crs.execute("INSERT INTO event_tag_mapping5 (event_id,tag_id) VALUES ('%s', '%s')" % (str(lastid), str(tag_id)))
self.con.commit()
except:
self.con.rollback()
raise Error("Data storing error", 00, detail={'event': event})
errs.append({"event": event})
return errs
def map_id (self, section, key):
# Should by placed in config file
data = {}
data['Tag'] = {
"Connection" : 1,
"Datagram" : 2,
"Content" : 3,
"Data" : 4,
"File" : 5,
"Flow" : 6,
"Log": 7,
"Protocol" : 8,
"Host" : 9,
"Network" : 10,
"Correlation" : 11,
"External" : 12,
"Reporting" : 13,
"Other" : 99
}
data['Category'] = {
"Abusive.Spam" : 101,
"Abusive.Harassment" : 102,
"Abusive.Child" : 103,
"Abusive.Sexual" : 104,
"Abusive.Violence" : 105,
"Malware.Virus" : 201,
"Malware.Worm" : 202,
"Malware.Trojan" : 203,
"Malware.Spyware" : 204,
"Malware.Dialer" : 205,
"Malware.Rootkit" : 206,
"Recon.Scanning" : 301,
"Recon.Sniffing" : 302,
"Recon.SocialEngineering" : 303,
"Recon.Searching" : 304,
"Attempt.Exploit" : 401,
"Attempt.Login" : 402,
"Attempt.NewSignature" : 403,
"Intrusion.AdminCompromise" : 501,
"Intrusion.UserCompromise" : 502,
"Intrusion.AppCompromise" : 503,
"Intrusion.Botnet" : 504,
"Availability.DoS" : 601,
"Availability.DDoS" : 602,
"Availability.Sabotage" : 603,
"Availability.Outage" : 604,
"Information.UnauthorizedAccess" : 701,
"Information.UnauthorizedModification" : 702,
"Fraud.UnauthorizedUsage" : 801,
"Fraud.Copyright" : 802,
"Fraud.Masquerade" : 803,
"Fraud.Phishing" : 804,
"Fraud.Scam" : 805,
"Vulnerable.Open" : 901,
"Anomaly.Traffic" : 1001,
"Anomaly.Connection" : 1002,
"Anomaly.Protocol" : 1003,
"Anomaly.System" : 1004,
"Anomaly.Application" : 1005,
"Anomaly.Behaviour" : 1006,
"Other" : 9998,
"Test" : 9999,
}
try:
return data[section][key]
except:
return data[section]['Other']
def generateDynamicQuery(self, section, query_string, variables):
variables_id = [self.map_id(section, v) for v in variables]
format_strings = ','.join(['\'%s\''] * len(variables_id))
temp_string = query_string % format_strings
return temp_string % tuple(variables_id)
def expose(meth):
......@@ -365,7 +544,7 @@ class Server(Object):
client = self.auth.authenticate(environ)
if not client:
raise Error("I'm watching YOU.", 403, method=path)
raise Error("I'm watching YOU. (Authenticate)", 403, method=path)
try:
events = json.loads(injson) if injson else None
......@@ -380,8 +559,8 @@ class Server(Object):
if events:
args["events"] = events
if not self.auth.authorize(environ, client, path, args):
raise Error("I'm watching YOU.", 403, method=path, detail={"client": client})
# if not self.auth.authorize(environ, client, path, args):
# raise Error("I'm watching YOU.", 403, method=path, detail={"client": client})
args = self.sanitize_args(path, method, args)
result = method(_env=environ, _client=client, **args) # call requested method
......@@ -428,10 +607,11 @@ class Server(Object):
class WardenHandler(Object):
def __init__(self, validator, db,
def __init__(self, validator, db, auth,
send_events_limit=100000, get_events_limit=100000,
description=None):
self.auth = auth
self.db = db
self.validator = validator
self.send_events_limit = send_events_limit
......@@ -507,13 +687,17 @@ class WardenHandler(Object):
okevents = []
valerrs = []
for event in events:
auth_cl = self.auth.authorize(_env, _client, 'sendEvents', event, None)
if not auth_cl:
raise Error("I'm watching YOU. (Authorization)", 403, method='sendEvents', detail={"client": _client})
verrs = self.validator.check(event)
if verrs:
valerrs.append({"errors": verrs, "event": event})
else:
okevents.append(event)
dberrs = self.db.store_events(_client, okevents)
dberrs = self.db.store_events(auth_cl, okevents)
if valerrs or dberrs:
raise Error("Event storage error", 500, method="sendEvents",
......@@ -633,12 +817,13 @@ def build_server(conf):
"host": {"type": str, "default": "localhost"},
"user": {"type": str, "default": "warden"},
"password": {"type": str, "default": ""},
"dbname": {"type": str, "default": "warden3"},
"dbname": {"type": str, "default": "warden3c"},
"port": {"type": natural, "default": 3306}
},
"WardenHandler": {
"validator": {"type": obj, "default": "validator"},
"db": {"type": obj, "default": "DB"},
"auth": {"type": obj, "default": "auth"},
"send_events_limit": {"type": natural, "default": 10000},
"get_events_limit": {"type": natural, "default": 10000},
"description": {"type": str, "default": ""}
......@@ -654,6 +839,8 @@ def build_server(conf):
sect_name = sect_name.lower()
sect_def = section_def[sect_name]
#logging.debug("Testing %s" % sect_name)
try: # Object type defined?
objtype = config["type"]
del config["type"]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment