Ejemplo n.º 1
0
class DCKeytabTests(tests.TestCase):
    def setUp(self):
        super(DCKeytabTests, self).setUp()
        self.lp = LoadParm()
        self.lp.load_default()
        self.creds = self.insta_creds(template=self.get_credentials())
        self.ktfile = os.path.join(self.lp.get('private dir'), 'test.keytab')
        self.principal = self.creds.get_principal()

    def tearDown(self):
        super(DCKeytabTests, self).tearDown()
        os.remove(self.ktfile)

    def test_export_keytab(self):
        net = Net(None, self.lp)
        net.export_keytab(keytab=self.ktfile, principal=self.principal)
        assert os.path.exists(self.ktfile), 'keytab was not created'
        with open_bytes(self.ktfile) as bytes_kt:
            result = ''
            for c in bytes_kt.read():
                if c in string.printable:
                    result += c
            principal_parts = self.principal.split('@')
            assert principal_parts[0] in result and \
                principal_parts[1] in result, \
                'Principal not found in generated keytab'
Ejemplo n.º 2
0
def main():
    lp = LoadParm()
    lp.load_default()

    print("\nLoaded loadparm:")
    print("  samdb_url:      ", lp.samdb_url())
    print("  server_role:    ", lp.server_role())

    creds = Credentials()
    creds.guess(lp)
    print("\nCredentials:")
    creds.set_kerberos_state(MUST_USE_KERBEROS)
    # If MUST_USE_KERBEROS and we have no ticket, yields this error:
    # "Failed to connect to 'ldap://dc1' with backend 'ldap': LDAP client internal error: NT_STATUS_INVALID_PARAMETER"

    # Local
    #samdb = SamDB(lp=lp)

    # Remote
    samdb = SamDB(lp=lp, url='ldap://dc1', credentials=creds)

    print("\nOpened SAM DB:")
    print("  domain_dn:      ", samdb.domain_dn())
    print("  domain_dns_name:", samdb.domain_dns_name())

    for q in sys.argv[1:]:
        query(samdb, q)
Ejemplo n.º 3
0
def user_policy_apply(user, password):
    user = user.split('\\')[-1]

    logger = logging.getLogger('gpupdate')
    logger.addHandler(logging.StreamHandler(sys.stdout))
    logger.setLevel(logging.CRITICAL)
    log_level = lp.log_level()
    if log_level == 1:
        logger.setLevel(logging.ERROR)
    elif log_level == 2:
        logger.setLevel(logging.WARNING)
    elif log_level == 3:
        logger.setLevel(logging.INFO)
    elif log_level >= 4:
        logger.setLevel(logging.DEBUG)
    lp = LoadParm()
    lp.load_default()
    creds = Credentials()
    creds.guess(lp)
    creds.set_username(user)
    creds.set_password(password)

    _, user_exts = get_gp_client_side_extensions(logger)
    gp_extensions = []
    for ext in user_exts:
        gp_extensions.append(ext(logger, lp, creds, store))

    cache_dir = lp.get('cache directory')
    store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
    try:
        apply_gp(lp, creds, logger, store, gp_extensions)
    except NTSTATUSError as e:
        logger.info(e.message)
Ejemplo n.º 4
0
class SambaOptions(optparse.OptionGroup):
    """General Samba-related command line options."""

    def __init__(self, parser):
        from samba.param import LoadParm
        optparse.OptionGroup.__init__(self, parser, "Samba Common Options")
        self.add_option("-s", "--configfile", action="callback",
                        type=str, metavar="FILE", help="Configuration file",
                        callback=self._load_configfile)
        self.add_option("-d", "--debuglevel", action="callback",
                        type=int, metavar="DEBUGLEVEL", help="debug level",
                        callback=self._set_debuglevel)
        self.add_option("--option", action="callback",
                        type=str, metavar="OPTION",
                        help="set smb.conf option from command line",
                        callback=self._set_option)
        self.add_option("--realm", action="callback",
                        type=str, metavar="REALM", help="set the realm name",
                        callback=self._set_realm)
        self._configfile = None
        self._lp = LoadParm()
        self.realm = None

    def get_loadparm_path(self):
        """Return path to the smb.conf file specified on the command line."""
        return self._configfile

    def _load_configfile(self, option, opt_str, arg, parser):
        self._configfile = arg

    def _set_debuglevel(self, option, opt_str, arg, parser):
        if arg < 0:
            raise optparse.OptionValueError("invalid %s option value: %s" %
                                            (opt_str, arg))
        self._lp.set('debug level', str(arg))

    def _set_realm(self, option, opt_str, arg, parser):
        self._lp.set('realm', arg)
        self.realm = arg

    def _set_option(self, option, opt_str, arg, parser):
        if arg.find('=') == -1:
            raise optparse.OptionValueError(
                "--option option takes a 'a=b' argument")
        a = arg.split('=')
        try:
            self._lp.set(a[0], a[1])
        except Exception as e:
            raise optparse.OptionValueError(
                "invalid --option option value %r: %s" % (arg, e))

    def get_loadparm(self):
        """Return loadparm object with data specified on the command line."""
        if self._configfile is not None:
            self._lp.load(self._configfile)
        elif os.getenv("SMB_CONF_PATH") is not None:
            self._lp.load(os.getenv("SMB_CONF_PATH"))
        else:
            self._lp.load_default()
        return self._lp
Ejemplo n.º 5
0
class DCKeytabTests(tests.TestCase):
    def setUp(self):
        super(DCKeytabTests, self).setUp()
        self.lp = LoadParm()
        self.lp.load_default()
        self.creds = self.insta_creds(template=self.get_credentials())
        self.ktfile = os.path.join(self.lp.get('private dir'), 'test.keytab')
        self.principal = self.creds.get_principal()

    def tearDown(self):
        super(DCKeytabTests, self).tearDown()
        os.remove(self.ktfile)

    def test_export_keytab(self):
        net = Net(None, self.lp)
        net.export_keytab(keytab=self.ktfile, principal=self.principal)
        assert os.path.exists(self.ktfile), 'keytab was not created'
        with open_bytes(self.ktfile) as bytes_kt:
            result = ''
            for c in bytes_kt.read():
                if c in string.printable:
                    result += c
            principal_parts = self.principal.split('@')
            assert principal_parts[0] in result and \
                   principal_parts[1] in result, \
                        'Principal not found in generated keytab'
Ejemplo n.º 6
0
Archivo: getopt.py Proyecto: reqa/samba
class SambaOptions(optparse.OptionGroup):
    """General Samba-related command line options."""

    def __init__(self, parser):
        from samba import fault_setup
        fault_setup()
        from samba.param import LoadParm
        optparse.OptionGroup.__init__(self, parser, "Samba Common Options")
        self.add_option("-s", "--configfile", action="callback",
                        type=str, metavar="FILE", help="Configuration file",
                        callback=self._load_configfile)
        self.add_option("-d", "--debuglevel", action="callback",
                        type=str, metavar="DEBUGLEVEL", help="debug level",
                        callback=self._set_debuglevel)
        self.add_option("--option", action="callback",
                        type=str, metavar="OPTION",
                        help="set smb.conf option from command line",
                        callback=self._set_option)
        self.add_option("--realm", action="callback",
                        type=str, metavar="REALM", help="set the realm name",
                        callback=self._set_realm)
        self._configfile = None
        self._lp = LoadParm()
        self.realm = None

    def get_loadparm_path(self):
        """Return path to the smb.conf file specified on the command line."""
        return self._configfile

    def _load_configfile(self, option, opt_str, arg, parser):
        self._configfile = arg

    def _set_debuglevel(self, option, opt_str, arg, parser):
        self._lp.set('debug level', arg)
        parser.values.debuglevel = arg

    def _set_realm(self, option, opt_str, arg, parser):
        self._lp.set('realm', arg)
        self.realm = arg

    def _set_option(self, option, opt_str, arg, parser):
        if arg.find('=') == -1:
            raise optparse.OptionValueError(
                "--option option takes a 'a=b' argument")
        a = arg.split('=')
        try:
            self._lp.set(a[0], a[1])
        except Exception as e:
            raise optparse.OptionValueError(
                "invalid --option option value %r: %s" % (arg, e))

    def get_loadparm(self):
        """Return loadparm object with data specified on the command line."""
        if self._configfile is not None:
            self._lp.load(self._configfile)
        elif os.getenv("SMB_CONF_PATH") is not None:
            self._lp.load(os.getenv("SMB_CONF_PATH"))
        else:
            self._lp.load_default()
        return self._lp
Ejemplo n.º 7
0
class AuthSMB4(object):
    def __init__(self, user, password):
        self.user = user
        self.password = password
        _isLastErrorAvailable = False
        self.lp = LoadParm()
        self.lp.load_default()
        self.ip = '127.0.0.1'
        self.WorkGroup = str(self.lp.get("workgroup"))
        self.creds = credentials.Credentials()
        self.creds.set_username(self.user)
        self.creds.set_password(self.password)
        self.creds.set_domain(self.WorkGroup)
        self.creds.set_workstation("")

        self.logger = logging.getLogger(__name__)
        self.logger.addHandler(logging.StreamHandler(sys.stdout))
        self.logger.setLevel(logging.INFO)

    def Autenticate(self):
        try:
            session_info_flags = (AUTH_SESSION_INFO_DEFAULT_GROUPS
                                  | AUTH_SESSION_INFO_AUTHENTICATED)

            LdapConn = samba.Ldb("ldap://%s" % self.ip,
                                 lp=self.lp,
                                 credentials=self.creds)
            DomainDN = LdapConn.get_default_basedn()
            search_filter = "sAMAccountName=%s" % self.user
            res = LdapConn.search(base=DomainDN,
                                  scope=SCOPE_SUBTREE,
                                  expression=search_filter,
                                  attrs=["dn"])
            if len(res) == 0:
                return False

            user_dn = res[0].dn
            session = samba.auth.user_session(
                LdapConn,
                lp_ctx=self.lp,
                dn=user_dn,
                session_info_flags=session_info_flags)
            token = session.security_token

            if (token.has_builtin_administrators()):
                return True

            if (token.is_system()):
                return True

        except Exception, e:
            if (len(e.args) > 1):
                self.logger.info("%s %s" % (e.args[1], e.args[0]))
                self.SetError(e.args[1], e.args[0])
            else:
                self.logger.info("%s " % (e.args[0]))
                self.SetError(e.args, 0)
        return False
Ejemplo n.º 8
0
class SambaOCHelper(object):
    def __init__(self):
        self.samba_lp = LoadParm()
        self.samba_lp.set('debug level', '0')
        self.samba_lp.load_default()
        url = self.samba_lp.get('dcerpc_mapiproxy:samdb_url') or \
            self.samba_lp.private_path("sam.ldb")
        self.samdb = SamDB(url=url,
                           lp=self.samba_lp,
                           session_info=system_session())
        self.conn = self._open_mysql_connection()

    def _open_mysql_connection(self):
        connection_string = self.samba_lp.get('mapiproxy:openchangedb')
        if not connection_string:
            raise Exception(
                "Not found mapiproxy:openchangedb on samba configuration")
        # mysql://openchange:password@localhost/openchange
        m = re.search(
            r'(?P<scheme>.+)://(?P<user>.+):(?P<pass>.+)@(?P<host>.+)/(?P<db>.+)',
            connection_string)
        if not m:
            raise Exception("Unable to parse mapiproxy:openchangedb: %s" %
                            connection_string)
        group_dict = m.groupdict()
        if group_dict['scheme'] != 'mysql':
            raise Exception(
                "mapiproxy:openchangedb should start with mysql:// (we got %s)",
                group_dict['scheme'])

        conn = MySQLdb.connect(host=group_dict['host'],
                               user=group_dict['user'],
                               passwd=group_dict['pass'],
                               db=group_dict['db'])
        conn.autocommit(True)
        return conn

    def invalid_user(self, username):
        ret = self.samdb.search(base=self.samdb.domain_dn(),
                                scope=ldb.SCOPE_SUBTREE,
                                expression="(sAMAccountName=%s)" %
                                ldb.binary_encode(username))
        return len(ret) != 1

    def find_email_of(self, username):
        ret = self.samdb.search(base=self.samdb.domain_dn(),
                                scope=ldb.SCOPE_SUBTREE,
                                attrs=["mail"],
                                expression="(sAMAccountName=%s)" %
                                ldb.binary_encode(username))
        return ret[0]["mail"][0]

    def active_openchange_users(self):
        c = self.conn.cursor()
        c.execute("SELECT name FROM mailboxes")
        return sorted([row[0] for row in c.fetchall()])
