Ejemplo n.º 1
0
def add_activedirectory_conf(client, smb4_conf):
    try:
        ad = Struct(
            client.call('datastore.query', 'directoryservice.ActiveDirectory',
                        None, {'get': True}))
        ad.ds_type = 1  # FIXME: DS_TYPE_ACTIVEDIRECTORY = 1
    except:
        return

    try:
        os.makedirs(cachedir)
        os.chmod(cachedir, 0o755)
    except:
        pass

    ad_workgroup = None
    try:
        fad = Struct(client.call('notifier.directoryservice', 'AD'))
        ad_workgroup = fad.netbiosname.upper()
    except:
        return

    confset2(smb4_conf, "workgroup = %s", ad_workgroup)
    confset2(smb4_conf, "realm = %s", ad.ad_domainname.upper())
    confset1(smb4_conf, "security = ADS")
    confset1(smb4_conf, "client use spnego = yes")

    confset1(smb4_conf, "local master = no")
    confset1(smb4_conf, "domain master = no")
    confset1(smb4_conf, "preferred master = no")

    confset2(smb4_conf, "ads dns update = %s",
             "yes" if ad.ad_allow_dns_updates else "no")

    confset1(smb4_conf, "winbind cache time = 7200")
    confset1(smb4_conf, "winbind offline logon = yes")
    confset1(smb4_conf, "winbind enum users = yes")
    confset1(smb4_conf, "winbind enum groups = yes")
    confset1(smb4_conf, "winbind nested groups = yes")
    confset2(smb4_conf, "winbind use default domain = %s",
             "yes" if ad.ad_use_default_domain else "no")
    confset1(smb4_conf, "winbind refresh tickets = yes")

    if ad.ad_nss_info:
        confset2(smb4_conf, "winbind nss info = %s", ad.ad_nss_info)

    idmap = Struct(
        client.call('notifier.ds_get_idmap_object', ad.ds_type, ad.id,
                    ad.ad_idmap_backend))
    configure_idmap_backend(client, smb4_conf, idmap, ad_workgroup)

    confset2(smb4_conf, "allow trusted domains = %s",
             "yes" if ad.ad_allow_trusted_doms else "no")

    confset2(smb4_conf, "client ldap sasl wrapping = %s",
             ad.ad_ldap_sasl_wrapping)

    confset1(smb4_conf, "template shell = /bin/sh")
    cifs_homedir = "%s/%%D/%%U" % get_cifs_homedir(client)
    confset2(smb4_conf, "template homedir = %s", cifs_homedir)
Ejemplo n.º 2
0
def get_samba_config_data(client):
    samba_config = []
    cifs_config = Struct(
        client.call('datastore.query', 'services.cifs', None, {'get': True}))
    ad_config = Struct(
        client.call('datastore.query', 'directoryservice.activedirectory',
                    None, {'get': True}))
    default_idmap_config = Struct(
        client.call('datastore.query', 'directoryservice.idmap_tdb', None,
                    {'get': True}))

    idmap_backend_call = "directoryservice.idmap_%s" % ad_config.ad_idmap_backend

    try:
        idmap_config = Struct(
            client.call('datastore.query', idmap_backend_call, None,
                        {'get': True}))
    except:
        print("failed to get idmap data via middleware calls")
        return False

    for item in [cifs_config, ad_config, idmap_config, default_idmap_config]:
        samba_config.append(item)

    return samba_config
Ejemplo n.º 3
0
def main():
    client = Client()
    cifs_config = Struct(
        client.call('datastore.query', 'services.cifs', None, {'get': True}))
    krb_config = Struct(
        client.call('datastore.query', 'services.cifs', None, {'get': True}))

    if not validate_hosts(cifs_config):
        print("restarting ix-hostname service")
        service_launcher("ix-hostname", "quietstart")

# validate_klist("krb_config.krb_realm")

    service_launcher("ix-kerberos", "quietstart")

    service_launcher("ix-nsswitch", "quietstart")

    if not service_launcher("ix-kinit", "status"):
        if not service_launcher("ix-kinit", "quietstart"):
            print("ix-kinit failed")

    service_launcher("ix-pre-samba", "quietstart")

    service_launcher("ix-activedirectory", "quietstart")

    service_launcher("samba_server", "restart")

    service_launcher("ix-pam", "quietstart")
    service_launcher("ix-cache", "quietstart")
Ejemplo n.º 4
0
def add_activedirectory_conf(client, smb4_conf):
    try:
        ad = Struct(client.call('datastore.query', 'directoryservice.ActiveDirectory', None, {'get': True}))
        ad.ds_type = 1  # FIXME: DS_TYPE_ACTIVEDIRECTORY = 1
    except:
        return

    cachedir = "/var/tmp/.cache/.samba"

    try:
        os.makedirs(cachedir)
        os.chmod(cachedir, 0755)
    except:
        pass

    ad_workgroup = None
    try:
        fad = Struct(client.call('notifier.directoryservice', 'AD'))
        ad_workgroup = fad.netbiosname.upper()
    except:
        return

    confset2(smb4_conf, "workgroup = %s", ad_workgroup)
    confset2(smb4_conf, "realm = %s", ad.ad_domainname.upper())
    confset1(smb4_conf, "security = ADS")
    confset1(smb4_conf, "client use spnego = yes")
    confset2(smb4_conf, "cache directory = %s", cachedir)

    confset1(smb4_conf, "local master = no")
    confset1(smb4_conf, "domain master = no")
    confset1(smb4_conf, "preferred master = no")

    confset2(smb4_conf, "ads dns update = %s",
             "yes" if ad.ad_allow_dns_updates else "no")

    confset1(smb4_conf, "winbind cache time = 7200")
    confset1(smb4_conf, "winbind offline logon = yes")
    confset1(smb4_conf, "winbind enum users = yes")
    confset1(smb4_conf, "winbind enum groups = yes")
    confset1(smb4_conf, "winbind nested groups = yes")
    confset2(smb4_conf, "winbind use default domain = %s",
             "yes" if ad.ad_use_default_domain else "no")
    confset1(smb4_conf, "winbind refresh tickets = yes")

    if ad.ad_nss_info:
        confset2(smb4_conf, "winbind nss info = %s", ad.ad_nss_info)

    idmap = Struct(client.call('notifier.ds_get_idmap_object', ad.ds_type, ad.id, ad.ad_idmap_backend))
    configure_idmap_backend(client, smb4_conf, idmap, ad_workgroup)

    confset2(smb4_conf, "allow trusted domains = %s",
             "yes" if ad.ad_allow_trusted_doms else "no")

    confset2(smb4_conf, "client ldap sasl wrapping = %s",
             ad.ad_ldap_sasl_wrapping)

    confset1(smb4_conf, "template shell = /bin/sh")
    confset2(smb4_conf, "template homedir = %s",
             "/home/%D/%U" if not ad.ad_use_default_domain else "/home/%U")
Ejemplo n.º 5
0
def add_nt4_conf(client, smb4_conf):
    # TODO: These are unused, will they be at some point?
    # rid_range_start = 20000
    # rid_range_end = 20000000

    try:
        nt4 = Struct(
            client.call('datastore.query', 'directoryservice.nt4', None,
                        {'get': True}))
        nt4.ds_type = 4  # FIXME: DS_TYPE_NT4 = 4
    except:
        return

    dc_ip = None
    try:
        answers = resolver.query(nt4.nt4_dcname, 'A')
        dc_ip = answers[0]

    except Exception as e:
        log.debug("resolver query for {0}'s A record failed with {1}".format(
            nt4.nt4_dcname, e))
        log_traceback(log=log)
        dc_ip = nt4.nt4_dcname

    nt4_workgroup = nt4.nt4_workgroup.upper()

    with open("/usr/local/etc/lmhosts", "w") as f:
        f.write("%s\t%s\n" % (dc_ip, nt4.nt4_dcname.upper()))

    confset2(smb4_conf, "workgroup = %s", nt4_workgroup)

    confset1(smb4_conf, "security = domain")
    confset1(smb4_conf, "password server = *")

    idmap = Struct(
        client.call('notifier.ds_get_idmap_object', nt4.ds_type, nt4.id,
                    nt4.nt4_idmap_backend))
    configure_idmap_backend(client, smb4_conf, idmap, nt4_workgroup)

    confset1(smb4_conf, "winbind cache time = 7200")
    confset1(smb4_conf, "winbind offline logon = yes")
    confset1(smb4_conf, "winbind enum users = yes")
    confset1(smb4_conf, "winbind enum groups = yes")
    confset1(smb4_conf, "winbind nested groups = yes")
    confset2(smb4_conf, "winbind use default domain = %s",
             "yes" if nt4.nt4_use_default_domain else "no")

    confset1(smb4_conf, "template shell = /bin/sh")

    confset1(smb4_conf, "local master = no")
    confset1(smb4_conf, "domain master = no")
    confset1(smb4_conf, "preferred master = no")
Ejemplo n.º 6
0
def add_nt4_conf(client, smb4_conf):
    # TODO: These are unused, will they be at some point?
    # rid_range_start = 20000
    # rid_range_end = 20000000

    try:
        nt4 = Struct(client.call('datastore.query', 'directoryservice.nt4', None, {'get': True}))
        nt4.ds_type = 4  # FIXME: DS_TYPE_NT4 = 4
    except:
        return

    dc_ip = None
    try:
        answers = resolver.query(nt4.nt4_dcname, 'A')
        dc_ip = answers[0]

    except Exception as e:
        log.debug(
            "resolver query for {0}'s A record failed with {1}".format(nt4.nt4_dcname, e)
        )
        log_traceback(log=log)
        dc_ip = nt4.nt4_dcname

    nt4_workgroup = nt4.nt4_workgroup.upper()

    with open("/usr/local/etc/lmhosts", "w") as f:
        f.write("%s\t%s\n" % (dc_ip, nt4.nt4_dcname.upper()))

    confset2(smb4_conf, "workgroup = %s", nt4_workgroup)

    confset1(smb4_conf, "security = domain")
    confset1(smb4_conf, "password server = *")

    idmap = Struct(client.call('notifier.ds_get_idmap_object', nt4.ds_type, nt4.id, nt4.nt4_idmap_backend))
    configure_idmap_backend(client, smb4_conf, idmap, nt4_workgroup)

    confset1(smb4_conf, "winbind cache time = 7200")
    confset1(smb4_conf, "winbind offline logon = yes")
    confset1(smb4_conf, "winbind enum users = yes")
    confset1(smb4_conf, "winbind enum groups = yes")
    confset1(smb4_conf, "winbind nested groups = yes")
    confset2(
        smb4_conf, "winbind use default domain = %s", "yes" if nt4.nt4_use_default_domain else "no"
    )

    confset1(smb4_conf, "template shell = /bin/sh")

    confset1(smb4_conf, "local master = no")
    confset1(smb4_conf, "domain master = no")
    confset1(smb4_conf, "preferred master = no")
