예제 #1
0
    def bind(self):
        while True:
            with self.cv:
                notify = self.cv.wait(60)

                if self.enabled:
                    if self.parameters['krb_principal']:
                        try:
                            obtain_or_renew_ticket(
                                self.principal,
                                keytab=True,
                                renew_life=TICKET_RENEW_LIFE
                            )
                        except krb5.KrbException as err:
                            self.directory.put_status(errno.ENXIO, '{0} <{1}>'.format(str(err), type(err).__name__))
                            self.directory.put_state(DirectoryState.FAILURE)
                            continue

                    if self.directory.state == DirectoryState.BOUND and not notify:
                        continue

                    try:
                        self.directory.put_state(DirectoryState.JOINING)

                        if self.parameters['krb_principal']:
                            self.conn = ldap3.Connection(
                                self.server,
                                client_strategy='ASYNC',
                                authentication=ldap3.SASL,
                                sasl_mechanism='GSSAPI'
                            )
                        else:
                            self.conn = ldap3.Connection(
                                self.server,
                                client_strategy='ASYNC',
                                user=self.parameters['bind_dn'],
                                password=self.parameters['password']
                            )

                            if self.start_tls:
                                logger.debug('Performing STARTTLS...')
                                self.conn.open()
                                self.conn.start_tls()

                        if not self.conn.bind():
                            raise RuntimeError('Bind failed: wrong credentials')

                        self.directory.put_state(DirectoryState.BOUND)
                        continue
                    except BaseException as err:
                        self.directory.put_status(errno.ENXIO, '{0} <{1}>'.format(str(err), type(err).__name__))
                        self.directory.put_state(DirectoryState.FAILURE)
                        continue
                else:
                    if self.directory.state != DirectoryState.DISABLED:
                        self.directory.put_state(DirectoryState.EXITING)
                        self.conn.unbind()
                        self.directory.put_state(DirectoryState.DISABLED)
                        continue
예제 #2
0
    def bind(self):
        while True:
            with self.cv:
                notify = self.cv.wait(60)

                if self.enabled:
                    try:
                        obtain_or_renew_ticket(self.principal,
                                               self.parameters['password'],
                                               renew_life=TICKET_RENEW_LIFE)
                    except krb5.KrbException as err:
                        self.directory.put_status(
                            errno.ENXIO,
                            '{0} <{1}>'.format(str(err),
                                               type(err).__name__))
                        self.directory.put_state(DirectoryState.FAILURE)
                        continue

                    if self.directory.state == DirectoryState.BOUND and not notify:
                        continue

                    try:
                        self.directory.put_state(DirectoryState.JOINING)
                        self.servers = [
                            ldap3.Server(i) for i in self.ldap_addresses
                        ]
                        self.conn = ldap3.Connection(self.servers,
                                                     client_strategy='ASYNC',
                                                     authentication=ldap3.SASL,
                                                     sasl_mechanism='GSSAPI')

                        self.conn.bind()
                        self.directory.put_state(DirectoryState.BOUND)
                        continue
                    except BaseException as err:
                        self.directory.put_status(
                            errno.ENXIO,
                            '{0} <{1}>'.format(str(err),
                                               type(err).__name__))
                        self.directory.put_state(DirectoryState.FAILURE)
                        continue
                else:
                    if self.directory.state != DirectoryState.DISABLED:
                        if self.conn:
                            self.conn.unbind()

                        self.directory.put_state(DirectoryState.DISABLED)
                        continue