Ejemplo n.º 9
0
def parse_gpext_conf(smb_conf):
    lp = LoadParm()
    if smb_conf is not None:
        lp.load(smb_conf)
    else:
        lp.load_default()
    ext_conf = lp.state_path('gpext.conf')
    parser = ConfigParser()
    parser.read(ext_conf)
    return lp, parser
Ejemplo n.º 10
0
class SambaOCHelper(object):
    def __init__(self):
        self.samba_lp = LoadParm()
        self.samba_lp.set('debug level', '0')
        self.samba_lp.load_default()
        url = self.samba_lp.get('dcerpc_mapiproxy:samdb_url') or \
            self.samba_lp.private_path("sam.ldb")
        self.samdb = SamDB(url=url,
                           lp=self.samba_lp,
                           session_info=system_session())
        self.conn = self._open_mysql_connection()

    def _open_mysql_connection(self):
        connection_string = self.samba_lp.get('mapiproxy:openchangedb')
        if not connection_string:
            raise Exception("Not found mapiproxy:openchangedb on samba configuration")
        # mysql://openchange:password@localhost/openchange
        m = re.search(r'(?P<scheme>.+)://(?P<user>.+):(?P<pass>.+)@(?P<host>.+)/(?P<db>.+)',
                      connection_string)
        if not m:
            raise Exception("Unable to parse mapiproxy:openchangedb: %s" %
                            connection_string)
        group_dict = m.groupdict()
        if group_dict['scheme'] != 'mysql':
            raise Exception("mapiproxy:openchangedb should start with mysql:// (we got %s)",
                            group_dict['scheme'])

        conn = MySQLdb.connect(host=group_dict['host'], user=group_dict['user'],
                               passwd=group_dict['pass'], db=group_dict['db'])
        conn.autocommit(True)
        return conn

    def invalid_user(self, username):
        ret = self.samdb.search(base=self.samdb.domain_dn(),
                                scope=ldb.SCOPE_SUBTREE,
                                expression="(sAMAccountName=%s)" % ldb.binary_encode(username))
        return len(ret) != 1

    def find_email_of(self, username):
        ret = self.samdb.search(base=self.samdb.domain_dn(),
                                scope=ldb.SCOPE_SUBTREE, attrs=["mail"],
                                expression="(sAMAccountName=%s)" % ldb.binary_encode(username))
        return ret[0]["mail"][0]

    def active_openchange_users(self):
        c = self.conn.cursor()
        c.execute("SELECT name FROM mailboxes")
        return sorted([row[0] for row in c.fetchall()])

    def get_indexing_cache(self):
        memcached_server = self.samba_lp.get('mapistore:indexing_cache')
        if not memcached_server:
            return "127.0.0.1:11211"
        # This should has a format like: --SERVER=11.22.33.44:11211
        return memcached_server.split('=')[1]
Ejemplo n.º 11
0
def parametros(fichero=False):
    """
    Intento ser un poco cuidadoso con la forma en que obtenemos la configuración
    """
    try:
        lp = LoadParm()
        lp.load_default() if fichero is False else lp.load(fichero)
        return lp
    except RuntimeError as e:
        log.warning(e.message)
        raise ConfiguracionException(e)
Ejemplo n.º 12
0
class GPOTests(tests.TestCase):
    def setUp(self):
        super(GPOTests, self).setUp()
        self.server = os.environ["SERVER"]
        self.lp = LoadParm()
        self.lp.load_default()
        self.creds = self.insta_creds(template=self.get_credentials())

    def tearDown(self):
        super(GPOTests, self).tearDown()

    def test_gpo_list(self):
        global poldir, dspath
        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.creds.get_username())
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        names = ['Local Policy', guid]
        file_sys_paths = [None, '%s\\%s' % (poldir, guid)]
        ds_paths = [None, 'CN=%s,%s' % (guid, dspath)]
        for i in range(0, len(gpos)):
            assert gpos[i].name == names[i], \
              'The gpo name did not match expected name %s' % gpos[i].name
            assert gpos[i].file_sys_path == file_sys_paths[i], \
              'file_sys_path did not match expected %s' % gpos[i].file_sys_path
            assert gpos[i].ds_path == ds_paths[i], \
              'ds_path did not match expected %s' % gpos[i].ds_path


    def test_gpo_ads_does_not_segfault(self):
        try:
            ads = gpo.ADS_STRUCT(self.server, 42, self.creds)
        except:
            pass

    def test_gpt_version(self):
        global gpt_data
        local_path = self.lp.get("path", "sysvol")
        policies = 'addom.samba.example.com/Policies'
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        gpo_path = os.path.join(local_path, policies, guid)
        old_vers = gpo.gpo_get_sysvol_gpt_version(gpo_path)[1]

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % 42)
        assert gpo.gpo_get_sysvol_gpt_version(gpo_path)[1] == 42, \
          'gpo_get_sysvol_gpt_version() did not return the expected version'

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % old_vers)
        assert gpo.gpo_get_sysvol_gpt_version(gpo_path)[1] == old_vers, \
          'gpo_get_sysvol_gpt_version() did not return the expected version'
Ejemplo n.º 13
0
def main():
    args = parse_args()
    logging.basicConfig(level=logging.DEBUG if args.debug else logging.WARNING)

    inpipe = sys.stdin
    outpipe = sys.stdout

    if args.unix:
        import socket
        try:
            os.remove(args.unix)
        except OSError:
            pass

        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.bind(args.unix)
        os.chmod(args.unix, 0o777)
        logger.debug("Bound unix socket: {}".format(args.unix))

        logger.info("Waiting for connection at {}".format(args.unix))
        sock.listen(1)
        csock, client_address = sock.accept()

        logger.info("Accepted connection from {}".format(client_address))
        inpipe = outpipe = csock.makefile()

    lp = LoadParm()
    lp.load_default()

    creds = Credentials()
    creds.guess(lp)
    creds.set_kerberos_state(MUST_USE_KERBEROS)
    # If MUST_USE_KERBEROS and we have no ticket, yields this error:
    # "Failed to connect to 'ldap://dc1' with backend 'ldap': LDAP client
    # internal error: NT_STATUS_INVALID_PARAMETER"

    # lp is required by ldap_connect_send() -> lpcfg_resolve_context()
    samdb = SamDB(lp=lp, url=args.url, credentials=creds)

    logger.debug("Opened SAM DB:")
    logger.debug("  domain_dn:       {}".format(samdb.domain_dn()))
    logger.debug("  domain_dns_name: {}".format(samdb.domain_dns_name()))

    try:
        r = SambaResponder(samdb, inpipe, outpipe)
        r.run()
    finally:
        if args.unix:
            try:
                os.remove(args.unix)
            except OSError:
                pass
Ejemplo n.º 14
0
class GPOTests(tests.TestCase):
    def setUp(self):
        super(GPOTests, self).setUp()
        self.server = os.environ["SERVER"]
        self.lp = LoadParm()
        self.lp.load_default()
        self.creds = self.insta_creds(template=self.get_credentials())

    def tearDown(self):
        super(GPOTests, self).tearDown()

    def test_gpo_list(self):
        global poldir, dspath
        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.creds.get_username())
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        names = ['Local Policy', guid]
        file_sys_paths = [None, '%s\\%s' % (poldir, guid)]
        ds_paths = [None, 'CN=%s,%s' % (guid, dspath)]
        for i in range(0, len(gpos)):
            assert gpos[i].name == names[i], \
              'The gpo name did not match expected name %s' % gpos[i].name
            assert gpos[i].file_sys_path == file_sys_paths[i], \
              'file_sys_path did not match expected %s' % gpos[i].file_sys_path
            assert gpos[i].ds_path == ds_paths[i], \
              'ds_path did not match expected %s' % gpos[i].ds_path

    def test_gpo_ads_does_not_segfault(self):
        try:
            ads = gpo.ADS_STRUCT(self.server, 42, self.creds)
        except:
            pass

    def test_gpt_version(self):
        global gpt_data
        local_path = self.lp.get("path", "sysvol")
        policies = 'addom.samba.example.com/Policies'
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        gpo_path = os.path.join(local_path, policies, guid)
        old_vers = gpo.gpo_get_sysvol_gpt_version(gpo_path)[1]

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % 42)
        assert gpo.gpo_get_sysvol_gpt_version(gpo_path)[1] == 42, \
          'gpo_get_sysvol_gpt_version() did not return the expected version'

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % old_vers)
        assert gpo.gpo_get_sysvol_gpt_version(gpo_path)[1] == old_vers, \
          'gpo_get_sysvol_gpt_version() did not return the expected version'
Ejemplo n.º 15
0
class AuthSMB4(object):
	def __init__(self,user,password):
		self.user = user
		self.password = password
		_isLastErrorAvailable=False
		self.lp = LoadParm()
		self.lp.load_default()
                self.ip = '127.0.0.1'
                self.WorkGroup = str(self.lp.get("workgroup"))
                self.creds = credentials.Credentials()
                self.creds.set_username(self.user)
                self.creds.set_password(self.password)
                self.creds.set_domain(self.WorkGroup)
                self.creds.set_workstation("")


		self.logger = logging.getLogger(__name__)
		self.logger.addHandler(logging.StreamHandler(sys.stdout))
		self.logger.setLevel(logging.INFO)
		
        def Autenticate(self):
                try:
                        session_info_flags = ( AUTH_SESSION_INFO_DEFAULT_GROUPS | AUTH_SESSION_INFO_AUTHENTICATED )

                        LdapConn = samba.Ldb("ldap://%s" % self.ip,lp=self.lp,credentials=self.creds)
                        DomainDN = LdapConn.get_default_basedn()
                        search_filter="sAMAccountName=%s" % self.user
                        res = LdapConn.search(base=DomainDN, scope=SCOPE_SUBTREE,expression=search_filter, attrs=["dn"])
                        if len(res) == 0:
                                return False

                        user_dn = res[0].dn
                        session = samba.auth.user_session(LdapConn, lp_ctx=self.lp, dn=user_dn,session_info_flags=session_info_flags)
                        token = session.security_token


                        if (token.has_builtin_administrators()):
                                return True

                        if(token.is_system()):
                                return True

                except Exception,e:
                        if(len(e.args)>1):
                                self.logger.info("%s %s" % (e.args[1],e.args[0]))
                                self.SetError(e.args[1],e.args[0])
                        else:
                                self.logger.info("%s " % (e.args[0]))
                                self.SetError(e.args,0)
                return False
