# base install
RUN apk update && \
- apk add lighttpd && \
+ apk add lighttpd openldap-dev && \
+ docker-php-ext-install ldap && \
+ docker-php-ext-enable ldap && \
rm -rf /var/cache/apk/* && \
ln -snf /usr/share/zoneinfo/Etc/UTC /etc/localtime && \
echo "UTC" > /etc/timezone
- Shows progression: speed, percentage and remaining upload time
- Preview content in browser (if possible)
- Optional password protection (for uploading or downloading)
+- LDAP authentication for uploaders
- Set expiration time for downloads
- Option to self-destruct after first download
- Shortened URLs using base 64 encoding
- The button "delete link" will delete the reference to the file but might not destroy the file.
- The button "delete file and links" will delete all references pointing to the file and will destroy the file.
+### How can I setup LDAP authentication?
+
+LDAP authentication is disabled by default. To use it, you will need to install [PHP LDAP extension](https://www.php.net/manual/en/book.ldap.php) and edit your `lib/config.local.php` to set those options:
+- `upload_ldap_auth`: set it to `true`
+- `upload_ldap_host`: set it to your ldap host
+- `upload_ldap_base_dn`: set it to your base DN
+
+More details in [config.original.php](lib/config.original.php)'s documentation.
+
+Note that you can test around LDAP with [docker-compose example](./docker/docker-compose-examples/ldap/).
+
### How to contact someone from Jirafeau?
Feel free to create an issue if you found a bug.
- `UPLOAD_IP_NO_PASSWORD`: set one or more ip allowed to upload files without password (separated by comma).
- `PROXY_IP`: set one or more proxy ip (separated by comma).
- `STORE_UPLOADER_IP`: set to 1 or 0 to enable or disable keeping sender's IP with the _link_ file.
+- `UPLOAD_LDAP_AUTH`: set 1 or 0 to enable or disable LDAP authentication.
+- `UPLOAD_LDAP_HOST`: set LDAP host to contact (with `UPLOAD_LDAP_AUTH=1`)
+- `UPLOAD_LDAP_BASE_DN`: set LDAP base DN to use (with `UPLOAD_LDAP_AUTH=1`)
Example:
```
--- /dev/null
+# Docker-compose example with LDAP
+
+This example help users (and developpers) to setup a LDAP deployment with Jirafeau.
+
+# Build Jirafeau's image
+
+You can skip this step if you are not developping Jirafeau.
+
+In Jirafeau's project folder:
+```
+docker build . -t mojo42/jirafeau:dev
+```
+
+# Customize docker-compose.yml
+
+Open [docker-compose.yml](docker-compose.yml) file and tweak it as needed.
+You can change Jirafeau's image to an official release if you are not developping Jirafeau.
+
+# Run docker compose
+
+```
+docker-compose up -d
+docker-compose logs -f
+```
+
+# Testing
+
+You can now connect to [127.0.0.1:8080](http://127.0.0.1:8080/) to access Jirafeau instance and [127.0.0.1:8090](http://127.0.0.1:8090/) to access PHP LDAP Admin.
+
+You can login on PHP LDAP admin with those default credentials:
+- login DN: `cn=admin,dc=jirafeau,dc=net`
+- Password: `admin`
+
+Once connected on PHP LDAP Admin, you can import [bootstrap.jirafeau.ldif](bootstrap.jirafeau.ldif) to inject a test user.
+Once imported, you should be able to login on Jirafeau with those credentials:
+- Login: `jerome`
+- Password: `password`
+
--- /dev/null
+# LDIF Export for dc=jirafeau,dc=net
+# Server: openldap_server (openldap_server)
+# Search Scope: sub
+# Search Filter: (objectClass=*)
+# Total Entries: 3
+#
+# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on August 5, 2022 4:20 pm
+# Version: 1.2.3
+
+version: 1
+
+# Entry 1: dc=jirafeau,dc=net
+dn: dc=jirafeau,dc=net
+dc: jirafeau
+o: Example Inc.
+objectclass: top
+objectclass: dcObject
+objectclass: organization
+
+# Entry 2: cn=jerome,dc=jirafeau,dc=net
+dn: cn=jerome,dc=jirafeau,dc=net
+cn: jerome
+gidnumber: 500
+givenname: jerome
+homedirectory: /home/users/jjutteau
+objectclass: inetOrgPerson
+objectclass: posixAccount
+objectclass: top
+sn: jutteau
+uid: jjutteau
+uidnumber: 1000
+userpassword: password
+
+# Entry 3: cn=users,dc=jirafeau,dc=net
+dn: cn=users,dc=jirafeau,dc=net
+cn: users
+gidnumber: 500
+objectclass: posixGroup
+objectclass: top
\ No newline at end of file
--- /dev/null
+version: '3.7'
+
+networks:
+ jirafeau:
+
+services:
+ openldap_server:
+ image: osixia/openldap:1.5.0
+ ports:
+ - "389:389"
+ environment:
+ LDAP_TLS: "false"
+ LDAP_ADMIN_PASSWORD: "admin"
+ LDAP_DOMAIN: "jirafeau.net"
+ LDAP_BASE_DN: "dc=jirafeau,dc=net"
+ volumes:
+ - 'openldap_data:/bitnami/openldap'
+ networks:
+ - jirafeau
+ phpldapadmin:
+ image: osixia/phpldapadmin:0.7.2
+ ports:
+ - 8090:80
+ environment:
+ PHPLDAPADMIN_LDAP_HOSTS: openldap_server
+ PHPLDAPADMIN_HTTPS: "false"
+ networks:
+ - jirafeau
+ jirafeau:
+ image: mojo42/jirafeau:dev
+ ports:
+ - "8080:80"
+ environment:
+ DEBUG: 0
+ ADMIN_PASSWORD: "password"
+ UPLOAD_LDAP_AUTH: 1
+ UPLOAD_LDAP_HOST: openldap_server
+ UPLOAD_LDAP_BASE_DS: "dc=jirafeau,dc=net"
+ networks:
+ - jirafeau
+
+volumes:
+ openldap_data:
env_2_cfg_string_array($cfg, 'upload_ip_nopassword');
env_2_cfg_string_array($cfg, 'proxy_ip');
env_2_cfg_bool($cfg, 'store_uploader_ip');
+ env_2_cfg_bool($cfg, 'upload_ldap_auth');
+ env_2_cfg_string($cfg, 'upload_ldap_host');
+ env_2_cfg_string($cfg, 'upload_ldap_base_dn');
if ($setup_ok) {
$cfg['installation_done'] = true;
}
/* Check if user is allowed to upload. */
-// First check: Is user already logged
+// check if user already logged
if (jirafeau_user_session_logged()) {
}
-// Second check: Challenge by IP NO PASSWORD
+// check of ldap authentication
+elseif (jirafeau_has_ldap_auth($cfg)) {
+ if (isset($_POST['ldap_user']) and isset($_POST['ldap_password'])) {
+ $result = jirafeau_challenge_ldap_auth($cfg, $_POST['ldap_user'], $_POST['ldap_password']);
+ if (true === $result) {
+ jirafeau_user_session_start();
+ } else {
+ jirafeau_session_end();
+ jirafeau_non_fatal_error(t('BAD_PSW'));
+ }
+ }
+ // Show login form if user session is not authorized yet
+ if (!jirafeau_user_session_logged()) {
+ ?>
+ <form method="post" class="form login">
+ <fieldset>
+ <table>
+ <tr>
+ <td class = "label"><label for = "enter_user">
+ <?php echo t('UP_USER') . ':'; ?></label>
+ </td>
+ </tr><tr>
+ <td class = "field">
+ <input type="text" name="ldap_user" id="ldap_user" size="40" autocomplete="ldap-user"/>
+ </td>
+ </tr><tr>
+ <td class="label"><label for="enter_password">
+ <?php echo t('PASSWORD') . ':'; ?></label>
+ </td>
+ </tr><tr>
+ <td class="field">
+ <input type="password" name="ldap_password" id="ldap_password" size="40" autocomplete="ldap-password" />
+ </td>
+ </tr><tr class = "nav">
+ <td class = "nav next">
+ <input type="submit" name="key" value="<?php echo t('LOGIN'); ?>"/>
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ </form>
+<?php
+ require(JIRAFEAU_ROOT.'lib/template/footer.php');
+ exit;
+ }
+}
+// Allow certains IP to upload with no password
elseif (true === jirafeau_challenge_upload_ip_without_password($cfg, get_ip_address($cfg))) {
jirafeau_user_session_start();
}
-// Third check: Challenge by IP
+// Challenge by IP
elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
// Is an upload password required?
if (jirafeau_has_upload_password($cfg)) {
* Set to 0 to remove limitation.
*/
$cfg['max_upload_chunk_size_bytes'] = 100000000; // 100MB
+
+/** Enable LDAP authentication for uploaders
+ * Cannot be used with 'upload_password' or 'upload_ip_nopassword' options.
+ */
+$cfg['upload_ldap_auth'] = false;
+
+/** LDAP host to reach when 'upload_ldap_auth' is enabled */
+$cfg['upload_ldap_host'] = "";
+
+/** LDAP Base DN to authenticate users with 'upload_ldap_auth' option enabled*/
+$cfg['upload_ldap_base_dn'] = "dc=jirafeau,dc=net";
exit;
}
+function jirafeau_non_fatal_error($errorText)
+{
+ echo '<div class="error"><p>' . $errorText . '</p></div>';
+}
+
function jirafeau_clean_rm_link($link)
{
$p = s2p("$link");
if ($cfg['one_time_download'] && $cfg['litespeed_workaround']) {
add_error(t('INCOMPATIBLE_OPTIONS_W'), 'one_time_download=true<br>litespeed_workaround=true');
}
+ if ($cfg['upload_ldap_auth'] === true) {
+ if (sizeof($cfg['upload_password']) > 0) {
+ add_error(t('INCOMPATIBLE_OPTIONS_W'), 'upload_ldap_auth=true<br>sizeof(upload_password) > 0');
+ }
+ if (sizeof($cfg['upload_ip_nopassword']) > 0) {
+ add_error(t('INCOMPATIBLE_OPTIONS_W'), 'upload_ldap_auth=true<br>sizeof(upload_ip_nopassword) > 0');
+ }
+ }
}
/**
{
return $_SERVER['HTTP_HOST'] . str_replace('install.php', '', $_SERVER['REQUEST_URI']);
}
+
+function jirafeau_has_ldap_auth($cfg)
+{
+ return $cfg['upload_ldap_auth'] === true;
+}
+
+function jirafeau_challenge_ldap_auth($cfg, $user, $password)
+{
+ if (!jirafeau_has_ldap_auth($cfg)) {
+ return "upload_ldap_auth not set";
+ }
+ if (strlen($cfg['upload_ldap_host']) == 0) {
+ return "upload_ldap_host not set";
+ }
+ if (strlen($cfg['upload_ldap_base_dn']) == 0) {
+ return "upload_ldap_base_dn not set";
+ }
+ $host = $cfg['upload_ldap_host'];
+ $base_dn = $cfg['upload_ldap_base_dn'];
+ $con = ldap_connect("ldap://$host");
+ $ldap_user = "cn=$user,$base_dn";
+ if (!$con) {
+ return "cannot initiate connection to ldap server";
+ }
+ ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
+ ldap_set_option($con, LDAP_OPT_REFERRALS, 0);
+ $bind = ldap_bind_ext($con, $ldap_user, $password, [['oid' => LDAP_CONTROL_PASSWORDPOLICYREQUEST]]);
+ if (!$bind) {
+ ldap_close($con);
+ return "cannot bind to ldap server";
+ }
+ $parsing = ldap_parse_result($con, $bind, $errcode, $matcheddn, $errmsg, $referrals, $ctrls);
+ if (!$parsing) {
+ ldap_close($con);
+ return "cannot parlse ldap results";
+ }
+ if ($errcode == 49) {
+ ldap_close($con);
+ return "bad password";
+ }
+ if ($errcode != 0) {
+ ldap_close($con);
+ return "ldap auth error: $errmsg ($errcode)";
+ }
+ return true;
+}
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "Una quincena",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "Zwei Wochen",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "Password",
+ "UP_USER": "User",
"INSTALL_FILE_NOT_FOUND_TITLE": "Installation file not found",
"INSTALL_FILE_NOT_FOUND_DESC": "Installation is not complete and install.php file does not seem to exist",
"REPORTING_AN_ISSUE": "Reporting an issue",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "Una quincena",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "Mot de passe",
+ "UP_USER": "Utilisateur",
"INSTALL_FILE_NOT_FOUND_TITLE": "Fichier d'installation non-trouvé",
"INSTALL_FILE_NOT_FOUND_DESC": "L'installation est incomplète et le ficher install.php est introuvable",
"2_W": "Deux semaines",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "Due settimane",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "To uker",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "Twee weken",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "Uma quinzena",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "Uma quinzena",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"REPORTING_AN_ISSUE": "",
"SIZE_DATA": "",
"INCOMPATIBLE_OPTIONS_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "Två veckor",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "İki hafta",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",
{
+ "PASSWORD": "",
+ "UP_USER": "",
"INSTALL_FILE_NOT_FOUND_TITLE": "",
"INSTALL_FILE_NOT_FOUND_DESC": "",
"2_W": "",