HW4

LDAP Server

LDAP server IP: 192.168.14.8
Workstation IP: 192.168.14.9

  • Install packages
sudo apt update
sudo apt install slapd ldap-utils rsyslog sudo-ldap
  • Trust the certs
sudo vim /usr/local/share/ca-certificates/ldap.crt
sudo update-ca-certificates
  • Cert & key permission
-rw------- 1 openldap openldap 1704 May 14 14:05 ldap.key
-rw-r--r-- 1 openldap openldap 3160 May 14 14:05 ldap.pem
  • Configure LDAPS
sudo dpkg-reconfigure slapd

vim /etc/ldap/ldaps.ldif
# dn: cn=config
# changetype: modify
# add: olcTLSCACertificateFile
# olcTLSCACertificateFile: /etc/ssl/certs/ca-certificates.crt
# -
# add: olcTLSCertificateKeyFile
# olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap.key
# -
# add: olcTLSCertificateFile
# olcTLSCertificateFile: /etc/ldap/ssl/ldap.pem

ldapmodify -Y EXTERNAL -H ldapi:/// -f ldaps.ldif
  • LDAPS and force TLS search
sudo vim /etc/default/slapd
# SLAPD_SERVICES="ldapi:/// ldaps:///"
  • Set ou
vim /etc/ldap/baseou.ldif
# dn: ou=People,dc=14,dc=nasa
# objectClass: organizationalUnit
# ou: People

# dn: ou=Group,dc=14,dc=nasa
# objectClass: organizationalUnit
# ou: Group

# dn: ou=Ppolicy,dc=14,dc=nasa
# objectClass: organizationalUnit
# ou: Ppolicy

# dn: ou=SUDOers,dc=14,dc=nasa
# objectClass: organizationalUnit
# ou: SUDOers

# dn: ou=Fortune,dc=14,dc=nasa
# objectClass: organizationalUnit
# ou: Fortune

ldapadd -x -H ldapi:/// -D "cn=admin,dc=14,dc=nasa" -W -f baseou.ldif
  • Set groups
vim /etc/ldap/group.ldif
# dn: cn=ta,ou=Group,dc=14,dc=nasa
# objectClass: posixGroup
# cn: ta
# gidNumber: 10000

# dn: cn=stu,ou=Group,dc=14,dc=nasa
# objectClass: posixGroup
# cn: stu
# gidNumber: 20000

ldapadd -x -H ldapi:/// -D cn=admin,dc=14,dc=nasa -W -f group.ldif
  • Add sudoer schema
sudo vim /etc/ldap/schema/sudo.ldif
# dn: cn=sudo,cn=schema,cn=config
# objectClass: olcSchemaConfig
# cn: sudo
# olcAttributeTypes: {0}( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may  run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
# olcAttributeTypes: {1}( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
# olcAttributeTypes: {2}( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
# olcAttributeTypes: {3}( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
# olcAttributeTypes: {4}( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
# olcAttributeTypes: {5}( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
# olcAttributeTypes: {6}( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
# olcAttributeTypes: {7}( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'Start of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
# olcAttributeTypes: {8}( 1.3.6.1.4.1.15953.9.1.9 NAME 'sudoNotAfter' DESC 'End of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
# olcAttributeTypes: {9}( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'an integer to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
# olcObjectClasses: {0}( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' DESC 'Sudoer Entries' SUP top STRUCTURAL MUST cn MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ description ) )

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/sudo.ldif
  • Set sudoer
vim /etc/ldap/sudoer.ldif
# dn: cn=ta,ou=SUDOers,dc=14,dc=nasa
# objectClass: sudoRole
# cn: ta
# sudoUser: %ta
# sudoHost: ALL
# sudoCommand: ALL

# dn: cn=stu,ou=SUDOers,dc=14,dc=nasa
# objectClass: sudoRole
# cn: stu
# sudoUser: %stu
# sudoHost: ALL
# sudoCommand: /usr/bin/ls

ldapadd -x -H ldapi:/// -D cn=admin,dc=14,dc=nasa -W -f sudoer.ldif
  • Get hash password
slappasswd -s {your_password}
# {SSHA}cRlbt/snhxEwgG56xKCqjWLY0zZZclNU
  • Add ldap publickey schema