예제 #3
0
    def join(self):
        logger.info('Trying to join to {0}...'.format(self.realm))

        try:
            self.configure_smb(True)
            obtain_or_renew_ticket(self.principal, self.parameters['password'])

            subprocess.call(
                ['/usr/local/bin/net', 'ads', 'join', self.realm, '-k'])
            subprocess.call(['/usr/sbin/service', 'samba_server', 'restart'])

            self.dc = self.wbc.ping_dc(self.realm)
            self.domain_info = self.wbc.get_domain_info(self.realm)
            self.domain_name = self.wbc.interface.netbios_domain
        except BaseException as err:
            self.directory.put_status(errno.ENXIO, str(err))
            self.directory.put_state(DirectoryState.FAILURE)
            return False

        logger.info('Sucessfully joined to the domain {0}'.format(self.realm))
        self.directory.put_state(DirectoryState.BOUND)
        return True
예제 #4
0
    def bind(self):
        def create_args(params):
            validate = ssl.CERT_REQUIRED if params.get(
                'verify_certificate', False) else ssl.CERT_NONE

            if params['encryption'] == 'OFF':
                return {}

            if params['encryption'] == 'SSL':
                tls = ldap3.Tls(validate=validate)
                return {'port': 636, 'use_ssl': True, 'tls': tls}

            if params['encryption'] == 'TLS':
                tls = ldap3.Tls(validate=validate)
                return {'tls': tls}

        while True:
            with self.cv:
                notify = self.cv.wait(60)

                if self.enabled:
                    try:
                        obtain_or_renew_ticket(self.principal,
                                               self.parameters['password'],
                                               renew_life=TICKET_RENEW_LIFE)
                    except krb5.KrbException as err:
                        self.directory.put_status(
                            errno.ENXIO,
                            '{0} <{1}>'.format(str(err),
                                               type(err).__name__))
                        self.directory.put_state(DirectoryState.FAILURE)
                        continue

                    if self.directory.state == DirectoryState.BOUND and not notify:
                        continue

                    try:
                        self.directory.put_state(DirectoryState.JOINING)
                        self.servers = [
                            ldap3.Server(i, **create_args(self.parameters))
                            for i in self.ldap_addresses
                        ]
                        self.conn = ldap3.Connection(self.servers,
                                                     client_strategy='ASYNC',
                                                     authentication=ldap3.SASL,
                                                     sasl_mechanism='GSSAPI')

                        if self.parameters['encryption'] == 'TLS':
                            logger.debug('Performing STARTTLS...')
                            self.conn.open()
                            self.conn.start_tls()

                        self.conn.bind()
                        self.directory.put_state(DirectoryState.BOUND)
                        continue
                    except BaseException as err:
                        logger.debug('Failure details', exc_info=True)
                        self.directory.put_status(
                            errno.ENXIO,
                            '{0} <{1}>'.format(str(err),
                                               type(err).__name__))
                        self.directory.put_state(DirectoryState.FAILURE)
                        continue
                else:
                    if self.directory.state != DirectoryState.DISABLED:
                        if self.conn:
                            self.conn.unbind()

                        self.directory.put_state(DirectoryState.DISABLED)
                        continue