Ejemplo n.º 7
0
def get_groups(client):
    _groups = {}

    groups = client.call('datastore.query', 'account.bsdGroups', [('bsdgrp_builtin', '=', False)])
    for g in groups:
        g = Struct(g)
        key = str(g.bsdgrp_group)
        _groups[key] = []
        members = client.call('datastore.query', 'account.bsdGroupMembership', [('bsdgrpmember_group', '=', g.id)])
        for m in members:
            m = Struct(m)
            if m.bsdgrpmember_user:
                _groups[key].append(str(m.bsdgrpmember_user.bsdusr_username))

    return _groups
Ejemplo n.º 8
0
def add_domaincontroller_conf(client, smb4_conf):
    try:
        dc = Struct(
            client.call('datastore.query', 'services.DomainController', None,
                        {'get': True}))
        cifs = Struct(client.call('cifs.config'))
    except:
        return

    # server_services = get_server_services()
    # dcerpc_endpoint_servers = get_dcerpc_endpoint_servers()

    confset2(smb4_conf, "netbios name = %s", cifs.netbiosname.upper())
    if cifs.cifs_srv_netbiosalias:
        confset2(smb4_conf, "netbios aliases = %s",
                 cifs.cifs_srv_netbiosalias.upper())
    confset2(smb4_conf, "workgroup = %s", dc.dc_domain.upper())
    confset2(smb4_conf, "realm = %s", dc.dc_realm)
    confset2(smb4_conf, "dns forwarder = %s", dc.dc_dns_forwarder)
    confset1(smb4_conf, "idmap_ldb:use rfc2307 = yes")

    # confset2(smb4_conf, "server services = %s",
    #    string.join(server_services, ',').rstrip(','))
    # confset2(smb4_conf, "dcerpc endpoint servers = %s",
    #    string.join(dcerpc_endpoint_servers, ',').rstrip(','))

    ipv4_addrs = []
    if cifs.cifs_srv_bindip:
        for i in cifs.cifs_srv_bindip:
            try:
                socket.inet_aton(i)
                ipv4_addrs.append(i)
            except:
                pass

    else:
        interfaces = client.call('notifier.choices', 'IPChoices',
                                 [True, False])
        for i in interfaces:
            try:
                socket.inet_aton(i[0])
                ipv4_addrs.append(i[0])
            except:
                pass

    with open("/usr/local/etc/lmhosts", "w") as f:
        for ipv4 in ipv4_addrs:
            f.write("%s\t%s\n" % (ipv4, dc.dc_domain.upper()))
Ejemplo n.º 9
0
def generate_smb4_system_shares(client, smb4_shares):
    if client.call('notifier.common', 'system', 'domaincontroller_enabled'):
        try:
            dc = Struct(
                client.call('datastore.query', 'services.DomainController',
                            None, {'get': True}))
            sysvol_path = "/var/db/samba4/sysvol"

            for share in ["sysvol", "netlogon"]:
                confset1(smb4_shares, "\n")
                confset1(smb4_shares, "[%s]" % (share), space=0)

                if share == "sysvol":
                    path = sysvol_path
                else:
                    path = "%s/%s/scripts" % (sysvol_path, dc.dc_realm.lower())

                confset1(smb4_shares, "path = %s" % (path))
                confset1(smb4_shares, "read only = no")

                vfs_objects = []

                extend_vfs_objects_for_zfs(path, vfs_objects)
                config_share_for_vfs_objects(smb4_shares, vfs_objects)

                config_share_for_nfs4(smb4_shares)
                config_share_for_zfs(smb4_shares)

        except:
            pass
Ejemplo n.º 10
0
def idmap_backend_rfc2307(client):
    try:
        ad = Struct(client.call('datastore.query', 'directoryservice.ActiveDirectory', None, {'get': True}))
    except:
        return False

    return ad.ad_idmap_backend == 'rfc2307'
Ejemplo n.º 11
0
def ldap_conf_activedirectory(client, ldap_conf):
    ad = Struct(client.call('notifier.directoryservice', 'AD'))

    config = {}
    config["URI"] = "%s://%s" % ("ldaps" if ad.ssl == "on" else "ldap",
                                 ad.domainname)
    config["BASE"] = ad.basedn

    if ad.ssl in ("start_tls", "on"):
        if ad.certfile:
            config["TLS_CACERT"] = ad.certfile
        config["TLS_REQCERT"] = "allow"

    #
    # So what if the AD server is configured to use SSL or TLS,
    # and the idmap backend is as well? WTF? whaddoyoudo?
    #
    ad = Struct(
        client.call('datastore.query', 'directoryservice.activedirectory',
                    None, {'get': True}))
    if ad.ad_idmap_backend in ("rfc2307", "ldap"):
        idmap = Struct(
            client.call('notifier.ds_get_idmap_object', ad.ds_type, ad.id,
                        ad.ad_idmap_backend))
        idmap_url = idmap.url
        idmap_url = re.sub('^(ldaps?://)', '', idmap_url)

        config["URI"] = "%s://%s" % ("ldaps" if idmap.ssl == "on" else "ldap",
                                     idmap_url)

        if idmap.ssl in ('start_tls', 'on'):
            ca = client.call('certificateauthority.query',
                             [('id', '=', idmap.certificate.id)],
                             {'get': True})
            capath = ca['cert_ceritifcate_path']
            if capath:
                config["TLS_CACERT"] = capath
            config["TLS_REQCERT"] = "allow"

    keys = ["URI", "BASE", "TLS_CACERT", "TLS_REQCERT"]
    with open(ldap_conf, "w") as f:
        for key in keys:
            if key in config:
                f.write("%s %s\n" % (key, config[key]))
        f.close()
    os.chmod(ldap_conf, 0644)
Ejemplo n.º 12
0
def set_idmap_rfc2307_secret(client):
    try:
        ad = Struct(client.call('datastore.query', 'directoryservice.ActiveDirectory', None, {'get': True}))
        ad.ds_type = 1  # FIXME: DS_TYPE_ACTIVEDIRECTORY = 1
    except:
        return False

    domain = None
    # FIXME: ad ds_type, extend model
    idmap = Struct(client.call('notifier.ds_get_idmap_object', ad.ds_type, ad.id, ad.ad_idmap_backend))

    try:
        fad = Struct(client.call('notifier.directoryservice', 'AD'))
        domain = fad.netbiosname.upper()
    except:
        return False

    args = [
        "/usr/local/bin/net",
        "-d 0",
        "idmap",
        "secret"
    ]

    net_cmd = "%s '%s' '%s'" % (
        ' '.join(args),
        domain,
        idmap.idmap_rfc2307_ldap_user_dn_password
    )

    p = pipeopen(net_cmd, quiet=True)
    net_out = p.communicate()
    if net_out and net_out[0]:
        for line in net_out[0].split('\n'):
            if not line:
                continue
            print(line)

    ret = True
    if p.returncode != 0:
        print("Failed to set idmap secret!", file=sys.stderr)
        ret = False

    return ret
Ejemplo n.º 13
0
def set_idmap_rfc2307_secret(client):
    try:
        ad = Struct(client.call('datastore.query', 'directoryservice.ActiveDirectory', None, {'get': True}))
        ad.ds_type = 1  # FIXME: DS_TYPE_ACTIVEDIRECTORY = 1
    except:
        return False

    domain = None
    # FIXME: ad ds_type, extend model
    idmap = Struct(client.call('notifier.ds_get_idmap_object', ad.ds_type, ad.id, ad.ad_idmap_backend))

    try:
        fad = Struct(client.call('notifier.directoryservice', 'AD'))
        domain = fad.netbiosname.upper()
    except:
        return False

    args = [
        "/usr/local/bin/net",
        "-d 0",
        "idmap",
        "secret"
    ]

    net_cmd = "%s '%s' '%s'" % (
        ' '.join(args),
        domain,
        idmap.idmap_rfc2307_ldap_user_dn_password
    )

    p = pipeopen(net_cmd, quiet=True)
    net_out = p.communicate()
    if net_out and net_out[0]:
        for line in net_out[0].split('\n'):
            if not line:
                continue
            print(line)

    ret = True
    if p.returncode != 0:
        print("Failed to set idmap secret!", file=sys.stderr)
        ret = False

    return ret
Ejemplo n.º 14
0
def smb4_set_database_SID(client, SID):
    ret = False
    if not SID:
        return ret

    try:
        cifs = Struct(client.call('datastore.query', 'services.cifs', None, {'get': True}))
        cifs.cifs_SID = SID
        cifs.save()
        ret = True

    except Exception as e:
        log.debug(
            'The following exception occured while trying to set database SID: {0}'.format(e)
        )
        log_traceback(log=log)
        ret = False

    return ret
Ejemplo n.º 15
0
def get_ldap_cookie(client):
    cookie = ''

    if client.call('notifier.common', 'system', 'ldap_enabled'):
        ldap = Struct(client.call('datastore.query', 'directoryservice.ldap', None, {'get': True}))
        cookie = ldap.ldap_hostname.upper()
        parts = cookie.split('.')
        cookie = parts[0]

    return cookie
Ejemplo n.º 16
0
def get_activedirectory_cookie(client):
    cookie = ''

    if client.call('notifier.common', 'system', 'activedirectory_enabled'):
        smb = Struct(client.call('smb.config'))
        cookie = smb.netbiosname.upper()
        parts = cookie.split('.')
        cookie = parts[0]

    return cookie
Ejemplo n.º 17
0
def smb4_set_database_SID(client, SID):
    ret = False
    if not SID:
        return ret

    try:
        cifs = Struct(client.call('datastore.query', 'services.cifs', None, {'get': True}))
        cifs.cifs_SID = SID
        cifs.save()
        ret = True

    except Exception as e:
        log.debug(
            'The following exception occured while trying to set database SID: {0}'.format(e)
        )
        log_traceback(log=log)
        ret = False

    return ret
Ejemplo n.º 18
0
def smb4_autorid_enabled(client):
    ret = False

    try:
        ad = Struct(client.call('datastore.query', 'directoryservice.ActiveDirectory', None, {'get': True}))
    except:
        return ret

    if ad.ad_idmap_backend.lower() == "autorid":
        ret = True

    return ret
Ejemplo n.º 19
0
def add_ldap_conf(client, smb4_conf):
    try:
        ldap = Struct(client.call('datastore.query', 'directoryservice.LDAP', None, {'get': True}))
        ldap.ds_type = 2  # FIXME: DS_TYPE_LDAP = 2
        cifs = Struct(client.call('smb.config'))
    except:
        return

    confset1(smb4_conf, "security = user")

    confset1(
        smb4_conf,
        "passdb backend = ldapsam:%s://%s" % (
            "ldaps" if ldap.ldap_ssl == 'on' else "ldap",
            ldap.ldap_hostname
        )
    )

    ldap_workgroup = cifs.workgroup.upper()

    confset2(smb4_conf, "ldap admin dn = %s", ldap.ldap_binddn)
    confset2(smb4_conf, "ldap suffix = %s", ldap.ldap_basedn)
    confset2(smb4_conf, "ldap user suffix = %s", ldap.ldap_usersuffix)
    confset2(smb4_conf, "ldap group suffix = %s", ldap.ldap_groupsuffix)
    confset2(smb4_conf, "ldap machine suffix = %s", ldap.ldap_machinesuffix)
    confset2(
        smb4_conf,
        "ldap ssl = %s",
        "start tls" if (ldap.ldap_ssl == 'start_tls') else 'off'
    )

    confset1(smb4_conf, "ldap replication sleep = 1000")
    confset1(smb4_conf, "ldap passwd sync = yes")
    confset1(smb4_conf, "ldapsam:trusted = yes")

    confset2(smb4_conf, "workgroup = %s", ldap_workgroup)
    confset1(smb4_conf, "domain logons = yes")

    idmap = Struct(client.call('notifier.ds_get_idmap_object', ldap.ds_type, ldap.id, ldap.ldap_idmap_backend))
    configure_idmap_backend(client, smb4_conf, idmap, ldap_workgroup)