vim /etc/ldap/schema/openssh-lpk.ldif
# dn: cn=openssh-lpk,cn=schema,cn=config
# objectClass: olcSchemaConfig
# cn: openssh-lpk
# olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DESC 'OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
# olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' DESC 'OpenSSH LPK objectclass' SUP top AUXILIARY MUST ( sshPublicKey $ uid ) )

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/openssh-lpk.ldif
  • Set user
vim /etc/ldap/users.ldif
# dn: uid=generalta,ou=People,dc=14,dc=nasa
# objectClass: posixAccount
# objectClass: ldapPublicKey
# objectClass: account
# cn: generalta
# uid: generalta
# uidNumber: 10000
# gidNumber: 10000
# homeDirectory: /home/generalta
# loginShell: /bin/bash
# userPassword: {SSHA}cRlbt/snhxEwgG56xKCqjWLY0zZZclNU
# sshPublicKey: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFfg2DMY3DfBBvZCnqN8Az5tUnVQca+qXkJ9HceOcRAy 2025-na-hw4

# dn: uid=stu14,ou=People,dc=14,dc=nasa
# objectClass: posixAccount
# objectClass: ldapPublicKey
# objectClass: account
# cn: stu14
# uid: stu14
# uidNumber: 20014
# gidNumber: 20000
# homeDirectory: /home/stu14
# loginShell: /bin/bash
# userPassword: {SSHA}cRlbt/snhxEwgG56xKCqjWLY0zZZclNU
# sshPublickey: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFfg2DMY3DfBBvZCnqN8Az5tUnVQca+qXkJ9HceOcRAy 2025-na-hw4

ldapadd -x -H ldapi:/// -D cn=admin,dc=14,dc=nasa -W -f users.ldif
  • ACL
vim /etc/ldap/access.ldif
# dn: olcDatabase={1}mdb,cn=config
# changetype: modify
# replace: olcAccess
# olcAccess: to attrs=userPassword
#   by dn.exact="uid=generalta,ou=People,dc=14,dc=nasa" =mwscdx
#   by self write
#   by anonymous auth
#   by * none
# olcAccess: to attrs=loginShell,sshPublicKey
#   by dn.exact="cn=admin,dc=14,dc=nasa" manage
#   by dn.exact="uid=generalta,ou=People,dc=14,dc=nasa" manage
#   by self write
#   by * read
# olcAccess: to dn.subtree="ou=People,dc=14,dc=nasa"
#   by dn.exact="cn=admin,dc=14,dc=nasa" manage
#   by dn.exact="uid=generalta,ou=People,dc=14,dc=nasa" manage
#   by * read
# olcAccess: to dn.subtree="ou=Group,dc=14,dc=nasa"
#   by dn.exact="cn=admin,dc=14,dc=nasa" manage
#   by dn.exact="uid=generalta,ou=People,dc=14,dc=nasa" manage
#   by * read
# olcAccess: to attrs=shadowLastChange
#   by self write 
#   by * read
# olcAccess: to *
#   by * read

ldapmodify -Y EXTERNAL -H ldapi:/// -f access.ldif
  • Modify some entry (e.g. password)
vim modify.ldif
# dn: uid=generalta,ou=People,dc=14,dc=nasa
# changetype: modify
# replace: userPassword
# userPassword: {SSHA}cRlbt/snhxEwgG56xKCqjWLY0zZZclNU

sudo ldapmodify -x -H ldapi:/// -D cn=admin,dc=14,dc=nasa -W -f modify.ldif
  • Install ppolicy module (source)
sudo apt install libpwquality-dev cracklib-runtime libdb-dev 

apt-get source slapd
cd openldap-2.5.13+dfsg

./configure
make depend

vim /etc/ldap/pwquality.conf
# minlen = 8
# minclass = 3

cd /tmp
git clone https://github.com/isarandi/openldap-check-pwquality.git
cd openldap-check-pwquality
sudo make install LDAP_SRC=/root/openldap-2.5.13+dfsg CONFIG_PATH=/etc/ldap/pwquality.conf LDAP_LIBDIR=/usr/lib/ldap

cd /tmp
git clone https://github.com/cracklib/cracklib.git
cd cracklib/words
make
sudo cp cracklib-words /etc/cracklib/
sudo sed -i 's/cracklib_dictpath_src=""/cracklib_dictpath_src="\/etc\/cracklib\/cracklib-words"/' /etc/cracklib/cracklib.conf
sudo update-cracklib
sudo cp /var/cache/cracklib/cracklib_dict* /etc/ldap/
echo 'dictpath = /etc/ldap/cracklib_dict' | sudo tee -a /etc/ldap/pwquality.conf

