コード例 #1
0
    def authenticate(self, username, password, save=None):

        # Retrieve the user object so we can query it further
        # TODO: test that the user.last_login field gets updated with this call
        user = auth.authenticate(username=username, password=password)

        # AUTH_INVALID_PASSWORD: if user is None, the authentication has failed
        # for some reason other than the user not existing
        if user != None:
            log(1, "Authentication success: LOCAL user '%s' logged in." % username)
            return AuthenticatorResult(code=AuthenticatorResult.AUTH_SUCCESS)

        # Auth has failed if we've got this far.  Find out why.

        # Ensure user exists
        try:
            self.user = User.objects.get(username=username)
        except User.DoesNotExist:
            log(1, "Authentication failed: username '%s' not found." % username)
            return AuthenticatorResult(code=AuthenticatorResult.AUTH_USER_NOT_FOUND)

        # AUTH_USER_DISABLED: The user is disabled
        if not self.user.is_active:
            log(1, "Authentication failed: RADIUS user '%s' is disabled." % username)
            return AuthenticatorResult(code=AuthenticatorResult.AUTH_USER_DISABLED)

        # AUTH_USER_EXPIRED: The User is expired
        if self.user.userprofile.is_expired():
            log(1, "Authentication failed: RADIUS user '%s' has expired." % username)
            return AuthenticatorResult(code=AuthenticatorResult.AUTH_USER_EXPIRED)

        log(1, "Authentication failed: invalid password for LOCAL user '%s'." % username)
        return AuthenticatorResult(code=AuthenticatorResult.AUTH_INVALID_PASSWORD)
コード例 #2
0
    def get_server_type(self, redetect=False):
        """This determines what type of LDAP server we're dealing with"""

        log(3, "Detecting LDAP server type")

        if self.auth_server.ldap_type != None and redetect != True:
            return self.auth_server.ldap_type
            
        self.connect()
        results = self.ldap_conn.search_s("", ldap.SCOPE_BASE,
                "objectClass=*", ["vendorversion", "objectClass", \
                "isGlobalCatalogReady", "vendorname"])

        log(6, "LDAP query probe result: %s" % str(results))
        if len(results) <= 0 or len(results[0]) < 2:
            log(3, "Generic LDAP server detected")
            return "GenericLDAP"

        entry = results[0][1]
        if "isGlobalCatalogReady" in entry and \
                entry["isGlobalCatalogReady"] == ["TRUE"]:
            log(3, "Active Directory LDAP server detected")
            return "ActiveDirectory"

        log(3, "No specific type of LDAP server found, using GenericLDAP")
        return "GenericLDAP"
コード例 #3
0
    def __getattr__(self, attr):
        if not attr.startswith("map_"):
            raise AttributeError()

        attr = attr.replace("map_", "")
        log(6, "Getting attribute: %s" % attr)

        value = None
        if attr in self.COPY_ATTRS:
            # this is a list of all the LDAP attributes that could potentially
            # be used to populate the fcombine attribute in user/userprofile
            dir_attrs = self.COPY_ATTRS[attr]

            # we search for the first non-blank/non-null attribute and use
            # that
            for dir_attr in dir_attrs:
                if dir_attr in self.entry_attrs:
                    value = self.entry_attrs[dir_attr][0]

                    # see if we need to parse the value at all
                    parse_fn_name = "parse_%s" % dir_attr.lower()
                    if hasattr(self, parse_fn_name) == True:
                        value = getattr(self, parse_fn_name)(value)
                        

                    if value != None and len(value) != 0:
                        log(6, ("Found LDAP attribute, mapping %s to %s,"
                                " value= %s") % (dir_attr, attr, value))
                        break

        else:
            raise AttributeError()

        return lambda: value
コード例 #4
0
ファイル: FcombineDaemon.py プロジェクト: gmurdocca/fcombine
    def run(self):
        log(1, "Now listening for requests on FcombineDaemon XML RPC server")

        try:
            self.server.serve_forever()
        except KeyboardInterrupt:
            log(1, "FcombineDaemon stopping")
