Compare commits

...

8 Commits
main ... debian

Author SHA1 Message Date
8dc358ded5 Added phplogin.php 2025-12-18 09:24:35 -05:00
326895dffd Delete index.php 2025-12-18 08:04:08 -05:00
6b0742634c phplogin TLS test 2025-12-18 08:03:52 -05:00
45564fa83e Small fixes from Ubuntu 22 -> Debian 12 switch 2025-12-18 07:25:35 -05:00
162951d6dd Small fixes from Ubuntu 22 -> Debian 12 switch 2025-12-18 07:25:02 -05:00
d3c54dd9bc Delete index.php.tls 2025-12-14 14:00:51 -05:00
512f07eb25 Update INSTALL.md 2025-12-14 14:00:34 -05:00
8beb4b6055 Changed from Ubuntu 22 to Debian 12 2025-12-14 15:19:28 -03:00
7 changed files with 252 additions and 141 deletions

View File

@ -366,26 +366,65 @@ root@example:/etc/ldap/certs# export LDAPTLS_CACERT=/etc/ldap/certs/ca-cert.pem
root@example:/etc/ldap/certs# echo 'export LDAPTLS_CACERT=/etc/ldap/certs/ca-cert.pem' >> ~/.bashrc root@example:/etc/ldap/certs# echo 'export LDAPTLS_CACERT=/etc/ldap/certs/ca-cert.pem' >> ~/.bashrc
root@example:/etc/ldap/certs# source ~/.bashrc root@example:/etc/ldap/certs# source ~/.bashrc
``` ```
\ ## _6- Connect to OpenLDAP server via StartTLS/SSL_
Check STARTTLS
```
root@example:/etc/ldap/certs# ldapwhoami -x -ZZ -H ldap://${LDAP_HOST}
```
Check SSL/ldaps
```
root@example:/etc/ldap/certs# ldapwhoami -x -H ldaps://${LDAP_HOST}
```
Both should return Anonymous.
Another example to try STARTTLS/ldap it is working: Vital checks of different levels to test **openLDAP's StartTLS and SSL**:\
1.Check StartTLS and SSL, both should output "anonymous"
``` ```
openssl s_client -connect ${LDAP_HOST}:389 -starttls ldap -servername ${LDAP_HOST} root@example:/# ldapwhoami -x -ZZ -H ldap://${LDAP_HOST}
anonymous
root@example:/# ldapwhoami -x -H ldaps://${LDAP_HOST}
anonymous
``` ```
SSL/ldaps \
2.Check direct connection via openssl to confirm certificates are working properly:
``` ```
openssl s_client -connect ${LDAP_HOST}:636 -servername ${LDAP_HOST} root@example:/# openssl s_client -connect ${LDAP_HOST}:389 -starttls ldap -servername ${LDAP_HOST} #StartTLS
CONNECTED(00000003)
depth=1 CN = Example Company CA
verify return:1
depth=0 O = Example Company, CN = example.com
verify return:1
...
SSL handshake has read 2977 bytes and written 424 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
root@example:/# openssl s_client -connect ${LDAP_HOST}:636 -servername ${LDAP_HOST} #SSL
CONNECTED(00000003)
depth=1 CN = Example Company CA
verify return:1
depth=0 O = Example Company, CN = example.com
verify return:1
...
SSL handshake has read 2963 bytes and written 393 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
```
The output of both of these commands should be similar. Also, both will show the openLDAP's server CN (example.com in this case). You can terminate the connection with Ctrl+C.
3.A very important check is to make sure connections as users from the OpenLDAP's tree other than admin works:
```
root@example:/# ldapwhoami -x -D "uid=marisa,ou=People,dc=example,dc=com" -w MarisaNewPass2025 -H ldap://127.0.0.1 #StartTLS
dn:uid=marisa,ou=People,dc=example,dc=com
root@example:/# ldapwhoami -x -D "uid=marisa,ou=People,dc=example,dc=com" -w MarisaNewPass2025 -H ldap://127.0.0.1 #SSL
dn:uid=marisa,ou=People,dc=example,dc=com
``` ```
Both will show the connection to the openLDAP server showing the CN(dc=example,dc=com)
To connect to the server via `STARTTLS`, use port 389, to connect to the server via `SSL`, use port 636, both auth method Simple. To connect to the server via `STARTTLS`, use port 389, to connect to the server via `SSL`, use port 636, both auth method Simple.
If asked, accept the certificate as with any certificate, or copy the CA file that resides inside ldapdock from out of the container to our host system certificate trust directory (/usr/local/share/ca-certificates/ works for any Debian based distribution): If asked, accept the certificate as with any certificate, or copy the CA file that resides inside ldapdock from out of the container to our host system certificate trust directory (/usr/local/share/ca-certificates/ works for any Debian based distribution):
@ -395,5 +434,9 @@ If asked, accept the certificate as with any certificate, or copy the CA file th
> sudo update-ca-certificates > sudo update-ca-certificates
``` ```
In both cases, providing -h ${LDAP_HOST}, by default the login "user" and password are:\ In both cases, providing -h ${LDAP_HOST}, by default the login "user" and password are:\
BIND DN=cn=admin,dc=example,dc=com\ As admin:
BIND DN="cn=admin,dc=example,dc=com"\
BIND password=admin BIND password=admin
As marisa:
BIND DN="uid=marisa,ou=People,dc=example,dc=com"\
BIND password=MarisaNewPass2025