Ejemplo n.º 16
0
class Options:
	def __init__(self):
		self.function_level = None
		self.use_xattrs = "auto" 
		self.lp = LoadParm();
		self.lp.load_default();
		self.realm = self.lp.get('realm') #default
		self.domain = self.lp.get('workgroup') #default
		self.adminpass = ''
		self.smbconf = self.lp.configfile
		self.server_role = self.lp.get("server role") #default
		self.samdb_fill = FILL_FULL #default
		self.blank = False
		self.partitions_only = False
Ejemplo n.º 17
0
class SambaOCHelper(object):
    def __init__(self):
        self.samba_lp = LoadParm()
        self.samba_lp.set("debug level", "0")
        self.samba_lp.load_default()
        url = self.samba_lp.get("dcerpc_mapiproxy:samdb_url") or self.samba_lp.private_path("sam.ldb")
        self.samdb = SamDB(url=url, lp=self.samba_lp, session_info=system_session())
        self.conn = self._open_mysql_connection()

    def _open_mysql_connection(self):
        connection_string = self.samba_lp.get("mapiproxy:openchangedb")
        if not connection_string:
            raise Exception("Not found mapiproxy:openchangedb on samba configuration")
        # mysql://openchange:password@localhost/openchange
        m = re.search(r"(?P<scheme>.+)://(?P<user>.+):(?P<pass>.+)@(?P<host>.+)/(?P<db>.+)", connection_string)
        if not m:
            raise Exception("Unable to parse mapiproxy:openchangedb: %s" % connection_string)
        group_dict = m.groupdict()
        if group_dict["scheme"] != "mysql":
            raise Exception("mapiproxy:openchangedb should start with mysql:// (we got %s)", group_dict["scheme"])

        conn = MySQLdb.connect(
            host=group_dict["host"], user=group_dict["user"], passwd=group_dict["pass"], db=group_dict["db"]
        )
        conn.autocommit(True)
        return conn

    def invalid_user(self, username):
        ret = self.samdb.search(
            base=self.samdb.domain_dn(),
            scope=ldb.SCOPE_SUBTREE,
            expression="(sAMAccountName=%s)" % ldb.binary_encode(username),
        )
        return len(ret) != 1

    def find_email_of(self, username):
        ret = self.samdb.search(
            base=self.samdb.domain_dn(),
            scope=ldb.SCOPE_SUBTREE,
            attrs=["mail"],
            expression="(sAMAccountName=%s)" % ldb.binary_encode(username),
        )
        return ret[0]["mail"][0]

    def active_openchange_users(self):
        c = self.conn.cursor()
        c.execute("SELECT name FROM mailboxes")
        return sorted([row[0] for row in c.fetchall()])
Ejemplo n.º 18
0
class auth_base(object):
    def __init__(self, user, password):
        self.user = user
        self.password = password
        self.lp = LoadParm()
        self.lp.load_default()
        self.ip = '127.0.0.1'
        self.WorkGroup = str(self.lp.get("workgroup"))
        self.creds = credentials.Credentials()
        self.creds.set_username(self.user)
        self.creds.set_password(self.password)
        self.creds.set_domain(self.WorkGroup)
        self.creds.set_workstation("")

    def autenticate(self):
        try:
            session_info_flags = (df_gp1 | df_gp2)

            LdapConn = samba.Ldb("ldap://%s" % self.ip,
                                 lp=self.lp,
                                 credentials=self.creds)
            DomainDN = LdapConn.get_default_basedn()
            search_filter = "sAMAccountName=%s" % self.user
            res = LdapConn.search(base=DomainDN,
                                  scope=SCOPE_SUBTREE,
                                  expression=search_filter,
                                  attrs=["dn"])
            if len(res) == 0:
                return False

            user_dn = res[0].dn
            session = samba.auth.user_session(
                LdapConn,
                lp_ctx=self.lp,
                dn=user_dn,
                session_info_flags=session_info_flags)
            token = session.security_token

            if (token.has_builtin_administrators()):
                return True

            if (token.is_system()):
                return True

        except Exception:
            return False

        return False
Ejemplo n.º 19
0
    def get_samba_sam_ldb_path(self):
        """
		Returns the 'sam.ldb' path using samba conf or defaults.
		"""
        print(
            "\nObtaining the Samba configuration to determine Samba private path"
        )
        smb_conf_path = getenv("SMB_CONF_PATH")
        SambaLP = LoadParm()

        if smb_conf_path:
            SambaLP.load(smb_conf_path)
        else:
            SambaLP.load_default()

        return SambaLP.private_path('sam.ldb')
Ejemplo n.º 20
0
    def apply(cls, cur, **kwargs):
        # Mimetise what mapistore_interface.c (mapistore_init) does
        # to get the mapping path
        if 'lp' in kwargs:
            mapping_path = kwargs['lp'].private_path("mapistore")
        else:
            lp = LoadParm()
            lp.load_default()
            mapping_path = lp.private_path("mapistore")

        if mapping_path is None:
            return

        cur.execute("START TRANSACTION")
        try:
            # Get all mailboxes
            cur.execute("SELECT name FROM mailboxes")
            for row in cur.fetchall():
                username = row[0]
                path = "{0}/{1}/replica_mapping.tdb".format(
                    mapping_path, username)
                try:
                    tdb_file = tdb.Tdb(path, 0, tdb.DEFAULT, os.O_RDONLY)
                    for k in tdb_file.iterkeys():
                        # Check if the key is an integer
                        try:
                            repl_id = int(k, base=16)
                            cls._insert_map(cur, username, repl_id,
                                            tdb_file[k])
                        except ValueError:
                            # Cannot convert to int, so no repl_id
                            continue
                except IOError:
                    # Cannot read any replica mapping
                    continue

            cur.execute("COMMIT")
        except Exception as e:
            print("Error migrating TDB files into the database {}, rollback".
                  format(e),
                  file=sys.stderr)
            cur.execute("ROLLBACK")
            raise
Ejemplo n.º 21
0
class GPOTests(tests.TestCase):
    def setUp(self):
        super(GPOTests, self).setUp()
        self.server = os.environ["SERVER"]
        self.dc_account = self.server.upper() + '$'
        self.lp = LoadParm()
        self.lp.load_default()
        self.creds = self.insta_creds(template=self.get_credentials())

    def tearDown(self):
        super(GPOTests, self).tearDown()

    def test_sec_ext_load_on_member(self):
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
        try:
            gp_access_ext(logger, self.lp, self.creds, store)
        except Exception:
            self.fail('Initializing gp_access_ext should not require ad-dc')
Ejemplo n.º 22
0
    def apply(cls, cur, **kwargs):
        # Mimetise what mapistore_interface.c (mapistore_init) does
        # to get the mapping path
        if 'lp' in kwargs:
            mapping_path = kwargs['lp'].private_path("mapistore")
        else:
            lp = LoadParm()
            lp.load_default()
            mapping_path = lp.private_path("mapistore")

        if mapping_path is None:
            return

        cur.execute("START TRANSACTION")
        try:
            # Get all mailboxes
            cur.execute("SELECT name FROM mailboxes")
            for row in cur.fetchall():
                username = row[0]
                path = "{0}/{1}/replica_mapping.tdb".format(mapping_path, username)
                try:
                    tdb_file = tdb.Tdb(path, 0, tdb.DEFAULT, os.O_RDONLY)
                    for k in tdb_file.iterkeys():
                        # Check if the key is an integer
                        try:
                            repl_id = int(k, base=16)
                            cls._insert_map(cur, username, repl_id, tdb_file[k])
                        except ValueError:
                            # Cannot convert to int, so no repl_id
                            continue
                except IOError:
                    # Cannot read any replica mapping
                    continue

            cur.execute("COMMIT")
        except Exception as e:
            print("Error migrating TDB files into the database {}, rollback".format(e), file=sys.stderr)
            cur.execute("ROLLBACK")
            raise
Ejemplo n.º 23
0
class AuthBase(object):
	def __init__(self,user,password):
		self.user = user
		self.password = password
		_isLastErrorAvailable=False
		self.lp = LoadParm()
		self.lp.load_default()

		self.logger = logging.getLogger(__name__)
		self.logger.addHandler(logging.StreamHandler(sys.stdout))
		self.logger.setLevel(logging.INFO)
		
	def Autenticate(self):
		pass
	
	def SetError(self,message,number=-1):
		self.LastErrorStr = message
		self.LastErrorNumber = number
		#self.Log.LogError(message)
		self._isLastErrorAvailable=True
			
	def IHaveError(self):
		return self._isLastErrorAvailable
Ejemplo n.º 24
0
class AuthBase(object):
    def __init__(self, user, password):
        self.user = user
        self.password = password
        _isLastErrorAvailable = False
        self.lp = LoadParm()
        self.lp.load_default()

        self.logger = logging.getLogger(__name__)
        self.logger.addHandler(logging.StreamHandler(sys.stdout))
        self.logger.setLevel(logging.INFO)

    def Autenticate(self):
        pass

    def SetError(self, message, number=-1):
        self.LastErrorStr = message
        self.LastErrorNumber = number
        #self.Log.LogError(message)
        self._isLastErrorAvailable = True

    def IHaveError(self):
        return self._isLastErrorAvailable
Ejemplo n.º 25
0
    credopts.add_option('--password', dest='password', help='Password')
    credopts.add_option('-U', '--username', dest='username', help='Username')
    credopts.add_option('--krb5-ccache',
                        dest='krb5_ccache',
                        help='Kerberos Credentials cache')
    parser.add_option_group(credopts)

    # Set the options and the arguments
    (opts, args) = parser.parse_args()

    # Set the loadparm context
    lp = LoadParm()
    if os.getenv("SMB_CONF_PATH") is not None:
        lp.load(os.getenv("SMB_CONF_PATH"))
    else:
        lp.load_default()

    # Initialize the session
    creds = Credentials()
    if opts.username and opts.password:
        creds.set_username(opts.username)
        creds.set_password(opts.password)
    elif opts.krb5_ccache:
        creds.set_named_ccache(opts.krb5_ccache)
    creds.guess(lp)

    from dialogs import GPMC, GPME
    from yast import UISequencer
    s = UISequencer(lp, creds)
    funcs = [(lambda lp, creds: GPMC(lp, creds).Show()),
             (lambda gpo, lp, creds: GPME(gpo, lp, creds).Show())]