Ejemplo n.º 20
0
def add_ldap_conf(client, smb4_conf):
    try:
        ldap = Struct(client.call('datastore.query', 'directoryservice.LDAP', None, {'get': True}))
        ldap.ds_type = 2  # FIXME: DS_TYPE_LDAP = 2
        cifs = Struct(client.call('smb.config'))
    except:
        return

    confset1(smb4_conf, "security = user")

    confset1(
        smb4_conf,
        "passdb backend = ldapsam:%s://%s" % (
            "ldaps" if ldap.ldap_ssl == 'on' else "ldap",
            ldap.ldap_hostname
        )
    )

    ldap_workgroup = cifs.workgroup.upper()

    confset2(smb4_conf, "ldap admin dn = %s", ldap.ldap_binddn)
    confset2(smb4_conf, "ldap suffix = %s", ldap.ldap_basedn)
    confset2(smb4_conf, "ldap user suffix = %s", ldap.ldap_usersuffix)
    confset2(smb4_conf, "ldap group suffix = %s", ldap.ldap_groupsuffix)
    confset2(smb4_conf, "ldap machine suffix = %s", ldap.ldap_machinesuffix)
    confset2(
        smb4_conf,
        "ldap ssl = %s",
        "start tls" if (ldap.ldap_ssl == 'start_tls') else 'off'
    )

    confset1(smb4_conf, "ldap replication sleep = 1000")
    confset1(smb4_conf, "ldap passwd sync = yes")
    confset1(smb4_conf, "ldapsam:trusted = yes")

    confset2(smb4_conf, "workgroup = %s", ldap_workgroup)
    confset1(smb4_conf, "domain logons = yes")

    idmap = Struct(client.call('notifier.ds_get_idmap_object', ldap.ds_type, ldap.id, ldap.ldap_idmap_backend))
    configure_idmap_backend(client, smb4_conf, idmap, ldap_workgroup)
Ejemplo n.º 21
0
def smb4_import_users(client, smb_conf_path, smb4_tdb, exportfile=None):
    f = tempfile.NamedTemporaryFile(mode='w+', dir="/tmp")
    for line in smb4_tdb:
        f.write(line + '\n')
    f.flush()

    args = [
        "/usr/local/bin/pdbedit",
        "-d 0",
        "-i smbpasswd:%s" % f.name,
        "-s %s" % smb_conf_path
    ]

    if exportfile is not None:
        # smb4_unlink(exportfile)
        args.append("-e tdbsam:%s" % exportfile)

    p = pipeopen(' '.join(args))
    pdbedit_out = p.communicate()
    if pdbedit_out and pdbedit_out[0]:
        for line in pdbedit_out[0].split('\n'):
            line = line.strip()
            if not line:
                continue
            print(line)

    f.close()
    smb4_users = get_smb4_users(client)
    for u in smb4_users:
        u = Struct(u)
        smbhash = u.bsdusr_smbhash
        parts = smbhash.split(':')
        user = parts[0]

        flags = "-e"
        if u.bsdusr_locked or u.bsdusr_password_disabled:
            flags = "-d"

        p = pipeopen("/usr/local/bin/smbpasswd %s '%s'" % (flags, user))
        smbpasswd_out = p.communicate()

        if p.returncode != 0:
            print("Failed to disable %s" % user, file=sys.stderr)
            continue

        if smbpasswd_out and smbpasswd_out[0]:
            for line in smbpasswd_out[0].split('\n'):
                line = line.strip()
                if not line:
                    continue
                print(line)
Ejemplo n.º 22
0
def smb4_import_users(client, smb_conf_path, smb4_tdb, exportfile=None):
    (fd, tmpfile) = tempfile.mkstemp(dir="/tmp")
    for line in smb4_tdb:
        os.write(fd, line + '\n')
    os.close(fd)

    args = [
        "/usr/local/bin/pdbedit",
        "-d 0",
        "-i smbpasswd:%s" % tmpfile,
        "-s %s" % smb_conf_path
    ]

    if exportfile is not None:
        # smb4_unlink(exportfile)
        args.append("-e tdbsam:%s" % exportfile)

    p = pipeopen(string.join(args, ' '))
    pdbedit_out = p.communicate()
    if pdbedit_out and pdbedit_out[0]:
        for line in pdbedit_out[0].split('\n'):
            line = line.strip()
            if not line:
                continue
            print line

    os.unlink(tmpfile)
    smb4_users = get_smb4_users(client)
    for u in smb4_users:
        u = Struct(u)
        smbhash = u.bsdusr_smbhash
        parts = smbhash.split(':')
        user = parts[0]

        flags = "-e"
        if u.bsdusr_locked or u.bsdusr_password_disabled:
            flags = "-d"

        p = pipeopen("/usr/local/bin/smbpasswd %s '%s'" % (flags, user))
        smbpasswd_out = p.communicate()

        if p.returncode != 0:
            print >> sys.stderr, "Failed to disable %s" % user
            continue

        if smbpasswd_out and smbpasswd_out[0]:
            for line in smbpasswd_out[0].split('\n'):
                line = line.strip()
                if not line:
                    continue
                print line
Ejemplo n.º 23
0
def get_cifs_homedir(client):
    cifs_homedir = "/home"

    shares = client.call('datastore.query', 'sharing.CIFS_Share')
    if len(shares) == 0:
        return

    for share in shares:
        share = Struct(share)
        if share.cifs_home and share.cifs_path:
            cifs_homedir = share.cifs_path
            break

    return cifs_homedir
Ejemplo n.º 24
0
 def ad_monitor(self, client, option):
     ad = Struct(
         client.call('datastore.query', 'directoryservice.activedirectory',
                     None, {'get': True}))
     if ad.ad_enable_monitor and ad.ad_enable:
         if option == 'start':
             return client.call('service.enable_test_service_connection',
                                ad.ad_monitor_frequency,
                                ad.ad_recover_retry, ad.ad_domainname, 3268,
                                'activedirectory')
         elif option == 'stop':
             return client.call('service.disable_test_service_connection',
                                ad.ad_monitor_frequency,
                                ad.ad_recover_retry, ad.ad_domainname, 3268,
                                'activedirectory')
Ejemplo n.º 25
0
def generate_smbusers(client):
    # FIXME: test query
    users = client.call('datastore.query', 'account.bsdusers', [
        ('bsdusr_microsoft_account', '=', True),
        ('bsdusr_email', '!=', None),
        ('bsdusr_email', '!=', ''),
    ])
    if not users:
        return

    with open("/usr/local/etc/smbusers", "w") as f:
        for u in users:
            u = Struct(u)
            f.write("%s = %s\n" % (u.bsdusr_username, u.bsdusr_email))
    os.chmod("/usr/local/etc/smbusers", 0o644)
Ejemplo n.º 26
0
def smb4_get_database_SID(client):
    SID = None

    try:
        cifs = Struct(client.call('datastore.query', 'services.cifs', None, {'get': True}))
        if cifs:
            SID = cifs.cifs_SID
    except Exception as e:
        log.debug(
            'The following exception occured while trying to obtain database SID: {0}'.format(e)
        )
        log_traceback(log=log)
        SID = None

    return SID
Ejemplo n.º 27
0
def set_ldap_password(client):
    try:
        ldap = Struct(client.call('datastore.query', 'directoryservice.LDAP', None, {'get': True}))
    except:
        return

    if ldap.ldap_bindpw:
        p = pipeopen("/usr/local/bin/smbpasswd -w '%s'" % (
            ldap.ldap_bindpw,
        ), quiet=True)
        out = p.communicate()
        if out and out[1]:
            for line in out[1].split('\n'):
                if not line:
                    continue
                print(line)
Ejemplo n.º 28
0
def ldap_conf_ldap(client, ldap_conf):
    try:
        ldap = Struct(client.call('datastore.query', 'directoryservice.ldap', None, {'get': True}))
    except:
        sys.exit(0)

    f = open(ldap_conf, "w")
    f.write("URI %s://%s\n" % (
        "ldaps" if ldap.ldap_ssl == "on" else "ldap",
        ldap.ldap_hostname
    ))
    f.write("BASE %s\n" % ldap.ldap_basedn)

    if ldap.ldap_ssl in ("start_tls", "on"):
        ca = client.call('certificateauthority.query', [('id', '=', ldap.ldap_certificate.id)], {'get': True})
        capath = ca['cert_certificate_path']
        if capath:
            f.write("TLS_CACERT %s\n" % capath)
        f.write("TLS_REQCERT allow\n")

    f.close()
    os.chmod(ldap_conf, 0o644)
Ejemplo n.º 29
0
def ldap_conf_ldap(client, ldap_conf):
    try:
        ldap = Struct(
            client.call('datastore.query', 'directoryservice.LDAP', None,
                        {'get': True}))
    except:
        sys.exit(0)

    f = open(ldap_conf, "w")
    f.write("uri %s://%s\n" %
            ("ldaps" if ldap.ldap_ssl == "on" else "ldap", ldap.ldap_hostname))
    f.write("base %s\n" % ldap.ldap_basedn)

    if ldap.ldap_ssl in ("start_tls", "on"):
        f.write("ssl %s\n" % ldap.ldap_ssl)
        cert = client.call('certificateauthority.query',
                           [('id', '=', ldap.ldap_certificate.id)],
                           {'get': True})
        capath = cert['cert_certificate_path']
        if capath:
            f.write("tls_cacert %s\n" % capath)
        f.write("tls_reqcert allow\n")

    f.write("scope sub\n")
    f.write("timelimit 30\n")
    f.write("bind_timelimit 30\n")
    f.write("bind_policy soft\n")

    #    f.write("nss_map_attribute homeDirectory unixHomeDirectory\n")
    f.write("nss_override_attribute_value loginShell /bin/sh\n")

    if ldap.ldap_auxiliary_parameters:
        f.write(ldap.ldap_auxiliary_parameters)

    f.close()
    os.chmod(ldap_conf, 0o644)