コード例 #5
0
    def authenticate(self, username, password):
        #XXX: check expiry, check disabled, if we want

        try:
            user_entry = self.get_ldap_entry(username)

        except MultipleUsersException, ex:
            log(2, "LDAP authentication failure: %s" % ex)
            return AuthenticatorResult(AuthenticatorResult.AUTH_MULTIPLE_USERS)
コード例 #6
0
 def run(self):
     while True:
         for dir_server in DirectoryServer.objects.all():
             log(6, "processing dir_server: %s" % dir_server)
             # calculate time sice last run
             # compare to specified run frequency value. If we should run:
                 # get a directory server import handler via a factory
                 # spawn the import handler in a new thread
         time.sleep(600)
コード例 #7
0
ファイル: DemandMounter.py プロジェクト: gmurdocca/fcombine
    def __init__(self):
        self.home_source = xsftp.common.constants.HOMEDIR_SOURCE
        self.server_root_mount_point = xsftp.common.constants.SERVER_DIR

        self.mounter_factory = MounterFactory()
        self.mounted_servers = {}
#        self.mounted_bind_mounts = {}

        self.init_xml_rpc()

        log(1, "AutoMountManager started")
コード例 #8
0
    def to_user(self, entry):
        """Creates a basic Fcombine UserProfile object based on credentials"""

        log(3, "RADIUS add user, entry=%s" % str(entry))

        userprofile = UserProfile()
        userprofile.user = User()

        userprofile.user.username = entry

        return userprofile
コード例 #9
0
ファイル: FcombineDaemon.py プロジェクト: gmurdocca/fcombine
    def __init__(self):
        Thread.__init__(self)

        log(1, "Initializing FcombineDaemon XML RPC server")
        key_file = "/etc/pki/tls/private/fcombine_xmlrpc.key"
        cert_file = "/etc/pki/tls/certs/fcombine_xmlrpc.crt"
        ca_file = "/etc/pki/tls/certs/fcombine_xmlrpc.crt"

        self.server = SecureXMLRPCServer(("localhost", 9999), key_file,
                cert_file, ca_file)
        log(1, "Done initializing FcombineDaemon XML RPC server")
コード例 #10
0
ファイル: DemandMounter.py プロジェクト: gmurdocca/fcombine
    def check_path(self, path):
        """This is triggered whenever we suspect that we might need to
           do something in reaction to a user action/system call such as
           readdir(), open(), etc.  This gives us a chance to do things
           like populate the /home directory with users or do bind mounts."""

        log(6, "check_path")
        # the path given to us resembles that of an absolute path, relative
        # to /home
        # for example, if our fuse moudle is mounted at /home, then the path
        # we'll get is /.  It's like a chroot.
        parts = self.explode(os.path.normpath(path))
        # get rid of leading /
        parts.pop(0)

        # check to see if we've got enough path components to be in
        # a bind mount point i.e. /home/${user}/xsftp/${server}/......
        if len(parts) >= 3:
            username = parts.pop(0)
            bmp = parts.pop(0)
            server_name = parts.pop(0)

            log(3, "Checking: username = %s, bmp = %s, server_name = %s" % \
                    (username, bmp, server_name))

            # check to see if it's a bind mount point
            if bmp == self.BMP_DIR:
                server = None
                try:
                    # mount the server if neccessary
                    server = self.mount_server(server_name)
                except Exception, ex:
                    log(1, "Exception while mounting server: %s, error = %s" % \
                            (server_name, str(ex)))
                    return

                try:
                    # let's mount the mofo!
                    self.mount_bmp(username, server)
                except Exception, ex:
                    log(1, "Exception while bind mounting server: %s for user: \
                            %s, error: %s" % (server_name, username, str(ex)))

                    # see if we should unmount the server straight away
                    # due to no users
                    if len(server.bind_mounts) == 0:
                        log(3, "Unmounting %s from %s due to zero users" % \
                                (server.name, server.mount_point))
                        self.unmount_server(server.mount_point)

                    return