Ejemplo n.º 26
0
class GPOTests(tests.TestCase):
    def setUp(self):
        super(GPOTests, self).setUp()
        self.server = os.environ["SERVER"]
        self.lp = LoadParm()
        self.lp.load_default()
        self.creds = self.insta_creds(template=self.get_credentials())

    def tearDown(self):
        super(GPOTests, self).tearDown()

    def test_gpo_list(self):
        global poldir, dspath
        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.creds.get_username())
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        names = ['Local Policy', guid]
        file_sys_paths = [None, '%s\\%s' % (poldir, guid)]
        ds_paths = [None, 'CN=%s,%s' % (guid, dspath)]
        for i in range(0, len(gpos)):
            self.assertEquals(
                gpos[i].name, names[i],
                'The gpo name did not match expected name %s' % gpos[i].name)
            self.assertEquals(
                gpos[i].file_sys_path, file_sys_paths[i],
                'file_sys_path did not match expected %s' %
                gpos[i].file_sys_path)
            self.assertEquals(
                gpos[i].ds_path, ds_paths[i],
                'ds_path did not match expected %s' % gpos[i].ds_path)

    def test_gpo_ads_does_not_segfault(self):
        try:
            ads = gpo.ADS_STRUCT(self.server, 42, self.creds)
        except:
            pass

    def test_gpt_version(self):
        global gpt_data
        local_path = self.lp.cache_path('gpo_cache')
        policies = 'ADDOM.SAMBA.EXAMPLE.COM/POLICIES'
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        gpo_path = os.path.join(local_path, policies, guid)
        old_vers = gpo.gpo_get_sysvol_gpt_version(gpo_path)[1]

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % 42)
        self.assertEquals(
            gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], 42,
            'gpo_get_sysvol_gpt_version() did not return the expected version')

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % old_vers)
        self.assertEquals(
            gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], old_vers,
            'gpo_get_sysvol_gpt_version() did not return the expected version')

    def test_check_refresh_gpo_list(self):
        cache = self.lp.cache_path('gpo_cache')
        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.creds.get_username())
        check_refresh_gpo_list(self.server, self.lp, self.creds, gpos)

        self.assertTrue(os.path.exists(cache),
                        'GPO cache %s was not created' % cache)

        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        gpt_ini = os.path.join(cache, 'ADDOM.SAMBA.EXAMPLE.COM/POLICIES', guid,
                               'GPT.INI')
        self.assertTrue(os.path.exists(gpt_ini),
                        'GPT.INI was not cached for %s' % guid)

    def test_check_refresh_gpo_list_malicious_paths(self):
        # the path cannot contain ..
        path = '/usr/local/samba/var/locks/sysvol/../../../../../../root/'
        self.assertRaises(OSError, check_safe_path, path)

        self.assertEqual(check_safe_path('/etc/passwd'), 'etc/passwd')
        self.assertEqual(check_safe_path('\\\\etc/\\passwd'), 'etc/passwd')

        # there should be no backslashes used to delineate paths
        before = 'sysvol/addom.samba.example.com\\Policies/' \
            '{31B2F340-016D-11D2-945F-00C04FB984F9}\\GPT.INI'
        after = 'addom.samba.example.com/Policies/' \
            '{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI'
        result = check_safe_path(before)
        self.assertEquals(
            result, after, 'check_safe_path() didn\'t'
            ' correctly convert \\ to /')

    def test_gpt_ext_register(self):
        this_path = os.path.dirname(os.path.realpath(__file__))
        samba_path = os.path.realpath(os.path.join(this_path, '../../../'))
        ext_path = os.path.join(samba_path, 'python/samba/gp_sec_ext.py')
        ext_guid = '{827D319E-6EAC-11D2-A4EA-00C04F79F83A}'
        ret = register_gp_extension(ext_guid,
                                    'gp_sec_ext',
                                    ext_path,
                                    smb_conf=self.lp.configfile,
                                    machine=True,
                                    user=False)
        self.assertTrue(ret, 'Failed to register a gp ext')
        gp_exts = list_gp_extensions(self.lp.configfile)
        self.assertTrue(ext_guid in gp_exts.keys(), 'Failed to list gp exts')
        self.assertEquals(gp_exts[ext_guid]['DllName'], ext_path,
                          'Failed to list gp exts')

        unregister_gp_extension(ext_guid)
        gp_exts = list_gp_extensions(self.lp.configfile)
        self.assertTrue(ext_guid not in gp_exts.keys(),
                        'Failed to unregister gp exts')

        self.assertTrue(check_guid(ext_guid), 'Failed to parse valid guid')
        self.assertFalse(check_guid('AAAAAABBBBBBBCCC'), 'Parsed invalid guid')

        lp, parser = parse_gpext_conf(self.lp.configfile)
        self.assertTrue(lp and parser, 'parse_gpext_conf() invalid return')
        parser.add_section('test_section')
        parser.set('test_section', 'test_var', ext_guid)
        atomic_write_conf(lp, parser)

        lp, parser = parse_gpext_conf(self.lp.configfile)
        self.assertTrue('test_section' in parser.sections(),
                        'test_section not found in gpext.conf')
        self.assertEquals(parser.get('test_section', 'test_var'), ext_guid,
                          'Failed to find test variable in gpext.conf')
        parser.remove_section('test_section')
        atomic_write_conf(lp, parser)

    def test_gp_log_get_applied(self):
        local_path = self.lp.get('path', 'sysvol')
        guids = [
            '{31B2F340-016D-11D2-945F-00C04FB984F9}',
            '{6AC1786C-016F-11D2-945F-00C04FB984F9}'
        ]
        gpofile = '%s/addom.samba.example.com/Policies/%s/MACHINE/Microsoft/' \
                  'Windows NT/SecEdit/GptTmpl.inf'
        stage = '[System Access]\nMinimumPasswordAge = 998\n'
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
        for guid in guids:
            gpttmpl = gpofile % (local_path, guid)
            ret = stage_file(gpttmpl, stage)
            self.assertTrue(ret, 'Could not create the target %s' % gpttmpl)

        ret = gpupdate_force(self.lp)
        self.assertEquals(ret, 0, 'gpupdate force failed')

        gp_db = store.get_gplog('ADDC$')

        applied_guids = gp_db.get_applied_guids()
        self.assertEquals(len(applied_guids), 2, 'The guids were not found')
        self.assertIn(guids[0], applied_guids,
                      '%s not in applied guids' % guids[0])
        self.assertIn(guids[1], applied_guids,
                      '%s not in applied guids' % guids[1])

        applied_settings = gp_db.get_applied_settings(applied_guids)
        for policy in applied_settings:
            self.assertIn('System Access', policy[1],
                          'System Access policies not set')
            self.assertIn('minPwdAge', policy[1]['System Access'],
                          'minPwdAge policy not set')
            if policy[0] == guids[0]:
                self.assertEqual(int(policy[1]['System Access']['minPwdAge']),
                                 days2rel_nttime(1),
                                 'minPwdAge policy not set')
            elif policy[0] == guids[1]:
                self.assertEqual(int(policy[1]['System Access']['minPwdAge']),
                                 days2rel_nttime(998),
                                 'minPwdAge policy not set')

        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list('ADDC$')
        del_gpos = get_deleted_gpos_list(gp_db, gpos[:-1])
        self.assertEqual(len(del_gpos), 1, 'Returned delete gpos is incorrect')
        self.assertEqual(guids[-1], del_gpos[0][0],
                         'GUID for delete gpo is incorrect')
        self.assertIn('System Access', del_gpos[0][1],
                      'System Access policies not set for removal')
        self.assertIn('minPwdAge', del_gpos[0][1]['System Access'],
                      'minPwdAge policy not set for removal')

        for guid in guids:
            gpttmpl = gpofile % (local_path, guid)
            unstage_file(gpttmpl)

        ret = gpupdate_unapply(self.lp)
        self.assertEquals(ret, 0, 'gpupdate unapply failed')

    def test_process_group_policy(self):
        local_path = self.lp.cache_path('gpo_cache')
        guids = [
            '{31B2F340-016D-11D2-945F-00C04FB984F9}',
            '{6AC1786C-016F-11D2-945F-00C04FB984F9}'
        ]
        gpofile = '%s/ADDOM.SAMBA.EXAMPLE.COM/POLICIES/%s/MACHINE/MICROSOFT/' \
                  'WINDOWS NT/SECEDIT/GPTTMPL.INF'
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        # Initialize the group policy extension
        ext = gp_sec_ext(logger, self.lp, machine_creds, store)

        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
        if ads.connect():
            gpos = ads.get_gpo_list(machine_creds.get_username())

        stage = '[Kerberos Policy]\nMaxTicketAge = %d\n'
        opts = [100, 200]
        for i in range(0, 2):
            gpttmpl = gpofile % (local_path, guids[i])
            ret = stage_file(gpttmpl, stage % opts[i])
            self.assertTrue(ret, 'Could not create the target %s' % gpttmpl)

        # Process all gpos
        ext.process_group_policy([], gpos)

        ret = store.get_int('kdc:user_ticket_lifetime')
        self.assertEqual(ret, opts[1], 'Higher priority policy was not set')

        # Remove policy
        gp_db = store.get_gplog(machine_creds.get_username())
        del_gpos = get_deleted_gpos_list(gp_db, [])
        ext.process_group_policy(del_gpos, [])

        ret = store.get_int('kdc:user_ticket_lifetime')
        self.assertEqual(ret, None, 'MaxTicketAge should not have applied')

        # Process just the first gpo
        ext.process_group_policy([], gpos[:-1])

        ret = store.get_int('kdc:user_ticket_lifetime')
        self.assertEqual(ret, opts[0], 'Lower priority policy was not set')

        # Remove policy
        ext.process_group_policy(del_gpos, [])

        for guid in guids:
            gpttmpl = gpofile % (local_path, guid)
            unstage_file(gpttmpl)
Ejemplo n.º 27
0
class MigrationFix(object):
    def __init__(self, username=None, no_dry_run=False, mysql_string=None):
        self.lp = LoadParm()
        self.lp.set('debug level', '0')
        self.lp.load_default()
        self.username = username
        self.no_dry_run = no_dry_run
        self.conn = self._open_mysql_conn(mysql_string)

    def _open_mysql_conn(self, mysql_conn):
        if mysql_conn is None:
            conn_str = self.lp.get('mapiproxy:openchangedb')
        else:
            conn_str = mysql_conn
        if not conn_str:
            raise Exception("No mysql connection string specified and no mapiproxy:openchangedb param option found")
        # mysql://openchange:password@localhost/openchange
        m = re.search('(?P<scheme>.+)://(?P<user>.+):(?P<pass>.+)@'
                      '(?P<host>.+)/(?P<db>.+)',
                      conn_str)
        if not m:
            raise Exception("Unable to parse mysql connection string: %s" % conn_str)
        group_dict = m.groupdict()
        if group_dict['scheme'] != 'mysql':
            raise Exception("mysql connection string should start with mysql:// (got %s)", group_dict['scheme'])
        conn = MySQLdb.connect(host=group_dict['host'], user=group_dict['user'],
                               passwd=group_dict['pass'], db=group_dict['db'])
        conn.autocommit(True)
        return conn

    def fix(self, username, folder_id, uri, mailbox_id, ou_id):
        error = False
        c = self.conn.cursor()
        c.execute("SELECT fmid FROM mapistore_indexing WHERE username=%s AND url=%s", (username,uri))
	result = c.fetchone()
	if result is None:
		print '[KO]: %s: could not find fmid for %s' % (username, uri)
		return True

        fmid = result[0]
        if str(fmid) != str(folder_id):
            error = True
            if self.no_dry_run is True:
                c = self.conn.cursor()
                c.execute("UPDATE folders SET folder_id=%s WHERE MAPIStoreURI=%s AND mailbox_id=%s AND ou_id=%s", (fmid, uri, mailbox_id, ou_id))
                print '[FIX]: %s: folder_id for %s has been fixed and is now set to %s' % (username, uri, folder_id)
            else:
                print '[KO]: %s: Mismatch for %s: found %s, expected %s' % (username, uri, folder_id, fmid)
        return error

    def run_all(self):
        c = self.conn.cursor()
        c.execute("SELECT id,ou_id,name FROM mailboxes")
        rows = c.fetchall()

        for row in rows:
            mailbox_id = row[0]
            ou_id = row[1]
            username = row[2]
            # Retrieve all MAPIStoreURI from folders table for username
            c = self.conn.cursor()
            c.execute("SELECT folder_id,MAPIStoreURI FROM folders WHERE mailbox_id=%s AND ou_id=%s AND MAPIStoreURI!=\"\"", (mailbox_id,ou_id))
            frows = c.fetchall()

            # Now check in mapistore_indexing if fmid are matching for given URI
	    gl_error =  False 
            for frow in frows:
                folder_id = frow[0]
                uri = frow[1]
                error = self.fix(username, folder_id, uri, mailbox_id, ou_id)
		if error is True:
			gl_error = True 
            if gl_error is False:
                print '[OK]: %s is OK' % (username)

    def run(self):
        # Retrieve username id, ou_id
        c = self.conn.cursor()
        c.execute("SELECT id,ou_id FROM mailboxes WHERE name=%s", self.username)
        (mailbox_id,ou_id) = c.fetchone()

        # Retrieve all MAPIStoreURI from folders table for username
        c = self.conn.cursor()
        c.execute("SELECT folder_id,MAPIStoreURI FROM folders WHERE mailbox_id=%s AND ou_id=%s AND MAPIStoreURI!=\"\"", (mailbox_id,ou_id))
        rows = c.fetchall()

        # Now check in mapistore_indexing if fmid are matching for given URI
        for row in rows:
            folder_id = row[0]
            uri = row[1]
            self.fix(self.username, folder_id, uri, mailbox_id, ou_id)