Ejemplo n.º 30
0
def generate_smb4_conf(client, smb4_conf, role):
    cifs = Struct(client.call('cifs.config'))

    if not cifs.guest:
        cifs.guest = 'ftp'
    if not cifs.filemask:
        cifs.filemask = "0666"
    if not cifs.dirmask:
        cifs.dirmask = "0777"

    # standard stuff... should probably do this differently
    confset1(smb4_conf, "[global]", space=0)

    if os.path.exists("/usr/local/etc/smbusers"):
        confset1(smb4_conf, "username map = /usr/local/etc/smbusers")

    confset2(smb4_conf, "server min protocol = %s", cifs.min_protocol)
    confset2(smb4_conf, "server max protocol = %s", cifs.max_protocol)
    if cifs.bindip:
        interfaces = []

        bindips = ' '.join(cifs.bindip)
        if role != 'dc':
            bindips = "127.0.0.1 %s" % bindips

        bindips = bindips.split()
        for bindip in bindips:
            if not bindip:
                continue
            bindip = bindip.strip()
            iface = client.call('notifier.get_interface', bindip)
            if iface and client.call('notifier.is_carp_interface', iface):
                parent_iface = client.call('notifier.get_parent_interface',
                                           iface)
                if not parent_iface:
                    continue

                parent_iinfo = client.call('notifier.get_interface_info',
                                           parent_iface[0])
                if not parent_iinfo:
                    continue

                interfaces.append("%s/%s" % (bindip, parent_iface[2]))
            else:
                interfaces.append(bindip)

        if interfaces:
            confset2(smb4_conf, "interfaces = %s", ' '.join(interfaces))
        confset1(smb4_conf, "bind interfaces only = yes")

    confset1(smb4_conf, "encrypt passwords = yes")
    confset1(smb4_conf, "dns proxy = no")
    confset1(smb4_conf, "strict locking = no")
    confset1(smb4_conf, "oplocks = yes")
    confset1(smb4_conf, "deadtime = 15")
    confset1(smb4_conf, "max log size = 51200")

    confset2(smb4_conf, "max open files = %d",
             int(get_sysctl('kern.maxfilesperproc')) - 25)

    if cifs.loglevel and cifs.loglevel is not True:
        loglevel = cifs.loglevel
    else:
        loglevel = "0"

    if cifs.syslog:
        confset1(smb4_conf, "logging = syslog:%s" % loglevel)
    else:
        confset1(smb4_conf, "logging = file")

    confset1(smb4_conf, "load printers = no")
    confset1(smb4_conf, "printing = bsd")
    confset1(smb4_conf, "printcap name = /dev/null")
    confset1(smb4_conf, "disable spoolss = yes")
    confset1(smb4_conf, "getwd cache = yes")
    confset2(smb4_conf, "guest account = %s", cifs.guest)
    confset1(smb4_conf, "map to guest = Bad User")
    confset2(smb4_conf, "obey pam restrictions = %s",
             "yes" if cifs.obey_pam_restrictions else "no")
    confset2(smb4_conf, "ntlm auth = %s", "yes" if cifs.ntlmv1_auth else "no")
    confset1(smb4_conf, "directory name cache size = 0")
    confset1(smb4_conf, "kernel change notify = no")

    confset1(smb4_conf,
             "panic action = /usr/local/libexec/samba/samba-backtrace")
    confset1(smb4_conf, "nsupdate command = /usr/local/bin/samba-nsupdate -g")

    confset2(smb4_conf, "server string = %s", cifs.description)
    confset1(smb4_conf, "ea support = yes")
    confset1(smb4_conf, "store dos attributes = yes")
    confset1(smb4_conf, "lm announce = yes")
    confset2(smb4_conf, "hostname lookups = %s",
             "yes" if cifs.hostlookup else False)
    confset2(smb4_conf, "unix extensions = %s",
             "no" if not cifs.unixext else False)
    confset2(smb4_conf, "time server = %s",
             "yes" if cifs.timeserver else False)
    confset2(smb4_conf, "null passwords = %s", "yes" if cifs.nullpw else False)
    confset2(smb4_conf, "acl allow execute always = %s",
             "true" if cifs.allow_execute_always else "false")
    confset1(smb4_conf, "dos filemode = yes")
    confset2(smb4_conf, "multicast dns register = %s",
             "yes" if cifs.zeroconf else "no")

    if not smb4_ldap_enabled(client):
        confset2(smb4_conf, "domain logons = %s",
                 "yes" if cifs.domain_logons else "no")

    if (not client.call('notifier.common', 'system', 'nt4_enabled')
            and not client.call('notifier.common', 'system',
                                'activedirectory_enabled')):
        confset2(smb4_conf, "local master = %s",
                 "yes" if cifs.localmaster else "no")

    # 5 = DS_TYPE_CIFS
    idmap = Struct(
        client.call('notifier.ds_get_idmap_object', 5, cifs.id, 'tdb'))
    configure_idmap_backend(client, smb4_conf, idmap, None)

    if role == 'auto':
        confset1(smb4_conf, "server role = auto")

    elif role == 'classic':
        confset1(smb4_conf, "server role = classic primary domain controller")

    elif role == 'netbios':
        confset1(smb4_conf, "server role = netbios backup domain controller")

    elif role == 'dc':
        confset1(smb4_conf, "server role = active directory domain controller")
        add_domaincontroller_conf(client, smb4_conf)

    elif role == 'member':
        confset1(smb4_conf, "server role = member server")

        if client.call('notifier.common', 'system', 'nt4_enabled'):
            add_nt4_conf(client, smb4_conf)

        elif smb4_ldap_enabled(client):
            add_ldap_conf(client, smb4_conf)

        elif client.call('notifier.common', 'system',
                         'activedirectory_enabled'):
            add_activedirectory_conf(client, smb4_conf)

        confset2(smb4_conf, "netbios name = %s", cifs.netbiosname.upper())
        if cifs.netbiosalias:
            confset2(smb4_conf, "netbios aliases = %s",
                     cifs.netbiosalias.upper())

    elif role == 'standalone':
        confset1(smb4_conf, "server role = standalone")
        confset2(smb4_conf, "netbios name = %s", cifs.netbiosname.upper())
        if cifs.netbiosalias:
            confset2(smb4_conf, "netbios aliases = %s",
                     cifs.netbiosalias.upper())
        confset2(smb4_conf, "workgroup = %s", cifs.workgroup.upper())
        confset1(smb4_conf, "security = user")

    if role != 'dc':
        confset1(smb4_conf, "pid directory = /var/run/samba")

    confset2(smb4_conf, "create mask = %s", cifs.filemask)
    confset2(smb4_conf, "directory mask = %s", cifs.dirmask)
    confset2(smb4_conf, "client ntlmv2 auth = %s",
             "yes" if not cifs.ntlmv1_auth else "no")
    confset2(smb4_conf, "dos charset = %s", cifs.doscharset)
    confset2(smb4_conf, "unix charset = %s", cifs.unixcharset)

    if cifs.loglevel and cifs.loglevel is not True:
        confset2(smb4_conf, "log level = %s", cifs.loglevel)

    smb_options = cifs.smb_options.strip()
    for line in smb_options.split('\n'):
        line = line.strip()
        if not line:
            continue
        confset1(smb4_conf, line)
Ejemplo n.º 31
0
def generate_smb4_shares(client, smb4_shares):
    shares = client.call('datastore.query', 'sharing.CIFS_Share')

    if len(shares) == 0:
        return

    for share in shares:
        share = Struct(share)
        if (not share.cifs_home and not os.path.isdir(share.cifs_path)):
            continue

        confset1(smb4_shares, "\n")
        if share.cifs_home:
            confset1(smb4_shares, "[homes]", space=0)

            valid_users_path = "%U"
            valid_users = "%U"

            if client.call('notifier.common', 'system',
                           'activedirectory_enabled'):
                valid_users_path = "%D/%U"
                valid_users = "%D\%U"

                try:
                    ad = Struct(client.call('notifier.directoryservice', 'AD'))
                    for w in ad.workgroups:
                        homedir_path = "%s/%s" % (share.cifs_path, w)
                        if not os.access(homedir_path, os.F_OK):
                            smb4_mkdir(homedir_path)

                except:
                    pass

            confset2(smb4_shares, "valid users = %s", valid_users)

            if share.cifs_path:
                cifs_homedir_path = ("%s/%s" %
                                     (share.cifs_path, valid_users_path))
                confset2(smb4_shares, "path = %s", qw(cifs_homedir_path))
            if share.cifs_comment:
                confset2(smb4_shares, "comment = %s", share.cifs_comment)
            else:
                confset1(smb4_shares, "comment = Home Directories")
        else:
            confset2(smb4_shares, "[%s]", share.cifs_name, space=0)
            confset2(smb4_shares, "path = %s", qw(share.cifs_path))
            confset2(smb4_shares, "comment = %s", share.cifs_comment)
        confset1(smb4_shares, "printable = no")
        confset1(smb4_shares, "veto files = /.snapshot/.windows/.mac/.zfs/")
        confset2(smb4_shares, "writeable = %s",
                 "no" if share.cifs_ro else "yes")
        confset2(smb4_shares, "browseable = %s",
                 "yes" if share.cifs_browsable else "no")

        task = None
        if share.cifs_storage_task:
            task = share.cifs_storage_task

        vfs_objects = []
        if task:
            vfs_objects.append('shadow_copy2')
        extend_vfs_objects_for_zfs(share.cifs_path, vfs_objects)
        vfs_objects.extend(share.cifs_vfsobjects)

        if share.cifs_recyclebin:
            vfs_objects.append('recycle')
            confset1(smb4_shares, "recycle:repository = .recycle/%U")
            confset1(smb4_shares, "recycle:keeptree = yes")
            confset1(smb4_shares, "recycle:versions = yes")
            confset1(smb4_shares, "recycle:touch = yes")
            confset1(smb4_shares, "recycle:directory_mode = 0777")
            confset1(smb4_shares, "recycle:subdir_mode = 0700")

        if task:
            confset1(smb4_shares, "shadow:snapdir = .zfs/snapshot")
            confset1(smb4_shares, "shadow:sort = desc")
            confset1(smb4_shares, "shadow:localtime = yes")
            confset1(
                smb4_shares, "shadow:format = auto-%%Y%%m%%d.%%H%%M-%s%s" %
                (task.task_ret_count, task.task_ret_unit[0]))
            confset1(smb4_shares, "shadow:snapdirseverywhere = yes")

        config_share_for_vfs_objects(smb4_shares, vfs_objects)

        confset2(smb4_shares, "hide dot files = %s",
                 "no" if share.cifs_showhiddenfiles else "yes")
        confset2(smb4_shares, "hosts allow = %s", share.cifs_hostsallow)
        confset2(smb4_shares, "hosts deny = %s", share.cifs_hostsdeny)
        confset2(smb4_shares, "guest ok = %s",
                 "yes" if share.cifs_guestok else "no")

        confset2(smb4_shares, "guest only = %s",
                 "yes" if share.cifs_guestonly else False)

        config_share_for_nfs4(smb4_shares)
        config_share_for_zfs(smb4_shares)

        for line in share.cifs_auxsmbconf.split('\n'):
            line = line.strip()
            if not line:
                continue
            confset1(smb4_shares, line)