コード例 #11
0
ファイル: FcombineDaemon.py プロジェクト: gmurdocca/fcombine
    def create_ramdisk(self, mountpoint, size):
        # ensure serverdir exists
        if not os.path.exists(mountpoint):
            os.makedirs(mountpoint)

        # see if it's already mounted
        if mountutil.is_mounted(mountpoint) == True:
            log(2, "%s was already mounted, unmounting")
            mountutil.unmount(mountpoint)

        # create the ramdisk and mount it at SERVERDIR
        mount_cmd = ["mount", "-t", "tmpfs", "-o", \
                "size=" + str(size) + "M", "tmpfs", mountpoint]

        popenutil.quick_popen(mount_cmd)
コード例 #12
0
ファイル: DemandMounter.py プロジェクト: gmurdocca/fcombine
    def mount_bmp(self, username, server):
        #_name, server_mount_point):
        log(6, "mount_bmp")
        bind_mount_point = os.path.join(self.home_source, \
                username, self.BMP_DIR, server.server_name)

        if mountutil.is_mounted(bind_mount_point) == True:
            log(3, "BMP already mounted: %s" % bind_mount_point)
            return

        cmd = ["mount", "-o", "bind", server.mount_point, \
              bind_mount_point]

        popenutil.quick_popen(cmd)

        server.add_bind_mount(username, bind_mount_point)
コード例 #13
0
ファイル: UserDAO.py プロジェクト: gmurdocca/fcombine
    def pam_authenticate(self, username, password):
        """This is called to authenticate a user via PAM"""

        log(6, "pam_authenticate")
 
        # get the user object from our DB
        try:
            result = self.authenticate_user(username, password)
            if result == AuthenticatorResult.AUTH_SUCCESS:
                return self.FCOMBINE_AUTH_SUCCESS
            else:
                return self.FCOMBINE_AUTH_FAILED
        except User.DoesNotExist:
            log(2, 'Authentication failed for user "%s": User Not Found' % \
                    username)
            return self.FCOMBINE_DAEMON_ERR
コード例 #14
0
ファイル: DemandMounter.py プロジェクト: gmurdocca/fcombine
    def explode(self, path):
        """Explode a path into all its little giblets.
           _path_ should ideally be normalized first"""
        log(6, "explode")
        gibs = []

        head = path
        while True:

            if head == "/":
                gibs.insert(0, head)
                break

            head, tail = os.path.split(head)
            gibs.insert(0, tail)

        return gibs
コード例 #15
0
    def get_ldap_entry(self, username):
        """Return the entry from the LDAP server.  Returns None if the
           user is not found"""

        # check the username is valid
        if self.is_valid_username(username) == False:
            log(5, "Invalid username")
            return None

        log(6, "Attempting to connect to server: %s" % self.get_uri())

        try:
            self.connect()
        except ldap.INVALID_CREDENTIALS:
            log(2, "Service account bind failed for dn: %s" % bind_dn)
            raise DirectoryQueryException("Invalid LDAP bind credentials")
        except exceptions.ServerDownException:
            raise DirectoryQueryException("LDAP server down")


        # now search for the user
        filter_template = Template(self.auth_server.filter)
        filter = filter_template.substitute(username=username)

        log(5, "Searching, using filter: %s" % filter)
        
        results = self.ldap_conn.search_s(self.auth_server.base_dn, \
                ldap.SCOPE_SUBTREE, filter) #, ["dn"])

        # filter out referrals
        results = self.filter_results(results)

        if len(results) == 0:
            log(2, "LDAP Auth: User not found: %s" % username)
            return None

        if len(results) > 1:
            raise MultipleUsersException(
                    "LDAP Auth: Multiple users found: %s" % username)

        user_entry = results[0]

        return user_entry
コード例 #16
0
ファイル: FcombineFS.py プロジェクト: gmurdocca/fcombine
    def statfs(self):
        log(7, "statfs")
        """
        Should return an object with statvfs attributes (f_bsize, f_frsize...).
        Eg., the return value of os.statvfs() is such a thing (since py 2.2).
        If you are not reusing an existing statvfs object, start with
        fuse.StatVFS(), and define the attributes.

        To provide usable information (ie., you want sensible df(1)
        output, you are suggested to specify the following attributes:

            - f_bsize - preferred size of file blocks, in bytes
            - f_frsize - fundamental size of file blcoks, in bytes
                [if you have no idea, use the same as blocksize]
            - f_blocks - total number of blocks in the filesystem
            - f_bfree - number of free blocks
            - f_files - total number of file inodes
            - f_ffree - nunber of free file inodes
        """

        return os.statvfs(".")