ls /usr/lib/ldap/check_pwquality.so
  • log
ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats config acl args trace
EOF
  • Password policy
ldapadd -Y EXTERNAL -H ldapi:/// <<EOF
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy.la
EOF

vim /etc/ldap/overlay.ldif
# dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config
# objectClass: olcOverlayConfig
# objectClass: olcPPolicyConfig
# olcOverlay: ppolicy
# olcPPolicyDefault: cn=default,ou=Ppolicy,dc=14,dc=nasa

ldapadd -Y EXTERNAL -H ldapi:/// -f overlay.ldif

vim /etc/ldap/ppolicy.ldif
# dn: cn=default,ou=Ppolicy,dc=14,dc=nasa
# objectClass: organizationalRole
# objectClass: pwdPolicy
# objectClass: pwdPolicyChecker
# cn: default
# pwdAttribute: userPassword
# pwdAllowUserChange: TRUE
# pwdMinLength: 8
# pwdInHistory: 1
# pwdCheckQuality: 2
# pwdCheckModule: check_pwquality.so

ldapadd -x -H ldapi:/// -D "cn=admin,dc=14,dc=nasa" -W -f ppolicy.ldif

vim /etc/ldap/modify.ldif
# dn: uid=generalta,ou=People,dc=14,dc=nasa
# changetype: modify
# add: pwdPolicySubentry
# pwdPolicySubentry: cn=default,ou=Ppolicy,dc=14,dc=nasa

# dn: uid=stu14,ou=People,dc=14,dc=nasa
# changetype: modify
# add: pwdPolicySubentry
# pwdPolicySubentry: cn=default,ou=Ppolicy,dc=14,dc=nasa

ldapmodify -x -H ldapi:/// -D cn=admin,dc=14,dc=nasa -W -f modify.ldif
  • Test
slappasswd -s {yourPassword}

vim /etc/ldap/test.ldif
# dn: uid=test,ou=People,dc=14,dc=nasa
# objectClass: posixAccount
# objectClass: account
# cn: test
# uid: test
# uidNumber: 30000
# gidNumber: 10000
# homeDirectory: /home/test
# loginShell: /bin/bash
# userPassword: {SSHA}cKTeeev5+wQNgO1+Z4y9NDUqYVuCAW4/

ldapadd -x -H ldapi:/// -D uid=generalta,ou=People,dc=14,dc=nasa -W -f test.ldif

vim /etc/ldap/modify.ldif
# dn: uid=test,ou=People,dc=14,dc=nasa
# changetype: modify
# replace: userPassword
# userPassword: {SSHA}cKTeeev5+wQNgO1+Z4y9NDUqYVuCAW4/

ldapmodify -x -H ldapi:/// -D uid=generalta,ou=People,dc=14,dc=nasa -W -f modify.ldif
  • Add ObjectClass fortune
vim /etc/ldap/schema/fortune.ldif
# dn: cn=fortune,cn=schema,cn=config
# objectClass: olcSchemaConfig
# cn: fortune
# olcAttributeTypes: {0}( 2.25.20250524.1.1 NAME 'author' DESC 'author' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch ORDERING caseIgnoreOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
# olcAttributeTypes: {1}( 2.25.20250524.1.2 NAME 'id' DESC 'id' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
# olcObjectClasses: {0}( 2.25.20250524.2.1 NAME 'fortune' DESC 'fortune' SUP top STRUCTURAL MUST cn MAY ( author $ id $ description ) )

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/fortune.ldif

ldapsearch -H ldapi:/// -Y EXTERNAL -b cn={6}fortune,cn=schema,cn=config
  • Convert yml to ldif
import yaml

with open('hw4fortunes.yml', 'r') as file:
    entries = yaml.safe_load(file)

with open('hw4fortunes.ldif', 'w') as ldif:
    for entry in entries:
        id_value = entry.get('ID')
        author = entry.get('Author')
        description = entry.get('Description')

        dn = f"dn: cn=fortune-{id_value},ou=Fortune,dc=14,dc=nasa\n"
        obj_classes = "objectClass: fortune\nobjectClass: top\n"
        cn = f"cn: fortune-{id_value}\n"
        author_field = f"author: {author}\n"
        id_field = f"id: {id_value}\n"
        description_field = f"description: {description}\n"

        ldif_entry = dn + obj_classes + cn + author_field + id_field + description_field + "\n"
        ldif.write(ldif_entry) 