Ejemplo n.º 32
0
def main(middleware):
    """Use the middleware to generate a config file. We'll build the
    config file as a series of lines, and once that is done write it
    out in one go"""

    cf_contents.clear()
    cf_contents_shadow.clear()

    gconf = Struct(
        middleware.call_sync('datastore.query',
                             'services.iSCSITargetGlobalConfiguration', [],
                             {'get': True}))
    if gconf.iscsi_alua:
        node = middleware.call_sync('failover.node')

    if gconf.iscsi_isns_servers:
        for server in gconf.iscsi_isns_servers.split():
            addline('isns-server "%s"\n\n' % server)

    # Generate the portal-group section
    addline('portal-group "default" {\n}\n\n')
    for pg in middleware.call_sync('datastore.query',
                                   'services.iSCSITargetPortal'):
        pg = Struct(pg)
        # Prepare auth group for the portal group
        if pg.iscsi_target_portal_discoveryauthgroup:
            auth_list = [
                Struct(i) for i in middleware.call_sync(
                    'datastore.query', 'services.iSCSITargetAuthCredential', [(
                        'iscsi_target_auth_tag', '=',
                        pg.iscsi_target_portal_discoveryauthgroup)])
            ]
        else:
            auth_list = []
        agname = 'ag4pg%d' % pg.iscsi_target_portal_tag
        if not auth_group_config(
                auth_tag=agname,
                auth_list=auth_list,
                auth_type=pg.iscsi_target_portal_discoveryauthmethod):
            agname = 'no-authentication'

        # Prepare IPs to listen on for all portal groups.
        portals = [
            Struct(i) for i in middleware.call_sync(
                'datastore.query', 'services.iSCSITargetPortalIP', [(
                    'iscsi_target_portalip_portal', '=', pg.id)])
        ]
        listen = []
        listenA = []
        listenB = []
        for portal in portals:
            if ':' in portal.iscsi_target_portalip_ip:
                address = '[%s]' % portal.iscsi_target_portalip_ip
            else:
                address = portal.iscsi_target_portalip_ip
            found = False
            if gconf.iscsi_alua:
                if address == '0.0.0.0':
                    listenA.append(
                        '%s:%s' % (address, portal.iscsi_target_portalip_port))
                    listenB.append(
                        '%s:%s' % (address, portal.iscsi_target_portalip_port))
                    found = True
                    break
                if not found:
                    for net in middleware.call_sync('datastore.query',
                                                    'network.Interfaces'):
                        if net['int_vip'] == address and net[
                                'int_ipv4address'] and net['int_ipv4address_b']:
                            listenA.append('%s:%s' %
                                           (net['int_ipv4address'],
                                            portal.iscsi_target_portalip_port))
                            listenB.append('%s:%s' %
                                           (net['int_ipv4address_b'],
                                            portal.iscsi_target_portalip_port))
                            found = True
                            break
                if not found:
                    for alias in middleware.call_sync('datastore.query',
                                                      'network.Alias'):
                        if alias['alias_vip'] == address and alias[
                                'alias_v4address'] and alias[
                                    'alias_v4address_b']:
                            listenA.append('%s:%s' %
                                           (alias['alias_v4address'],
                                            portal.iscsi_target_portalip_port))
                            listenB.append('%s:%s' %
                                           (alias['alias_v4address_b'],
                                            portal.iscsi_target_portalip_port))
                            found = True
                            break
            else:
                listen.append('%s:%s' %
                              (address, portal.iscsi_target_portalip_port))

        if gconf.iscsi_alua:
            # Two portal groups for ALUA HA case.
            addline('portal-group "pg%dA" {\n' % pg.iscsi_target_portal_tag)
            addline('\ttag "0x%04x"\n' % pg.iscsi_target_portal_tag)
            addline('\tdiscovery-filter "portal-name"\n')
            addline('\tdiscovery-auth-group "%s"\n' % agname)
            for i in listenA:
                addline('\tlisten "%s"\n' % i)
            if node != 'A':
                addline('\tforeign\n')
            addline('}\n')
            addline('portal-group "pg%dB" {\n' % pg.iscsi_target_portal_tag)
            addline('\ttag "0x%04x"\n' % (pg.iscsi_target_portal_tag + 0x8000))
            addline('\tdiscovery-filter "portal-name"\n')
            addline('\tdiscovery-auth-group "%s"\n' % agname)
            for i in listenB:
                addline('\tlisten "%s"\n' % i)
            if node != 'B':
                addline('\tforeign\n')
            addline('}\n\n')
        else:
            # One portal group for non-HA and CARP HA cases.
            addline('portal-group "pg%d" {\n' % pg.iscsi_target_portal_tag)
            addline('\ttag "0x%04x"\n' % pg.iscsi_target_portal_tag)
            addline('\tdiscovery-filter "portal-name"\n')
            addline('\tdiscovery-auth-group "%s"\n' % agname)
            for i in listen:
                addline('\tlisten "%s"\n' % i)
            addline('\toption "ha_shared" "on"\n')
            addline('}\n\n')

    # Cache zpool threshold
    poolthreshold = {}
    zpoollist = {i['name']: i for i in middleware.call_sync('zfs.pool.query')}

    system_disks = middleware.call_sync('device.get_disks')
    # Generate the LUN section
    for extent in middleware.call_sync(
            'datastore.query', 'services.iSCSITargetExtent',
        [['iscsi_target_extent_enabled', '=', True]]):
        extent = Struct(extent)
        path = extent.iscsi_target_extent_path
        if not path:
            logger.warning('Path for extent id %d is null, skipping',
                           extent.id)
            continue

        poolname = None
        lunthreshold = None
        if extent.iscsi_target_extent_type == 'Disk':
            disk = middleware.call_sync('datastore.query', 'storage.Disk',
                                        [('disk_identifier', '=', path)],
                                        {'order_by': ['disk_expiretime']})
            if not disk:
                continue
            disk = Struct(disk[0])
            if disk.disk_multipath_name:
                path = '/dev/multipath/%s' % disk.disk_multipath_name
            else:
                path = '/dev/%s' % middleware.call_sync(
                    'disk.identifier_to_device', disk.disk_identifier,
                    system_disks)
        else:
            if not path.startswith('/mnt'):
                poolname = path.split('/', 2)[1]
                if gconf.iscsi_pool_avail_threshold:
                    if poolname in zpoollist:
                        poolthreshold[poolname] = int(
                            zpoollist[poolname]['properties']['size']['parsed']
                            * (gconf.iscsi_pool_avail_threshold / 100.0))
                if extent.iscsi_target_extent_avail_threshold:
                    zvolname = path.split('/', 1)[1]
                    zfslist = middleware.call_sync('pool.dataset.query',
                                                   [('id', '=', zvolname)])
                    if zfslist and zfslist[0]['type'] == 'VOLUME':
                        lunthreshold = int(
                            zfslist[0]['volsize']['parsed'] *
                            (extent.iscsi_target_extent_avail_threshold /
                             100.0))
                path = '/dev/' + path
            else:
                if extent.iscsi_target_extent_avail_threshold and os.path.exists(
                        path):
                    try:
                        stat = os.stat(path)
                        lunthreshold = int(
                            stat.st_size *
                            (extent.iscsi_target_extent_avail_threshold /
                             100.0))
                    except OSError:
                        pass
        addline('lun "%s" {\n' % extent.iscsi_target_extent_name)
        addline('\tctl-lun "%d"\n' % (extent.id - 1))
        size = extent.iscsi_target_extent_filesize
        addline('\tpath "%s"\n' % path)
        addline('\tblocksize "%s"\n' % extent.iscsi_target_extent_blocksize)
        if extent.iscsi_target_extent_pblocksize:
            addline('\toption "pblocksize" "0"\n')
        addline('\tserial "%s"\n' % (extent.iscsi_target_extent_serial, ))
        padded_serial = extent.iscsi_target_extent_serial
        if not extent.iscsi_target_extent_xen:
            for i in range(31 - len(extent.iscsi_target_extent_serial)):
                padded_serial += ' '
        addline('\tdevice-id "iSCSI Disk      %s"\n' % padded_serial)
        if size != '0':
            if size.endswith('B'):
                size = size.strip('B')
            addline('\t\tsize "%s"\n' % size)

        # We can't change the vendor name of existing
        # LUNs without angering VMWare, but we can
        # use the right names going forward.
        if extent.iscsi_target_extent_legacy is True:
            addline('\toption "vendor" "FreeBSD"\n')
        else:
            if middleware.call_sync('system.is_freenas'):
                addline('\toption "vendor" "FreeNAS"\n')
            else:
                addline('\toption "vendor" "TrueNAS"\n')

        addline('\toption "product" "iSCSI Disk"\n')
        addline('\toption "revision" "0123"\n')
        addline('\toption "naa" "%s"\n' % extent.iscsi_target_extent_naa)
        if extent.iscsi_target_extent_insecure_tpc:
            addline('\toption "insecure_tpc" "on"\n')
            if lunthreshold:
                addline('\toption "avail-threshold" "%s"\n' % lunthreshold)
        if poolname is not None and poolname in poolthreshold:
            addline('\toption "pool-avail-threshold" "%s"\n' %
                    poolthreshold[poolname])
        if extent.iscsi_target_extent_rpm == 'Unknown':
            addline('\toption "rpm" "0"\n')
        elif extent.iscsi_target_extent_rpm == 'SSD':
            addline('\toption "rpm" "1"\n')
        else:
            addline('\toption "rpm" "%s"\n' % extent.iscsi_target_extent_rpm)
        if extent.iscsi_target_extent_ro:
            addline('\toption "readonly" "on"\n')
        addline('}\n')
        addline('\n')

    # Generate the target section
    target_basename = gconf.iscsi_basename
    for target in middleware.call_sync('datastore.query',
                                       'services.iSCSITarget'):
        target = Struct(target)

        authgroups = {}
        for grp in middleware.call_sync('datastore.query',
                                        'services.iscsitargetgroups',
                                        [('iscsi_target', '=', target.id)]):
            grp = Struct(grp)
            if grp.iscsi_target_authgroup:
                auth_list = [
                    Struct(i) for i in middleware.call_sync(
                        'datastore.query',
                        'services.iSCSITargetAuthCredential', [(
                            'iscsi_target_auth_tag', '=',
                            grp.iscsi_target_authgroup)])
                ]
            else:
                auth_list = []
            agname = 'ag4tg%d_%d' % (target.id, grp.id)
            if auth_group_config(auth_tag=agname,
                                 auth_list=auth_list,
                                 auth_type=grp.iscsi_target_authtype,
                                 initiator=grp.iscsi_target_initiatorgroup):
                authgroups[grp.id] = agname
        if (target.iscsi_target_name.startswith('iqn.')
                or target.iscsi_target_name.startswith('eui.')
                or target.iscsi_target_name.startswith('naa.')):
            addline('target "%s" {\n' % target.iscsi_target_name)
        else:
            addline('target "%s:%s" {\n' %
                    (target_basename, target.iscsi_target_name))
        if target.iscsi_target_alias:
            addline('\talias "%s"\n' % target.iscsi_target_alias)
        elif target.iscsi_target_name:
            addline('\talias "%s"\n' % target.iscsi_target_name)

        for fctt in middleware.call_sync('datastore.query',
                                         'services.fibrechanneltotarget',
                                         [('fc_target', '=', target.id)]):
            fctt = Struct(fctt)
            addline('\tport "%s"\n' % fctt.fc_port)

        for grp in middleware.call_sync('datastore.query',
                                        'services.iscsitargetgroups',
                                        [('iscsi_target', '=', target.id)]):
            grp = Struct(grp)
            agname = authgroups.get(grp.id) or 'no-authentication'
            if gconf.iscsi_alua:
                addline('\tportal-group "pg%dA" "%s"\n' %
                        (grp.iscsi_target_portalgroup.iscsi_target_portal_tag,
                         agname))
                addline('\tportal-group "pg%dB" "%s"\n' %
                        (grp.iscsi_target_portalgroup.iscsi_target_portal_tag,
                         agname))
            else:
                addline('\tportal-group "pg%d" "%s"\n' %
                        (grp.iscsi_target_portalgroup.iscsi_target_portal_tag,
                         agname))
        addline('\n')
        used_lunids = [
            o['iscsi_lunid'] for o in middleware.
            call_sync('datastore.query', 'services.iscsitargettoextent', [(
                'iscsi_target', '=', target.id), ('iscsi_lunid', '!=', None)])
        ]
        cur_lunid = 0
        for t2e in middleware.call_sync(
                'datastore.query', 'services.iscsitargettoextent',
            [('iscsi_target', '=', target.id)],
            {'order_by': ['nulls_last:iscsi_lunid']}):
            t2e = Struct(t2e)
            if not t2e.iscsi_extent.iscsi_target_extent_enabled:
                # Skip adding extents to targets which are not enabled
                continue
            if t2e.iscsi_lunid is None:
                while cur_lunid in used_lunids:
                    cur_lunid += 1
                addline('\tlun "%s" "%s"\n' %
                        (cur_lunid, t2e.iscsi_extent.iscsi_target_extent_name))
                cur_lunid += 1
            else:
                addline('\tlun "%s" "%s"\n' %
                        (t2e.iscsi_lunid,
                         t2e.iscsi_extent.iscsi_target_extent_name))
        addline('}\n\n')

    # Write out the CTL config file
    with open(
            os.open(ctl_config, os.O_CREAT | os.O_WRONLY | os.O_TRUNC, 0o600),
            'w') as fh:
        for line in cf_contents:
            fh.write(line)

    # Write out the CTL config file with redacted CHAP passwords
    with open(
            os.open(ctl_config_shadow, os.O_CREAT | os.O_WRONLY | os.O_TRUNC,
                    0o600), 'w') as fh:
        for line in cf_contents_shadow:
            fh.write(line)