예제 #5
0
    def bind(self):
        logger.debug('Bind thread: starting')
        while True:
            with self.cv:
                notify = self.cv.wait(60)

                if notify:
                    pass

                if self.enabled:
                    try:
                        obtain_or_renew_ticket(self.principal,
                                               self.parameters['password'])
                    except krb5.KrbException as err:
                        self.directory.put_status(
                            errno.ENXIO,
                            '{0} <{1}>'.format(str(err),
                                               type(err).__name__))
                        self.directory.put_state(DirectoryState.FAILURE)
                        continue

                    if not self.is_joined(True):
                        # Try to rejoin
                        logger.debug('Keepalive thread: rejoining')
                        self.directory.put_state(DirectoryState.JOINING)
                        if not self.join():
                            continue
                    else:
                        self.domain_info = self.wbc.get_domain_info(self.realm)
                        self.domain_name = self.wbc.interface.netbios_domain
                        self.directory.put_state(DirectoryState.BOUND)

                    if not self.ldap:
                        logger.debug('Initializing LDAP connection')
                        logger.debug('LDAP server addresses: {0}'.format(
                            ', '.join(self.ldap_addresses)))
                        ldap_addresses = self.ldap_addresses
                        sasl_credentials = None

                        if self.parameters.get('dc_address'):
                            logger.debug(
                                'Using manually configured DC address')
                            sasl_credentials = (self.ldap_addresses[0][:-1], )
                            ldap_addresses = get_a_records(
                                self.ldap_addresses[0],
                                self.parameters['dc_address'])

                        self.ldap_servers = [
                            ldap3.Server(i) for i in ldap_addresses
                        ]
                        self.ldap = ldap3.Connection(
                            self.ldap_servers,
                            client_strategy='ASYNC',
                            authentication=ldap3.SASL,
                            sasl_mechanism='GSSAPI',
                            sasl_credentials=sasl_credentials)

                        try:
                            self.ldap.bind()
                            logger.debug('LDAP bound')
                        except BaseException as err:
                            logging.exception('err')
                            self.directory.put_status(errno.ENXIO, str(err))
                            self.directory.put_state(DirectoryState.FAILURE)
                            continue

                        # Prefetch "Domain Users" GUID
                        du = self.search_one(self.base_dn,
                                             '(sAMAccountName=Domain Users)')
                        self.domain_users_guid = uuid.UUID(
                            bytes=du['attributes']['objectGUID'][0])
                        logger.debug('Domain Users GUID is {0}'.format(
                            self.domain_users_guid))

                else:
                    if self.directory.state != DirectoryState.DISABLED:
                        self.leave()
                        self.directory.put_state(DirectoryState.DISABLED)
예제 #6
0
 def __renew_ticket(self):
     obtain_or_renew_ticket(self.principal, self.parameters['password'])
예제 #7
0
    def bind(self):
        logger.debug('Bind thread: starting')
        while True:
            with self.cv:
                notify = self.cv.wait(60)

                if notify:
                    if self.is_joined() and self.enabled:
                        self.directory.put_state(DirectoryState.EXITING)
                        self.leave()

                if self.enabled:
                    try:
                        obtain_or_renew_ticket(self.principal,
                                               self.parameters['password'])
                    except krb5.KrbException as err:
                        self.directory.put_status(
                            errno.ENXIO,
                            '{0} <{1}>'.format(str(err),
                                               type(err).__name__))
                        self.directory.put_state(DirectoryState.FAILURE)
                        continue

                    if not self.is_joined(True):
                        # Try to rejoin
                        logger.debug('Keepalive thread: rejoining')
                        self.directory.put_state(DirectoryState.JOINING)
                        if not self.join():
                            continue
                    else:
                        self.domain_info = self.wbc.get_domain_info(self.realm)
                        self.domain_name = self.wbc.interface.netbios_domain

                    if self.directory.state != DirectoryState.BOUND:
                        try:
                            logger.debug('Initializing LDAP connection')
                            logger.debug('LDAP server addresses: {0}'.format(
                                ', '.join(self.ldap_addresses)))
                            ldap_addresses = self.ldap_addresses

                            if self.parameters.get('dc_address'):
                                logger.debug(
                                    'Using manually configured DC address')
                                ldap_addresses = [
                                    self.parameters.get('dc_address')
                                ]

                            self.ldap_servers = [
                                ldap3.Server(i) for i in ldap_addresses
                            ]
                            self.ldap = ldap3.Connection(
                                self.ldap_servers,
                                client_strategy='ASYNC',
                                authentication=ldap3.SASL,
                                sasl_mechanism='GSSAPI',
                                sasl_credentials=None)

                            if not self.ldap.bind():
                                # try TLS now
                                logger.warning(
                                    'Regular bind failed, trying STARTTLS...')
                                self.ldap.start_tls()
                                if not self.ldap.bind():
                                    raise RuntimeError("Failed to bind")

                            logger.debug('LDAP bound')

                            # Get the domain object
                            domain = self.search_dn(self.base_dn)
                            if not domain:
                                raise RuntimeError(
                                    'Failed to fetch domain LDAP object, incorrect realm?'
                                )

                            self.domain_sid = domain['attributes']['objectSid']
                            logger.info('Domain SID: {0}'.format(
                                self.domain_sid))

                            # Figure out group DN and prefetch "Domain Users" GUID
                            dsid = sid.sid('{0}-{1}'.format(
                                self.domain_sid, 513))
                            du = self.search_one(
                                self.base_dn,
                                '(objectSid={0})'.format(dsid.ldap()))
                            if not du:
                                raise RuntimeError(
                                    'Failed to fetch Domain Users')

                            self.domain_users_guid = uuid.UUID(
                                du['attributes']['objectGUID'])
                            logger.debug('Domain Users GUID is {0}'.format(
                                self.domain_users_guid))
                        except BaseException as err:
                            logger.debug('Failure details', exc_info=True)
                            self.directory.put_status(
                                errno.ENXIO,
                                '{0} <{1}>'.format(str(err),
                                                   type(err).__name__))
                            self.directory.put_state(DirectoryState.FAILURE)
                        else:
                            self.directory.put_state(DirectoryState.BOUND)
                else:
                    if self.directory.state != DirectoryState.DISABLED:
                        self.leave()
                        self.directory.put_state(DirectoryState.DISABLED)
