in tacacs-F4.0.4.28/do_auth.py [0:0]
def main():
#Defaults
filename = "do_auth.ini"
log_name = "log.txt"
user_name = ""
ip_addr = ""
device = ""
is_debug = False
argv = sys.argv
try:
optlist, args = getopt.getopt(sys.argv[1:], 'i:u:f:l:d:?:D', ['fix_crs_bug','?', '-?', 'help', 'Help'])
except getopt.GetoptError, err:
print str(err)
print __doc__
sys.exit(1)
for (i, j) in optlist:
if i == '-i':
ip_addr = j
elif i == '-u':
user_name = j
elif i == '-f':
filename = j
elif i == '-l':
log_name = j
elif i == '-d':
device = j
elif i in ('?', '-?', 'help', 'Help'):
print __doc__
sys.exit(1)
elif i == '-D':
is_debug = True
else:
print 'Unknown option:', i
sys.exit(1)
if len(argv) < 7:
print __doc__
sys.exit(1)
log_file = open (log_name, "a")
#DEBUG! We at least got CALLED
# log_file.write('Hello World!' + '\n')
#read AV pairs
av_pairs = []
if not (is_debug):
for line in sys.stdin:
av_pairs.append(line)
else:
#Default Debug command is "show users wide"
#Later versions will allow this to be set
av_pairs.append("service=shell\n")
av_pairs.append("cmd=show\n")
av_pairs.append("cmd-arg=users\n")
av_pairs.append("cmd-arg=wide\n")
av_pairs.append("cmd-arg=<cr>\n")
#DEBUG - print tac pairs
# for item in av_pairs:
# log_file.write(item)
# Function to make cmd's readable
# Not very good, but will do for now
# I don't use any other service other than shell to test!
the_command = ""
return_pairs = ""
if (av_pairs[0] == "service=shell\n"):
if av_pairs[1] == ("cmd=\n"): # #&*@ Nexus!
if len(av_pairs) > 2:
#DEBUG
# log_file.write('Nexus pairs found\n')
return_pairs = av_pairs[2:] #strip the "cmd=" for consistency
#Commands - Concatenate to a readable command
elif av_pairs[1].startswith("cmd="):
our_command = av_pairs[1].split("=")
the_command = our_command[1].strip('\n')
if len(av_pairs) > 2:
i = 2
our_command = av_pairs[i].split("=")
while not (our_command[1] == "<cr>\n"):
the_command = the_command + " " + our_command[1].strip('\n')
i = i + 1
if i == len(av_pairs): # Firewalls don't give a <cr>!!
break
our_command = av_pairs[i].split("=")
#DEBUG - We got the command
#log_file.write(the_command + '\n')
#Login - Get av_pairs to pass back to tac_plus
elif av_pairs[1].startswith("cmd*"): #Anybody know why it's "cmd*"?
if len(av_pairs) > 2:
return_pairs = av_pairs[2:] #You MUST strip the "cmd*" av-pair
# Definately not a Nexus, so strip any nexus pair
for item in return_pairs:
if item.startswith("shell:roles"):
return_pairs.remove(item)
else:
return_pairs = av_pairs
if not user_name:
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "Error: No username entered!\n")
sys.exit(1)
config = ConfigParser.SafeConfigParser()
if not (filename in config.read(filename)):
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "Error: Can't open/parse '%s'\n"
% (filename))
sys.exit(1)
the_section = "users"
# If the user doesn't exist, just use the default settings
# Kind of a hack, but it works because we only get_attribute on user_name once.
# We have the : in there which we can use to split if required
if not check_username(config, log_file, user_name):
user_name = (user_name + ":(default)")
groups = get_attribute(config, "users", "default", log_file, filename)
else:
groups = get_attribute(config, "users", user_name, log_file, filename)
for this_group in groups:
if ip_addr:
if match_it(this_group, "host_deny", ip_addr, config, log_file, filename):
if this_group == groups[-1]:
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' denied from source '%s' in '%s'->'%s'\n"
% (user_name, ip_addr, this_group, "host_deny"))
sys.exit(1)
else:
# HUM... afterthought. We need it to continue if more groups exist
continue
if not match_it(this_group, "host_allow", ip_addr, config, log_file, filename):
#Stupid IOS-XR
if ip_addr == "-fix_crs_bug":
pass
elif this_group == groups[-1]:
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' not allowed from source '%s' in '%s'->'%s'\n"
% (user_name, ip_addr, this_group, "host_allow"))
sys.exit(1)
else:
continue
if device:
if match_it(this_group, "device_deny", device, config, log_file, filename):
if this_group == groups[-1]:
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' denied access to device '%s' in '%s'->'%s'\n"
% (user_name, device, this_group, "device_deny"))
sys.exit(1)
else:
continue
if not match_it(this_group, "device_permit", device, config, log_file, filename):
if this_group == groups[-1]:
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' not allowed access to device '%s' in '%s'->'%s'\n"
% (user_name, device, this_group, "device_permit"))
sys.exit(1)
else:
continue
# Attempt to modify return pairs
want_tac_pairs = False
if config.has_option(this_group, "av_pairs"):
temp_av_pairs = get_attribute(config, this_group, "av_pairs", log_file, filename)
i = 0
for item in return_pairs:
splt = item.split('=')
if len(splt) > 1:
#DEBUG
#for thing in splt:
# log_file.write('Thing:' + thing + '\n')
for item2 in temp_av_pairs:
item2 = item2.strip()
if item2.find(',') > -1:
splt2 = item2.split(',')
if len(splt2) > 1:
#splt3 = splt2[0].split('=')
if splt[0].find(splt2[0]) > -1:
want_tac_pairs = True
return_pairs[i] = ('%s' % splt2[1])
else:
splt2 = item2.split('=')
if len(splt2) > 1:
if splt[0] == splt2[0].strip(): # strip needed?
want_tac_pairs = True
#DEBUG
#log_file.write("Replacing pairs %s=%s\n" %
# (splt2[0].strip(),
# splt2[1].strip()))
return_pairs[i] = ('%s=%s' % (splt2[0].strip(),
splt2[1].strip()))
i = i + 1
# The previous 4 statements are to deny, it we passed them, proceed
# If we are logging in, return pairs, if not, go no to check the command
# Yes, simply printing them is how you return them
# First, let's make sure we're doing service = shell. If not, just
# allow it. I currently have little knowledge of cmd's sent by other
# services which is why this code is a little klugy.
if return_pairs:
splt = av_pairs[0].split('=') # Removed service in return_pairs
if len(splt) > 1:
if not splt[1].strip() == 'shell':
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' granted non-shell access to device '%s' in group '%s' from '%s'\n"
% (user_name, device, this_group, ip_addr))
return_pairs = av_pairs[2:] # Cut the first two?
for item in return_pairs:
#DEBUG
# log_file.write("Returning:%s\n" % item.strip())
print item.strip('\n')
if want_tac_pairs:
#DEBUG
# log_file.write("Exiting status 2\n")
sys.exit(2)
else:
#DEBUG
# log_file.write("Exiting status 0\n")
sys.exit(0) # Don't even TRY to mess with the tac pairs
#Proceed with shell stuff
if not len(the_command) > 0:
#DEBUG
# log_file.write("not len(the_command) > 0\n")
for item in return_pairs:
#DEBUG
# log_file.write("Returning:%s\n" % item.strip())
print item.strip('\n')
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' granted access to device '%s' in group '%s' from '%s'\n"
% (user_name, device, this_group, ip_addr))
sys.exit(2)
else: # Check command
if match_it(this_group, "command_deny", the_command, config, log_file, filename):
if this_group == groups[-1]:
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' denied command '%s' to device '%s' in '%s'->'%s'\n"
% (user_name, the_command, device, this_group, "command_deny"))
sys.exit(1)
else:
continue
elif match_it(this_group, "command_permit", the_command, config, log_file, filename):
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' allowed command '%s' to device '%s' in '%s'->'%s'\n"
% (user_name, the_command, device, this_group, "command_permit"))
sys.exit(0)
else: #exit & log if last group
if this_group == groups[-1]:
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' not allowed command '%s' to device '%s' in any group\n"
% (user_name, the_command, device))
#Can't... remember why I added this given the implicit deny
sys.exit(1)
else:
continue
#implicit deny at the end
log_file.write(strftime("%Y-%m-%d %H:%M:%S: ")
+ "User '%s' not allowed access to device '%s' from '%s' in any group\n"
% (user_name, device, ip_addr))
sys.exit(1)