Ejemplo n.º 33
0
def render(service, middleware):
    """
    The resulting afp.conf file will only allow kerberos authentication (add uams_gss.so)
    if a kerberos keytab is uploaded to the NAS. When afp_srv_map_acls is set to "mode"
    and the LDAP or AD directory service is enabled, the NAS is configured to query the LDAP server
    for a UUID attribute to present to MacOS clients. This is required for the permission editor to
    properly display users in the MacOS permissions editor because MacOS clients use UUIDs
    rather than UIDs and GIDs. SASL is not implemented in Netatalk, and so this feature requires
    storing the plain-text LDAP password in the afp.conf file. The default AD behavior clears
    the bindpw after successful domain join, and so additional configuration (persistently storing
    the bindpw and possibly LDAP schema changes) will be required for this feature to work correctly.
    """

    map_acls_mode = False
    ds_type = None
    afp_config = "/etc/afp.conf"
    if osc.IS_FREEBSD:
        afp_config = f'/usr/local{afp_config}'
    cf_contents = []

    afp = Struct(
        middleware.call_sync('datastore.query', 'services.afp', [],
                             {'get': True}))

    cf_contents.append("[Global]\n")
    uam_list = ['uams_dhx.so', 'uams_dhx2.so']
    if afp.afp_srv_guest:
        uam_list.append('uams_guest.so')
        cf_contents.append('\tguest account = %s\n' % afp.afp_srv_guest_user)
    # uams_gss.so bails out with an error if kerberos isn't configured
    if middleware.call_sync('datastore.query',
                            'directoryservice.kerberoskeytab', [],
                            {'count': True}) > 0:
        uam_list.append('uams_gss.so')
    cf_contents.append('\tuam list = %s\n' % (" ").join(uam_list))

    if afp.afp_srv_bindip:
        ifaces = get_interface(middleware, afp.afp_srv_bindip)
        if ifaces:
            cf_contents.append("\tafp listen = %s\n" %
                               ' '.join(afp.afp_srv_bindip))
            cf_contents.append("\tafp interfaces = %s\n" % ' '.join(ifaces))

    cf_contents.append("\tmax connections = %s\n" %
                       afp.afp_srv_connections_limit)
    cf_contents.append("\tmimic model = RackMac\n")
    cf_contents.append("\tafpstats = yes\n")
    if afp.afp_srv_dbpath:
        cf_contents.append("\tvol dbnest = no\n")
        cf_contents.append("\tvol dbpath = %s\n" % afp.afp_srv_dbpath)
    else:
        cf_contents.append("\tvol dbnest = yes\n")
    if afp.afp_srv_global_aux:
        cf_contents.append("\t%s\n" % afp.afp_srv_global_aux)

    if afp.afp_srv_map_acls:
        cf_contents.append("\tmap acls = %s\n" % afp.afp_srv_map_acls)

    if afp.afp_srv_chmod_request:
        cf_contents.append("\tchmod request = %s\n" %
                           afp.afp_srv_chmod_request)

    if afp.afp_srv_map_acls == 'mode':
        if middleware.call_sync('activedirectory.get_state') != 'DISABLED':
            ds_type = 'AD'
        elif middleware.call_sync('ldap.get_state') != 'DISABLED':
            ds_type = 'LDAP'

    if ds_type is not None:
        ds_config = {
            'bind_dn': None,
            'bind_pw': None,
            'server': None,
            'userbase': None,
            'groupbase': None,
        }
        if ds_type == 'AD':
            ad = middleware.call_sync('activedirectory.config')
            ds_config.update({
                'bind_dn': ad['bindname'],
                'bind_pw': ad['bindpw'],
                'server': ad['domainname'],
            })
        elif ds_type == 'LDAP':
            ldap = middleware.call_sync('ldap.config')
            ds_config.update({
                'bind_dn': ldap['binddn'],
                'bind_pw': ldap['bindpw'],
                'server': ldap['hostname'],
                'userbase': ldap['basedn'],
                'groupbase': ldap['basedn'],
            })

        cf_contents.append("\tldap auth method = %s\n" % "simple")
        cf_contents.append("\tldap auth dn = %s\n" % ds_config['bind_dn'])
        cf_contents.append("\tldap auth pw = %s\n" % ds_config['bind_pw'])
        cf_contents.append("\tldap server = %s\n" % ds_config['server'])

        # This should be configured when using this option
        if ds_config['userbase']:
            cf_contents.append("\tldap userbase = %s\n" %
                               ds_config['userbase'])

        cf_contents.append("\tldap userscope = %s\n" % "sub")

        # This should be configured when using this option
        if ds_config['groupbase']:
            cf_contents.append("\tldap groupbase = %s\n" %
                               ds_config['groupbase'])

        cf_contents.append("\tldap groupscope = %s\n" % "sub")

        cf_contents.append("\tldap user filter = %s\n" % "objectclass=user")
        cf_contents.append("\tldap group filter = %s\n" % "objectclass=group")
        cf_contents.append("\tldap uuid attr = %s\n" % "objectGUID")
        if ds_type == 'AD':
            cf_contents.append("\tldap uuid encoding = %s\n" % "ms-guid")
            cf_contents.append("\tldap name attr = %s\n" % "sAMAccountName")
            cf_contents.append("\tldap group attr = %s\n" % "sAMAccountName")

    cf_contents.append("\tlog file = %s\n" % "/var/log/afp.log")
    cf_contents.append("\tlog level = %s\n" % "default:warn")
    cf_contents.append("\n")

    for share in middleware.call_sync('datastore.query', 'sharing.afp_share',
                                      [['afp_enabled', '=', True]]):
        share = Struct(share)
        if share.afp_home:
            cf_contents.append("[Homes]\n")
            cf_contents.append("\tbasedir regex = %s\n" % share.afp_path)
            if share.afp_name and share.afp_name != "Homes":
                cf_contents.append("\thome name = %s\n" % share.afp_name)
        else:
            cf_contents.append("[%s]\n" % share.afp_name)
            cf_contents.append("\tpath = %s\n" % share.afp_path)
        if share.afp_allow:
            cf_contents.append("\tvalid users = %s\n" % share.afp_allow)
        if share.afp_deny:
            cf_contents.append("\tinvalid users = %s\n" % share.afp_deny)
        if share.afp_hostsallow:
            cf_contents.append("\thosts allow = %s\n" % share.afp_hostsallow)
        if share.afp_hostsdeny:
            cf_contents.append("\thosts deny = %s\n" % share.afp_hostsdeny)
        if share.afp_ro:
            cf_contents.append("\trolist = %s\n" % share.afp_ro)
        if share.afp_rw:
            cf_contents.append("\trwlist = %s\n" % share.afp_rw)
        if share.afp_timemachine:
            cf_contents.append("\ttime machine = yes\n")
        if not share.afp_nodev:
            cf_contents.append("\tcnid dev = no\n")
        if share.afp_nostat:
            cf_contents.append("\tstat vol = no\n")
        if not share.afp_upriv:
            cf_contents.append("\tunix priv = no\n")
        else:
            if share.afp_fperm and not map_acls_mode:
                cf_contents.append("\tfile perm = %s\n" % share.afp_fperm)
            if share.afp_dperm and not map_acls_mode:
                cf_contents.append("\tdirectory perm = %s\n" % share.afp_dperm)
            if share.afp_umask and not map_acls_mode:
                cf_contents.append("\tumask = %s\n" % share.afp_umask)
        cf_contents.append("\tveto files = .windows/.mac/\n")
        if map_acls_mode:
            cf_contents.append("\tacls = yes\n")
        # Do not fail if aux params are not properly entered by the user
        try:
            aux_params = [
                "\t{0}\n".format(p) for p in share.afp_auxparams.split("\n")
            ]
        except:
            pass
        else:
            cf_contents += aux_params
        # Update TimeMachine special files
        timemachine_supported_path = os.path.join(
            share.afp_path, ".com.apple.timemachine.supported")
        timemachine_quota_plist_path = os.path.join(
            share.afp_path, ".com.apple.TimeMachine.quota.plist")
        timemachine_quota_plist_managed_flag = os.path.join(
            share.afp_path,
            ".com.apple.TimeMachine.quota.plist.FreeNAS-managed")
        if share.afp_timemachine and share.afp_timemachine_quota:
            try:
                with open(timemachine_supported_path, "w"):
                    pass
            except IOError:
                pass

            try:
                with open(timemachine_quota_plist_path, "w") as f:
                    f.write(
                        textwrap.dedent("""\
                        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
                        <plist version="1.0">
                            <dict>
                                <key>GlobalQuota</key>
                                <integer>%d</integer>
                            </dict>
                        </plist>
                    """ % (share.afp_timemachine_quota * 1024 * 1024 * 1024)))
            except IOError:
                pass

            try:
                with open(timemachine_quota_plist_managed_flag, "w") as f:
                    pass
            except IOError:
                pass

            try:
                stat = os.stat(share.afp_path)
                os.chmod(timemachine_supported_path, 0o644)
                os.chown(timemachine_supported_path, stat.st_uid, stat.st_gid)
                os.chmod(timemachine_quota_plist_path, 0o644)
                os.chown(timemachine_quota_plist_path, stat.st_uid,
                         stat.st_gid)
                os.chmod(timemachine_quota_plist_managed_flag, 0o644)
                os.chown(timemachine_quota_plist_managed_flag, stat.st_uid,
                         stat.st_gid)
            except IOError:
                pass
        else:
            if os.path.exists(timemachine_quota_plist_managed_flag):
                try:
                    os.unlink(timemachine_supported_path)
                except IOError:
                    pass

                try:
                    os.unlink(timemachine_quota_plist_path)
                except IOError:
                    pass

    with open(afp_config, "w") as fh:
        for line in cf_contents:
            fh.write(line)