ldapadd -H ldapi:/// -x -D "cn=admin,dc=14,dc=nasa" -W -f hw4fortunes.ldif
  • sssvlv
ldapadd -Y EXTERNAL -H ldapi:/// <<EOF
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: sssvlv.la
EOF

vim /etc/ldap/sssvlv.ldif
# dn: olcOverlay=sssvlv,olcDatabase={1}mdb,cn=config
# objectClass: olcOverlayConfig
# objectClass: olcSssVlvConfig
# olcOverlay: sssvlv
# olcSssVlvMax: 10
# olcSssVlvMaxKeys: 5

ldapadd -Y EXTERNAL -H ldapi:/// -f sssvlv.ldif

ldapsearch -Y EXTERNAL -H ldapi:/// -b "ou=fortune,dc=14,dc=nasa"

Bonus - Mail server

  • Setting
sudo apt-get update
sudo apt-get install postfix-ldap dovecot-ldap

sudo vim /etc/dovecot/conf.d/10-auth.conf
# !include auth-ldap.conf.ext

sudo vim /etc/dovecot/conf.d/auth-ldap.conf.ext
# passdb {
#   driver = ldap
#   args = /etc/dovecot/dovecot-ldap.conf.ext
# }

# userdb {
#   driver = ldap
#   args = /etc/dovecot/dovecot-ldap.conf.ext
# }

sudo vim /etc/dovecot/dovecot-ldap.conf.ext
# hosts = ldap.14.nasa:636
# dn = cn=admin,dc=14,dc=nasa
# dnpass = 0000
# base = ou=People,dc=14,dc=nasa
# scope = subtree
# auth_bind = yes
# ldap_version = 3

# user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid
# user_filter = (&(objectClass=posixAccount)(uid=%u))
# pass_filter = (&(objectClass=posixAccount)(uid=%u))

sudo vim /etc/postfix/main.cf
# smtpd_sender_login_maps = hash:/etc/postfix/login_maps, ldap:/etc/postfix/ldap.cf

vim /etc/postfix/ldap.cf
# server_host = ldap.14.nasa:636
# search_base = ou=People,dc=14,dc=nasa
# version = 3

sudo systemctl restart postfix
sudo systemctl restart dovecot
  • Restart service & Check the config
slaptest -u

sudo systemctl restart slapd

sudo slapcat -n 0
ldapsearch -H ldapi:/// -Y EXTERNAL -b "cn=config" -LLL -Q -s base
ldapsearch -H ldapi:/// -x -b "dc=14,dc=nasa"
ldapsearch -H ldapi:/// -x -b "dc=14,dc=nasa" ou
ldapsearch -H ldapi:/// -x -b "ou=People,dc=14,dc=nasa"

LDAP client

5E842AEEEDB8F6EA8857E6D1FB72E76E

  • Trust the certs
sudo vim /usr/local/share/ca-certificates/ldap.crt
sudo update-ca-certificates
sudo apt install sssd libnss-sss libsss-sudo libpam-sss sssd-ldap ldap-utils -y

sudo vim /etc/sssd/sssd.conf
# [sssd]
# services = nss, pam, sudo
# config_file_version = 2
# domains = ldap

# [nss]
# default_shell = /bin/bash

# [domain/ldap]
# id_provider = ldap
# auth_provider = ldap
# chpass_provider = ldap
# access_provider = ldap

# ldap_uri = ldaps://ldap.14.nasa
# ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt
# ldap_search_base = dc=14,dc=nasa
# ldap_user_shell = loginShell
# ldap_sudo_search_base = ou=SUDOers,dc=14,dc=nasa
# ldap_user_ssh_public_key = sshPublicKey

# ldap_user_object_class = posixAccount
# ldap_group_object_class = posixGroup
# ldap_user_home_directory = homeDirectory

# ldap_access_order = filter
# ldap_access_filter = (|(gidNumber=10000)(gidNumber=20000))

sudo chmod 600 /etc/sssd/sssd.conf

sudo vim /etc/nsswitch.conf

sudo pam-auth-update --enable mkhomedir
sudo vim /etc/pam.d/common-session
# session required pam_mkhomedir.so skel=/etc/skel umask=077

sudo vim /etc/ssh/sshd_config
# AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys
# AuthorizedKeysCommandUser nobody

sudo systemctl enable sssd
sudo systemctl restart sssd
sudo systemctl restart sshd
sudo systemctl status sssd