370
370
return [bfrom, bto]
376
THESE ARE THE NEW STUFF!!!
382
It's a Linux-PAM parser optimized for timekpr and time/access pam modules.
383
In other words, many of the linux-pam capabilities are not supported
384
(and probably will never be!).
386
It can currently parse lines that have a comment "# Added by timekpr" at the
389
pyparsing was chosen because it's easier to look at, fix and manipulate
390
(compared to simple regular expressions). However, regular expressions are
391
still used in this module for simpler tasks.
394
# More information on pyparsing:
395
# - http://www.rexx.com/~dkuhlman/python_201/python_201.html#SECTION007600000000000000000
396
# - http://pyparsing.wikispaces.com/message/view/home/7002417
398
from pyparsing import *
402
# CLASS: parsers(type="time.conf", input="file", file="/etc/security/time.conf")
403
# type => time.conf or access.conf
404
# input => file (default) or string (for testing)
405
# file => filename (can be blank, will use default filenames)
406
# Examples? See "TEST"!
409
def __init__(self, type, input="file", file="", string=""):
410
# Set default file location if file is not defined
417
self.unrecognized = []
419
if type == "time.conf" and input == "file" and not file:
420
self.file == "/etc/security/time.conf"
421
elif type == "access.conf" and input == "file" and not file:
422
self.file == "/etc/security/access.conf"
424
if input == "string" and not string:
425
sys.stderr.write("ERROR: parsers() class: input is 'string' but text string is empty\n")
428
self.active = self.confGetActiveLines()
429
self.confParseLines()
430
#self.confOutputLines()
435
""" Get input, either the file contents or the string """
436
if self.input == "file":
441
elif self.input == "string":
444
def confGetActiveLines(self):
445
# Ignore commented lines (they start with #)
446
text = self.getInput()
447
result = re.compile('^(?!\s*#).+', re.M).findall(text)
450
def confPreCheckLine(self, line):
451
""" Pre-checks the line
453
0 = active line, with "# Added by timekpr"
454
1 = active line, without "# Added by timekpr"
457
# Ignore whitespace-only line
458
if re.match("^\s*$", line):
460
# timekpr lines have "# Added by timekpr" in the end
461
if line[-18::] != "# Added by timekpr":
465
def confParseLines(self):
466
""" Outputs lines and checks for unrecognized ones (not controlled by timekpr) """
467
#self.result => [original line from file, resulting parsed list]
468
#self.unrecognized => unrecognized lines
470
for line in self.active:
471
test = self.confPreCheckLine(line)
474
if self.type == "time.conf":
475
tconf_parse = self.time_conf_parser()
476
result = tconf_parse.parseString(line)
477
elif self.type == "access.conf":
478
aconf_parse = self.access_conf_parser()
479
result = aconf_parse.parseString(line)
480
self.result.append([line, result])
483
self.unrecognized.append(line)
485
#elif test == 2: just ignore it
487
def confOutputLines(self):
488
""" Print lines and unrecognized active lines (testing purposes) """
489
#if not self.result and not self.unrecognized:
490
# self.confParseLines()
491
for line in self.result:
492
print("%s => %s" % (line[0], line[1]))
494
if self.unrecognized:
495
list_string = "\n".join(self.unrecognized)
496
print("\nWARNING: Unrecognized active lines found:\n%s" % (list_string))
498
def confActiveLines(self):
499
""" Return the self.result list """
500
#self.confUnrecognizedLines()
505
def confUnrecognizedLines(self):
506
""" Return the self.unrecognized list """
507
if self.unrecognized:
508
list_string = "\n".join(self.unrecognized)
509
print("WARNING: Unrecognized active lines found:\n%s" % (list_string))
515
# services;ttys;users;times
516
# ! = NOT, & = AND, | = OR
517
# * = ANY (can be used only once)
520
def tconf_negation_replace(self, s, l, t):
525
def time_conf_parser(self):
527
tconf_commonops = "&|" # AND/OR
528
# Ignore the first two ";"-separated items (services;ttys;users)
529
tconf_start = Suppress(Regex("(?:.*?;){2}"))
531
tconf_users = Regex("[^;]*")
532
tconf_users.setParseAction(self.strip_whitespace)
534
tconf_splitchar = Suppress(Word(";"))
537
tconf_negation = Optional("!", "allow") # block (with "!") or allow (without "!")
538
tconf_negation.setParseAction(self.tconf_negation_replace)
540
daysofweek = Group(OneOrMore(Literal("Mo") | Literal("Tu") | Literal("We") | Literal("Th") | Literal("Fr") | Literal("Sa") | Literal("Su") | Literal("Wk") | Literal("Wd") | Literal("Al")))
541
# Get the timeofday (4 numbers and "-" and 4 numbers)
542
timeofday = Group(Word(nums,exact=4) + Suppress("-") + Word(nums,exact=4))
543
# Check negation, the days of week and the time of day
544
tconf_time = tconf_negation + daysofweek + timeofday
545
# While checking for & or | too
546
tconf_time_list = Group(tconf_time) + Optional(Word(tconf_commonops))
547
# Do the above all over again once or more times
548
tconf_parse = tconf_start + tconf_users + tconf_splitchar + OneOrMore(tconf_time_list) + Suppress(Regex("# Added by timekpr")) + LineEnd()
555
# permission (+ or -) : users : origins
557
def aconf_action_replace(self, s, l, t):
565
def strip_whitespace(self, s, l, t):
568
def access_conf_parser(self):
569
aconf_splitchar = Suppress(Word(":"))
570
# permission - either + or -, 1 character only
571
aconf_permission = Word("-+", exact=1)
572
aconf_permission.setParseAction(self.aconf_action_replace)
573
# users - alphanumeric and one of "_*() " characters
574
aconf_users = Word(alphanums + "_*() ")
575
aconf_users.setParseAction(self.strip_whitespace)
576
# origins - everything else excluding "# Added by timekpr"
577
aconf_origins = Regex("[^#]+")
578
aconf_origins.setParseAction(self.strip_whitespace)
579
aconf_parse = aconf_permission + aconf_splitchar + aconf_users + aconf_splitchar + aconf_origins
584
if __name__ == "__main__":
585
# CLASS: pamparsers()
588
print("INFO: Checking time.conf\n")
590
tconf_test_data = """
591
#xsh ; ttyp* ; root ; !WeMo1700-2030 | !WeFr0600-0830 # Added by timekpr
592
xsh & login ; ttyp* ; ro0_ters;!WdMo0000-2400 # Added by timekpr
593
xsh & login ; ttyp* ; root | moot;!WdMo0200-1500
594
xsh & login;ttyp*;root | moot;WdMo0000-2400 | Tu0800-2400 # Added by timekpr
595
xsh & login ; ttyp* ; root | moot;!WdMo0700-1500 & !MoWeFr1500-2000 # Added by timekpr
600
pamparsers(type="time.conf", input="string", string=tconf_test_data).confOutputLines()
601
# list = pamparsers(type="time.conf", input="string", string=tconf_test_data).confActiveLines()
606
print("\nINFO: Checking access.conf\n")
608
aconf_test_data = """
609
# testing # Added by timekpr
610
- : lala : ALL # Added by timekpr
611
-:lala:ALL # Added by timekpr
612
- : nana123_a : ALL # Added by timekpr
613
- : testing : ALL # test
614
- : testing : ALL EXCEPT root
615
+ : john : 2001:4ca0:0:101::1# Added by timekpr
616
+ : root : .foo.bar.org # Added by timekpr
617
- : john : 2001:4ca0:0:101::/64 # Added by timekpr
621
pamparsers(type="access.conf", input="string", string=aconf_test_data).confOutputLines()
622
# list2 = pamparsers(type="access.conf", input="string", string=aconf_test_data).confActiveLines()