def main():
    """Use the django ORM to generate a config file.  We'll build the
    config file as a series of lines, and once that is done write it
    out in one go"""

    map_acls_mode = False
    afp_config = "/usr/local/etc/afp.conf"
    cf_contents = []
    client = Client()

    afp = Struct(
        client.call('datastore.query', 'services.afp', None, {'get': True}))

    cf_contents.append("[Global]\n")
    uam_list = ['uams_dhx.so', 'uams_dhx2.so']
    if afp.afp_srv_guest:
        uam_list.append('uams_guest.so')
        cf_contents.append('\tguest account = %s\n' % afp.afp_srv_guest_user)
    # uams_gss.so bails out with an error if kerberos isn't configured
    if client.call('datastore.query', 'directoryservice.kerberoskeytab', None,
                   {'count': True}) > 0:
        uam_list.append('uams_gss.so')
    cf_contents.append('\tuam list = %s\n' % (" ").join(uam_list))

    if afp.afp_srv_bindip:
        cf_contents.append("\tafp listen = %s\n" %
                           ' '.join(afp.afp_srv_bindip))
        ifaces = get_interface(afp.afp_srv_bindip)
        cf_contents.append("\tafp interfaces = %s\n" % ' '.join(ifaces))
    cf_contents.append("\tmax connections = %s\n" %
                       afp.afp_srv_connections_limit)
    cf_contents.append("\tmimic model = RackMac\n")
    if afp.afp_srv_dbpath:
        cf_contents.append("\tvol dbnest = no\n")
        cf_contents.append("\tvol dbpath = %s\n" % afp.afp_srv_dbpath)
    else:
        cf_contents.append("\tvol dbnest = yes\n")
    if afp.afp_srv_global_aux:
        cf_contents.append("\t%s\n" % afp.afp_srv_global_aux)

    if afp.afp_srv_map_acls:
        cf_contents.append("\tmap acls = %s\n" % afp.afp_srv_map_acls)

    if afp.afp_srv_chmod_request:
        cf_contents.append("\tchmod request = %s\n" %
                           afp.afp_srv_chmod_request)

    if afp.afp_srv_map_acls == 'mode' and client.call(
            'notifier.common', 'system', 'activedirectory_enabled'):
        map_acls_mode = True

    if map_acls_mode:
        ad = Struct(client.call('notifier.directoryservice', 'AD'))

        cf_contents.append("\tldap auth method = %s\n" % "simple")
        cf_contents.append("\tldap auth dn = %s\n" % ad.binddn)
        cf_contents.append("\tldap auth pw = %s\n" % ad.bindpw)
        cf_contents.append("\tldap server = %s\n" % ad.domainname)

        # This should be configured when using this option
        if ad.userdn:
            cf_contents.append("\tldap userbase = %s\n" % ad.userdn)

        cf_contents.append("\tldap userscope = %s\n" % "sub")

        # This should be configured when using this option
        if ad.groupdn:
            cf_contents.append("\tldap groupbase = %s\n" % ad.groupdn)

        cf_contents.append("\tldap groupscope = %s\n" % "sub")

        cf_contents.append("\tldap user filter = %s\n" % "objectclass=user")
        cf_contents.append("\tldap group filter = %s\n" % "objectclass=group")
        cf_contents.append("\tldap uuid attr = %s\n" % "objectGUID")
        cf_contents.append("\tldap uuid encoding = %s\n" % "ms-guid")
        cf_contents.append("\tldap name attr = %s\n" % "sAMAccountName")
        cf_contents.append("\tldap group attr = %s\n" % "sAMAccountName")

    cf_contents.append("\n")

    for share in client.call('datastore.query', 'sharing.afp_share'):
        share = Struct(share)
        if share.afp_home:
            cf_contents.append("[Homes]\n")
            cf_contents.append("\tbasedir regex = %s\n" % share.afp_path)
            if share.afp_name and share.afp_name != "Homes":
                cf_contents.append("\thome name = %s\n" % share.afp_name)
        else:
            cf_contents.append("[%s]\n" % share.afp_name)
            cf_contents.append("\tpath = %s\n" % share.afp_path)
        if share.afp_allow:
            cf_contents.append("\tvalid users = %s\n" % share.afp_allow)
        if share.afp_deny:
            cf_contents.append("\tinvalid users = %s\n" % share.afp_deny)
        if share.afp_hostsallow:
            cf_contents.append("\thosts allow = %s\n" % share.afp_hostsallow)
        if share.afp_hostsdeny:
            cf_contents.append("\thosts deny = %s\n" % share.afp_hostsdeny)
        if share.afp_ro:
            cf_contents.append("\trolist = %s\n" % share.afp_ro)
        if share.afp_rw:
            cf_contents.append("\trwlist = %s\n" % share.afp_rw)
        if share.afp_timemachine:
            cf_contents.append("\ttime machine = yes\n")
        if not share.afp_nodev:
            cf_contents.append("\tcnid dev = no\n")
        if share.afp_nostat:
            cf_contents.append("\tstat vol = no\n")
        if not share.afp_upriv:
            cf_contents.append("\tunix priv = no\n")
        else:
            if share.afp_fperm and not map_acls_mode:
                cf_contents.append("\tfile perm = %s\n" % share.afp_fperm)
            if share.afp_dperm and not map_acls_mode:
                cf_contents.append("\tdirectory perm = %s\n" % share.afp_dperm)
            if share.afp_umask and not map_acls_mode:
                cf_contents.append("\tumask = %s\n" % share.afp_umask)
        cf_contents.append("\tveto files = .windows/.mac/\n")
        if map_acls_mode:
            cf_contents.append("\tacls = yes\n")
        # Do not fail if aux params are not properly entered by the user
        try:
            aux_params = [
                "\t{0}\n".format(p) for p in share.afp_auxparams.split("\n")
            ]
        except:
            pass
        else:
            cf_contents += aux_params
        # Update TimeMachine special files
        timemachine_supported_path = os.path.join(
            share.afp_path, ".com.apple.timemachine.supported")
        timemachine_quota_plist_path = os.path.join(
            share.afp_path, ".com.apple.TimeMachine.quota.plist")
        timemachine_quota_plist_managed_flag = os.path.join(
            share.afp_path,
            ".com.apple.TimeMachine.quota.plist.FreeNAS-managed")
        if share.afp_timemachine and share.afp_timemachine_quota:
            try:
                with open(timemachine_supported_path, "w"):
                    pass
            except IOError:
                pass

            try:
                with open(timemachine_quota_plist_path, "w") as f:
                    f.write(
                        textwrap.dedent("""\
                        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
                        <plist version="1.0">
                            <dict>
                                <key>GlobalQuota</key>
                                <integer>%d</integer>
                            </dict>
                        </plist>
                    """ % (share.afp_timemachine_quota * 1024 * 1024)))
            except IOError:
                pass

            try:
                with open(timemachine_quota_plist_managed_flag, "w") as f:
                    pass
            except IOError:
                pass

            try:
                stat = os.stat(share.afp_path)
                os.chmod(timemachine_supported_path, 0o644)
                os.chown(timemachine_supported_path, stat.st_uid, stat.st_gid)
                os.chmod(timemachine_quota_plist_path, 0o644)
                os.chown(timemachine_quota_plist_path, stat.st_uid,
                         stat.st_gid)
                os.chmod(timemachine_quota_plist_managed_flag, 0o644)
                os.chown(timemachine_quota_plist_managed_flag, stat.st_uid,
                         stat.st_gid)
            except IOError:
                pass
        else:
            if os.path.exists(timemachine_quota_plist_managed_flag):
                try:
                    os.unlink(timemachine_supported_path)
                except IOError:
                    pass

                try:
                    os.unlink(timemachine_quota_plist_path)
                except IOError:
                    pass

    with open(afp_config, "w") as fh:
        for line in cf_contents:
            fh.write(line)