コード例 #17
0
ファイル: DemandMounter.py プロジェクト: gmurdocca/fcombine
    def mount_server(self, server_name):
        log(6, "mount_server")

        # check to see if the server is already mounted by checking the dict
        if server_name in self.mounted_servers:
            # we're already SLAM mounted, so nothing more to do
            return

        # We're not mounted, so we need to get the server object from the daemon
        server = None
        try:
            server = self.xml_rpc_server.get_server_by_name(server_name)
        except XMLRPCClient.dex("xsftp.common.models.Server.DoesNotExist"):
            log(2, "Cannot mount server %s, don't know about it!" %
                    (server_name))
            return

        server.mount_point = os.path.join( \
                self.server_root_mount_point, server.name)

        if os.path.exists(server.mount_point) == False:
            os.makedirs(server.mount_point)

        if mountutil.is_mounted(server.mount_point) == True:
            log(3, "Server already mounted: %s" % server.mount_point)
        else:
            # determine the type of mounter needed
            mounter_class = self.mounter_factory.get_mounter_class( \
                    server.type)
            mounter = mounter_class()
            mounter.mount(server)

        self.mounted_servers[server_name] = server
        
        return server
コード例 #18
0
    def to_user(self, result):
        '''Creates and returns a Fcombine UserProfile object based on the 
           user's attributes stored within the LDAP server'''

        log(3, "LDAP add user, entry=%s" % str(entry))
        entry = result.entry

        userprofile = UserProfile()
        userprofile.user = User()

        entry_attrs = entry[1]

        server_type = self.get_server_type()
        mapper = self.get_mapper(server_type)(entry_attrs)

        for attr in self.USER_PROFILE_ATTRS:
            value = getattr(mapper, "map_%s" % attr)()
            log(6, "Setting %s to %s" % (attr, value))
            setattr(userprofile, attr, value)


        for attr in self.USER_ATTRS:
            value = getattr(mapper, "map_%s" % attr)()
            log(6, "Setting %s to %s" % (attr, value))
            setattr(userprofile.user, attr, value)

        return userprofile
コード例 #19
0
    def connect(self):
        """Connect and bind to the LDAP server"""

        # TODO
        log(1, "IMPLEMENT CA CERT VERIFICATION AND ACCEPT FIRST CERT")

        if self.auth_server.verify_cert == False:
            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)

        # bind as the service account
        self.ldap_conn = ldap.initialize(self.get_uri())
        self.ldap_conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
        self.ldap_conn.set_option(ldap.OPT_REFERRALS, 0)

        bind_dn = self.auth_server.bind_dn

        try:
            self.ldap_conn.simple_bind_s(bind_dn, \
                    self.auth_server.bind_password)
            log(3, "Successful service account bind to LDAP server: %s" % \
                    self.get_uri())
        except ldap.SERVER_DOWN:
            log(1, "LDAP server %s:%d down" % (self.auth_server.hostname, \
                    self.auth_server.port))
            raise exceptions.ServerDownException
コード例 #20
0
ファイル: DemandMounter.py プロジェクト: gmurdocca/fcombine
    def fsdestroy(self):
        """The fuse filesystem is being destroyed.
           This means we need to unmount everything"""
        log(6, "fsdestroy")

        try:
            self.unmount_all()

            log(1, "Finished unmounting all objects")
        except Exception, ex:
            log(1, "Exception while unmounting all: %s" % str(ex))
コード例 #21
0
ファイル: DemandMounter.py プロジェクト: gmurdocca/fcombine
    def unmount_all(self):
        # unmount all servers and their bind mounts
        # make a copy of the list to ensure we're not
        # mutating the items we're iterating over.
        # python 3.0 safe
        
        for server_name, server in list(self.mounted_servers.items()):
            log(2, "Unmounting all mountpoints for server %s" % \
                    server.name)

            # unmount bind mounts
            for username, bind_mount_point in list(server.bind_mounts.items()):
                log(2, "Unmounting bind mount %s for server %s" %
                        (bind_mount_point, server.name))
                self.unmount_bmp(bind_mount_point)

                del server.bind_mounts[username]

            # unmount the server itself
            log(2, "Unmounting server %s" % server.name)
            self.unmount_server(server)

            del self.mounted_servers[server_name]
