##########################################################################
#                                                                        #
# File:         pyauth.py                                                #
#                                                                        #
# Author:       Christian Hopp                                           #
#                                                                        #
# License:      GPL                                                      #
#                                                                        #
# Description:  Authorization helper module                              #
#                                                                        #
#               It is capable to handle to most passwd schemes (incl.    #
#               NIS, shadow).  The necessary setting can be changed in   #
#               the "USER SETTINGS" area in this file.                   #
#                                                                        #
##########################################################################

import grp
import pwd
import crypt
import socket
import re
import string
import types
try:
    import nis
except:
    pass

re_host_ip=re.compile(r"([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})")
re_net_ip=re.compile("(?P<network>([0-9]{1,3}\.){1,3}[0-9]{1,3})/(?P<netmask>(([0-9]{1,3}\.){1,3}[0-9]{1,3}))")


# Generation of grouplist
# -----------------------

def getallgrp(name):
    groups=[grp.getgrgid(pwd.getpwnam(name)[3])[0]]
    for group in grp.getgrall():
        if group[3].count(name)>0:
            if groups.count(group[0])==0:
                groups.append(group[0])
    return groups

# Comperation of groups
# ---------------------

def checkgrp(name, groups):
    return_value=0
    for group in groups:
        if getallgrp(name).count(group)>0:
            return 1==1
    return 1==0

# Comperation with userlist
# -------------------------

def checkuser(name, users):
    if users.count(name)>0:
        return 1==1
    else:
        return 1==0

# Comperation of passwords
# ------------------------

def checkpwd(name, userpwd):
    try:
        #original_crypted=pwd.getpwnam(name)[1]
        original_crypted=nis.match(name,"passwd").split(":")[1]
    except:
        return 1==0
    userpwd_crypted=crypt.crypt(userpwd,original_crypted[:2])
    if userpwd_crypted==original_crypted:
        return 1==1
    else:
        return 1==0

def checknologin(name):
    try:
        #original_crypted=pwd.getpwnam(name)[1]
        original_crypted=nis.match(name,"passwd").split(":")[1]
    except:
        return 1==0
    
    if original_crypted=="*LK*" or original_crypted=="*":
        return 1==1
    else:
        return 1==0
        

# Comperation of hosts
# --------------------

def checkhost(host, allows=[], denies=[], allowdeny=(1==0)):
    try:
        ip=socket.gethostbyname(host)
    except:
        return 1==0

    if type(allows)==types.StringType:
        allows=[allows]
    elif not (type(allows)==types.ListType or type(allows)==types.TupleType):
        return 1==0

    if type(denies)==types.StringType:
        denies=[denies]
    elif not (type(denies)==types.ListType or type(denies)==types.TupleType):
        return 1==0
    
    if allowdeny:
        for allow in allows:
            if checknet(ip,allow):
                return 1==1
        for deny in denies:
            if checknet(ip,deny):
                return 1==0
    else:
        for deny in denies:
            if checknet(ip,deny):
                return 1==0
        for allow in allows:
            if checknet(ip,allow):
                return 1==1

    return allowdeny
    
def iptoint(ip):
    return_value=0
    count=0
    
    try:
        subips=re_host_ip.match(ip).groups()
    except:
        return None

    for subip in subips:
        subip_int=string.atoi(subip)
        if subip_int > 255 or subip_int < 0:
            return None
        return_value += subip_int
        if count != 3:
            return_value <<= 8
            count += 1
    return return_value

def checknet(host, net):
    group = re_net_ip.match(net).groupdict()
    return ((iptoint(group["network"]) & iptoint(group["netmask"])) ==
            (iptoint(host) & iptoint(group["netmask"])))