Ejemplo n.º 35
0
def main():
    """Use the django ORM to generate a config file.  We'll build the
    config file as a series of lines, and once that is done write it
    out in one go"""

    map_acls_mode = False
    afp_config = "/usr/local/etc/afp.conf"
    cf_contents = []
    client = Client()

    afp = Struct(
        client.call('datastore.query', 'services.afp', None, {'get': True}))

    cf_contents.append("[Global]\n")
    uam_list = ['uams_dhx.so', 'uams_dhx2.so']
    if afp.afp_srv_guest:
        uam_list.append('uams_guest.so')
        cf_contents.append('\tguest account = %s\n' % afp.afp_srv_guest_user)
    # uams_gss.so bails out with an error if kerberos isn't configured
    if client.call('datastore.query', 'directoryservice.kerberoskeytab', None,
                   {'count': True}) > 0:
        uam_list.append('uams_gss.so')
    cf_contents.append('\tuam list = %s\n' % (" ").join(uam_list))

    if afp.afp_srv_bindip:
        cf_contents.append("\tafp listen = %s\n" %
                           ' '.join(afp.afp_srv_bindip))
        ifaces = get_interface(afp.afp_srv_bindip)
        cf_contents.append("\tafp interfaces = %s\n" % ' '.join(ifaces))
    cf_contents.append("\tmax connections = %s\n" %
                       afp.afp_srv_connections_limit)
    cf_contents.append("\tmimic model = RackMac\n")
    if afp.afp_srv_dbpath:
        cf_contents.append("\tvol dbnest = no\n")
        cf_contents.append("\tvol dbpath = %s\n" % afp.afp_srv_dbpath)
    else:
        cf_contents.append("\tvol dbnest = yes\n")
    if afp.afp_srv_global_aux:
        cf_contents.append("\t%s\n" % afp.afp_srv_global_aux)

    if afp.afp_srv_map_acls:
        cf_contents.append("\tmap acls = %s\n" % afp.afp_srv_map_acls)

    if afp.afp_srv_chmod_request:
        cf_contents.append("\tchmod request = %s\n" %
                           afp.afp_srv_chmod_request)

    if afp.afp_srv_map_acls == 'mode' and client.call(
            'notifier.common', 'system', 'activedirectory_enabled'):
        map_acls_mode = True

    if map_acls_mode:
        ad = Struct(client.call('notifier.directoryservice', 'AD'))

        cf_contents.append("\tldap auth method = %s\n" % "simple")
        cf_contents.append("\tldap auth dn = %s\n" % ad.binddn)
        cf_contents.append("\tldap auth pw = %s\n" % ad.bindpw)
        cf_contents.append("\tldap server = %s\n" % ad.domainname)

        # This should be configured when using this option
        if ad.userdn:
            cf_contents.append("\tldap userbase = %s\n" % ad.userdn)

        cf_contents.append("\tldap userscope = %s\n" % "sub")

        # This should be configured when using this option
        if ad.groupdn:
            cf_contents.append("\tldap groupbase = %s\n" % ad.groupdn)

        cf_contents.append("\tldap groupscope = %s\n" % "sub")

        cf_contents.append("\tldap user filter = %s\n" % "objectclass=user")
        cf_contents.append("\tldap group filter = %s\n" % "objectclass=group")
        cf_contents.append("\tldap uuid attr = %s\n" % "objectGUID")
        cf_contents.append("\tldap uuid encoding = %s\n" % "ms-guid")
        cf_contents.append("\tldap name attr = %s\n" % "sAMAccountName")
        cf_contents.append("\tldap group attr = %s\n" % "sAMAccountName")

    cf_contents.append("\n")

    if afp.afp_srv_homedir_enable:
        cf_contents.append("[Homes]\n")
        cf_contents.append("\tbasedir regex = %s\n" % afp.afp_srv_homedir)
        if afp.afp_srv_homename:
            cf_contents.append("\thome name = %s\n" % afp.afp_srv_homename)
        if afp.afp_srv_hometimemachine:
            cf_contents.append(f"\ttime machine = yes\n")
        cf_contents.append("\n")

    for share in client.call('datastore.query', 'sharing.afp_share'):
        share = Struct(share)
        cf_contents.append("[%s]\n" % share.afp_name)
        cf_contents.append("\tpath = %s\n" % share.afp_path)
        if share.afp_allow:
            cf_contents.append("\tvalid users = %s\n" % share.afp_allow)
        if share.afp_deny:
            cf_contents.append("\tinvalid users = %s\n" % share.afp_deny)
        if share.afp_hostsallow:
            cf_contents.append("\thosts allow = %s\n" % share.afp_hostsallow)
        if share.afp_hostsdeny:
            cf_contents.append("\thosts deny = %s\n" % share.afp_hostsdeny)
        if share.afp_ro:
            cf_contents.append("\trolist = %s\n" % share.afp_ro)
        if share.afp_rw:
            cf_contents.append("\trwlist = %s\n" % share.afp_rw)
        if share.afp_timemachine:
            cf_contents.append("\ttime machine = yes\n")
        if not share.afp_nodev:
            cf_contents.append("\tcnid dev = no\n")
        if share.afp_nostat:
            cf_contents.append("\tstat vol = no\n")
        if not share.afp_upriv:
            cf_contents.append("\tunix priv = no\n")
        else:
            if share.afp_fperm and not map_acls_mode:
                cf_contents.append("\tfile perm = %s\n" % share.afp_fperm)
            if share.afp_dperm and not map_acls_mode:
                cf_contents.append("\tdirectory perm = %s\n" % share.afp_dperm)
            if share.afp_umask and not map_acls_mode:
                cf_contents.append("\tumask = %s\n" % share.afp_umask)
        cf_contents.append("\tveto files = .windows/.mac/\n")
        if map_acls_mode:
            cf_contents.append("\tacls = yes\n")
        # Do not fail if aux params are not properly entered by the user
        try:
            aux_params = [
                "\t{0}\n".format(p) for p in share.afp_auxparams.split("\n")
            ]
        except:
            pass
        else:
            cf_contents += aux_params

    with open(afp_config, "w") as fh:
        for line in cf_contents:
            fh.write(line)
Ejemplo n.º 36
0
def generate_smb4_conf(client, smb4_conf, role):
    cifs = Struct(client.call('smb.config'))

    if not cifs.guest:
        cifs.guest = 'ftp'
    if not cifs.filemask:
        cifs.filemask = "0666"
    if not cifs.dirmask:
        cifs.dirmask = "0777"

    # standard stuff... should probably do this differently
    confset1(smb4_conf, "[global]", space=0)

    if os.path.exists("/usr/local/etc/smbusers"):
        confset1(smb4_conf, "username map = /usr/local/etc/smbusers")

    confset2(smb4_conf, "server min protocol = %s", cifs.min_protocol)
    confset2(smb4_conf, "server max protocol = %s", cifs.max_protocol)
    if cifs.bindip:
        interfaces = []

        bindips = ' '.join(cifs.bindip)
        if role != 'dc':
            bindips = "127.0.0.1 %s" % bindips

        bindips = bindips.split()
        for bindip in bindips:
            if not bindip:
                continue
            bindip = bindip.strip()
            iface = client.call('notifier.get_interface', bindip)

            is_carp_interface = False
            if iface:
                try:
                    is_carp_interface = client.call('notifier.is_carp_interface', iface)
                except:
                    pass

            if iface and is_carp_interface:
                parent_iface = client.call('notifier.get_parent_interface', iface)
                if not parent_iface:
                    continue

                parent_iinfo = client.call('notifier.get_interface_info', parent_iface[0])
                if not parent_iinfo:
                    continue

                interfaces.append("%s/%s" % (bindip, parent_iface[2]))
            else:
                interfaces.append(bindip)

        if interfaces:
            confset2(smb4_conf, "interfaces = %s", ' '.join(interfaces))
        confset1(smb4_conf, "bind interfaces only = yes")

    confset1(smb4_conf, "encrypt passwords = yes")
    confset1(smb4_conf, "dns proxy = no")
    confset1(smb4_conf, "strict locking = no")
    confset1(smb4_conf, "oplocks = yes")
    confset1(smb4_conf, "deadtime = 15")
    confset1(smb4_conf, "max log size = 51200")

    confset2(smb4_conf, "max open files = %d",
             int(get_sysctl('kern.maxfilesperproc')) - 25)

    if cifs.loglevel and cifs.loglevel is not True:
        loglevel = cifs.loglevel
    else:
        loglevel = "0"

    if cifs.syslog:
        confset1(smb4_conf, "logging = syslog:%s" % loglevel)
    else:
        confset1(smb4_conf, "logging = file")

    confset1(smb4_conf, "load printers = no")
    confset1(smb4_conf, "printing = bsd")
    confset1(smb4_conf, "printcap name = /dev/null")
    confset1(smb4_conf, "disable spoolss = yes")
    confset1(smb4_conf, "getwd cache = yes")
    confset2(smb4_conf, "guest account = %s", cifs.guest)
    confset1(smb4_conf, "map to guest = Bad User")
    confset2(smb4_conf, "obey pam restrictions = %s",
             "yes" if cifs.obey_pam_restrictions else "no")
    confset2(smb4_conf, "ntlm auth = %s",
             "yes" if cifs.ntlmv1_auth else "no")
    confset1(smb4_conf, "directory name cache size = 0")
    confset1(smb4_conf, "kernel change notify = no")

    confset1(smb4_conf,
             "panic action = /usr/local/libexec/samba/samba-backtrace")
    confset1(smb4_conf, "nsupdate command = /usr/local/bin/samba-nsupdate -g")

    confset2(smb4_conf, "server string = %s", cifs.description)
    confset1(smb4_conf, "ea support = yes")
    confset1(smb4_conf, "store dos attributes = yes")
    confset1(smb4_conf, "lm announce = yes")
    confset2(smb4_conf, "hostname lookups = %s",
             "yes" if cifs.hostlookup else False)
    confset2(smb4_conf, "unix extensions = %s",
             "no" if not cifs.unixext else False)
    confset2(smb4_conf, "time server = %s",
             "yes" if cifs.timeserver else False)
    confset2(smb4_conf, "null passwords = %s",
             "yes" if cifs.nullpw else False)
    confset2(smb4_conf, "acl allow execute always = %s",
             "true" if cifs.allow_execute_always else "false")
    confset1(smb4_conf, "dos filemode = yes")
    confset2(smb4_conf, "multicast dns register = %s",
             "yes" if cifs.zeroconf else "no")

    if not smb4_ldap_enabled(client):
        confset2(smb4_conf, "domain logons = %s",
                 "yes" if cifs.domain_logons else "no")

    if not client.call('notifier.common', 'system', 'activedirectory_enabled'):
        confset2(smb4_conf, "local master = %s",
                 "yes" if cifs.localmaster else "no")

    if not smb4_autorid_enabled(client):
        # 5 = DS_TYPE_CIFS
        idmap = Struct(client.call('notifier.ds_get_idmap_object', 5, cifs.id, 'tdb'))
        configure_idmap_backend(client, smb4_conf, idmap, None)

    if role == 'auto':
        confset1(smb4_conf, "server role = auto")

    elif role == 'classic':
        confset1(smb4_conf, "server role = classic primary domain controller")

    elif role == 'netbios':
        confset1(smb4_conf, "server role = netbios backup domain controller")

    elif role == 'dc':
        confset1(smb4_conf, "server role = active directory domain controller")
        add_domaincontroller_conf(client, smb4_conf)

    elif role == 'member':
        confset1(smb4_conf, "server role = member server")

        if smb4_ldap_enabled(client):
            add_ldap_conf(client, smb4_conf)

        elif client.call('notifier.common', 'system', 'activedirectory_enabled'):
            add_activedirectory_conf(client, smb4_conf)

        confset2(smb4_conf, "netbios name = %s", cifs.netbiosname.upper())
        if cifs.netbiosalias:
            confset2(smb4_conf, "netbios aliases = %s", cifs.netbiosalias.upper())

    elif role == 'standalone':
        confset1(smb4_conf, "server role = standalone")
        confset2(smb4_conf, "netbios name = %s", cifs.netbiosname.upper())
        if cifs.netbiosalias:
            confset2(smb4_conf, "netbios aliases = %s", cifs.netbiosalias.upper())
        confset2(smb4_conf, "workgroup = %s", cifs.workgroup.upper())
        confset1(smb4_conf, "security = user")

    confset2(smb4_conf, "create mask = %s", cifs.filemask)
    confset2(smb4_conf, "directory mask = %s", cifs.dirmask)
    confset2(smb4_conf, "client ntlmv2 auth = %s",
             "yes" if not cifs.ntlmv1_auth else "no")
    confset2(smb4_conf, "dos charset = %s", cifs.doscharset)
    confset2(smb4_conf, "unix charset = %s", cifs.unixcharset)

    if cifs.loglevel and cifs.loglevel is not True:
        confset2(smb4_conf, "log level = %s", cifs.loglevel)

    smb_options = cifs.smb_options.strip()
    for line in smb_options.split('\n'):
        line = line.strip()
        if not line:
            continue
        confset1(smb4_conf, line)