Ejemplo n.º 28
0
class MigrationFix(object):
    def __init__(self, username=None, no_dry_run=False, mysql_string=None):
        self.lp = LoadParm()
        self.lp.set('debug level', '0')
        self.lp.load_default()
        self.username = username
        self.no_dry_run = no_dry_run
        self.conn = self._open_mysql_conn(mysql_string)

    def _open_mysql_conn(self, mysql_conn):
        if mysql_conn is None:
            conn_str = self.lp.get('mapiproxy:openchangedb')
        else:
            conn_str = mysql_conn
        if not conn_str:
            raise Exception(
                "No mysql connection string specified and no mapiproxy:openchangedb param option found"
            )
        # mysql://openchange:password@localhost/openchange
        m = re.search(
            '(?P<scheme>.+)://(?P<user>.+):(?P<pass>.+)@'
            '(?P<host>.+)/(?P<db>.+)', conn_str)
        if not m:
            raise Exception("Unable to parse mysql connection string: %s" %
                            conn_str)
        group_dict = m.groupdict()
        if group_dict['scheme'] != 'mysql':
            raise Exception(
                "mysql connection string should start with mysql:// (got %s)",
                group_dict['scheme'])
        conn = MySQLdb.connect(host=group_dict['host'],
                               user=group_dict['user'],
                               passwd=group_dict['pass'],
                               db=group_dict['db'])
        conn.autocommit(True)
        return conn

    def fix(self, username, folder_id, uri, mailbox_id, ou_id):
        error = False
        c = self.conn.cursor()
        c.execute(
            "SELECT fmid FROM mapistore_indexing WHERE username=%s AND url=%s",
            (username, uri))
        result = c.fetchone()
        if result is None:
            print '[KO]: %s: could not find fmid for %s' % (username, uri)
            return True

        fmid = result[0]
        if str(fmid) != str(folder_id):
            error = True
            if self.no_dry_run is True:
                c = self.conn.cursor()
                c.execute(
                    "UPDATE folders SET folder_id=%s WHERE MAPIStoreURI=%s AND mailbox_id=%s AND ou_id=%s",
                    (fmid, uri, mailbox_id, ou_id))
                print '[FIX]: %s: folder_id for %s has been fixed and is now set to %s' % (
                    username, uri, folder_id)
            else:
                print '[KO]: %s: Mismatch for %s: found %s, expected %s' % (
                    username, uri, folder_id, fmid)
        return error

    def run_all(self):
        c = self.conn.cursor()
        c.execute("SELECT id,ou_id,name FROM mailboxes")
        rows = c.fetchall()

        for row in rows:
            mailbox_id = row[0]
            ou_id = row[1]
            username = row[2]
            # Retrieve all MAPIStoreURI from folders table for username
            c = self.conn.cursor()
            c.execute(
                "SELECT folder_id,MAPIStoreURI FROM folders WHERE mailbox_id=%s AND ou_id=%s AND MAPIStoreURI!=\"\"",
                (mailbox_id, ou_id))
            frows = c.fetchall()

            # Now check in mapistore_indexing if fmid are matching for given URI
            gl_error = False
            for frow in frows:
                folder_id = frow[0]
                uri = frow[1]
                error = self.fix(username, folder_id, uri, mailbox_id, ou_id)
                if error is True:
                    gl_error = True
            if gl_error is False:
                print '[OK]: %s is OK' % (username)

    def run(self):
        # Retrieve username id, ou_id
        c = self.conn.cursor()
        c.execute("SELECT id,ou_id FROM mailboxes WHERE name=%s",
                  self.username)
        (mailbox_id, ou_id) = c.fetchone()

        # Retrieve all MAPIStoreURI from folders table for username
        c = self.conn.cursor()
        c.execute(
            "SELECT folder_id,MAPIStoreURI FROM folders WHERE mailbox_id=%s AND ou_id=%s AND MAPIStoreURI!=\"\"",
            (mailbox_id, ou_id))
        rows = c.fetchall()

        # Now check in mapistore_indexing if fmid are matching for given URI
        for row in rows:
            folder_id = row[0]
            uri = row[1]
            self.fix(self.username, folder_id, uri, mailbox_id, ou_id)
Ejemplo n.º 29
0
class SambaOCHelper(object):
    def __init__(self):
        self.samba_lp = LoadParm()
        self.samba_lp.set('debug level', '0')
        self.samba_lp.load_default()
        self.next_fmid = None
        url = self.samba_lp.get('dcerpc_mapiproxy:samdb_url') or \
            self.samba_lp.private_path("sam.ldb")
        self.samdb = SamDB(url=url,
                           lp=self.samba_lp,
                           session_info=system_session())
        self.conn = self._open_mysql_connection()

    def _open_mysql_connection(self):
        connection_string = self.samba_lp.get('mapiproxy:openchangedb')
        if not connection_string:
            raise Exception("Not found mapiproxy:openchangedb on samba configuration")
        # mysql://openchange:password@localhost/openchange
        m = re.search(r'(?P<scheme>.+)://(?P<user>.+):(?P<pass>.+)@(?P<host>.+)/(?P<db>.+)',
                      connection_string)
        if not m:
            raise Exception("Unable to parse mapiproxy:openchangedb: %s" %
                            connection_string)
        group_dict = m.groupdict()
        if group_dict['scheme'] != 'mysql':
            raise Exception("mapiproxy:openchangedb should start with mysql:// (we got %s)",
                            group_dict['scheme'])

        conn = MySQLdb.connect(host=group_dict['host'], user=group_dict['user'],
                               passwd=group_dict['pass'], db=group_dict['db'])
        conn.autocommit(True)
        return conn

    def invalid_user(self, username):
        ret = self.samdb.search(base=self.samdb.domain_dn(),
                                scope=ldb.SCOPE_SUBTREE,
                                expression="(sAMAccountName=%s)" % ldb.binary_encode(username))
        return len(ret) != 1

    def find_email_of(self, username):
        ret = self.samdb.search(base=self.samdb.domain_dn(),
                                scope=ldb.SCOPE_SUBTREE, attrs=["mail"],
                                expression="(sAMAccountName=%s)" % ldb.binary_encode(username))
        return ret[0]["mail"][0]

    def active_openchange_users(self):
        c = self.conn.cursor()
        c.execute("SELECT name FROM mailboxes")
        return sorted([row[0] for row in c.fetchall()])

    def allocate_fmids(self, count, username):
        if self.next_fmid is None:
            c = self.conn.cursor()
            c.execute("SELECT next_fmid FROM mapistore_indexes WHERE username = '******'" % username)
            self.next_fmid = c.fetchone()[0]
        if self.next_fmid is not None:
            self.next_fmid = int(self.next_fmid) + count

        return (int(self.next_fmid) - count, self.next_fmid)

    def create_indexes(self, username):
        c = self.conn.cursor()
        c.execute("INSERT INTO mapistore_indexes (username,next_fmid) VALUES('%s','1024')" % (username))
        return

    def commit_start(self):
        self.conn.autocommit(False)

    def insert_indexing(self, username, fmid, url):
        c = self.conn.cursor()
        
        c.execute("INSERT INTO mapistore_indexing (username,fmid,url,soft_deleted) VALUES('%s','%s','%s', '0')" % (username, str(fmid), url))

    def update_indexes(self, count, username):
        c = self.conn.cursor()
        updated_number = int(count) + int(self.next_fmid)
        print "Updating next_fmid to %s" % str(updated_number)
        c.execute("UPDATE mapistore_indexes SET next_fmid='%s' WHERE username='******'" % (str(updated_number), username))

    def commit_end(self):
        c = self.conn.cursor()
        self.conn.commit()
        c.close()
        self.conn.autocommit(True)
Ejemplo n.º 30
0
Archivo: gpo.py Proyecto: rpasche/samba
class GPOTests(tests.TestCase):
    def setUp(self):
        super(GPOTests, self).setUp()
        self.server = os.environ["SERVER"]
        self.lp = LoadParm()
        self.lp.load_default()
        self.creds = self.insta_creds(template=self.get_credentials())

    def tearDown(self):
        super(GPOTests, self).tearDown()

    def test_gpo_list(self):
        global poldir, dspath
        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.creds.get_username())
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        names = ['Local Policy', guid]
        file_sys_paths = [None, '%s\\%s' % (poldir, guid)]
        ds_paths = [None, 'CN=%s,%s' % (guid, dspath)]
        for i in range(0, len(gpos)):
            self.assertEquals(gpos[i].name, names[i],
                              'The gpo name did not match expected name %s' % gpos[i].name)
            self.assertEquals(gpos[i].file_sys_path, file_sys_paths[i],
                              'file_sys_path did not match expected %s' % gpos[i].file_sys_path)
            self.assertEquals(gpos[i].ds_path, ds_paths[i],
                              'ds_path did not match expected %s' % gpos[i].ds_path)

    def test_gpo_ads_does_not_segfault(self):
        try:
            ads = gpo.ADS_STRUCT(self.server, 42, self.creds)
        except:
            pass

    def test_gpt_version(self):
        global gpt_data
        local_path = self.lp.cache_path('gpo_cache')
        policies = 'ADDOM.SAMBA.EXAMPLE.COM/POLICIES'
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        gpo_path = os.path.join(local_path, policies, guid)
        old_vers = gpo.gpo_get_sysvol_gpt_version(gpo_path)[1]

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % 42)
        self.assertEquals(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], 42,
                          'gpo_get_sysvol_gpt_version() did not return the expected version')

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % old_vers)
        self.assertEquals(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], old_vers,
                          'gpo_get_sysvol_gpt_version() did not return the expected version')

    def test_check_refresh_gpo_list(self):
        cache = self.lp.cache_path('gpo_cache')
        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.creds.get_username())
        check_refresh_gpo_list(self.server, self.lp, self.creds, gpos)

        self.assertTrue(os.path.exists(cache),
                        'GPO cache %s was not created' % cache)

        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        gpt_ini = os.path.join(cache, 'ADDOM.SAMBA.EXAMPLE.COM/POLICIES',
                               guid, 'GPT.INI')
        self.assertTrue(os.path.exists(gpt_ini),
                        'GPT.INI was not cached for %s' % guid)

    def test_check_refresh_gpo_list_malicious_paths(self):
        # the path cannot contain ..
        path = '/usr/local/samba/var/locks/sysvol/../../../../../../root/'
        self.assertRaises(OSError, check_safe_path, path)

        self.assertEqual(check_safe_path('/etc/passwd'), 'etc/passwd')
        self.assertEqual(check_safe_path('\\\\etc/\\passwd'), 'etc/passwd')

        # there should be no backslashes used to delineate paths
        before = 'sysvol/addom.samba.example.com\\Policies/' \
            '{31B2F340-016D-11D2-945F-00C04FB984F9}\\GPT.INI'
        after = 'addom.samba.example.com/Policies/' \
            '{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI'
        result = check_safe_path(before)
        self.assertEquals(result, after, 'check_safe_path() didn\'t'
                          ' correctly convert \\ to /')

    def test_gpt_ext_register(self):
        this_path = os.path.dirname(os.path.realpath(__file__))
        samba_path = os.path.realpath(os.path.join(this_path, '../../../'))
        ext_path = os.path.join(samba_path, 'python/samba/gp_sec_ext.py')
        ext_guid = '{827D319E-6EAC-11D2-A4EA-00C04F79F83A}'
        ret = register_gp_extension(ext_guid, 'gp_sec_ext', ext_path,
                                    smb_conf=self.lp.configfile,
                                    machine=True, user=False)
        self.assertTrue(ret, 'Failed to register a gp ext')
        gp_exts = list_gp_extensions(self.lp.configfile)
        self.assertTrue(ext_guid in gp_exts.keys(),
                        'Failed to list gp exts')
        self.assertEquals(gp_exts[ext_guid]['DllName'], ext_path,
                          'Failed to list gp exts')

        unregister_gp_extension(ext_guid)
        gp_exts = list_gp_extensions(self.lp.configfile)
        self.assertTrue(ext_guid not in gp_exts.keys(),
                        'Failed to unregister gp exts')

        self.assertTrue(check_guid(ext_guid), 'Failed to parse valid guid')
        self.assertFalse(check_guid('AAAAAABBBBBBBCCC'), 'Parsed invalid guid')

        lp, parser = parse_gpext_conf(self.lp.configfile)
        self.assertTrue(lp and parser, 'parse_gpext_conf() invalid return')
        parser.add_section('test_section')
        parser.set('test_section', 'test_var', ext_guid)
        atomic_write_conf(lp, parser)

        lp, parser = parse_gpext_conf(self.lp.configfile)
        self.assertTrue('test_section' in parser.sections(),
                        'test_section not found in gpext.conf')
        self.assertEquals(parser.get('test_section', 'test_var'), ext_guid,
                          'Failed to find test variable in gpext.conf')
        parser.remove_section('test_section')
        atomic_write_conf(lp, parser)