29
docker-compose.yml Normal file
View File

@ -0,0 +1,29 @@
version: '3.8'
services:
ldap:
# Tells Compose to build the image from the Dockerfile in the current directory
build:
context: .
args:
- LDAP_HOST=example.com
image: ldapdock
container_name: ldapdock
hostname: example.com
stdin_open: true # Equivalent of -i
tty: true # Equivalent of -t
ports:
- "389:389"
- "636:636"
- "80:80"
- "443:443"
volumes:
- ldap_data:/var/lib/ldap
- ldap_config:/etc/ldap/slapd.d
- ldap_certs:/etc/ldap/certs
- ./hosts-certs:/export-certs
volumes:
ldap_data:
ldap_config:
ldap_certs:

View File

@ -1,4 +1,4 @@
FROM ubuntu:22.04 FROM debian:12
# set container hostname and DN in case we don't set it on the docker build/run command # set container hostname and DN in case we don't set it on the docker build/run command
ARG LDAP_HOST=example.com ARG LDAP_HOST=example.com
@ -6,20 +6,25 @@ ENV LDAP_HOST=${LDAP_HOST}
# set non-interactive TERM for docker # set non-interactive TERM for docker
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
#──────────────────────────────────────────────────────────────
# install OpenLDAP, ldap-utils, and packages needed for ldapdock to work
#──────────────────────────────────────────────────────────────
RUN apt-get update && apt-get install -y --no-install-recommends \
slapd ldap-utils gnutls-bin ssl-cert ca-certificates schema2ldif vim mc && apt-get clean
#────────────────────────────────────────────────────────────── #──────────────────────────────────────────────────────────────
# APACHE && PHP && neccesary related software # Install ALL necessary packages in a single run for minimal image size
#────────────────────────────────────────────────────────────── #──────────────────────────────────────────────────────────────
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends gnupg lsb-release ca-certificates apt-transport-https software-properties-common wget curl \
# Add the Ondřej Surý PHP repository (modern Debian way)
&& wget -qO- https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/sury-php-archive-keyring.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/sury-php-archive-keyring.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list \
# Update package lists again to include the new PHP repo
&& apt-get update \
# Install all required packages, using PHP 8.1 from the Surý repo
&& apt-get install -y --no-install-recommends \
apt-utils \
slapd ldap-utils gnutls-bin ssl-cert schema2ldif vim mc \
apache2 \ apache2 \
php libapache2-mod-php \ php8.1 libapache2-mod-php8.1 \
php-ldap php-mbstring php-xml php-curl php-intl wget \ php8.1-ldap php8.1-mbstring php8.1-xml php8.1-curl php8.1-intl \
&& rm -rf /var/lib/apt/lists/* # Clean up APT caches to keep the image small
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Enable required Apache modules # Enable required Apache modules
RUN a2enmod rewrite headers ssl RUN a2enmod rewrite headers ssl

View File

@ -37,7 +37,8 @@ slapd -h "ldap:/// ldapi:///" -u openldap -g openldap &
SLAPD_PID=$! SLAPD_PID=$!
sleep 8 sleep 8
# Full tree with root entry # Full tree with root and users entries
echo "--> Creating base.ldif with root and user entries"
cat > /tmp/base.ldif <<EOF cat > /tmp/base.ldif <<EOF
dn: ${LDAP_BASE_DN} dn: ${LDAP_BASE_DN}
objectClass: top objectClass: top
@ -75,9 +76,98 @@ homeDirectory: /home/marisa
gecos: Marisa Kirisame gecos: Marisa Kirisame
EOF EOF
# Create phplogin.php with dynamic base DN
echo "--> Creating phplogin.php with full users support"
cat > /var/www/html/phplogin.php <<'EOF'
<?php
// Use the same logic as entrypoint.sh, but with better localhost handling
$raw_host = $_SERVER['HTTP_HOST'] ?? 'example.com';
$raw_host = preg_replace('/:\d+$/', '', $raw_host); // strip port if present
if ($raw_host === 'localhost' || $raw_host === '127.0.0.1') {
// When testing locally via http://localhost → assume default example.com
$base_dn = 'dc=example,dc=com';
} else {
// Normal case: build dc=... from real hostname
$host_parts = explode('.', $raw_host);
$base_dn = '';
foreach ($host_parts as $part) {
if ($part) $base_dn .= ($base_dn ? ',' : '') . 'dc=' . $part;
}
if (!$base_dn) $base_dn = 'dc=example,dc=com'; // ultimate fallback
}
$msg = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
if ($username && $password) {
$ldap = ldap_connect("ldap://127.0.0.1:389");
if ($ldap) {
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
if (ldap_start_tls($ldap)) {
// First: try admin bind (no ou=People)
$admin_dn = "cn=admin,{$base_dn}";
if (@ldap_bind($ldap, $admin_dn, $password)) {
$msg = "<p style='color:green;font-weight:bold'>Login successful! Welcome <strong>admin</strong> (full privileges)</p>";
}
// Second: if not admin, try regular user
elseif (@ldap_bind($ldap, "uid={$username},ou=People,{$base_dn}", $password)) {
$msg = "<p style='color:green;font-weight:bold'>Login successful! Welcome {$username}</p>";
}
else {
$msg = "<p style='color:red'>Invalid credentials</p>";
}
} else {
$msg = "<p style='color:red'>StartTLS failed</p>";
}
ldap_close($ldap);
} else {
$msg = "<p style='color:red'>Could not connect to LDAP server</p>";
}
} else {
$msg = "<p style='color:red'>Please fill both fields</p>";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>ldapdock LDAP login</title>
<style>
body { font-family: Arial, sans-serif; max-width: 400px; margin: 100px auto; text-align: center; }
input, button { padding: 10px; margin: 5px; width: 100%; font-size: 16px; box-sizing: border-box; }
button { background: #007cba; color: white; border: none; cursor: pointer; }
.note { font-size: 0.9em; color: #666; }
</style>
</head>
<body>
<h1>ldapdock login</h1>
<p>Server base DN: <strong><?= htmlspecialchars($base_dn) ?></strong></p>
<?= $msg ?>
<form method="post">
<input type="text" name="username" placeholder="Username (marisa or admin)" required autofocus>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Login</button>
</form>
<hr>
<div class="note">
<strong>Test accounts:</strong><br>
Regular user: <code>marisa</code> / password: <code>MarisaNewPass2025</code><br>
Admin user: <code>admin</code> / password: <code>admin</code>
</div>
</body>
</html>
EOF
ADMIN_DN="cn=admin,${LDAP_BASE_DN}"
ADMIN_PW="admin"
echo "--> Adding base structure" echo "--> Adding base structure"
ldapadd -c -x -D "cn=admin,dc=example,dc=com" -w admin -f /tmp/base.ldif || true ldapadd -c -x -D "$ADMIN_DN" -w "$ADMIN_PW" -f /tmp/base.ldif || true
#────────────────────────────────────────────────────────────── #──────────────────────────────────────────────────────────────
# TLS BLOCK # TLS BLOCK
@ -158,8 +248,6 @@ fi
# Set Marisa password (full LDIF — so ldapmodify knows what to modify) # Set Marisa password (full LDIF — so ldapmodify knows what to modify)
echo "--> Setting Marisa password to 'MarisaNewPass2025' using Admin Bind" echo "--> Setting Marisa password to 'MarisaNewPass2025' using Admin Bind"
ADMIN_DN="cn=admin,${LDAP_BASE_DN}"
ADMIN_PW="admin"
slappasswd -h '{SSHA}' -s MarisaNewPass2025 | \ slappasswd -h '{SSHA}' -s MarisaNewPass2025 | \
ldapmodify -x -D "$ADMIN_DN" -w "$ADMIN_PW" <<EOF >/dev/null 2>&1 ldapmodify -x -D "$ADMIN_DN" -w "$ADMIN_PW" <<EOF >/dev/null 2>&1
dn: uid=marisa,ou=People,${LDAP_BASE_DN} dn: uid=marisa,ou=People,${LDAP_BASE_DN}
@ -272,6 +360,7 @@ fi
echo "--> ldapdock ready — OpenLDAP + Apache + PHP running" echo "--> ldapdock ready — OpenLDAP + Apache + PHP running"
echo " → LDAP: 389/636" echo " → LDAP: 389/636"
echo " → PHPinfo: https://localhost/info.php" echo " → PHPinfo: https://localhost/info.php"
echo " → PHPlogin test: https://localhost/phplogin.php"
echo " → Shell: /bin/bash" echo " → Shell: /bin/bash"
echo " → Exit with CTRL+D or 'exit' command" echo " → Exit with CTRL+D or 'exit' command"

View File

@ -1,54 +0,0 @@
<?php
$host = $_SERVER['HTTP_HOST']; // works for example.com or any LDAP_HOST
$msg = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uid = trim($_POST['uid'] ?? '');
$password = $_POST['password'] ?? '';
if ($uid && $password) {
$ldap = ldap_connect("ldap://127.0.0.1:389");
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
// StartTLS required because your OpenLDAP enforces it
if (ldap_start_tls($ldap)) {
$bind_dn = "uid=$uid,ou=People,dc=$host";
if (@ldap_bind($ldap, $bind_dn, $password)) {
$msg = "<p style='color:green;font-weight:bold'>Login successful! Welcome $uid</p>";
} else {
$msg = "<p style='color:red'>Invalid credentials</p>";
}
} else {
$msg = "<p style='color:red'>TLS failure</p>";
}
ldap_close($ldap);
} else {
$msg = "<p style='color:red'>Please fill both fields</p>";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>ldapdock LDAP login</title>
<style>
body { font-family: Arial, sans-serif; max-width: 400px; margin: 100px auto; text-align: center; }
input, button { padding: 10px; margin: 5px; width: 100%; font-size: 16px; }
button { background: #007cba; color: white; cursor: pointer; }
</style>
</head>
<body>
<h1>ldapdock login</h1>
<p>Server: <strong><?= htmlspecialchars($host) ?></strong></p>
<?= $msg ?>
<form method="post">
<input type="text" name="uid" placeholder="uid (e.g. marisa)" required autofocus><br>
<input type="password" name="password" placeholder="password" required><br>
<button type="submit">Login</button>
</form>
<hr>
<small>Test user: marisa / qwerty</small>
</body>
</html>

View File

@ -1,55 +0,0 @@
<?php
$host = $_SERVER['HTTP_HOST']; // works for example.com or any LDAP_HOST
$msg = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uid = trim($_POST['uid'] ?? '');
$password = $_POST['password'] ?? '';
if ($uid && $password) {
// DIRECT LDAPS CONNECTION — NO STARTTLS NEEDED
$ldap = ldap_connect("ldaps://127.0.0.1:636");
// Allow self-signed cert for ldaps://
putenv('LDAPTLS_REQCERT=allow');
if (!$ldap) {
$msg = "<p style='color:red'>Cannot connect to LDAP server</p>";
} else {
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
$bind_dn = "uid=$uid,ou=People,dc=$host";
if (@ldap_bind($ldap, $bind_dn, $password)) {
$msg = "<p style='color:green;font-weight:bold'>Login successful! Welcome $uid 🎉</p>";
} else {
$msg = "<p style='color:red'>Invalid credentials</p>";
}
ldap_close($ldap);
}
} else {
$msg = "<p style='color:red'>uid=$uid,ou=People,dc=$host Please fill both fields</p>";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>ldapdock LDAP login</title>
<style>
body { font-family: Arial, sans-serif; max-width: 400px; margin: 100px auto; text-align: center; }
input, button { padding: 10px; margin: 5px; width: 100%; font-size: 16px; }
button { background: #007cba; color: white; cursor: pointer; }
</style>
</head>
<body>
<h1>ldapdock login</h1>
<p>Server: <strong><?= htmlspecialchars($host) ?></strong></p>
<?= $msg ?>
<form method="post">
<input type="text" name="uid" placeholder="uid (e.g. marisa)" required autofocus><br>
<input type="password" name="password" placeholder="password" required><br>
<button type="submit">Login</button>
</form>
<hr>
<small>Test user: marisa / q*****</small>
</body>
</html>

54
phplogin.php Normal file
View File

@ -0,0 +1,54 @@
<?php
$host = $_SERVER['HTTP_HOST']; // works for example.com or any LDAP_HOST
$msg = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uid = trim($_POST['uid'] ?? '');
$password = $_POST['password'] ?? '';
if ($uid && $password) {
$ldap = ldap_connect("ldap://127.0.0.1:389");
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
// StartTLS required because your OpenLDAP enforces it
if (ldap_start_tls($ldap)) {
$bind_dn = "$uid,dc=example,dc=com";
if (@ldap_bind($ldap, $bind_dn, $password)) {
$msg = "<p style='color:green;font-weight:bold'>Login successful! Welcome $uid</p>";
} else {
$msg = "<p style='color:red'>Invalid credentials</p>$bind_dn";
}
} else {
$msg = "<p style='color:red'>TLS failure</p>";
}
ldap_close($ldap);
} else {
$msg = "<p style='color:red'>Please fill both fields</p>";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>ldapdock LDAP login</title>
<style>
body { font-family: Arial, sans-serif; max-width: 400px; margin: 100px auto; text-align: center; }
input, button { padding: 10px; margin: 5px; width: 100%; font-size: 16px; }
button { background: #007cba; color: white; cursor: pointer; }
</style>
</head>
<body>
<h1>ldapdock login</h1>
<p>Server: <strong><?= htmlspecialchars($host) ?></strong></p>
<?= $msg ?>
<form method="post">
<input type="text" name="uid" placeholder="uid (e.g. marisa)" required autofocus><br>
<input type="password" name="password" placeholder="password" required><br>
<button type="submit">Login</button>
</form>
<hr>
<small>Test user: uid=marisa,ou=People / MarisaNewPass2025</small>
</body>
</html>