コード例 #22
0
ファイル: FcombineFS.py プロジェクト: gmurdocca/fcombine
 def fsdestroy(self):
     log(7, "fsdestroy")
     self.demand_mounter.fsdestroy()
コード例 #23
0
 def __init__(self):
     Thread.__init__(self)
     log(1, "Initialized FcombineDaemon Directory Server Importer")
コード例 #24
0
ファイル: DemandMounter.py プロジェクト: gmurdocca/fcombine
#        self.mounted_servers[server_name].last_activity = 
#                datetime.datetime.now()

    def fsdestroy(self):
        """The fuse filesystem is being destroyed.
           This means we need to unmount everything"""
        log(6, "fsdestroy")

        try:
            self.unmount_all()

            log(1, "Finished unmounting all objects")
        except Exception, ex:
            log(1, "Exception while unmounting all: %s" % str(ex))

        log(0, "AutoMounterManager stopped")

    def unmount_all(self):
        # unmount all servers and their bind mounts
        # make a copy of the list to ensure we're not
        # mutating the items we're iterating over.
        # python 3.0 safe
        
        for server_name, server in list(self.mounted_servers.items()):
            log(2, "Unmounting all mountpoints for server %s" % \
                    server.name)

            # unmount bind mounts
            for username, bind_mount_point in list(server.bind_mounts.items()):
                log(2, "Unmounting bind mount %s for server %s" %
                        (bind_mount_point, server.name))
コード例 #25
0
ファイル: FcombineFS.py プロジェクト: gmurdocca/fcombine
 def utime(self, path, times):
     log(7, "utime")
     self.update_activity(path)
     os.utime("." + path, times)
コード例 #26
0
ファイル: FcombineFS.py プロジェクト: gmurdocca/fcombine
 def access(self, path, mode):
     log(7, "access")
     if not os.access("." + path, mode):
         return -EACCES
コード例 #27
0
            return AuthenticatorResult(AuthenticatorResult.AUTH_MULTIPLE_USERS)

        except DirectoryQueryException, ex:
            log(2, "LDAP authentication failure: %s" % ex)
            return AuthenticatorResult(
                    code=AuthenticatorResult.AUTH_FAIL)

        if user_entry == None:
            return AuthenticatorResult(
                    code=AuthenticatorResult.AUTH_USER_NOT_FOUND)
        user_dn = user_entry[0]

        # rebind as the user
        try:
            self.ldap_conn.simple_bind_s(user_dn, password)
            log(2, "LDAP Authentication succeeded, user dn=%s" % user_dn)
            result = AuthenticatorResult()
            result.code = AuthenticatorResult.AUTH_SUCCESS
            result.entry = user_entry
            return result

        except ldap.INVALID_CREDENTIALS:
            log(2, "LDAP invalid password user=%s" % username)
            return AuthenticatorResult(
                    code=AuthenticatorResult.AUTH_INVALID_PASSWORD)

    def lookup(self, username, auth_result):
        if auth_result != None:
            entry = auth_result.entry
        else:
            entry = self.get_ldap_entry(username)