Ejemplo n.º 31
0
class SambaOptions(optparse.OptionGroup):
    """General Samba-related command line options."""
    def __init__(self, parser):
        from samba.param import LoadParm
        optparse.OptionGroup.__init__(self, parser, "Samba Common Options")
        self.add_option("-s",
                        "--configfile",
                        action="callback",
                        type=str,
                        metavar="FILE",
                        help="Configuration file",
                        callback=self._load_configfile)
        self.add_option("-d",
                        "--debuglevel",
                        action="callback",
                        type=int,
                        metavar="DEBUGLEVEL",
                        help="debug level",
                        callback=self._set_debuglevel)
        self.add_option("--option",
                        action="callback",
                        type=str,
                        metavar="OPTION",
                        help="set smb.conf option from command line",
                        callback=self._set_option)
        self.add_option("--realm",
                        action="callback",
                        type=str,
                        metavar="REALM",
                        help="set the realm name",
                        callback=self._set_realm)
        self._configfile = None
        self._lp = LoadParm()

    def get_loadparm_path(self):
        """Return the path to the smb.conf file specified on the command line.  """
        return self._configfile

    def _load_configfile(self, option, opt_str, arg, parser):
        self._configfile = arg

    def _set_debuglevel(self, option, opt_str, arg, parser):
        self._lp.set('debug level', str(arg))

    def _set_realm(self, option, opt_str, arg, parser):
        self._lp.set('realm', arg)

    def _set_option(self, option, opt_str, arg, parser):
        if arg.find('=') == -1:
            print("--option takes a 'a=b' argument")
            sys.exit(1)
        a = arg.split('=')
        self._lp.set(a[0], a[1])

    def get_loadparm(self):
        """Return a loadparm object with data specified on the command line.  """
        if self._configfile is not None:
            self._lp.load(self._configfile)
        elif os.getenv("SMB_CONF_PATH") is not None:
            self._lp.load(os.getenv("SMB_CONF_PATH"))
        else:
            self._lp.load_default()
        return self._lp

    def get_hostconfig(self):
        return Hostconfig(self.get_loadparm())
