def main()

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)