コード例 #28
0
    def authenticate(self, username, password):
        log(6, "authenticate")

        server = self.auth_server.radius_server
        port = self.auth_server.radius_authport
        secret = self.auth_server.radius_secret

        # Attempt to autenticate against the configured RADIUS server
        try:
            radius_dictionary = Dictionary(constants.RADIUS_DICTIONARY)

            log(6, ("RADIUS module connecting to server: " \
                    "%s, authport: %s") % (server, port))

            srv = Client(server=server, authport=port, \
                    secret=secret.encode("ascii"), \
                    dict=radius_dictionary)

            req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest)
            req["User-Name"] = str(username)
            req["User-Password"] = req.PwCrypt(password.encode('ascii'))
            req["NAS-Identifier"] = "fcombine"

            log(6, "Senging RADIUS Access Request to server")
            reply = srv.SendPacket(req)
            log(6, "Received reply from RADIUS server, reply code was: %s" % \
                reply.code)

            if reply.code == pyrad.packet.AccessAccept:
                log(1, "Authentication success: RADIUS user '%s' logged in." % \
                        username)
                result = AuthenticatorResult()
                result.code = AuthenticatorResult.AUTH_SUCCESS
                result.entry = username
                return result

            elif reply.code == pyrad.packet.AccessReject:
                log(1, ("Authentication failed: Access rejected for " \
                        "RADIUS user '%s'.") % username)
                # This may not necessarily be caused by an invalid password, so
                # we are forced to return a general AUTH_FAIL here
                return AuthenticatorResult(
                        code=AuthenticatorResult.AUTH_FAIL)

            else:
                log(1, ("Authentication failed: Access request failed for"
                        " RADIUS user '%s'. RADIUS packet code was: %s") \
                        % reply.code)
                return AuthenticatorResult(
                        code=AuthenticatorResult.AUTH_FAIL)

        except pyrad.client.Timeout:
            log(1, "Radius server %s:%d down" % (server, port))
            return AuthenticatorResult(
                    code=AuthenticatorResult.AUTH_FAIL)

        except Exception, e:
            log(1, ("Authentication failed: Error authenticating RADIUS "
                    " user '%s'. Error Type: %s, Message: %s") % \
                    (username, type(e), e.message or None))
            stacktrace(3)
            return AuthenticatorResult(
                    code=AuthenticatorResult.AUTH_FAIL)
コード例 #29
0
ファイル: UserDAO.py プロジェクト: gmurdocca/fcombine
    def authenticate_user(self, username, password):
        # This function will first try to authenticate the user.  If it's
        # successful, we will query the associated directory server to
        # pull down user details.  We don't care if the directory server
        # returns nothing as it's just pretty user details etc.

        # first see if we've already seen the user, that is, they are in
        # the Fcombine database
        try:
            user = User.objects.get(username=username)
            authenticator = self.authenticators[user.userprofile.auth_server.id]
            log(6, "User found in the database, authenticator = %d" % \
                    (user.userprofile.auth_server.id))
            result = authenticator.authenticate(username, password)

            # TODO: do we need to synchronize the user/userprofile objects
            # here?

            return result.code
        except User.DoesNotExist:
            pass

        # if we're here, it's possible the user does exist, but is not in the
        # database yet, ie, they are in the process of being imported into the
        # database which may be a slow operation as it is serialised.

        # authenticate the user against each server until we're successful with
        # one, or none. We handle potential duplication of usernames across
        # different directory servers at the import phase in that we raise an
        # error if an admin tries to import a user whos username already exists
        # on the Fcombine.

        result_queue = Queue()
        auth_threads = []
        for auth_server_id, authenticator in self.authenticators.items():
            log(6, "Thread count = %d" % len(auth_threads))

            # TODO: make sure this doesn't cause memory problems if a server
            # goes down.  We should probably track if a server is having
            # problems so we can rate limit authentication
            auth_thread = AuthenticatorThread(authenticator, auth_server_id, \
                    result_queue, username, password)
            auth_threads.append(auth_thread)
            auth_thread.start()


        failed = False
        user = User()
        user_profile = UserProfile()
        for i in xrange(len(auth_threads)):
            result = result_queue.get()
            log(6, "Got result from queue")

            if result.is_successful():
                # insert the user into our database now.
                # look up the auth server and directory server for this user
                auth_server = AuthServer.objects.get(id=result.auth_server_id)
                dir_server_id = auth_server.directory_server.id
                directory_queryer = self.directory_queryers[dir_server_id]

                # look up the user in the directory
                #user_profile = result.authenticator.to_user(result.entry)
                try:
                    user_profile = directory_queryer.lookup(result)

                    # save the user profile
                    user_profile.auth_server = auth_server
                    user_profile.user.save()
                    user_profile.save()
                except DirectoryQueryException, ex:
                    log(2, "DirectoryQueryException: %s" % str(ex))

                return result.code

            if result.is_failure() == False:
                failed = True
コード例 #30
0
ファイル: FcombineFS.py プロジェクト: gmurdocca/fcombine
 def fsinit(self):
     log(7, "fsinit")
     os.chdir(self.home_source)