Ejemplo n.º 32
0
class GPOTests(tests.TestCase):
    def setUp(self):
        super(GPOTests, self).setUp()
        self.server = os.environ["SERVER"]
        self.dc_account = self.server.upper() + '$'
        self.lp = LoadParm()
        self.lp.load_default()
        self.creds = self.insta_creds(template=self.get_credentials())

    def tearDown(self):
        super(GPOTests, self).tearDown()

    def test_gpo_list(self):
        global poldir, dspath
        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.creds.get_username())
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        names = ['Local Policy', guid]
        file_sys_paths = [None, '%s\\%s' % (poldir, guid)]
        ds_paths = [None, 'CN=%s,%s' % (guid, dspath)]
        for i in range(0, len(gpos)):
            self.assertEqual(
                gpos[i].name, names[i],
                'The gpo name did not match expected name %s' % gpos[i].name)
            self.assertEqual(
                gpos[i].file_sys_path, file_sys_paths[i],
                'file_sys_path did not match expected %s' %
                gpos[i].file_sys_path)
            self.assertEqual(
                gpos[i].ds_path, ds_paths[i],
                'ds_path did not match expected %s' % gpos[i].ds_path)

    def test_gpo_ads_does_not_segfault(self):
        try:
            ads = gpo.ADS_STRUCT(self.server, 42, self.creds)
        except:
            pass

    def test_gpt_version(self):
        global gpt_data
        local_path = self.lp.cache_path('gpo_cache')
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        gpo_path = os.path.join(local_path, policies, guid)
        old_vers = gpo.gpo_get_sysvol_gpt_version(gpo_path)[1]

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % 42)
        self.assertEqual(
            gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], 42,
            'gpo_get_sysvol_gpt_version() did not return the expected version')

        with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
            gpt.write(gpt_data % old_vers)
        self.assertEqual(
            gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], old_vers,
            'gpo_get_sysvol_gpt_version() did not return the expected version')

    def test_check_refresh_gpo_list(self):
        cache = self.lp.cache_path('gpo_cache')
        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.creds.get_username())
        check_refresh_gpo_list(self.server, self.lp, self.creds, gpos)

        self.assertTrue(os.path.exists(cache),
                        'GPO cache %s was not created' % cache)

        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        gpt_ini = os.path.join(cache, policies, guid, 'GPT.INI')
        self.assertTrue(os.path.exists(gpt_ini),
                        'GPT.INI was not cached for %s' % guid)

    def test_check_refresh_gpo_list_malicious_paths(self):
        # the path cannot contain ..
        path = '/usr/local/samba/var/locks/sysvol/../../../../../../root/'
        self.assertRaises(OSError, check_safe_path, path)

        self.assertEqual(check_safe_path('/etc/passwd'), 'etc/passwd')
        self.assertEqual(check_safe_path('\\\\etc/\\passwd'), 'etc/passwd')

        # there should be no backslashes used to delineate paths
        before = 'sysvol/' + realm + '\\Policies/' \
            '{31B2F340-016D-11D2-945F-00C04FB984F9}\\GPT.INI'
        after = realm + '/Policies/' \
            '{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI'
        result = check_safe_path(before)
        self.assertEqual(
            result, after, 'check_safe_path() didn\'t'
            ' correctly convert \\ to /')

    def test_gpt_ext_register(self):
        this_path = os.path.dirname(os.path.realpath(__file__))
        samba_path = os.path.realpath(os.path.join(this_path, '../../../'))
        ext_path = os.path.join(samba_path, 'python/samba/gp_sec_ext.py')
        ext_guid = '{827D319E-6EAC-11D2-A4EA-00C04F79F83A}'
        ret = register_gp_extension(ext_guid,
                                    'gp_access_ext',
                                    ext_path,
                                    smb_conf=self.lp.configfile,
                                    machine=True,
                                    user=False)
        self.assertTrue(ret, 'Failed to register a gp ext')
        gp_exts = list_gp_extensions(self.lp.configfile)
        self.assertTrue(ext_guid in gp_exts.keys(), 'Failed to list gp exts')
        self.assertEqual(gp_exts[ext_guid]['DllName'], ext_path,
                         'Failed to list gp exts')

        unregister_gp_extension(ext_guid)
        gp_exts = list_gp_extensions(self.lp.configfile)
        self.assertTrue(ext_guid not in gp_exts.keys(),
                        'Failed to unregister gp exts')

        self.assertTrue(check_guid(ext_guid), 'Failed to parse valid guid')
        self.assertFalse(check_guid('AAAAAABBBBBBBCCC'), 'Parsed invalid guid')

        lp, parser = parse_gpext_conf(self.lp.configfile)
        self.assertTrue(lp and parser, 'parse_gpext_conf() invalid return')
        parser.add_section('test_section')
        parser.set('test_section', 'test_var', ext_guid)
        atomic_write_conf(lp, parser)

        lp, parser = parse_gpext_conf(self.lp.configfile)
        self.assertTrue('test_section' in parser.sections(),
                        'test_section not found in gpext.conf')
        self.assertEqual(parser.get('test_section', 'test_var'), ext_guid,
                         'Failed to find test variable in gpext.conf')
        parser.remove_section('test_section')
        atomic_write_conf(lp, parser)

    def test_gp_log_get_applied(self):
        local_path = self.lp.get('path', 'sysvol')
        guids = [
            '{31B2F340-016D-11D2-945F-00C04FB984F9}',
            '{6AC1786C-016F-11D2-945F-00C04FB984F9}'
        ]
        gpofile = '%s/' + realm + '/Policies/%s/MACHINE/Microsoft/' \
                  'Windows NT/SecEdit/GptTmpl.inf'
        stage = '[System Access]\nMinimumPasswordAge = 998\n'
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
        for guid in guids:
            gpttmpl = gpofile % (local_path, guid)
            ret = stage_file(gpttmpl, stage)
            self.assertTrue(ret, 'Could not create the target %s' % gpttmpl)

        ret = gpupdate_force(self.lp)
        self.assertEqual(ret, 0, 'gpupdate force failed')

        gp_db = store.get_gplog(self.dc_account)

        applied_guids = gp_db.get_applied_guids()
        self.assertEqual(len(applied_guids), 2, 'The guids were not found')
        self.assertIn(guids[0], applied_guids,
                      '%s not in applied guids' % guids[0])
        self.assertIn(guids[1], applied_guids,
                      '%s not in applied guids' % guids[1])

        applied_settings = gp_db.get_applied_settings(applied_guids)
        for policy in applied_settings:
            self.assertIn('System Access', policy[1],
                          'System Access policies not set')
            self.assertIn('minPwdAge', policy[1]['System Access'],
                          'minPwdAge policy not set')
            if policy[0] == guids[0]:
                self.assertEqual(int(policy[1]['System Access']['minPwdAge']),
                                 days2rel_nttime(1),
                                 'minPwdAge policy not set')
            elif policy[0] == guids[1]:
                self.assertEqual(int(policy[1]['System Access']['minPwdAge']),
                                 days2rel_nttime(998),
                                 'minPwdAge policy not set')

        ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
        if ads.connect():
            gpos = ads.get_gpo_list(self.dc_account)
        del_gpos = get_deleted_gpos_list(gp_db, gpos[:-1])
        self.assertEqual(len(del_gpos), 1, 'Returned delete gpos is incorrect')
        self.assertEqual(guids[-1], del_gpos[0][0],
                         'GUID for delete gpo is incorrect')
        self.assertIn('System Access', del_gpos[0][1],
                      'System Access policies not set for removal')
        self.assertIn('minPwdAge', del_gpos[0][1]['System Access'],
                      'minPwdAge policy not set for removal')

        for guid in guids:
            gpttmpl = gpofile % (local_path, guid)
            unstage_file(gpttmpl)

        ret = gpupdate_unapply(self.lp)
        self.assertEqual(ret, 0, 'gpupdate unapply failed')

    def test_process_group_policy(self):
        local_path = self.lp.cache_path('gpo_cache')
        guids = [
            '{31B2F340-016D-11D2-945F-00C04FB984F9}',
            '{6AC1786C-016F-11D2-945F-00C04FB984F9}'
        ]
        gpofile = '%s/' + policies + '/%s/MACHINE/MICROSOFT/' \
                  'WINDOWS NT/SECEDIT/GPTTMPL.INF'
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        # Initialize the group policy extension
        ext = gp_krb_ext(logger, self.lp, machine_creds, store)

        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
        if ads.connect():
            gpos = ads.get_gpo_list(machine_creds.get_username())

        stage = '[Kerberos Policy]\nMaxTicketAge = %d\n'
        opts = [100, 200]
        for i in range(0, 2):
            gpttmpl = gpofile % (local_path, guids[i])
            ret = stage_file(gpttmpl, stage % opts[i])
            self.assertTrue(ret, 'Could not create the target %s' % gpttmpl)

        # Process all gpos
        ext.process_group_policy([], gpos)

        ret = store.get_int('kdc:user_ticket_lifetime')
        self.assertEqual(ret, opts[1], 'Higher priority policy was not set')

        # Remove policy
        gp_db = store.get_gplog(machine_creds.get_username())
        del_gpos = get_deleted_gpos_list(gp_db, [])
        ext.process_group_policy(del_gpos, [])

        ret = store.get_int('kdc:user_ticket_lifetime')
        self.assertEqual(ret, None, 'MaxTicketAge should not have applied')

        # Process just the first gpo
        ext.process_group_policy([], gpos[:-1])

        ret = store.get_int('kdc:user_ticket_lifetime')
        self.assertEqual(ret, opts[0], 'Lower priority policy was not set')

        # Remove policy
        ext.process_group_policy(del_gpos, [])

        for guid in guids:
            gpttmpl = gpofile % (local_path, guid)
            unstage_file(gpttmpl)

    def test_gp_scripts(self):
        local_path = self.lp.cache_path('gpo_cache')
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        reg_pol = os.path.join(local_path, policies, guid,
                               'MACHINE/REGISTRY.POL')
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        # Initialize the group policy extension
        ext = gp_scripts_ext(logger, self.lp, machine_creds, store)

        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
        if ads.connect():
            gpos = ads.get_gpo_list(machine_creds.get_username())

        reg_key = b'Software\\Policies\\Samba\\Unix Settings'
        sections = {
            b'%s\\Daily Scripts' % reg_key: '.cron.daily',
            b'%s\\Monthly Scripts' % reg_key: '.cron.monthly',
            b'%s\\Weekly Scripts' % reg_key: '.cron.weekly',
            b'%s\\Hourly Scripts' % reg_key: '.cron.hourly'
        }
        for keyname in sections.keys():
            # Stage the Registry.pol file with test data
            stage = preg.file()
            e = preg.entry()
            e.keyname = keyname
            e.valuename = b'Software\\Policies\\Samba\\Unix Settings'
            e.type = 1
            e.data = b'echo hello world'
            stage.num_entries = 1
            stage.entries = [e]
            ret = stage_file(reg_pol, ndr_pack(stage))
            self.assertTrue(ret, 'Could not create the target %s' % reg_pol)

            # Process all gpos, with temp output directory
            with TemporaryDirectory(sections[keyname]) as dname:
                ext.process_group_policy([], gpos, dname)
                scripts = os.listdir(dname)
                self.assertEquals(
                    len(scripts), 1,
                    'The %s script was not created' % keyname.decode())
                out, _ = Popen([os.path.join(dname, scripts[0])],
                               stdout=PIPE).communicate()
                self.assertIn(b'hello world', out,
                              '%s script execution failed' % keyname.decode())

                # Remove policy
                gp_db = store.get_gplog(machine_creds.get_username())
                del_gpos = get_deleted_gpos_list(gp_db, [])
                ext.process_group_policy(del_gpos, [])
                self.assertEquals(len(os.listdir(dname)), 0,
                                  'Unapply failed to cleanup scripts')

            # Unstage the Registry.pol file
            unstage_file(reg_pol)

    def test_gp_sudoers(self):
        local_path = self.lp.cache_path('gpo_cache')
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        reg_pol = os.path.join(local_path, policies, guid,
                               'MACHINE/REGISTRY.POL')
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        # Initialize the group policy extension
        ext = gp_sudoers_ext(logger, self.lp, machine_creds, store)

        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
        if ads.connect():
            gpos = ads.get_gpo_list(machine_creds.get_username())

        # Stage the Registry.pol file with test data
        stage = preg.file()
        e = preg.entry()
        e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights'
        e.valuename = b'Software\\Policies\\Samba\\Unix Settings'
        e.type = 1
        e.data = b'fakeu  ALL=(ALL) NOPASSWD: ALL'
        stage.num_entries = 1
        stage.entries = [e]
        ret = stage_file(reg_pol, ndr_pack(stage))
        self.assertTrue(ret, 'Could not create the target %s' % reg_pol)

        # Process all gpos, with temp output directory
        with TemporaryDirectory() as dname:
            ext.process_group_policy([], gpos, dname)
            sudoers = os.listdir(dname)
            self.assertEquals(len(sudoers), 1,
                              'The sudoer file was not created')
            self.assertIn(e.data,
                          open(os.path.join(dname, sudoers[0]), 'r').read(),
                          'The sudoers entry was not applied')

            # Remove policy
            gp_db = store.get_gplog(machine_creds.get_username())
            del_gpos = get_deleted_gpos_list(gp_db, [])
            ext.process_group_policy(del_gpos, [])
            self.assertEquals(len(os.listdir(dname)), 0,
                              'Unapply failed to cleanup scripts')

        # Unstage the Registry.pol file
        unstage_file(reg_pol)

    def test_gp_inf_ext_utf(self):
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        ext = gp_inf_ext(logger, self.lp, machine_creds, store)
        test_data = '[Kerberos Policy]\nMaxTicketAge = 99\n'

        with NamedTemporaryFile() as f:
            with codecs.open(f.name, 'w', 'utf-16') as w:
                w.write(test_data)
            try:
                inf_conf = ext.read(f.name)
            except UnicodeDecodeError:
                self.fail('Failed to parse utf-16')
            self.assertIn('Kerberos Policy', inf_conf.keys(),
                          'Kerberos Policy was not read from the file')
            self.assertEquals(inf_conf.get('Kerberos Policy', 'MaxTicketAge'),
                              '99', 'MaxTicketAge was not read from the file')

        with NamedTemporaryFile() as f:
            with codecs.open(f.name, 'w', 'utf-8') as w:
                w.write(test_data)
            inf_conf = ext.read(f.name)
            self.assertIn('Kerberos Policy', inf_conf.keys(),
                          'Kerberos Policy was not read from the file')
            self.assertEquals(inf_conf.get('Kerberos Policy', 'MaxTicketAge'),
                              '99', 'MaxTicketAge was not read from the file')

    def test_rsop(self):
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        local_path = self.lp.cache_path('gpo_cache')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
        if ads.connect():
            gpos = ads.get_gpo_list(machine_creds.get_username())

        gp_extensions = []
        gp_extensions.append(gp_krb_ext)
        gp_extensions.append(gp_scripts_ext)
        gp_extensions.append(gp_sudoers_ext)
        gp_extensions.append(gp_smb_conf_ext)
        gp_extensions.append(gp_msgs_ext)

        # Create registry stage data
        reg_pol = os.path.join(local_path, policies, '%s/MACHINE/REGISTRY.POL')
        reg_stage = preg.file()
        e = preg.entry()
        e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Daily Scripts'
        e.valuename = b'Software\\Policies\\Samba\\Unix Settings'
        e.type = 1
        e.data = b'echo hello world'
        e2 = preg.entry()
        e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights'
        e2.valuename = b'Software\\Policies\\Samba\\Unix Settings'
        e2.type = 1
        e2.data = b'fakeu  ALL=(ALL) NOPASSWD: ALL'
        e3 = preg.entry()
        e3.keyname = 'Software\\Policies\\Samba\\smb_conf\\apply group policies'
        e3.type = 4
        e3.data = 1
        e3.valuename = 'apply group policies'
        e4 = preg.entry()
        e4.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages'
        e4.valuename = b'issue'
        e4.type = 1
        e4.data = b'Welcome to \\s \\r \\l'
        reg_stage.num_entries = 4
        reg_stage.entries = [e, e2, e3, e4]

        # Create krb stage date
        gpofile = os.path.join(local_path, policies, '%s/MACHINE/MICROSOFT/' \
                  'WINDOWS NT/SECEDIT/GPTTMPL.INF')
        krb_stage = '[Kerberos Policy]\nMaxTicketAge = 99\n'

        for g in [g for g in gpos if g.file_sys_path]:
            ret = stage_file(gpofile % g.name, krb_stage)
            self.assertTrue(
                ret, 'Could not create the target %s' % (gpofile % g.name))
            ret = stage_file(reg_pol % g.name, ndr_pack(reg_stage))
            self.assertTrue(
                ret, 'Could not create the target %s' % (reg_pol % g.name))
            for ext in gp_extensions:
                ext = ext(logger, self.lp, machine_creds, store)
                ret = ext.rsop(g)
                self.assertEquals(
                    len(ret.keys()), 1,
                    'A single policy should have been displayed')

                # Check the Security Extension
                if type(ext) == gp_krb_ext:
                    self.assertIn('Kerberos Policy', ret.keys(),
                                  'Kerberos Policy not found')
                    self.assertIn('MaxTicketAge', ret['Kerberos Policy'],
                                  'MaxTicketAge setting not found')
                    self.assertEquals(ret['Kerberos Policy']['MaxTicketAge'],
                                      '99', 'MaxTicketAge was not set to 99')
                # Check the Scripts Extension
                elif type(ext) == gp_scripts_ext:
                    self.assertIn('Daily Scripts', ret.keys(),
                                  'Daily Scripts not found')
                    self.assertIn('echo hello world', ret['Daily Scripts'],
                                  'Daily script was not created')
                # Check the Sudoers Extension
                elif type(ext) == gp_sudoers_ext:
                    self.assertIn('Sudo Rights', ret.keys(),
                                  'Sudoers not found')
                    self.assertIn('fakeu  ALL=(ALL) NOPASSWD: ALL',
                                  ret['Sudo Rights'],
                                  'Sudoers policy not created')
                # Check the smb.conf Extension
                elif type(ext) == gp_smb_conf_ext:
                    self.assertIn('smb.conf', ret.keys(),
                                  'apply group policies was not applied')
                    self.assertIn(e3.valuename, ret['smb.conf'],
                                  'apply group policies was not applied')
                    self.assertEquals(ret['smb.conf'][e3.valuename], e3.data,
                                      'apply group policies was not set')
                # Check the Messages Extension
                elif type(ext) == gp_msgs_ext:
                    self.assertIn('/etc/issue', ret,
                                  'Login Prompt Message not applied')
                    self.assertEquals(ret['/etc/issue'], e4.data,
                                      'Login Prompt Message not set')
            unstage_file(gpofile % g.name)
            unstage_file(reg_pol % g.name)

        # Check that a call to gpupdate --rsop also succeeds
        ret = rsop(self.lp)
        self.assertEquals(ret, 0, 'gpupdate --rsop failed!')

    def test_gp_unapply(self):
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        local_path = self.lp.cache_path('gpo_cache')
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
        if ads.connect():
            gpos = ads.get_gpo_list(machine_creds.get_username())

        gp_extensions = []
        gp_extensions.append(gp_krb_ext)
        gp_extensions.append(gp_scripts_ext)
        gp_extensions.append(gp_sudoers_ext)

        # Create registry stage data
        reg_pol = os.path.join(local_path, policies, '%s/MACHINE/REGISTRY.POL')
        reg_stage = preg.file()
        e = preg.entry()
        e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Daily Scripts'
        e.valuename = b'Software\\Policies\\Samba\\Unix Settings'
        e.type = 1
        e.data = b'echo hello world'
        e2 = preg.entry()
        e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights'
        e2.valuename = b'Software\\Policies\\Samba\\Unix Settings'
        e2.type = 1
        e2.data = b'fakeu  ALL=(ALL) NOPASSWD: ALL'
        reg_stage.num_entries = 2
        reg_stage.entries = [e, e2]

        # Create krb stage date
        gpofile = os.path.join(local_path, policies, '%s/MACHINE/MICROSOFT/' \
                  'WINDOWS NT/SECEDIT/GPTTMPL.INF')
        krb_stage = '[Kerberos Policy]\nMaxTicketAge = 99\n'

        ret = stage_file(gpofile % guid, krb_stage)
        self.assertTrue(ret,
                        'Could not create the target %s' % (gpofile % guid))
        ret = stage_file(reg_pol % guid, ndr_pack(reg_stage))
        self.assertTrue(ret,
                        'Could not create the target %s' % (reg_pol % guid))

        # Process all gpos, with temp output directory
        remove = []
        with TemporaryDirectory() as dname:
            for ext in gp_extensions:
                ext = ext(logger, self.lp, machine_creds, store)
                if type(ext) == gp_krb_ext:
                    ext.process_group_policy([], gpos)
                    ret = store.get_int('kdc:user_ticket_lifetime')
                    self.assertEqual(ret, 99, 'Kerberos policy was not set')
                elif type(ext) in [gp_scripts_ext, gp_sudoers_ext]:
                    ext.process_group_policy([], gpos, dname)
                    gp_db = store.get_gplog(machine_creds.get_username())
                    applied_settings = gp_db.get_applied_settings([guid])
                    for _, fname in applied_settings[-1][-1][str(ext)].items():
                        self.assertIn(dname, fname,
                                      'Test file not created in tmp dir')
                        self.assertTrue(os.path.exists(fname),
                                        'Test file not created')
                        remove.append(fname)

            # Unapply policy, and ensure policies are removed
            gpupdate_unapply(self.lp)

            for fname in remove:
                self.assertFalse(os.path.exists(fname),
                                 'Unapply did not remove test file')
            ret = store.get_int('kdc:user_ticket_lifetime')
            self.assertNotEqual(ret, 99, 'Kerberos policy was not unapplied')

        unstage_file(gpofile % guid)
        unstage_file(reg_pol % guid)

    def test_smb_conf_ext(self):
        local_path = self.lp.cache_path('gpo_cache')
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        reg_pol = os.path.join(local_path, policies, guid,
                               'MACHINE/REGISTRY.POL')
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
        if ads.connect():
            gpos = ads.get_gpo_list(machine_creds.get_username())

        entries = []
        e = preg.entry()
        e.keyname = 'Software\\Policies\\Samba\\smb_conf\\template homedir'
        e.type = 1
        e.data = '/home/samba/%D/%U'
        e.valuename = 'template homedir'
        entries.append(e)
        e = preg.entry()
        e.keyname = 'Software\\Policies\\Samba\\smb_conf\\apply group policies'
        e.type = 4
        e.data = 1
        e.valuename = 'apply group policies'
        entries.append(e)
        e = preg.entry()
        e.keyname = 'Software\\Policies\\Samba\\smb_conf\\ldap timeout'
        e.type = 4
        e.data = 9999
        e.valuename = 'ldap timeout'
        entries.append(e)
        stage = preg.file()
        stage.num_entries = len(entries)
        stage.entries = entries

        ret = stage_file(reg_pol, ndr_pack(stage))
        self.assertTrue(ret, 'Failed to create the Registry.pol file')

        with NamedTemporaryFile(suffix='_smb.conf') as f:
            copyfile(self.lp.configfile, f.name)
            lp = LoadParm(f.name)

            # Initialize the group policy extension
            ext = gp_smb_conf_ext(logger, lp, machine_creds, store)
            ext.process_group_policy([], gpos)
            lp = LoadParm(f.name)

            template_homedir = lp.get('template homedir')
            self.assertEquals(template_homedir, '/home/samba/%D/%U',
                              'template homedir was not applied')
            apply_group_policies = lp.get('apply group policies')
            self.assertTrue(apply_group_policies,
                            'apply group policies was not applied')
            ldap_timeout = lp.get('ldap timeout')
            self.assertEquals(ldap_timeout, 9999,
                              'ldap timeout was not applied')

            # Remove policy
            gp_db = store.get_gplog(machine_creds.get_username())
            del_gpos = get_deleted_gpos_list(gp_db, [])
            ext.process_group_policy(del_gpos, [])

            lp = LoadParm(f.name)

            template_homedir = lp.get('template homedir')
            self.assertEquals(template_homedir,
                              self.lp.get('template homedir'),
                              'template homedir was not unapplied')
            apply_group_policies = lp.get('apply group policies')
            self.assertEquals(apply_group_policies,
                              self.lp.get('apply group policies'),
                              'apply group policies was not unapplied')
            ldap_timeout = lp.get('ldap timeout')
            self.assertEquals(ldap_timeout, self.lp.get('ldap timeout'),
                              'ldap timeout was not unapplied')

        # Unstage the Registry.pol file
        unstage_file(reg_pol)

    def test_gp_motd(self):
        local_path = self.lp.cache_path('gpo_cache')
        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
        reg_pol = os.path.join(local_path, policies, guid,
                               'MACHINE/REGISTRY.POL')
        logger = logging.getLogger('gpo_tests')
        cache_dir = self.lp.get('cache directory')
        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))

        machine_creds = Credentials()
        machine_creds.guess(self.lp)
        machine_creds.set_machine_account()

        # Initialize the group policy extension
        ext = gp_msgs_ext(logger, self.lp, machine_creds, store)

        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
        if ads.connect():
            gpos = ads.get_gpo_list(machine_creds.get_username())

        # Stage the Registry.pol file with test data
        stage = preg.file()
        e1 = preg.entry()
        e1.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages'
        e1.valuename = b'motd'
        e1.type = 1
        e1.data = b'Have a lot of fun!'
        stage.num_entries = 2
        e2 = preg.entry()
        e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages'
        e2.valuename = b'issue'
        e2.type = 1
        e2.data = b'Welcome to \\s \\r \\l'
        stage.entries = [e1, e2]
        ret = stage_file(reg_pol, ndr_pack(stage))
        self.assertTrue(ret, 'Could not create the target %s' % reg_pol)

        # Process all gpos, with temp output directory
        with TemporaryDirectory() as dname:
            ext.process_group_policy([], gpos, dname)
            motd_file = os.path.join(dname, 'motd')
            self.assertTrue(os.path.exists(motd_file),
                            'Message of the day file not created')
            data = open(motd_file, 'r').read()
            self.assertEquals(data, e1.data, 'Message of the day not applied')
            issue_file = os.path.join(dname, 'issue')
            self.assertTrue(os.path.exists(issue_file),
                            'Login Prompt Message file not created')
            data = open(issue_file, 'r').read()
            self.assertEquals(data, e2.data,
                              'Login Prompt Message not applied')

            # Unapply policy, and ensure the test files are removed
            gp_db = store.get_gplog(machine_creds.get_username())
            del_gpos = get_deleted_gpos_list(gp_db, [])
            ext.process_group_policy(del_gpos, [], dname)
            data = open(motd_file, 'r').read()
            self.assertFalse(data, 'Message of the day file not removed')
            data = open(issue_file, 'r').read()
            self.assertFalse(data, 'Login Prompt Message file not removed')

        # Unstage the Registry.pol file
        unstage_file(reg_pol)