예제 #8
0
    def bind(self):
        logger.debug('Bind thread: starting')
        while True:
            with self.cv:
                notify = self.cv.wait(60)

                if notify:
                    if self.is_joined() and self.enabled:
                        self.directory.put_state(DirectoryState.EXITING)
                        self.leave()

                if self.enabled:
                    try:
                        obtain_or_renew_ticket(self.principal,
                                               self.parameters['password'])
                    except krb5.KrbException as err:
                        self.directory.put_status(
                            errno.ENXIO,
                            '{0} <{1}>'.format(str(err),
                                               type(err).__name__))
                        self.directory.put_state(DirectoryState.FAILURE)
                        continue

                    if not self.is_joined(True):
                        # Try to rejoin
                        logger.debug('Keepalive thread: rejoining')
                        self.directory.put_state(DirectoryState.JOINING)
                        if not self.join():
                            continue
                    else:
                        self.domain_info = self.wbc.get_domain_info(self.realm)
                        self.domain_name = self.wbc.interface.netbios_domain

                    if self.directory.state != DirectoryState.BOUND:
                        try:
                            # Get the domain object
                            domain = self.search_dn(self.base_dn)
                            if not domain:
                                raise RuntimeError(
                                    'Failed to fetch domain LDAP object, incorrect realm?'
                                )

                            self.domain_sid = domain['attributes']['objectSid']
                            self.domain_admins_sid = f'{self.domain_sid}-512'
                            logger.info('Domain SID: {0}'.format(
                                self.domain_sid))

                            # Figure out group DN and prefetch "Domain Users" GUID
                            dsid = SID('{0}-{1}'.format(self.domain_sid, 513))
                            du = self.search_one(
                                self.base_dn,
                                '(objectSid={0})'.format(dsid.ldap()))
                            if not du:
                                raise RuntimeError(
                                    'Failed to fetch Domain Users')

                            self.domain_users_guid = uuid.UUID(
                                du['attributes']['objectGUID'])
                            logger.debug('Domain Users GUID is {0}'.format(
                                self.domain_users_guid))
                        except BaseException as err:
                            logger.debug('Failure details', exc_info=True)
                            self.directory.put_status(
                                errno.ENXIO,
                                '{0} <{1}>'.format(str(err),
                                                   type(err).__name__))
                            self.directory.put_state(DirectoryState.FAILURE)
                        else:
                            self.directory.put_state(DirectoryState.BOUND)
                else:
                    if self.directory.state != DirectoryState.DISABLED:
                        self.leave()
                        self.directory.put_state(DirectoryState.DISABLED)