Ejemplo n.º 33
0
class AdminToolsTestCase(unittest.TestCase):
    def assertSeen(self, what, msg=None, timeout=10):
        try:
            self.at.await_text(what, timeout=timeout)
        except hecate.hecate.Timeout:
            pass
        self.assertRegex(self.at.screenshot(), what, msg)

    def assertNotSeen(self, what, msg=None, timeout=10):
        sleep(.5)
        slept = 0
        while slept < timeout:
            slept += .1
            if not re.search(what, self.at.screenshot()):
                break
            sleep(.1)
        self.assertNotRegex(self.at.screenshot(), what, msg)

    def press(self, msg):
        self.at.press(msg)
        sleep(.1)

    def __validate_kinit(self):
        out, _ = Popen(['klist'], stdout=PIPE, stderr=PIPE).communicate()
        m = re.findall(six.b('Ticket cache:\s*(.*)'), out)
        if len(m) != 1:
            return False
        self.creds.set_named_ccache(m[0].decode())
        m = re.findall(six.b('Default principal:\s*(\w+)@([\w\.]+)'), out)
        if len(m) == 0:
            return False
        user, realm = m[0]
        self.creds.set_username(user.decode())
        self.creds.set_domain(realm.decode())
        with Popen(['klist', '-s'], stdout=PIPE, stderr=PIPE) as p:
            if p.wait() != 0:
                return False
        self.creds.set_kerberos_state(MUST_USE_KERBEROS)
        return True

    def get_password(self):
        if not self.creds.get_password():
            self.creds.set_password(
                getpass('Password for %s: ' % self.creds.get_username()))
        return self.creds.get_password()

    def kinit(self):
        while not self.__validate_kinit():
            print(
                'Domain administrator credentials are required to run the test.'
            )
            upn = '%s@%s' % (self.creds.get_username(), self.creds.get_domain(
            )) if self.creds.get_username() and self.creds.get_domain(
            ) else None
            username = input('Domain user principal name%s: ' %
                             (' (%s)' % upn if upn else ''))
            if username:
                self.creds.set_username(username)
            else:
                self.creds.set_username(upn)
            self.creds.set_password(
                getpass('Password for %s: ' % self.creds.get_username()))
            kinit_for_gssapi(self.creds, None)

    def setUp(self):
        self.lp = LoadParm()
        try:
            self.lp.load_default()
        except RuntimeError:
            pass
        self.creds = Credentials()
        self.config = ConfigParser()
        self.config.read('.tcreds')
        if self.config.has_section('creds'):
            self.creds.set_username('%s@%s' % (self.config.get(
                'creds', 'username'), self.config.get('creds', 'domain')))
            self.creds.set_domain(self.config.get('creds', 'domain'))
            self.creds.set_password(self.config.get('creds', 'password'))
            kinit_for_gssapi(self.creds, None)
        self.kinit()
        self.lp.set('realm', self.creds.get_domain())
        self.at = hecate.Runner("admin-tools", width=120, height=50)

    def tearDown(self):
        self.at.shutdown()
        if self.creds.get_password():
            if not self.config.has_section('creds'):
                self.config.add_section('creds')
            self.config.set('creds', 'username', self.creds.get_username())
            self.config.set('creds', 'domain', self.creds.get_domain())
            self.config.set('creds', 'password', self.creds.get_password())
            with open('.tcreds', 'w') as w:
                self.config.write(w)