Next release (#151)

* Custom email body (#51)

* get email body from ENV

* read subject from env

* html mail

* replace special string with username and password

* missing ;

* more str_replace

* utf8 in mail

* typo

* docs

* fix var

* count accounts

* fix print

* Add the ability to set the server path.  Get directed to the appropriate module when you log in.

* Fixes to allow overriding attribute labels properly

* Fix server_path in various places, update to cookies use 'samesite', include boostrap and queryjs files so LUM can run without internet access.

* Add support for consuming docker / kubernetes secrets passed as _FILE environment variables (#136)

* mod: condense Dockerfile

* add: _FILE feature
add: list of sensitive env_vars

* mod: sorted env_var list

* add: complete current env_var list

* fix: formatting

* mod: revert Dockerfile to prev. version

* mod: updated comment to be more descriptive
mod: rename variables to be more descriptive

* rem: list of env_var; no longer needed.
mod: env_file_replace function
^ search for all <env_var>_FILE variables and replace
^ <env_var> if the file exists and is not empty
mod: env_file_replace comment

Co-authored-by: pyunramura <jeremy.cummings@live.com>

* Update the README with information on using _FILE

* Change username regex variables

* Named server certs, as suggested by @huzvar

* Update LDAP filter method as suggested by @xgaia

* Feature/http header username (#120)

* Implement Remote Headers Auth

* Hide Logout on Remote Sessions

* Add Explanation for REMOTRE_HTTP_HEADERS_LOGIN settiing

Co-authored-by: Damian Galli <damian.galli@galli.site>

* Updated Readme, fixed random number generation for ARM systems, fixed JS to generate the username

* Fix issues #124 and #126

* Change badges to buttons for list counts

* Don't secretly set displayName

* Add Group Additional (#113)

* Add doku Group additional.

* Read Group additional configuration.

* New group add Additional objectclasses

* Allow for attributes that take multiple values.

* Updated README

* Formatting fixes, fix parsing params from account requests, initial code for the simple interface flag.

* Add attribute fields for groups and allow user-defined attributes to be displayed.  Move alert banner JS to a function.

* Update entries with any missing additional objectclasses when updating entries.  Update README to describe changes. Initial work to allow file uploads for attributes.

* Functionality to upload binary files and display them in the form it's a JPEG.  Added a new page to download existing binary content.

* Bugfixes for compatibility with older osixia/openldap versions.  Change SIMPLE_INTERFACE to SHOW_POSIX_ATTRIBUTES.

* Update version number in README.

Co-authored-by: Monsieur X <xgaia@gmx.com>
Co-authored-by: pyunramura <35285259+pyunramura@users.noreply.github.com>
Co-authored-by: pyunramura <jeremy.cummings@live.com>
Co-authored-by: Damian Galli <da.ga@live.de>
Co-authored-by: Damian Galli <damian.galli@galli.site>
Co-authored-by: huzvar <89766648+huzvar@users.noreply.github.com>
This commit is contained in:
Brian Lycett 2022-04-12 15:43:21 +01:00 committed by GitHub
parent 1ae87b6582
commit 57af7c4e9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1324 additions and 687 deletions

View File

@ -53,7 +53,7 @@ docker run \
-e "LDAP_ADMIN_BIND_PWD=secret"\ -e "LDAP_ADMIN_BIND_PWD=secret"\
-e "LDAP_IGNORE_CERT_ERRORS=true" \ -e "LDAP_IGNORE_CERT_ERRORS=true" \
-e "EMAIL_DOMAIN=ldapusermanager.org" \ -e "EMAIL_DOMAIN=ldapusermanager.org" \
wheelybird/ldap-user-manager:v1.7 wheelybird/ldap-user-manager:v1.8
``` ```
Change the variable values to suit your environment. Now go to https://lum.example.com/setup. Change the variable values to suit your environment. Now go to https://lum.example.com/setup.
@ -64,7 +64,12 @@ Change the variable values to suit your environment. Now go to https://lum.exam
Configuration is via environmental variables. Please bear the following in mind: Configuration is via environmental variables. Please bear the following in mind:
* This tool needs to bind to LDAP as a user that has the permissions to modify everything under the base DN. * This tool needs to bind to LDAP as a user that has the permissions to modify everything under the base DN.
* This interface is designed to work with a fresh LDAP server and should only be used against existing populated LDAP directories with caution and at your own risk. * This interface is designed to work with a fresh LDAP server and should only be against existing, populated LDAP directories with caution and at your own risk.
#### Containers: using files/secrets to set configuration variables
When running the user manager as a container you can append `_FILE` to any of the configuration variables and set the value to a filepath. Then when the container starts up it will set the appropriate configuration variable with the contents of the file.
For example, if you're using Docker Swarm and you've set the LDAP bind password as a Docker secret (`echo "myLDAPadminPassword" | docker secret create ldap_admin_bind_pwd -`) then you can set `LDAP_ADMIN_BIND_PWD_FILE=/run/secrets/ldap_admin_bind_pwd`. This will result in `LDAP_ADMIN_BIND_PWD` being set with the contents of `/run/secrets/ldap_admin_bind_pwd`.
### Mandatory: ### Mandatory:
@ -88,19 +93,26 @@ Configuration is via environmental variables. Please bear the following in mind
* `SERVER_PATH` (default: */*): The path to the user manager on the webserver. Useful if running this behind a reverse proxy. * `SERVER_PATH` (default: */*): The path to the user manager on the webserver. Useful if running this behind a reverse proxy.
* `SERVER_PORT` (default: *80 or 80+443*): The port the webserver inside the container will listen on. If undefined then the internal webserver will listen on ports 80 and 443 (if `NO_HTTPS` is true it's just 80) and HTTP traffic is redirected to HTTPS. When set this will disable the redirection and the internal webserver will listen for HTTPS traffic on this port (or for HTTP traffic if `NO_HTTPS` is true). This is for use when the container's Docker network mode is set to `host`. * `SERVER_PORT` (default: *80 or 80 & 443*): The port the webserver inside the container will listen on. If undefined then the internal webserver will listen on ports 80 and 443 (if `NO_HTTPS` is true it's just 80) and HTTP traffic is redirected to HTTPS. When set this will disable the redirection and the internal webserver will listen for HTTPS traffic on this port (or for HTTP traffic if `NO_HTTPS` is true). This is for use when the container's Docker network mode is set to `host`.
* `NO_HTTPS` (default: *FALSE*): If you set this to *TRUE* then the server will run in HTTP mode, without any encryption. This is insecure and should only be used for testing. See [HTTPS certificates](#https-certificates) * `NO_HTTPS` (default: *FALSE*): If you set this to *TRUE* then the server will run in HTTP mode, without any encryption. This is insecure and should only be used for testing. See [HTTPS certificates](#https-certificates)
* `SERVER_KEY_FILENAME`: (default *server.key*): The filename of the HTTPS server key file. See [HTTPS certificates](#https-certificates)
* `SERVER_CERT_FILENAME`: (default *server.crt*): The filename of the HTTPS certficate file. See [HTTPS certificates](#https-certificates)
* `CA_CERT_FILENAME`: (default *ca.crt*): The filename of the HTTPS server key file. See [HTTPS certificates](#https-certificates)
* `SESSION_TIMEOUT` (default: *10 minutes*): How long before an idle session will be timed out. * `SESSION_TIMEOUT` (default: *10 minutes*): How long before an idle session will be timed out.
#### Organisation settings #### Interface customisation
* `ORGANISATION_NAME`: (default: *LDAP*): Your organisation's name. * `ORGANISATION_NAME`: (default: *LDAP*): Your organisation's name.
* `SITE_NAME` (default: *{ORGANISATION_NAME} user manager*): Change this to replace the title in the menu, e.g. "My Company Account Management". * `SITE_NAME` (default: *`ORGANISATION_NAME` user manager*): Change this to replace the title in the menu, e.g. "My Company Account Management".
* `SHOW_POSIX_ATTRIBUTES` (default: *FALSE*): If set to `TRUE` this show extra attributes for **posixAccount** and **posixGroup** in the account and group forms. Leave this set to `FALSE` if you don't use LDAP accounts to log into servers etc., as it makes the interface much simpler. The Posix values are still set in the background using the default values. This setting doesn't hide any Posix attributes set via `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES` or `LDAP_GROUP_ADDITIONAL_ATTRIBUTES`.
#### LDAP settings #### LDAP settings
@ -112,13 +124,15 @@ Configuration is via environmental variables. Please bear the following in mind
* `LDAP_IGNORE_CERT_ERRORS` (default: *FALSE*): If *TRUE* then problems with the certificate presented by the LDAP server will be ignored (for example FQDN mismatches). Use this if your LDAP server is using a self-signed certificate and you don't have a CA certificate for it or you're connecting to a pool of different servers via round-robin DNS. * `LDAP_IGNORE_CERT_ERRORS` (default: *FALSE*): If *TRUE* then problems with the certificate presented by the LDAP server will be ignored (for example FQDN mismatches). Use this if your LDAP server is using a self-signed certificate and you don't have a CA certificate for it or you're connecting to a pool of different servers via round-robin DNS.
* `LDAP_TLS_CACERT` (no default): If you need to use a specific CA certificate for TLS connections to the LDAP server (when `LDAP_REQUIRE_STARTTLS` is set) then assign the contents of the CA certificate to this variable. e.g. `-e LDAP_TLS_CACERT="$(</path/to/ca.crt)"` (ensure you're using quotes or you'll get an "invalid reference format: repository name must be lowercase" error. * `LDAP_TLS_CACERT` (no default): If you need to use a specific CA certificate for TLS connections to the LDAP server (when `LDAP_REQUIRE_STARTTLS` is set) then assign the contents of the CA certificate to this variable. e.g. `-e LDAP_TLS_CACERT="$(</path/to/ca.crt)"` (ensure you're using quotes or you'll get an "invalid reference format: repository name must be lowercase" error). Alternatively you can bind-mount a certificate into the container and use `LDAP_TLS_CACERT_FILE` to specify the path to the file.
#### Advanced LDAP settings #### Advanced LDAP settings
These settings should only be changed if you're trying to make the user manager work with an LDAP directory that's already populated and the defaults don't work. These settings should only be changed if you're trying to make the user manager work with an LDAP directory that's already populated and the defaults don't work.
* `LDAP_ACCOUNT_ATTRIBUTE` (default: *uid*): The account attribute used as the account identifier. See [Account names](#account-names) for more information. * `LDAP_ACCOUNT_ATTRIBUTE` (default: *uid*): The attribute used as the account identifier. See [Account names](#account-names) for more information.
* `LDAP_GROUP_ATTRIBUTE` (default: *cn*): The attribute used as the group identifier.
* `LDAP_GROUP_MEMBERSHIP_ATTRIBUTE` (default: *memberUID* or *uniqueMember*): The attribute used when adding a user's account to a group. When the `groupOfMembers` objectClass is detected `FORCE_RFC2307BIS` is `TRUE` it defaults to `uniqueMember`, otherwise it'll default to `memberUID`. Explicitly setting this variable will override any default. * `LDAP_GROUP_MEMBERSHIP_ATTRIBUTE` (default: *memberUID* or *uniqueMember*): The attribute used when adding a user's account to a group. When the `groupOfMembers` objectClass is detected `FORCE_RFC2307BIS` is `TRUE` it defaults to `uniqueMember`, otherwise it'll default to `memberUID`. Explicitly setting this variable will override any default.
@ -126,6 +140,10 @@ These settings should only be changed if you're trying to make the user manager
* `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES` (no default): A comma-separated list of extra attributes to display when creating an account. See [Extra objectClasses and attributes](#extra-objectclasses-and-attributes) for more information. * `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES` (no default): A comma-separated list of extra attributes to display when creating an account. See [Extra objectClasses and attributes](#extra-objectclasses-and-attributes) for more information.
* `GROUP_ACCOUNT_ADDITIONAL_OBJECTCLASSES` (no default): A comma-separated list of additional objectClasses to use when creating a group. See [Extra objectClasses and attributes](#extra-objectclasses-and-attributes) for more information.
* `GROUP_ACCOUNT_ADDITIONAL_ATTRIBUTES` (no default): A comma-separated list of extra attributes to display when creating a group. See [Extra objectClasses and attributes](#extra-objectclasses-and-attributes) for more information.
* `LDAP_GROUP_MEMBERSHIP_USES_UID` (default: *TRUE* or *FALSE*): If *TRUE* then the entry for a member of a group will be just the username, otherwise it's the member's full DN. When the `groupOfMembers` objectClass is detected or `FORCE_RFC2307BIS` is `TRUE` it defaults to `FALSE`, otherwise it'll default to `TRUE`. Explicitly setting this variable will override the default. * `LDAP_GROUP_MEMBERSHIP_USES_UID` (default: *TRUE* or *FALSE*): If *TRUE* then the entry for a member of a group will be just the username, otherwise it's the member's full DN. When the `groupOfMembers` objectClass is detected or `FORCE_RFC2307BIS` is `TRUE` it defaults to `FALSE`, otherwise it'll default to `TRUE`. Explicitly setting this variable will override the default.
* `FORCE_RFC2307BIS` (default: *FALSE*): Set to *TRUE* if the auto-detection is failing to spot that the RFC2307BIS schema is available. When *FALSE* the user manager will use auto-detection. See [Using the RFC2307BIS schema](#using-the-rfc2307bis-schema) for more information. * `FORCE_RFC2307BIS` (default: *FALSE*): Set to *TRUE* if the auto-detection is failing to spot that the RFC2307BIS schema is available. When *FALSE* the user manager will use auto-detection. See [Using the RFC2307BIS schema](#using-the-rfc2307bis-schema) for more information.
@ -149,6 +167,7 @@ These settings should only be changed if you're trying to make the user manager
* `ACCEPT_WEAK_PASSWORDS` (default: *FALSE*): Set this to *TRUE* to prevent a password being rejected for being too weak. The password strength indicators will still gauge the strength of the password. Don't enable this in a production environment. * `ACCEPT_WEAK_PASSWORDS` (default: *FALSE*): Set this to *TRUE* to prevent a password being rejected for being too weak. The password strength indicators will still gauge the strength of the password. Don't enable this in a production environment.
* `REMOTE_HTTP_HEADERS_LOGIN`(default: *FALSE*) Enables session managment from an external service like Authelia. _This setting will compromise your security if you're not using an Auth-Proxy in front of this application_.
#### Email sending settings #### Email sending settings
@ -170,7 +189,7 @@ To send emails you'll need to use an existing SMTP server. Email sending will b
* `EMAIL_FROM_NAME` (default: *`SITE_NAME`*): The FROM name used when sending out emails. The default name is taken from `SITE_NAME` under **Organisation settings**. * `EMAIL_FROM_NAME` (default: *`SITE_NAME`*): The FROM name used when sending out emails. The default name is taken from `SITE_NAME` under **Organisation settings**.
* `MAIL_SUBJECT` (default: *Your $ORGANISATION_NAME account has been created.*): The mail subject for new account emails. * `MAIL_SUBJECT` (default: *Your `ORGANISATION_NAME` account has been created.*): The mail subject for new account emails.
* `NEW_ACCOUNT_EMAIL_SUBJECT`, `NEW_ACCOUNT_EMAIL_BODY`, `RESET_PASSWORD_EMAIL_SUBJECT` & `RESET_PASSWORD_EMAIL_BODY`: Change the email contents for emails sent to users when you create an account or reset a password. See [Sending emails](#sending_emails) for full details. * `NEW_ACCOUNT_EMAIL_SUBJECT`, `NEW_ACCOUNT_EMAIL_BODY`, `RESET_PASSWORD_EMAIL_SUBJECT` & `RESET_PASSWORD_EMAIL_BODY`: Change the email contents for emails sent to users when you create an account or reset a password. See [Sending emails](#sending_emails) for full details.
@ -194,7 +213,6 @@ To send emails you'll need to use an existing SMTP server. Email sending will b
* `SMTP_LOG_LEVEL` (default: *0*): Set to between 1-4 to get SMTP logging information (0 disables SMTP debugging logs though it will still display errors). See https://github.com/PHPMailer/PHPMailer/wiki/SMTP-Debugging for details of the levels. * `SMTP_LOG_LEVEL` (default: *0*): Set to between 1-4 to get SMTP logging information (0 disables SMTP debugging logs though it will still display errors). See https://github.com/PHPMailer/PHPMailer/wiki/SMTP-Debugging for details of the levels.
*** ***
## Initial setup ## Initial setup
@ -226,24 +244,30 @@ Other services or software might use the *Common Name* (`cn`) attribute, which i
The account identifier is what uniquely identifies the account, so you can't create multiple accounts where the account identifier is the same. The account identifier is what uniquely identifies the account, so you can't create multiple accounts where the account identifier is the same.
You should ensure your LDAP clients use the same account identifier attribute when authenticating users. You should ensure your LDAP clients use the same account identifier attribute when authenticating users.
If you're using LDAP for server accounts then you'll find there are normally constraints on how many cahracters and the type of characters you're allowed to use. The user manager will validate user and group names against `USERNAME_REGEX`. If you don't need to be so strict then you can disable these checks by setting `ENFORCE_SAFE_SYSTEM_NAMES` to `FALSE`. If you're using LDAP for server accounts then you'll find there are normally constraints on how many characters and the type of characters you're allowed to use. The user manager will validate user and group names against `USERNAME_REGEX`. If you don't need to be so strict then you can disable these checks by setting `ENFORCE_SAFE_SYSTEM_NAMES` to `FALSE`.
*** ***
## HTTPS certificates ## HTTPS certificates
When `NO_HTTPS` is set to **FALSE** (the default), the user manager expects to find SSL files at `/opt/ssl/server.key` and `/opt/ssl/server.crt`. These certificates should match `SERVER_HOSTNAME`. If these files aren't found then the startup script will create self-signed certificates based on `SERVER_HOSTNAME`. To use your own key and certificate then you need to bind-mount a directory containing them to `/opt/ssl`. You can also add a certificate chain file (the Apache `SSLCertificateChainFile` option) if needed - name it `chain.pem` and place it in the same directory as `server.key` and `server.crt` . The user manager runs in HTTPS mode by default and so uses HTTPS certificates. You can pass in your own certificates by bind-mounting a local path to `/opt/ssl` in the container and then specifying the names of the files via `SERVER_KEY_FILENAME`, `SERVER_CERT_FILENAME` and optionally `CA_CERT_FILENAME` (this will set Apache's `SSLCertificateChainFile` directive).
If the certificate and key files don't exist then a self-signed certificate will be created when the container starts.
For example, if your key and certificate files are in `/home/myaccount/ssl` you can bind-mount that folder by adding this line to the docker run example above, just after the last line starting with `-e`: When using your own certificates, the certificate's common name (or one of the alternative names) need to match the value you set for `SERVER_HOSTNAME`.
For example, if your key and certificate files are in `/home/myaccount/ssl` you can bind-mount that folder by adding these lines to the `docker run` example above (place them above the final line):
``` ```
-e "SERVER_KEY_FILENAME=lum.example.com.key" \
-e "SERVER_CERT_FILENAME=lum.example.com.crt" \
-e "CA_CERT_FILENAME=ca_bundle.pem" \
-v /home/myaccount/ssl:/opt/ssl \ -v /home/myaccount/ssl:/opt/ssl \
``` ```
If you don't want to use HTTPS certificates then set `NO_HTTPS` to **TRUE** to run in HTTP mode. It's advised that you only do this when testing.
*** ***
## Sending emails ## Sending emails
When you create an account you'll have an option to send an email to the person you created the account for. The email will give them their new username, password and a link to the self-service password change utility. When you create an account you'll have an option to send an email to the person you created the account for. The email will give them their new username, password and a link to the self-service password change utility.
Emails are sent via SMTP, so you'll need to be able to connect to an SMTP server and pass in the settings for that server via environmental variables - see **Email sending** above. Emails are sent via SMTP, so you'll need to be able to connect to an SMTP server and pass in the settings for that server via environmental variables - see **Email sending** above.
@ -292,23 +316,50 @@ If `EMAIL_DOMAIN` is set then the email address field will be automatically upda
## Extra objectClasses and attributes ## Extra objectClasses and attributes
If you need to use this user manager with an existing LDAP directory and your account records need additional objectClasses and attributes then you can add them via `LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES` and `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES`. By default accounts are created with `person`, `inetOrgPerson` and `posixAccount` object classes. Groups are created with `posixGroup` - if [the RFC2307BIS schema](#using-the-rfc2307bis-schema) is available then `groupOfUniqueNames` is automatically added too.
`LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES` is a comma-separated list of objectClasses to add when creating the account record. For example, `LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES=ldappublickey,couriermailaccount`. If you need to add additional objectClasses and attributes to accounts or groups then you can add them via `LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES`, `LDAP_GROUP_ADDITIONAL_OBJECTCLASSES`, `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES` and `LDAP_GROUP_ADDITIONAL_ATTRIBUTES`.
To add extra fields for new attributes you need to pass a comma-separated string of the attributes and optionally the label for the attribute (which will be shown on the user form) and a default value to `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES` separated by colons (`:`). `LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES` and `LDAP_GROUP_ADDITIONAL_OBJECTCLASSES take a comma-separated list of objectClasses to add. For example, `LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES=ldappublickey,couriermailaccount`.
The format for configuring an attribute is: `attribute1:label1:default_value1,attribute2:label2:default_value2`. If you don't supply a label then the form field will be labelled with the attribute name.
An example (for the couriermailaccount objectClass) would be: `mailbox:Mailbox:domain.com,quota:Mail quota:20`
ObjectClasses often have attributes that must have a value, so you should definitely set a default for those attributes. `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES` and `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES` take a comma-separated list of attributes to be displayed as extra fields for the account or group.
By default these fields will be empty with the field named for the attribute, but you can set the field labels (and optionally the default values) by appending the attribute names with colon-separated values like so: `attribute_name:label:default_value`.
Multiple attributes are separated by commas, so you can define the label and default values for several attributes as follows: `attribute1:label1:default_value1,attribute2:label2:default_value2,attribute3:label3`.
This is advanced stuff and the user manager doesn't attempt to validate any objectClasses or any attributes, labels or default values you pass in. It's up to you to ensure that your LDAP server has the appropriate schemas and that the labels and values are sane. As an example, to set a mailbox name and quota for the `couriermailaccount` schema you can pass these variables to the container:
```
LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES=couriermailaccount
LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES="mailbox:Mailbox:domain.com,quota:Mail quota:20"
```
_Note_: ObjectClasses often have attributes that _must_ have a value, so you should set a default value for these attributes, otherwise if you forget to add a value when filling in the form an error will be thrown on submission.
### Multi-value attributes
If you have an attribute that could have several values, you can add a `+` to end of the attribute name. This will modify the form so you can add or remove extra values for that attribute. For example, if you want to have multiple email aliases when using the _PostfixBookMailAccount_ schema then you can pass these variables to the container:
```
LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES=PostfixBookMailAccount" \
LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES=mailAlias+:Email aliases"
```
### Binary attributes
If you have an attribute that stores the contents of a binary file (for example, a JPEG) then you can add a `^` to the end of the attribute name. This will modify the form so that this attribute has an upload button. If a JPEG has already been uploaded then it will display the image. Otherwise the mime-type is displayed and there's a link for downloading the file. For example, to allow you to set a user's photo:
```
LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES=jpegPhoto^:Photograph"
```
The maximum filesize you can upload is 2MB.
### Caveat
These settings are advanced usage and the user manager doesn't attempt to validate any objectClasses, attributes, labels or default values you pass in. It's up to you to ensure that your LDAP server has the appropriate schemas and that the labels and values are sane.
*** ***
## Using the RFC2307BIS schema ## Using the RFC2307BIS schema
Using the **RFC2307BIS** will allow you to use `memberOf` in LDAP searches which gives you an easy way to check if a user is a member of a group. For example: `(&(objectClass=posixAccount)(memberof=cn=somegroup,ou=groups,dc=ldapusermanager,dc=org))`. Using the **RFC2307BIS** will allow you to use `memberOf` in LDAP searches which gives you an easy way to check if a user is a member of a group. For example: `(&(objectClass=posixAccount)(memberof=cn=somegroup,ou=groups,dc=ldapusermanager,dc=org))`.
OpenLDAP will use the RFC2307 (NIS) schema by default; you'll need to configure your server to use the **RFC2307BIS** schema when setting up your directory. See [this guide](https://unofficialaciguide.com/2019/07/31/ldap-schemas-for-aci-administrators-rfc2307-vs-rfc2307bis/) for more information regarding RFC2307 vs RFC2307BIS. OpenLDAP will use the RFC2307 (NIS) schema by default; you'll need to configure your server to use the **RFC2307BIS** schema when setting up your directory. See [this guide](https://unofficialaciguide.com/2019/07/31/ldap-schemas-for-aci-administrators-rfc2307-vs-rfc2307bis/) for more information regarding RFC2307 vs RFC2307BIS.

View File

@ -4,6 +4,17 @@ set -e
ssl_dir="/opt/ssl" ssl_dir="/opt/ssl"
php_dir="/opt/ldap_user_manager" php_dir="/opt/ldap_user_manager"
env_file_replace() {
for env_file in $(env|grep _FILE=); do
read -a env <<< "$(echo "$env_file" | sed 's/\(.*\)_FILE=\(.*\)/\1 \2/')"
if [ -s "${env[1]}" ]; then
echo Setting "${env[0]}" from "${env[1]}"
export "${env[0]}"="$(cat "${env[1]}")"
else echo "${env[1]} does not exist or is empty. Leaving ${env[0]} unset"
fi
done
}
if [ ! "$SERVER_HOSTNAME" ]; then export SERVER_HOSTNAME="ldapusermanager.org"; fi if [ ! "$SERVER_HOSTNAME" ]; then export SERVER_HOSTNAME="ldapusermanager.org"; fi
if [ ! "$SERVER_PATH" ]; then if [ ! "$SERVER_PATH" ]; then
export SERVER_PATH="/"; export SERVER_PATH="/";
@ -18,7 +29,7 @@ fi
if [ "$LDAP_TLS_CACERT" ]; then if [ "$LDAP_TLS_CACERT" ]; then
echo "$LDAP_TLS_CACERT" >/opt/ca.crt echo "$LDAP_TLS_CACERT" >/opt/ca.crt
mkdir -p /etc/ldap mkdir -p /etc/ldap
echo "TLS_CACERT /opt/ca.crt/" > /etc/ldap/ldap.conf sed -i "s/TLS_CACERT.*/TLS_CACERT \/opt\/ca.crt/" /etc/ldap/ldap.conf
fi fi
if [ "${NO_HTTPS,,}" == "true" ]; then if [ "${NO_HTTPS,,}" == "true" ]; then
@ -47,15 +58,15 @@ else
######################## ########################
#If there aren't any SSL certs then create a CA and then CA-signed certificate #If there aren't any SSL certs then create a CA and then CA-signed certificate
if [ ! -f "${ssl_dir}/server.key" ] && [ ! -f "${ssl_dir}/server.crt" ]; then if [ ! -f "${ssl_dir}/${SERVER_CERT_FILENAME:-server.crt}" ] && [ ! -f "${ssl_dir}/${SERVER_KEY_FILENAME:-server.key}" ]; then
mkdir -p $ssl_dir mkdir -p $ssl_dir
confout="${ssl_dir}/conf" confout="${ssl_dir}/conf"
keyout="${ssl_dir}/server.key" keyout="${ssl_dir}/server.key"
certout="${ssl_dir}/server.crt" certout="${ssl_dir}/server.crt"
cakey="${ssl_dir}/ca.key" cakey="${ssl_dir}/.ca.key"
cacert="${ssl_dir}/ca.crt" cacert="${ssl_dir}/.ca.crt"
serialfile="${ssl_dir}/serial" serialfile="${ssl_dir}/.serial"
echo "Generating CA key" echo "Generating CA key"
openssl genrsa -out $cakey 2048 openssl genrsa -out $cakey 2048
@ -75,7 +86,7 @@ else
echo "Generating openssl configuration" echo "Generating openssl configuration"
cat <<EoCertConf>$confout cat <<EoCertConf >$confout
subjectAltName = DNS:${SERVER_HOSTNAME},IP:127.0.0.1 subjectAltName = DNS:${SERVER_HOSTNAME},IP:127.0.0.1
extendedKeyUsage = serverAuth extendedKeyUsage = serverAuth
EoCertConf EoCertConf
@ -113,7 +124,7 @@ EoCertConf
######################## ########################
#Create Apache config #Create Apache config
if [ -f "${ssl_dir}/chain.pem" ]; then ssl_chain="SSLCertificateChainFile ${ssl_dir}/chain.pem"; fi if [ -f "${ssl_dir}/${CA_CERT_FILENAME}" ]; then ssl_chain="SSLCertificateChainFile ${ssl_dir}/${CA_CERT_FILENAME}"; fi
echo > /etc/apache2/sites-enabled/lum.conf echo > /etc/apache2/sites-enabled/lum.conf
echo > /etc/apache2/ports.conf echo > /etc/apache2/ports.conf
@ -152,8 +163,8 @@ EoHTTPrd
</Directory> </Directory>
SSLEngine On SSLEngine On
SSLCertificateFile /opt/ssl/server.crt SSLCertificateFile ${ssl_dir}/${SERVER_CERT_FILENAME:-server.crt}
SSLCertificateKeyFile /opt/ssl/server.key SSLCertificateKeyFile ${ssl_dir}/${SERVER_KEY_FILENAME:-server.key}
$ssl_chain $ssl_chain
</VirtualHost> </VirtualHost>
@ -161,6 +172,9 @@ EoHTTPSC
fi fi
########################
#If <env_var>_FILE is set, read and export env_var from the referenced file's contents
env_file_replace
######################## ########################
#Run Apache #Run Apache

View File

@ -0,0 +1,41 @@
<?php
set_include_path( ".:" . __DIR__ . "/../includes/");
include_once "web_functions.inc.php";
include_once "ldap_functions.inc.php";
include_once "module_functions.inc.php";
set_page_access("admin");
if (!isset($_GET['resource_identifier']) or !isset($_GET['attribute'])) {
exit(0);
}
else {
$this_resource=ldap_escape($_GET['resource_identifier'], "", LDAP_ESCAPE_FILTER);
$this_attribute=ldap_escape($_GET['attribute'], "", LDAP_ESCAPE_FILTER);
}
$exploded = ldap_explode_dn($this_resource,0);
$filter = $exploded[0];
$ldap_connection = open_ldap_connection();
$ldap_search_query="($filter)";
$ldap_search = ldap_search($ldap_connection, $this_resource, $ldap_search_query,array($this_attribute));
if ($ldap_search) {
$records = ldap_get_entries($ldap_connection, $ldap_search);
if ($records['count'] == 1) {
$this_record = $records[0];
if (isset($this_record[$this_attribute][0])) {
header("Content-Type: application/octet-stream");
header("Cache-Control: no-cache private");
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename='${this_resource}.${this_attribute}'");
header("Content-Length: ". strlen($this_record[$this_attribute][0]));
print $this_record[$this_attribute][0];
}
}
}
?>

View File

@ -14,37 +14,18 @@ $ldap_connection = open_ldap_connection();
if (isset($_POST['delete_group'])) { if (isset($_POST['delete_group'])) {
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<?php
$this_group = $_POST['delete_group']; $this_group = $_POST['delete_group'];
$this_group = urldecode($this_group); $this_group = urldecode($this_group);
$del_group = ldap_delete_group($ldap_connection,$this_group); $del_group = ldap_delete_group($ldap_connection,$this_group);
if ($del_group) { if ($del_group) {
?> render_alert_banner("Group <strong>$this_group</strong> was deleted.");
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">Group <strong><?php print $this_group; ?> was deleted.</p>
</div>
<?php
} }
else { else {
?> render_alert_banner("Group <strong>$this_group</strong> wasn't deleted. See the logs for more information.","danger",15000);
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">Group <strong><?php print $this_group; ?></strong> wasn't deleted.</p>
</div>
<?php
} }
} }
$groups = ldap_get_group_list($ldap_connection); $groups = ldap_get_group_list($ldap_connection);
@ -72,18 +53,28 @@ render_js_username_check();
<div class="form-inline" id="new_group_div"> <div class="form-inline" id="new_group_div">
<form action="<?php print "${THIS_MODULE_PATH}"; ?>/show_group.php" method="post"> <form action="<?php print "${THIS_MODULE_PATH}"; ?>/show_group.php" method="post">
<input type="hidden" name="new_group"> <input type="hidden" name="new_group">
<span class="badge badge-secondary" style="font-size:1.9rem;"><?php print count($groups);?> group<?php if (count($groups) != 1) { print "s"; }?></span> &nbsp; <button id="show_new_group" class="form-control btn btn-default" type="button" onclick="show_new_group_form();">New group</button> <button type="button" class="btn btn-light"><?php print count($groups);?> group<?php if (count($groups) != 1) { print "s"; }?></button> &nbsp; <button id="show_new_group" class="form-control btn btn-default" type="button" onclick="show_new_group_form();">New group</button>
<input type="text" class="form-control invisible" name="group_name" id="group_name" placeholder="Group name" onkeyup="check_entity_name_validity(document.getElementById('group_name').value,'new_group_div');"><button id="add_group" class="form-control btn btn-primary btn-sm invisible" type="submit">Add</button> <input type="text" class="form-control invisible" name="group_name" id="group_name" placeholder="Group name" onkeyup="check_entity_name_validity(document.getElementById('group_name').value,'new_group_div');"><button id="add_group" class="form-control btn btn-primary btn-sm invisible" type="submit">Add</button>
</form> </form>
</div> </div>
<input class="form-control" id="search_input" type="text" placeholder="Search..">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th>Group name</th> <th>Group name</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody id="grouplist">
<script>
$(document).ready(function(){
$("#search_input").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#grouplist tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>
<?php <?php
foreach ($groups as $group){ foreach ($groups as $group){
print " <tr>\n <td><a href='${THIS_MODULE_PATH}/show_group.php?group_name=" . urlencode($group) . "'>$group</a></td>\n </tr>\n"; print " <tr>\n <td><a href='${THIS_MODULE_PATH}/show_group.php?group_name=" . urlencode($group) . "'>$group</a></td>\n </tr>\n";

View File

@ -14,46 +14,29 @@ $ldap_connection = open_ldap_connection();
if (isset($_POST['delete_user'])) { if (isset($_POST['delete_user'])) {
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<?php
$this_user = $_POST['delete_user']; $this_user = $_POST['delete_user'];
$this_user = urldecode($this_user); $this_user = urldecode($this_user);
$del_user = ldap_delete_account($ldap_connection,$this_user); $del_user = ldap_delete_account($ldap_connection,$this_user);
if ($del_user) { if ($del_user) {
?> render_alert_banner("User <strong>$this_user</strong> was deleted.");
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">User <strong><?php print $this_user; ?> was deleted.</p>
</div>
<?php
} }
else { else {
?> render_alert_banner("User <strong>$this_user</strong> wasn't deleted. See the logs for more information.","danger",15000);
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">User <strong><?php print $this_user; ?></strong> wasn't deleted.</p>
</div>
<?php
} }
} }
#'
$people = ldap_get_user_list($ldap_connection); $people = ldap_get_user_list($ldap_connection);
?> ?>
<div class="container"> <div class="container">
<form action="<?php print $THIS_MODULE_PATH; ?>/new_user.php" method="post"> <form action="<?php print $THIS_MODULE_PATH; ?>/new_user.php" method="post">
<span class="badge badge-secondary" style="font-size:1.9rem;"><?php print count($people);?> account<?php if (count($people) != 1) { print "s"; }?></span> &nbsp; <button id="add_group" class="btn btn-default" type="submit">New user</button> <button type="button" class="btn btn-light"><?php print count($people);?> account<?php if (count($people) != 1) { print "s"; }?></button> &nbsp; <button id="add_group" class="btn btn-default" type="submit">New user</button>
</form> </form>
<input class="form-control" id="search_input" type="text" placeholder="Search..">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
@ -64,7 +47,17 @@ $people = ldap_get_user_list($ldap_connection);
<th>Member of</th> <th>Member of</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody id="userlist">
<script>
$(document).ready(function(){
$("#search_input").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#userlist tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>
<?php <?php
foreach ($people as $account_identifier => $attribs){ foreach ($people as $account_identifier => $attribs){

View File

@ -6,9 +6,17 @@ include_once "web_functions.inc.php";
include_once "ldap_functions.inc.php"; include_once "ldap_functions.inc.php";
include_once "module_functions.inc.php"; include_once "module_functions.inc.php";
$attribute_map = ldap_complete_account_attribute_array(); $attribute_map = $LDAP['default_attribute_map'];
if (isset($LDAP['account_additional_attributes'])) { $attribute_map = ldap_complete_attribute_array($attribute_map,$LDAP['account_additional_attributes']); }
unset($attribute_map['uidnumber']);
unset($attribute_map['gidnumber']);
if (! array_key_exists($LDAP['account_attribute'], $attribute_map)) {
$attribute_r = array_merge($attribute_map, array($LDAP['account_attribute'] => array("label" => "Account UID")));
}
if ( isset($_POST['setup_admin_account']) ) { if ( isset($_POST['setup_admin_account']) ) {
$admin_setup = TRUE; $admin_setup = TRUE;
validate_setup_cookie(); validate_setup_cookie();
@ -39,45 +47,72 @@ $invalid_email = FALSE;
$disabled_email_tickbox = TRUE; $disabled_email_tickbox = TRUE;
$invalid_cn = FALSE; $invalid_cn = FALSE;
$invalid_account_identifier = FALSE; $invalid_account_identifier = FALSE;
$account_attribute = $LDAP['account_attribute'];
$new_account_r = array(); $new_account_r = array();
foreach ($attribute_map as $attribute => $attr_r) { foreach ($attribute_map as $attribute => $attr_r) {
if (isset($_FILES[$attribute]['size']) and $_FILES[$attribute]['size'] > 0) {
$this_attribute = array();
$this_attribute['count'] = 1;
$this_attribute[0] = file_get_contents($_FILES[$attribute]['tmp_name']);
$$attribute = $this_attribute;
$new_account_r[$attribute] = $this_attribute;
unset($new_account_r[$attribute]['count']);
}
if (isset($_POST[$attribute])) { if (isset($_POST[$attribute])) {
$$attribute = filter_var($_POST[$attribute], FILTER_SANITIZE_STRING);
$this_attribute = array();
if (is_array($_POST[$attribute]) and count($_POST[$attribute]) > 0) {
foreach($_POST[$attribute] as $key => $value) {
if ($value != "") { $this_attribute[$key] = filter_var($value, FILTER_SANITIZE_FULL_SPECIAL_CHARS); }
} }
elseif (isset($attr_r['default'])) { if (count($this_attribute) > 0) {
$$attribute = $attr_r['default']; $this_attribute['count'] = count($this_attribute);
$$attribute = $this_attribute;
} }
if (isset($$attribute)) { $new_account_r[$attribute] = $$attribute; } }
elseif ($_POST[$attribute] != "") {
$this_attribute['count'] = 1;
$this_attribute[0] = filter_var($_POST[$attribute], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$$attribute = $this_attribute;
}
}
if (!isset($$attribute) and isset($attr_r['default'])) {
$$attribute['count'] = 1;
$$attribute[0] = $attr_r['default'];
}
if (isset($$attribute)) {
$new_account_r[$attribute] = $$attribute;
unset($new_account_r[$attribute]['count']);
}
} }
## ##
if (isset($_GET['account_request'])) { if (isset($_GET['account_request'])) {
$givenname=filter_var($_GET['first_name'], FILTER_SANITIZE_STRING); $givenname[0]=filter_var($_GET['first_name'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$new_account_r['givenname'] = $givenname; $new_account_r['givenname'] = $givenname;
unset($new_account_r['givenname']['count']);
$sn=filter_var($_GET['last_name'], FILTER_SANITIZE_STRING); $sn[0]=filter_var($_GET['last_name'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$new_account_r['sn'] = $sn; $new_account_r['sn'] = $sn;
unset($new_account_r['sn']['count']);
$uid = generate_username($givenname,$sn); $mail[0]=filter_var($_GET['email'], FILTER_SANITIZE_EMAIL);
$new_account_r['uid'] = $uid; if ($mail[0] == "") {
if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE) {
$cn = "$givenname$sn";
}
else {
$cn = "$givenname $sn";
}
$new_account_r['cn'] = $cn;
$mail=filter_var($_GET['email'], FILTER_SANITIZE_EMAIL);
if ($mail == "") {
if (isset($EMAIL_DOMAIN)) { if (isset($EMAIL_DOMAIN)) {
$mail = $uid . "@" . $EMAIL_DOMAIN; $mail[0] = $uid . "@" . $EMAIL_DOMAIN;
$disabled_email_tickbox = FALSE; $disabled_email_tickbox = FALSE;
} }
} }
@ -85,27 +120,56 @@ if (isset($_GET['account_request'])) {
$disabled_email_tickbox = FALSE; $disabled_email_tickbox = FALSE;
} }
$new_account_r['mail'] = $mail; $new_account_r['mail'] = $mail;
unset($new_account_r['mail']['count']);
} }
if (isset($_GET['account_request']) or isset($_POST['create_account'])) {
if (!isset($uid[0])) {
$uid[0] = generate_username($givenname[0],$sn[0]);
$new_account_r['uid'] = $uid;
unset($new_account_r['uid']['count']);
}
if (!isset($cn[0])) {
if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE) {
$cn[0] = $givenname[0] . $sn[0];
}
else {
$cn[0] = $givenname[0] . " " . $sn[0];
}
$new_account_r['cn'] = $cn;
unset($new_account_r['cn']['count']);
}
}
if (isset($_POST['create_account'])) { if (isset($_POST['create_account'])) {
$password = $_POST['password']; $password = $_POST['password'];
$new_account_r['password'] = $password; $new_account_r['password'][0] = $password;
$account_identifier = $new_account_r[$LDAP["account_attribute"]]; $account_identifier = $new_account_r[$account_attribute][0];
$this_cn=$cn[0];
$this_mail=$mail[0];
$this_givenname=$givenname[0];
$this_sn=$sn[0];
$this_password=$password[0];
if (!isset($cn) or $cn == "") { $invalid_cn = TRUE; } if (!isset($this_cn) or $this_cn == "") { $invalid_cn = TRUE; }
if ((!isset($account_identifier) or $account_identifier == "") and $invalid_cn != TRUE) { $invalid_account_identifier = TRUE; } if ((!isset($account_identifier) or $account_identifier == "") and $invalid_cn != TRUE) { $invalid_account_identifier = TRUE; }
if ((!is_numeric($_POST['pass_score']) or $_POST['pass_score'] < 3) and $ACCEPT_WEAK_PASSWORDS != TRUE) { $weak_password = TRUE; } if ((!is_numeric($_POST['pass_score']) or $_POST['pass_score'] < 3) and $ACCEPT_WEAK_PASSWORDS != TRUE) { $weak_password = TRUE; }
if (isset($mail) and !is_valid_email($mail)) { $invalid_email = TRUE; } if (isset($this_mail) and !is_valid_email($this_mail)) { $invalid_email = TRUE; }
if (preg_match("/\"|'/",$password)) { $invalid_password = TRUE; } if (preg_match("/\"|'/",$password)) { $invalid_password = TRUE; }
if ($password != $_POST['password_match']) { $mismatched_passwords = TRUE; } if ($password != $_POST['password_match']) { $mismatched_passwords = TRUE; }
if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE and !preg_match("/$POSIX_REGEX/",$account_identifier)) { $invalid_account_identifier = TRUE; } if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE and !preg_match("/$USERNAME_REGEX/",$account_identifier)) { $invalid_account_identifier = TRUE; }
if (isset($_POST['send_email']) and isset($mail) and $EMAIL_SENDING_ENABLED == TRUE) { $send_user_email = TRUE; } if (isset($_POST['send_email']) and isset($mail) and $EMAIL_SENDING_ENABLED == TRUE) { $send_user_email = TRUE; }
if ( isset($givenname) if ( isset($this_givenname)
and isset($sn) and isset($this_sn)
and isset($password) and isset($this_password)
and !$mismatched_passwords and !$mismatched_passwords
and !$weak_password and !$weak_password
and !$invalid_password and !$invalid_password
@ -124,13 +188,13 @@ if (isset($_POST['create_account'])) {
include_once "mail_functions.inc.php"; include_once "mail_functions.inc.php";
$mail_body = parse_mail_text($new_account_mail_body, $password, $account_identifier, $givenname, $sn); $mail_body = parse_mail_text($new_account_mail_body, $password, $account_identifier, $this_givenname, $this_sn);
$mail_subject = parse_mail_text($new_account_mail_subject, $password, $account_identifier, $givenname, $sn); $mail_subject = parse_mail_text($new_account_mail_subject, $password, $account_identifier, $this_givenname, $this_sn);
$sent_email = send_email($mail,"$givenname $sn",$mail_subject,$mail_body); $sent_email = send_email($this_mail,"$this_givenname $this_sn",$mail_subject,$mail_body);
$creation_message = "The account was created"; $creation_message = "The account was created";
if ($sent_email) { if ($sent_email) {
$creation_message .= " and an email sent to $mail."; $creation_message .= " and an email sent to $this_mail.";
} }
else { else {
$creation_message .= " but unfortunately the email wasn't sent.<br>More information will be available in the logs."; $creation_message .= " but unfortunately the email wasn't sent.<br>More information will be available in the logs.";
@ -189,7 +253,7 @@ if (isset($_POST['create_account'])) {
$errors=""; $errors="";
if ($invalid_cn) { $errors.="<li>The Common Name is required</li>\n"; } if ($invalid_cn) { $errors.="<li>The Common Name is required</li>\n"; }
if ($invalid_account_identifier) { $errors.="<li>The account identifier (" . $attribute_map[$LDAP['account_attribute']]['label'] . ") is invalid.</li>\n"; } if ($invalid_account_identifier) { $errors.="<li>The account identifier (" . $attribute_map[$account_attribute]['label'] . ") is invalid.</li>\n"; }
if ($weak_password) { $errors.="<li>The password is too weak</li>\n"; } if ($weak_password) { $errors.="<li>The password is too weak</li>\n"; }
if ($invalid_password) { $errors.="<li>The password contained invalid characters</li>\n"; } if ($invalid_password) { $errors.="<li>The password contained invalid characters</li>\n"; }
if ($invalid_email) { $errors.="<li>The email address is invalid</li>\n"; } if ($invalid_email) { $errors.="<li>The email address is invalid</li>\n"; }
@ -212,6 +276,7 @@ render_js_username_check();
render_js_username_generator('givenname','sn','uid','uid_div'); render_js_username_generator('givenname','sn','uid','uid_div');
render_js_cn_generator('givenname','sn','cn','cn_div'); render_js_cn_generator('givenname','sn','cn','cn_div');
render_js_email_generator('uid','mail'); render_js_email_generator('uid','mail');
render_js_homedir_generator('uid','homedirectory');
$tabindex=1; $tabindex=1;
@ -273,37 +338,32 @@ $tabindex=1;
</script> </script>
<?php render_dynamic_field_js(); ?>
<div class="container"> <div class="container">
<div class="col-sm-8"> <div class="col-sm-8 col-md-offset-2">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading text-center"><?php print $page_title; ?></div> <div class="panel-heading text-center"><?php print $page_title; ?></div>
<div class="panel-body text-center"> <div class="panel-body text-center">
<form class="form-horizontal" action="" method="post"> <form class="form-horizontal" action="" enctype="multipart/form-data" method="post">
<?php if ($admin_setup == TRUE) { ?><input type="hidden" name="setup_admin_account" value="true"><?php } ?> <?php if ($admin_setup == TRUE) { ?><input type="hidden" name="setup_admin_account" value="true"><?php } ?>
<input type="hidden" name="create_account"> <input type="hidden" name="create_account">
<input type="hidden" id="pass_score" value="0" name="pass_score"> <input type="hidden" id="pass_score" value="0" name="pass_score">
<?php
<?php
foreach ($attribute_map as $attribute => $attr_r) { foreach ($attribute_map as $attribute => $attr_r) {
$label = $attr_r['label']; $label = $attr_r['label'];
if (isset($attr_r['onkeyup'])) { $onkeyup = $attr_r['onkeyup']; } else { $onkeyup = ""; }
if ($attribute == $LDAP['account_attribute']) { $label = "<strong>$label</strong><sup>&ast;</sup>"; } if ($attribute == $LDAP['account_attribute']) { $label = "<strong>$label</strong><sup>&ast;</sup>"; }
?> if (isset($$attribute)) { $these_values=$$attribute; } else { $these_values = array(); }
<div class="form-group" id="<?php print $attribute; ?>_div"> if (isset($attr_r['inputtype'])) { $inputtype = $attr_r['inputtype']; } else { $inputtype = ""; }
<label for="<?php print $attribute; ?>" class="col-sm-3 control-label"><?php print $label; ?></label> render_attribute_fields($attribute,$label,$these_values,"",$onkeyup,$inputtype,$tabindex);
<div class="col-sm-6">
<input tabindex="<?php print $tabindex; ?>" type="text" class="form-control" id="<?php print $attribute; ?>" name="<?php print $attribute; ?>" value="<?php if (isset($$attribute)) { print $$attribute; } ?>" <?php
if (isset($attr_r['onkeyup'])) { print "onkeyup=\"${attr_r['onkeyup']};\""; } ?>>
</div>
</div>
<?php
$tabindex++; $tabindex++;
} }
?> ?>
<div class="form-group" id="password_div"> <div class="form-group" id="password_div">
<label for="password" class="col-sm-3 control-label">Password</label> <label for="password" class="col-sm-3 control-label">Password</label>

View File

@ -12,55 +12,126 @@ render_submenu();
$ldap_connection = open_ldap_connection(); $ldap_connection = open_ldap_connection();
if (!isset($_POST['group_name']) and !isset($_GET['group_name'])) { if (!isset($_POST['group_name']) and !isset($_GET['group_name'])) {
?> ?>
<div class="alert alert-danger"> <div class="alert alert-danger">
<p class="text-center">The group name is missing.</p> <p class="text-center">The group name is missing.</p>
</div> </div>
<?php <?php
render_footer(); render_footer();
exit(0); exit(0);
} }
else { else {
$group_cn = (isset($_POST['group_name']) ? $_POST['group_name'] : $_GET['group_name']); $group_cn = (isset($_POST['group_name']) ? $_POST['group_name'] : $_GET['group_name']);
$group_cn = urldecode($group_cn); $group_cn = urldecode($group_cn);
} }
if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE and !preg_match("/$POSIX_REGEX/",$group_cn)) { if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE and !preg_match("/$USERNAME_REGEX/",$group_cn)) {
?> ?>
<div class="alert alert-danger"> <div class="alert alert-danger">
<p class="text-center">The group name is invalid.</p> <p class="text-center">The group name is invalid.</p>
</div> </div>
<?php <?php
render_footer(); render_footer();
exit(0); exit(0);
} }
###################################################################################### ######################################################################################
$initialise_group = FALSE;
$new_group = FALSE;
$group_exists = FALSE;
$create_group_message = "Add members to create the new group";
$current_members = array();
$full_dn = $create_group_message;
$has_been = "";
$attribute_map = $LDAP['default_group_attribute_map'];
if (isset($LDAP['group_additional_attributes'])) {
$attribute_map = ldap_complete_attribute_array($attribute_map,$LDAP['group_additional_attributes']);
}
$to_update = array();
$this_group = array();
if (isset($_POST['new_group'])) { if (isset($_POST['new_group'])) {
$new_group = TRUE; $new_group = TRUE;
$current_members = array();
$full_dn = "Add members to create the new group";
$has_been = "";
} }
elseif (isset($_POST['initialise_group'])) { elseif (isset($_POST['initialise_group'])) {
$new_group = FALSE;
$initialise_group = TRUE; $initialise_group = TRUE;
$current_members = array();
$full_dn = "${LDAP['group_attribute']}=$group_cn,${LDAP['group_dn']}"; $full_dn = "${LDAP['group_attribute']}=$group_cn,${LDAP['group_dn']}";
$has_been = "created"; $has_been = "created";
} }
else { else {
$new_group = FALSE; $this_group = ldap_get_group_entry($ldap_connection,$group_cn);
$initialise_group = TRUE; if ($this_group) {
$current_members = ldap_get_group_members($ldap_connection,$group_cn); $current_members = ldap_get_group_members($ldap_connection,$group_cn);
$full_dn = ldap_get_dn_of_group($ldap_connection,$group_cn); $full_dn = $this_group[0]['dn'];
$has_been = "updated"; $has_been = "updated";
}
else {
$new_group = TRUE;
}
} }
foreach ($attribute_map as $attribute => $attr_r) {
if (isset($this_group[0][$attribute]) and $this_group[0][$attribute]['count'] > 0) {
$$attribute = $this_group[0][$attribute];
}
else {
$$attribute = array();
}
if (isset($_FILES[$attribute]['size']) and $_FILES[$attribute]['size'] > 0) {
$this_attribute = array();
$this_attribute['count'] = 1;
$this_attribute[0] = file_get_contents($_FILES[$attribute]['tmp_name']);
$$attribute = $this_attribute;
$to_update[$attribute] = $this_attribute;
unset($to_update[$attribute]['count']);
}
if (isset($_POST[$attribute])) {
$this_attribute = array();
if (is_array($_POST[$attribute])) {
foreach($_POST[$attribute] as $key => $value) {
if ($value != "") { $this_attribute[$key] = filter_var($value, FILTER_SANITIZE_FULL_SPECIAL_CHARS); }
}
$this_attribute['count'] = count($this_attribute);
}
elseif ($_POST[$attribute] != "") {
$this_attribute['count'] = 1;
$this_attribute[0] = filter_var($_POST[$attribute], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
}
if ($this_attribute != $$attribute) {
$$attribute = $this_attribute;
$to_update[$attribute] = $this_attribute;
unset($to_update[$attribute]['count']);
}
}
if (!isset($$attribute) and isset($attr_r['default'])) {
$$attribute['count'] = 1;
$$attribute[0] = $attr_r['default'];
}
}
if (!isset($gidnumber[0]) or !is_numeric($gidnumber[0])) {
$gidnumber[0]=ldap_get_highest_id($ldap_connection,$type="gid");
$gidnumber['count']=1;
}
######################################################################################
$all_accounts = ldap_get_user_list($ldap_connection); $all_accounts = ldap_get_user_list($ldap_connection);
$all_people = array(); $all_people = array();
@ -75,10 +146,9 @@ if (isset($_POST["update_members"])) {
$updated_membership = array(); $updated_membership = array();
foreach ($_POST as $index => $member) { foreach ($_POST['membership'] as $index => $member) {
if (is_numeric($index)) { if (is_numeric($index)) {
array_push($updated_membership,$member); array_push($updated_membership,filter_var($member, FILTER_SANITIZE_FULL_SPECIAL_CHARS));
} }
} }
@ -90,9 +160,42 @@ if (isset($_POST["update_members"])) {
$members_to_add = array_diff($updated_membership,$current_members); $members_to_add = array_diff($updated_membership,$current_members);
if ($initialise_group == TRUE) { if ($initialise_group == TRUE) {
$initial_member = array_shift($members_to_add); $initial_member = array_shift($members_to_add);
$group_add = ldap_new_group($ldap_connection,$group_cn,$initial_member); $group_add = ldap_new_group($ldap_connection,$group_cn,$initial_member,$to_update);
if (!$group_add) {
render_alert_banner("There was a problem creating the group. See the logs for more information.","danger",10000);
$group_exists = FALSE;
$new_group = TRUE;
} }
else {
$group_exists = TRUE;
$new_group = FALSE;
}
}
if ($group_exists == TRUE) {
if ($initialise_group != TRUE and count($to_update) > 0) {
if (isset($this_group[0]['objectclass'])) {
$existing_objectclasses = $this_group[0]['objectclass'];
unset($existing_objectclasses['count']);
if ($existing_objectclasses != $LDAP['group_objectclasses']) { $to_update['objectclass'] = $LDAP['group_objectclasses']; }
}
$updated_attr = ldap_update_group_attributes($ldap_connection,$group_cn,$to_update);
if ($updated_attr) {
render_alert_banner("The group attributes have been updated.");
}
else {
render_alert_banner("There was a problem updating the group attributes. See the logs for more information.","danger",15000);
}
}
foreach ($members_to_add as $this_member) { foreach ($members_to_add as $this_member) {
ldap_add_member_to_group($ldap_connection,$group_cn,$this_member); ldap_add_member_to_group($ldap_connection,$group_cn,$this_member);
} }
@ -104,22 +207,30 @@ if (isset($_POST["update_members"])) {
$non_members = array_diff($all_people,$updated_membership); $non_members = array_diff($all_people,$updated_membership);
$group_members = $updated_membership; $group_members = $updated_membership;
?> $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection);
<script> if ($rfc2307bis_available == TRUE and count($group_members) == 0) {
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">The group has been <?php print $has_been; ?>.</p>
</div>
<?php $group_members = ldap_get_group_members($ldap_connection,$group_cn);
$non_members = array_diff($all_people,$group_members);
render_alert_banner("Groups can't be empty, so the final member hasn't been removed. You could try deleting the group","danger",15000);
}
else {
render_alert_banner("The group has been ${has_been}.");
}
}
else {
$group_members = array();
$non_members = $all_people;
}
} }
else { else {
$group_members = $current_members; $group_members = $current_members;
} }
ldap_close($ldap_connection); ldap_close($ldap_connection);
@ -147,7 +258,7 @@ ldap_close($ldap_connection);
for (var i = 0; i < member_list.length; ++i) { for (var i = 0; i < member_list.length; ++i) {
var hidden = document.createElement("input"); var hidden = document.createElement("input");
hidden.type = "hidden"; hidden.type = "hidden";
hidden.name = i; hidden.name = 'membership[]';
hidden.value = member_list[i]['textContent']; hidden.value = member_list[i]['textContent'];
members_form.appendChild(hidden); members_form.appendChild(hidden);
@ -175,7 +286,10 @@ ldap_close($ldap_connection);
$('.list-right ul li.active').removeClass('active'); $('.list-right ul li.active').removeClass('active');
actives.remove(); actives.remove();
} }
if ($("#membership_list").length > 0) {
$("#submit_members").prop("disabled", false); $("#submit_members").prop("disabled", false);
$("#submit_attributes").prop("disabled", false);
}
}); });
$('.dual-list .selector').click(function () { $('.dual-list .selector').click(function () {
var $checkBox = $(this); var $checkBox = $(this);
@ -226,22 +340,23 @@ ldap_close($ldap_connection);
</style> </style>
<div class="container"> <div class="container">
<div class="col-md-12">
<div class="panel-group">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading clearfix"> <div class="panel-heading clearfix">
<h3 class="panel-title pull-left" style="padding-top: 7.5px;"><?php print $group_cn; ?><?php if ($group_cn == $LDAP["admins_group"]) { print " <sup>(admin group)</sup>" ; } ?></h3> <h3 class="panel-title pull-left" style="padding-top: 7.5px;"><?php print $group_cn; ?><?php if ($group_cn == $LDAP["admins_group"]) { print " <sup>(admin group)</sup>" ; } ?></h3>
<button class="btn btn-warning pull-right" onclick="show_delete_group_button();" <?php if ($group_cn == $LDAP["admins_group"]) { print "disabled"; } ?>>Delete group</button> <button class="btn btn-warning pull-right" onclick="show_delete_group_button();" <?php if ($group_cn == $LDAP["admins_group"]) { print "disabled"; } ?>>Delete group</button>
<form action="<?php print "${THIS_MODULE_PATH}"; ?>/groups.php" method="post"><input type="hidden" name="delete_group" value="<?php print $group_cn; ?>"><button class="btn btn-danger pull-right invisible" id="delete_group">Confirm deletion</button></form> <form action="<?php print "${THIS_MODULE_PATH}"; ?>/groups.php" method="post" enctype="multipart/form-data"><input type="hidden" name="delete_group" value="<?php print $group_cn; ?>"><button class="btn btn-danger pull-right invisible" id="delete_group">Confirm deletion</button></form>
</div> </div>
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item"><?php print $full_dn; ?></li> <li class="list-group-item"><?php print $full_dn; ?></li>
</li> </li>
<div class="panel-body"> <div class="panel-body">
<div class="row"> <div class="row">
<div class="dual-list list-left col-md-5"> <div class="dual-list list-left col-md-5">
<strong>Members</strong> <strong>Members</strong>
<div class="well"> <div class="well">
@ -272,7 +387,6 @@ ldap_close($ldap_connection);
</ul> </ul>
</div> </div>
</div> </div>
<div class="list-arrows col-md-1 text-center"> <div class="list-arrows col-md-1 text-center">
<button class="btn btn-default btn-sm move-left"> <button class="btn btn-default btn-sm move-left">
<span class="glyphicon glyphicon-chevron-left"></span> <span class="glyphicon glyphicon-chevron-left"></span>
@ -280,12 +394,11 @@ ldap_close($ldap_connection);
<button class="btn btn-default btn-sm move-right"> <button class="btn btn-default btn-sm move-right">
<span class="glyphicon glyphicon-chevron-right"></span> <span class="glyphicon glyphicon-chevron-right"></span>
</button> </button>
<form id="group_members" action="<?php print "${THIS_MODULE_PATH}"; ?>/show_group.php" method="post"> <form id="group_members" action="<?php print $CURRENT_PAGE; ?>" method="post">
<input type="hidden" name="update_members"> <input type="hidden" name="update_members">
<input type="hidden" name="group_name" value="<?php print urlencode($group_cn); ?>"> <input type="hidden" name="group_name" value="<?php print urlencode($group_cn); ?>">
<?php if ($new_group == TRUE) { ?><input type="hidden" name="initialise_group"><?php } ?> <?php if ($new_group == TRUE) { ?><input type="hidden" name="initialise_group"><?php } ?>
</form> <button id="submit_members" class="btn btn-info" <?php if (count($group_members)==0) print 'disabled'; ?> type="submit" onclick="update_form_with_users()">Save</button>
<button id="submit_members" class="btn btn-info" disabled type="submit" onclick="update_form_with_users()">Save</button>
</div> </div>
<div class="dual-list list-right col-md-5"> <div class="dual-list list-right col-md-5">
@ -313,12 +426,44 @@ ldap_close($ldap_connection);
</ul> </ul>
</div> </div>
</div> </div>
</div>
</div>
</div>
<?php
if (count($attribute_map) > 0) { ?>
<div class="panel panel-default">
<div class="panel-heading clearfix">
<h3 class="panel-title pull-left" style="padding-top: 7.5px;">Group attributes</h3>
</div>
<div class="panel-body">
<div class="col-md-8">
<?php
$tabindex=1;
foreach ($attribute_map as $attribute => $attr_r) {
$label = $attr_r['label'];
if (isset($$attribute)) { $these_values=$$attribute; } else { $these_values = array(); }
print "<div class='row'>";
$dl_identifider = ($full_dn != $create_group_message) ? $full_dn : "";
if (isset($attr_r['inputtype'])) { $inputtype = $attr_r['inputtype']; } else { $inputtype=""; }
render_attribute_fields($attribute,$label,$these_values,$dl_identifider,"",$inputtype,$tabindex);
print "</div>";
$tabindex++;
}
?>
<div class="row">
<div class="col-md-4 col-md-offset-3">
<div class="form-group">
<button id="submit_attributes" class="btn btn-info" <?php if (count($group_members)==0) print 'disabled'; ?> type="submit" tabindex="<?php print $tabindex; ?>" onclick="update_form_with_users()">Save</button>
</div>
</div>
</div>
</div>
</div>
</div>
<?php } ?>
</form>
</div>
</div> </div>
</div> </div>
<?php render_footer(); ?>
<?php
render_footer();
?>

View File

@ -18,13 +18,13 @@ $to_update = array();
if ($SMTP['host'] != "") { $can_send_email = TRUE; } else { $can_send_email = FALSE; } if ($SMTP['host'] != "") { $can_send_email = TRUE; } else { $can_send_email = FALSE; }
$LDAP['default_attribute_map']["uidnumber"] = array("label" => "UID");
$LDAP['default_attribute_map']["gidnumber"] = array("label" => "GID");
$LDAP['default_attribute_map']["loginshell"] = array("label" => "Login shell");
$LDAP['default_attribute_map']["homedirectory"] = array("label" => "Home directory");
$LDAP['default_attribute_map']["mail"] = array("label" => "Email", "onkeyup" => "check_if_we_should_enable_sending_email();"); $LDAP['default_attribute_map']["mail"] = array("label" => "Email", "onkeyup" => "check_if_we_should_enable_sending_email();");
$attribute_map = ldap_complete_account_attribute_array(); $attribute_map = $LDAP['default_attribute_map'];
if (isset($LDAP['account_additional_attributes'])) { $attribute_map = ldap_complete_attribute_array($attribute_map,$LDAP['account_additional_attributes']); }
if (! array_key_exists($LDAP['account_attribute'], $attribute_map)) {
$attribute_r = array_merge($attribute_map, array($LDAP['account_attribute'] => array("label" => "Account UID")));
}
if (!isset($_POST['account_identifier']) and !isset($_GET['account_identifier'])) { if (!isset($_POST['account_identifier']) and !isset($_GET['account_identifier'])) {
?> ?>
@ -44,30 +44,98 @@ $ldap_connection = open_ldap_connection();
$ldap_search_query="(${LDAP['account_attribute']}=". ldap_escape($account_identifier, "", LDAP_ESCAPE_FILTER) . ")"; $ldap_search_query="(${LDAP['account_attribute']}=". ldap_escape($account_identifier, "", LDAP_ESCAPE_FILTER) . ")";
$ldap_search = ldap_search( $ldap_connection, $LDAP['user_dn'], $ldap_search_query); $ldap_search = ldap_search( $ldap_connection, $LDAP['user_dn'], $ldap_search_query);
#########################
if ($ldap_search) { if ($ldap_search) {
$user = ldap_get_entries($ldap_connection, $ldap_search); $user = ldap_get_entries($ldap_connection, $ldap_search);
if ($user["count"] > 0) {
foreach ($attribute_map as $attribute => $attr_r) { foreach ($attribute_map as $attribute => $attr_r) {
$$attribute = $user[0][$attribute][0]; if (isset($user[0][$attribute]) and $user[0][$attribute]['count'] > 0) {
$$attribute = $user[0][$attribute];
if (isset($_POST['update_account']) and isset($_POST[$attribute]) and $_POST[$attribute] != $$attribute) {
$$attribute = filter_var($_POST[$attribute], FILTER_SANITIZE_STRING);
$to_update[$attribute] = $$attribute;
} }
elseif (isset($attr_r['default'])) { else {
$$attribute = $attr_r['default']; $$attribute = array();
}
if (isset($_FILES[$attribute]['size']) and $_FILES[$attribute]['size'] > 0) {
$this_attribute = array();
$this_attribute['count'] = 1;
$this_attribute[0] = file_get_contents($_FILES[$attribute]['tmp_name']);
$$attribute = $this_attribute;
$to_update[$attribute] = $this_attribute;
unset($to_update[$attribute]['count']);
}
if (isset($_POST['update_account']) and isset($_POST[$attribute])) {
$this_attribute = array();
if (is_array($_POST[$attribute])) {
foreach($_POST[$attribute] as $key => $value) {
if ($value != "") { $this_attribute[$key] = filter_var($value, FILTER_SANITIZE_FULL_SPECIAL_CHARS); }
}
$this_attribute['count'] = count($this_attribute);
}
elseif ($_POST[$attribute] != "") {
$this_attribute['count'] = 1;
$this_attribute[0] = filter_var($_POST[$attribute], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
}
if ($this_attribute != $$attribute) {
$$attribute = $this_attribute;
$to_update[$attribute] = $this_attribute;
unset($to_update[$attribute]['count']);
}
}
if (!isset($$attribute) and isset($attr_r['default'])) {
$$attribute['count'] = 1;
$$attribute[0] = $attr_r['default'];
} }
} }
$dn = $user[0]['dn']; $dn = $user[0]['dn'];
}
else {
?>
<div class="alert alert-danger">
<p class="text-center">This account doesn't exist.</p>
</div>
<?php
render_footer();
exit(0);
}
### Update values ### Update values
if (isset($_POST['update_account'])) { if (isset($_POST['update_account'])) {
if (!isset($uid[0])) {
$uid[0] = generate_username($givenname[0],$sn[0]);
$to_update['uid'] = $uid;
unset($to_update['uid']['count']);
}
if (!isset($cn[0])) {
if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE) {
$cn[0] = $givenname[0] . $sn[0];
}
else {
$cn[0] = $givenname[0] . " " . $sn[0];
}
$to_update['cn'] = $cn;
unset($to_update['cn']['count']);
}
if (isset($_POST['password']) and $_POST['password'] != "") { if (isset($_POST['password']) and $_POST['password'] != "") {
$password = $_POST['password']; $password = $_POST['password'];
@ -81,16 +149,18 @@ if ($ldap_search) {
and !$weak_password and !$weak_password
and !$invalid_password and !$invalid_password
) { ) {
$to_update['userpassword'] = ldap_hashed_password($password); $to_update['userpassword'][0] = ldap_hashed_password($password);
} }
} }
if (array_key_exists($LDAP['account_attribute'], $to_update)) { if (array_key_exists($LDAP['account_attribute'], $to_update)) {
$new_rdn = "${LDAP['account_attribute']}=${to_update[$LDAP['account_attribute']]}"; $account_attribute = $LDAP['account_attribute'];
$new_account_identifier = $to_update[$account_attribute][0];
$new_rdn = "${account_attribute}=${new_account_identifier}";
$renamed_entry = ldap_rename($ldap_connection, $dn, $new_rdn, $LDAP['user_dn'], true); $renamed_entry = ldap_rename($ldap_connection, $dn, $new_rdn, $LDAP['user_dn'], true);
if ($renamed_entry) { if ($renamed_entry) {
$dn = "${new_rdn},${LDAP['user_dn']}"; $dn = "${new_rdn},${LDAP['user_dn']}";
$account_identifier = $to_update[$LDAP['account_attribute']]; $account_identifier = $new_account_identifier;
} }
else { else {
ldap_get_option($ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detailed_err); ldap_get_option($ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detailed_err);
@ -98,7 +168,12 @@ if ($ldap_search) {
} }
} }
$existing_objectclasses = $user[0]['objectclass'];
unset($existing_objectclasses['count']);
if ($existing_objectclasses != $LDAP['account_objectclasses']) { $to_update['objectclass'] = $LDAP['account_objectclasses']; }
$updated_account = @ ldap_mod_replace($ldap_connection, $dn, $to_update); $updated_account = @ ldap_mod_replace($ldap_connection, $dn, $to_update);
if (!$updated_account) { if (!$updated_account) {
ldap_get_option($ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detailed_err); ldap_get_option($ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detailed_err);
error_log("$log_prefix Failed to modify account details for ${account_identifier}: " . ldap_error($ldap_connection) . " -- " . $detailed_err,0); error_log("$log_prefix Failed to modify account details for ${account_identifier}: " . ldap_error($ldap_connection) . " -- " . $detailed_err,0);
@ -122,30 +197,10 @@ if ($ldap_search) {
} }
if ($updated_account) { if ($updated_account) {
?> render_alert_banner("The account has been updated. $sent_email_message");
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">The account has been updated.<?php print $sent_email_message; ?></p>
</div>
<?php
} }
else { else {
?> render_alert_banner("There was a problem updating the account. Check the logs for more information.","danger",15000);
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">There was a problem updating the account. Check the logs for more information.</p>
</div>
<?php
} }
} }
@ -206,19 +261,7 @@ if ($ldap_search) {
$not_member_of = array_diff($all_groups,$updated_group_membership); $not_member_of = array_diff($all_groups,$updated_group_membership);
$member_of = $updated_group_membership; $member_of = $updated_group_membership;
render_alert_banner("The group membership has been updated.");
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">The group membership has been updated.</p>
</div>
<?php
} }
else { else {
@ -366,6 +409,9 @@ if ($ldap_search) {
} }
</script> </script>
<?php render_dynamic_field_js(); ?>
<style type='text/css'> <style type='text/css'>
.dual-list .list-group { .dual-list .list-group {
margin-top: 8px; margin-top: 8px;
@ -403,30 +449,22 @@ if ($ldap_search) {
<li class="list-group-item"><?php print $dn; ?></li> <li class="list-group-item"><?php print $dn; ?></li>
</li> </li>
<div class="panel-body"> <div class="panel-body">
<form class="form-horizontal" action="" method="post"> <form class="form-horizontal" action="" enctype="multipart/form-data" method="post">
<input type="hidden" name="update_account"> <input type="hidden" name="update_account">
<input type="hidden" id="pass_score" value="0" name="pass_score"> <input type="hidden" id="pass_score" value="0" name="pass_score">
<input type="hidden" name="account_identifier" value="<?php print $account_identifier; ?>"> <input type="hidden" name="account_identifier" value="<?php print $account_identifier; ?>">
<?php
<?php
foreach ($attribute_map as $attribute => $attr_r) { foreach ($attribute_map as $attribute => $attr_r) {
$label = $attr_r['label']; $label = $attr_r['label'];
if (isset($attr_r['onkeyup'])) { $onkeyup = $attr_r['onkeyup']; } else { $onkeyup = ""; } if (isset($attr_r['onkeyup'])) { $onkeyup = $attr_r['onkeyup']; } else { $onkeyup = ""; }
if (isset($attr_r['inputtype'])) { $inputtype = $attr_r['inputtype']; } else { $inputtype = ""; }
if ($attribute == $LDAP['account_attribute']) { $label = "<strong>$label</strong><sup>&ast;</sup>"; } if ($attribute == $LDAP['account_attribute']) { $label = "<strong>$label</strong><sup>&ast;</sup>"; }
?> if (isset($$attribute)) { $these_values=$$attribute; } else { $these_values = array(); }
<div class="form-group" id="<?php print $attribute; ?>_div"> render_attribute_fields($attribute,$label,$these_values,$dn,$onkeyup,$inputtype);
<label for="<?php print $attribute; ?>" class="col-sm-3 control-label"><?php print $label; ?></label>
<div class="col-sm-6">
<input type="text" class="form-control" id="<?php print $attribute; ?>" name="<?php print $attribute; ?>" value="<?php if (isset($$attribute)) { print $$attribute; } ?>" <?php
if (isset($onkeyup)) { print "onkeyup=\"$onkeyup;\""; } ?>>
</div>
</div>
<?php
} }
?> ?>
<div class="form-group" id="password_div"> <div class="form-group" id="password_div">
<label for="password" class="col-sm-3 control-label">Password</label> <label for="password" class="col-sm-3 control-label">Password</label>
@ -522,7 +560,7 @@ if ($ldap_search) {
<button class="btn btn-default btn-sm move-right"> <button class="btn btn-default btn-sm move-right">
<span class="glyphicon glyphicon-chevron-right"></span> <span class="glyphicon glyphicon-chevron-right"></span>
</button> </button>
<form id="update_with_groups" action="<?php print "${THIS_MODULE_PATH}"; ?>/show_user.php" method="post"> <form id="update_with_groups" action="<?php print $CURRENT_PAGE ?>" method="post">
<input type="hidden" name="update_member_of"> <input type="hidden" name="update_member_of">
<input type="hidden" name="account_identifier" value="<?php print $account_identifier; ?>"> <input type="hidden" name="account_identifier" value="<?php print $account_identifier; ?>">
</form> </form>

View File

@ -21,8 +21,15 @@ if (isset($_POST['change_password'])) {
render_header("$ORGANISATION_NAME account manager - password changed"); render_header("$ORGANISATION_NAME account manager - password changed");
?> ?>
<div class="alert alert-success"> <div class="container">
<p class="text-center">Your password has been changed.</p> <div class="col-sm-6 col-sm-offset-3">
<div class="panel panel-success">
<div class="panel-heading">Success</div>
<div class="panel-body">
Your password has been updated.
</div>
</div>
</div>
</div> </div>
<?php <?php
render_footer(); render_footer();
@ -58,7 +65,7 @@ if (isset($mismatched)) { ?>
<script type="text/javascript">$(document).ready(function(){ $("#StrengthProgressBar").zxcvbnProgressBar({ passwordInput: "#password" });});</script> <script type="text/javascript">$(document).ready(function(){ $("#StrengthProgressBar").zxcvbnProgressBar({ passwordInput: "#password" });});</script>
<div class="container"> <div class="container">
<div class="col-sm-6"> <div class="col-sm-6 col-sm-offset-3">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading text-center">Change your password</div> <div class="panel-heading text-center">Change your password</div>

View File

@ -1,50 +1,99 @@
<?php <?php
$log_prefix = ""; $log_prefix="";
#Fixed # User account defaults
$DEFAULT_USER_GROUP = (getenv('DEFAULT_USER_GROUP') ? getenv('DEFAULT_USER_GROUP') : 'everybody');
$DEFAULT_USER_SHELL = (getenv('DEFAULT_USER_SHELL') ? getenv('DEFAULT_USER_SHELL') : '/bin/bash');
$ENFORCE_SAFE_SYSTEM_NAMES = ((strcasecmp(getenv('ENFORCE_SAFE_SYSTEM_NAMES'),'FALSE') == 0) ? FALSE : TRUE);
$USERNAME_FORMAT = (getenv('USERNAME_FORMAT') ? getenv('USERNAME_FORMAT') : '{first_name}-{last_name}');
$USERNAME_REGEX = (getenv('USERNAME_REGEX') ? getenv('USERNAME_REGEX') : '^[a-z][a-zA-Z0-9\._-]{3,32}$'); #We use the username regex for groups too.
if (getenv('PASSWORD_HASH')) { $PASSWORD_HASH = strtoupper(getenv('PASSWORD_HASH')); }
$ACCEPT_WEAK_PASSWORDS = ((strcasecmp(getenv('ACCEPT_WEAK_PASSWORDS'),'TRUE') == 0) ? TRUE : FALSE);
$min_uid = 2000;
$min_gid = 2000;
#Default attributes and objectclasses
$LDAP['account_attribute'] = (getenv('LDAP_ACCOUNT_ATTRIBUTE') ? getenv('LDAP_ACCOUNT_ATTRIBUTE') : 'uid');
$LDAP['account_objectclasses'] = array( 'person', 'inetOrgPerson', 'posixAccount' ); $LDAP['account_objectclasses'] = array( 'person', 'inetOrgPerson', 'posixAccount' );
$LDAP['default_attribute_map'] = array( "givenname" => array("label" => "First name", "onkeyup" => "update_username(); update_email(); update_cn(); check_email_validity(document.getElementById('mail').value)"), $LDAP['default_attribute_map'] = array( "givenname" => array("label" => "First name", "onkeyup" => "update_username(); update_email(); update_cn(); update_homedir(); check_email_validity(document.getElementById('mail').value);"),
"sn" => array("label" => "Last name", "onkeyup" => "update_username(); update_email(); update_cn(); check_email_validity(document.getElementById('mail').value)"), "sn" => array("label" => "Last name", "onkeyup" => "update_username(); update_email(); update_cn(); update_homedir(); check_email_validity(document.getElementById('mail').value);"),
"uid" => array("label" => "System username", "onkeyup" => "check_entity_name_validity(document.getElementById('uid').value,'uid_div'); update_email(); check_email_validity(document.getElementById('mail').value)"), "uid" => array("label" => "System username", "onkeyup" => "check_entity_name_validity(document.getElementById('uid').value,'uid_div'); update_email(); update_homedir(); check_email_validity(document.getElementById('mail').value);"),
"cn" => array("label" => "Common Name", "onkeyup" => "auto_cn_update = false;"), "cn" => array("label" => "Common name", "onkeyup" => "auto_cn_update = false;"),
"mail" => array("label" => "Email", "onkeyup" => "auto_email_update = false; check_email_validity(document.getElementById('mail').value)") "mail" => array("label" => "Email", "onkeyup" => "auto_email_update = false; check_email_validity(document.getElementById('mail').value);")
); );
#Mandatory $LDAP['group_attribute'] = (getenv('LDAP_GROUP_ATTRIBUTE') ? getenv('LDAP_GROUP_ATTRIBUTE') : 'cn');
$LDAP['group_objectclasses'] = array( 'top', 'posixGroup' ); #groupOfUniqueNames is added automatically if rfc2307bis is available.
$LDAP['default_group_attribute_map'] = array( "description" => array("label" => "Description"));
$SHOW_POSIX_ATTRIBUTES = ((strcasecmp(getenv('SHOW_POSIX_ATTRIBUTES'),'TRUE') == 0) ? TRUE : FALSE);
if ($SHOW_POSIX_ATTRIBUTES != TRUE) {
if ($LDAP['account_attribute'] == "uid") {
unset($LDAP['default_attribute_map']['cn']);
}
else {
unset($LDAP['default_attribute_map']['uid']);
}
}
else {
$LDAP['default_attribute_map']["uidnumber"] = array("label" => "UID");
$LDAP['default_attribute_map']["gidnumber"] = array("label" => "GID");
$LDAP['default_attribute_map']["homedirectory"] = array("label" => "Home directory", "onkeyup" => "auto_homedir_update = false;");
$LDAP['default_attribute_map']["loginshell"] = array("label" => "Shell", "default" => $DEFAULT_USER_SHELL);
$LDAP['default_group_attribute_map']["gidnumber"] = array("label" => "Group ID number");
}
## LDAP server
$LDAP['uri'] = getenv('LDAP_URI'); $LDAP['uri'] = getenv('LDAP_URI');
$LDAP['base_dn'] = getenv('LDAP_BASE_DN'); $LDAP['base_dn'] = getenv('LDAP_BASE_DN');
$LDAP['admins_group'] = getenv('LDAP_ADMINS_GROUP');
$LDAP['admin_bind_dn'] = getenv('LDAP_ADMIN_BIND_DN'); $LDAP['admin_bind_dn'] = getenv('LDAP_ADMIN_BIND_DN');
$LDAP['admin_bind_pwd'] = getenv('LDAP_ADMIN_BIND_PWD'); $LDAP['admin_bind_pwd'] = getenv('LDAP_ADMIN_BIND_PWD');
$LDAP['connection_type'] = "plain"; $LDAP['connection_type'] = "plain";
$LDAP['require_starttls'] = ((strcasecmp(getenv('LDAP_REQUIRE_STARTTLS'),'TRUE') == 0) ? TRUE : FALSE);
$LDAP['ignore_cert_errors'] = ((strcasecmp(getenv('LDAP_IGNORE_CERT_ERRORS'),'TRUE') == 0) ? TRUE : FALSE);
$LDAP['rfc2307bis_check_run'] = FALSE;
#Optional
$LDAP['account_attribute'] = (getenv('LDAP_ACCOUNT_ATTRIBUTE') ? getenv('LDAP_ACCOUNT_ATTRIBUTE') : 'uid'); # Various advanced LDAP settings
$LDAP['group_attribute'] = (getenv('LDAP_GROUP_ATTRIBUTE') ? getenv('LDAP_GROUP_ATTRIBUTE') : 'cn');
$LDAP['admins_group'] = getenv('LDAP_ADMINS_GROUP');
$LDAP['group_ou'] = (getenv('LDAP_GROUP_OU') ? getenv('LDAP_GROUP_OU') : 'groups'); $LDAP['group_ou'] = (getenv('LDAP_GROUP_OU') ? getenv('LDAP_GROUP_OU') : 'groups');
$LDAP['user_ou'] = (getenv('LDAP_USER_OU') ? getenv('LDAP_USER_OU') : 'people'); $LDAP['user_ou'] = (getenv('LDAP_USER_OU') ? getenv('LDAP_USER_OU') : 'people');
$LDAP['forced_rfc2307bis'] = ((strcasecmp(getenv('FORCE_RFC2307BIS'),'TRUE') == 0) ? TRUE : FALSE); $LDAP['forced_rfc2307bis'] = ((strcasecmp(getenv('FORCE_RFC2307BIS'),'TRUE') == 0) ? TRUE : FALSE);
if (getenv('LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES')) { $LDAP['account_additional_objectclasses'] = strtolower(getenv('LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES')); } if (getenv('LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES')) { $account_additional_objectclasses = strtolower(getenv('LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES')); }
if (getenv('LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES')) { $LDAP['account_additional_attributes'] = getenv('LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES'); } if (getenv('LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES')) { $LDAP['account_additional_attributes'] = getenv('LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES'); }
if (getenv('LDAP_GROUP_ADDITIONAL_OBJECTCLASSES')) { $group_additional_objectclasses = getenv('LDAP_GROUP_ADDITIONAL_OBJECTCLASSES'); }
if (getenv('LDAP_GROUP_ADDITIONAL_ATTRIBUTES')) { $LDAP['group_additional_attributes'] = getenv('LDAP_GROUP_ADDITIONAL_ATTRIBUTES'); }
if (getenv('LDAP_GROUP_MEMBERSHIP_ATTRIBUTE')) { $LDAP['group_membership_attribute'] = getenv('LDAP_GROUP_MEMBERSHIP_ATTRIBUTE'); } if (getenv('LDAP_GROUP_MEMBERSHIP_ATTRIBUTE')) { $LDAP['group_membership_attribute'] = getenv('LDAP_GROUP_MEMBERSHIP_ATTRIBUTE'); }
if (getenv('LDAP_GROUP_MEMBERSHIP_USES_UID')) { if (getenv('LDAP_GROUP_MEMBERSHIP_USES_UID')) {
if (strtoupper(getenv('LDAP_GROUP_MEMBERSHIP_USES_UID')) == 'TRUE' ) { $LDAP['group_membership_uses_uid'] = TRUE; } if (strtoupper(getenv('LDAP_GROUP_MEMBERSHIP_USES_UID')) == 'TRUE' ) { $LDAP['group_membership_uses_uid'] = TRUE; }
if (strtoupper(getenv('LDAP_GROUP_MEMBERSHIP_USES_UID')) == 'FALSE' ) { $LDAP['group_membership_uses_uid'] = FALSE; } if (strtoupper(getenv('LDAP_GROUP_MEMBERSHIP_USES_UID')) == 'FALSE' ) { $LDAP['group_membership_uses_uid'] = FALSE; }
} }
$LDAP['require_starttls'] = ((strcasecmp(getenv('LDAP_REQUIRE_STARTTLS'),'TRUE') == 0) ? TRUE : FALSE); $LDAP['group_dn'] = "ou=${LDAP['group_ou']},${LDAP['base_dn']}";
$LDAP['ignore_cert_errors'] = ((strcasecmp(getenv('LDAP_IGNORE_CERT_ERRORS'),'TRUE') == 0) ? TRUE : FALSE); $LDAP['user_dn'] = "ou=${LDAP['user_ou']},${LDAP['base_dn']}";
$LDAP['rfc2307bis_check_run'] = FALSE;
$DEFAULT_USER_GROUP = (getenv('DEFAULT_USER_GROUP') ? getenv('DEFAULT_USER_GROUP') : 'everybody'); if (isset($account_additional_objectclasses) and $account_additional_objectclasses != "") {
$DEFAULT_USER_SHELL = (getenv('DEFAULT_USER_SHELL') ? getenv('DEFAULT_USER_SHELL') : '/bin/bash'); $LDAP['account_objectclasses'] = array_merge($LDAP['account_objectclasses'], explode(",", $account_additional_objectclasses));
}
if (isset($group_additional_objectclasses) and $group_additional_objectclasses != "") {
$LDAP['group_objectclasses'] = array_merge($LDAP['group_objectclasses'], explode(",", $group_additional_objectclasses));
}
# Interface customisation
$ORGANISATION_NAME = (getenv('ORGANISATION_NAME') ? getenv('ORGANISATION_NAME') : 'LDAP'); $ORGANISATION_NAME = (getenv('ORGANISATION_NAME') ? getenv('ORGANISATION_NAME') : 'LDAP');
$SITE_NAME = (getenv('SITE_NAME') ? getenv('SITE_NAME') : "$ORGANISATION_NAME user manager"); $SITE_NAME = (getenv('SITE_NAME') ? getenv('SITE_NAME') : "$ORGANISATION_NAME user manager");
@ -52,27 +101,13 @@
$SERVER_HOSTNAME = (getenv('SERVER_HOSTNAME') ? getenv('SERVER_HOSTNAME') : "ldapusermanager.org"); $SERVER_HOSTNAME = (getenv('SERVER_HOSTNAME') ? getenv('SERVER_HOSTNAME') : "ldapusermanager.org");
$SERVER_PATH = (getenv('SERVER_PATH') ? getenv('SERVER_PATH') : "/"); $SERVER_PATH = (getenv('SERVER_PATH') ? getenv('SERVER_PATH') : "/");
$ENFORCE_SAFE_SYSTEM_NAMES = ((strcasecmp(getenv('ENFORCE_SAFE_SYSTEM_NAMES'),'FALSE') == 0) ? FALSE : TRUE);
$POSIX_USERNAME_FORMAT = (getenv('USERNAME_FORMAT') ? getenv('USERNAME_FORMAT') : '{first_name}-{last_name}');
$POSIX_REGEX = (getenv('USERNAME_REGEX') ? getenv('USERNAME_REGEX') : '^[a-z][a-zA-Z0-9\._-]{3,32}$');
#We'll use the username regex for groups too.
if (getenv('PASSWORD_HASH')) { $PASSWORD_HASH = strtoupper(getenv('PASSWORD_HASH')); }
$ACCEPT_WEAK_PASSWORDS = ((strcasecmp(getenv('ACCEPT_WEAK_PASSWORDS'),'TRUE') == 0) ? TRUE : FALSE);
$SESSION_TIMEOUT = (getenv('SESSION_TIMEOUT') ? getenv('SESSION_TIMEOUT') : 10); $SESSION_TIMEOUT = (getenv('SESSION_TIMEOUT') ? getenv('SESSION_TIMEOUT') : 10);
$LDAP_DEBUG = ((strcasecmp(getenv('LDAP_DEBUG'),'TRUE') == 0) ? TRUE : FALSE); $NO_HTTPS = ((strcasecmp(getenv('NO_HTTPS'),'TRUE') == 0) ? TRUE : FALSE);
$LDAP_VERBOSE_CONNECTION_LOGS = ((strcasecmp(getenv('LDAP_VERBOSE_CONNECTION_LOGS'),'TRUE') == 0) ? TRUE : FALSE);
$SESSION_DEBUG = ((strcasecmp(getenv('SESSION_DEBUG'),'TRUE') == 0) ? TRUE : FALSE); $REMOTE_HTTP_HEADERS_LOGIN = ((strcasecmp(getenv('REMOTE_HTTP_HEADERS_LOGIN'),'TRUE') == 0) ? TRUE : FALSE);
### # Sending email
$LDAP['group_dn'] = "ou=${LDAP['group_ou']},${LDAP['base_dn']}";
$LDAP['user_dn'] = "ou=${LDAP['user_ou']},${LDAP['base_dn']}";
###
$SMTP['host'] = getenv('SMTP_HOSTNAME'); $SMTP['host'] = getenv('SMTP_HOSTNAME');
$SMTP['user'] = (getenv('SMTP_USERNAME') ? getenv('SMTP_USERNAME') : NULL); $SMTP['user'] = (getenv('SMTP_USERNAME') ? getenv('SMTP_USERNAME') : NULL);
@ -82,9 +117,6 @@
$SMTP['tls'] = ((strcasecmp(getenv('SMTP_USE_TLS'),'TRUE') == 0) ? TRUE : FALSE); $SMTP['tls'] = ((strcasecmp(getenv('SMTP_USE_TLS'),'TRUE') == 0) ? TRUE : FALSE);
if ($SMTP['tls'] == TRUE) { $SMTP['ssl'] = FALSE; } if ($SMTP['tls'] == TRUE) { $SMTP['ssl'] = FALSE; }
$SMTP['debug_level'] = getenv('SMTP_LOG_LEVEL');
if (!is_numeric($SMTP['debug_level']) or $SMTP['debug_level'] >4 or $SMTP['debug_level'] <0) { $SMTP['debug_level'] = 0; }
$EMAIL_DOMAIN = (getenv('EMAIL_DOMAIN') ? getenv('EMAIL_DOMAIN') : Null); $EMAIL_DOMAIN = (getenv('EMAIL_DOMAIN') ? getenv('EMAIL_DOMAIN') : Null);
$default_email_from_domain = ($EMAIL_DOMAIN ? $EMAIL_DOMAIN : 'ldapusermanger.org'); $default_email_from_domain = ($EMAIL_DOMAIN ? $EMAIL_DOMAIN : 'ldapusermanger.org');
@ -94,7 +126,7 @@
if ($SMTP['host'] != "") { $EMAIL_SENDING_ENABLED = TRUE; } else { $EMAIL_SENDING_ENABLED = FALSE; } if ($SMTP['host'] != "") { $EMAIL_SENDING_ENABLED = TRUE; } else { $EMAIL_SENDING_ENABLED = FALSE; }
### # Account requests
$ACCOUNT_REQUESTS_ENABLED = ((strcasecmp(getenv('ACCOUNT_REQUESTS_ENABLED'),'TRUE') == 0) ? TRUE : FALSE); $ACCOUNT_REQUESTS_ENABLED = ((strcasecmp(getenv('ACCOUNT_REQUESTS_ENABLED'),'TRUE') == 0) ? TRUE : FALSE);
if (($EMAIL_SENDING_ENABLED == FALSE) && ($ACCOUNT_REQUESTS_ENABLED == TRUE)) { if (($EMAIL_SENDING_ENABLED == FALSE) && ($ACCOUNT_REQUESTS_ENABLED == TRUE)) {
@ -104,11 +136,16 @@
$ACCOUNT_REQUESTS_EMAIL = (getenv('ACCOUNT_REQUESTS_EMAIL') ? getenv('ACCOUNT_REQUESTS_EMAIL') : $EMAIL['from_address']); $ACCOUNT_REQUESTS_EMAIL = (getenv('ACCOUNT_REQUESTS_EMAIL') ? getenv('ACCOUNT_REQUESTS_EMAIL') : $EMAIL['from_address']);
###
$NO_HTTPS = ((strcasecmp(getenv('NO_HTTPS'),'TRUE') == 0) ? TRUE : FALSE); # Debugging
### $LDAP_DEBUG = ((strcasecmp(getenv('LDAP_DEBUG'),'TRUE') == 0) ? TRUE : FALSE);
$LDAP_VERBOSE_CONNECTION_LOGS = ((strcasecmp(getenv('LDAP_VERBOSE_CONNECTION_LOGS'),'TRUE') == 0) ? TRUE : FALSE);
$SESSION_DEBUG = ((strcasecmp(getenv('SESSION_DEBUG'),'TRUE') == 0) ? TRUE : FALSE);
$SMTP['debug_level'] = getenv('SMTP_LOG_LEVEL');
if (!is_numeric($SMTP['debug_level']) or $SMTP['debug_level'] >4 or $SMTP['debug_level'] <0) { $SMTP['debug_level'] = 0; }
# Sanity checking
$errors = ""; $errors = "";
@ -135,8 +172,6 @@
exit(1); exit(1);
} }
#POSIX accounts
$min_uid = 2000;
$min_gid = 2000;
?> ?>

View File

@ -24,7 +24,7 @@ function open_ldap_connection($ldap_bind=TRUE) {
if ($tls_result != TRUE) { if ($tls_result != TRUE) {
error_log("$log_prefix Failed to start STARTTLS connection to ${LDAP['uri']}: " . ldap_error($ldap_connection),0); if (!preg_match('/^ldap:\/\/127\.0\.0\.([0-9]+)(:[0-9]+)$/', $LDAP['uri'])) { error_log("$log_prefix Failed to start STARTTLS connection to ${LDAP['uri']}: " . ldap_error($ldap_connection),0); }
if ($LDAP["require_starttls"] == TRUE) { if ($LDAP["require_starttls"] == TRUE) {
print "<div style='position: fixed;bottom: 0;width: 100%;' class='alert alert-danger'>Fatal: Couldn't create a secure connection to ${LDAP['uri']} and LDAP_REQUIRE_STARTTLS is TRUE.</div>"; print "<div style='position: fixed;bottom: 0;width: 100%;' class='alert alert-danger'>Fatal: Couldn't create a secure connection to ${LDAP['uri']} and LDAP_REQUIRE_STARTTLS is TRUE.</div>";
@ -320,7 +320,7 @@ function ldap_get_user_list($ldap_connection,$start=0,$entries=NULL,$sort="asc",
$add_these = array(); $add_these = array();
foreach($fields as $this_attr) { foreach($fields as $this_attr) {
if ($this_attr !== $sort_key) { $add_these[$this_attr] = $record[$this_attr][0]; } if ($this_attr !== $sort_key and isset($record[$this_attr])) { $add_these[$this_attr] = $record[$this_attr][0]; }
} }
$records[$record[$sort_key][0]] = $add_these; $records[$record[$sort_key][0]] = $add_these;
@ -438,18 +438,21 @@ function ldap_get_group_list($ldap_connection,$start=0,$entries=NULL,$sort="asc"
################################## ##################################
function ldap_get_dn_of_group($ldap_connection,$group_name) { function ldap_get_group_entry($ldap_connection,$group_name) {
global $log_prefix, $LDAP, $LDAP_DEBUG; global $log_prefix, $LDAP, $LDAP_DEBUG;
if (isset($group_name)) { if (isset($group_name)) {
$ldap_search_query = "(${LDAP['group_attribute']}=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ")"; $ldap_search_query = "(${LDAP['group_attribute']}=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ")";
$ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query , array("dn")); $ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query);
$result = @ ldap_get_entries($ldap_connection, $ldap_search); $result = @ ldap_get_entries($ldap_connection, $ldap_search);
if (isset($result[0]['dn'])) { if ($result['count'] > 0) {
return $result[0]['dn']; return $result;
}
else {
return FALSE;
} }
} }
@ -464,13 +467,13 @@ function ldap_get_group_members($ldap_connection,$group_name,$start=0,$entries=N
global $log_prefix, $LDAP, $LDAP_DEBUG; global $log_prefix, $LDAP, $LDAP_DEBUG;
if ($LDAP['rfc2307bis_check_run'] != TRUE) { $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection); } $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection);
$ldap_search_query = "(${LDAP['group_attribute']}=". ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ")"; $ldap_search_query = "(${LDAP['group_attribute']}=". ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ")";
$ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query, array($LDAP['group_membership_attribute'])); $ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query, array($LDAP['group_membership_attribute']));
$result = @ ldap_get_entries($ldap_connection, $ldap_search); $result = @ ldap_get_entries($ldap_connection, $ldap_search);
$result_count = $result[0]['count']; if ($result) { $result_count = $result['count']; } else { $result_count = 0; }
$records = array(); $records = array();
@ -511,7 +514,7 @@ function ldap_is_group_member($ldap_connection,$group_name,$username) {
global $log_prefix, $LDAP, $LDAP_DEBUG; global $log_prefix, $LDAP, $LDAP_DEBUG;
if ($LDAP['rfc2307bis_check_run'] != TRUE) { $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection); } $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection);
$ldap_search_query = "(${LDAP['group_attribute']}=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ")"; $ldap_search_query = "(${LDAP['group_attribute']}=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ")";
$ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query); $ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query);
@ -543,7 +546,7 @@ function ldap_user_group_membership($ldap_connection,$username) {
global $log_prefix, $LDAP, $LDAP_DEBUG; global $log_prefix, $LDAP, $LDAP_DEBUG;
if ($LDAP['rfc2307bis_check_run'] != TRUE) { $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection); } $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection);
if ($LDAP['group_membership_uses_uid'] == FALSE) { if ($LDAP['group_membership_uses_uid'] == FALSE) {
$username = "${LDAP['account_attribute']}=$username,${LDAP['user_dn']}"; $username = "${LDAP['account_attribute']}=$username,${LDAP['user_dn']}";
@ -567,16 +570,17 @@ function ldap_user_group_membership($ldap_connection,$username) {
################################## ##################################
function ldap_new_group($ldap_connection,$group_name,$initial_member="") { function ldap_new_group($ldap_connection,$group_name,$initial_member="",$extra_attributes=array()) {
global $log_prefix, $LDAP, $LDAP_DEBUG; global $log_prefix, $LDAP, $LDAP_DEBUG;
if ($LDAP['rfc2307bis_check_run'] != TRUE) { $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection); } $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection);
if (isset($group_name)) { if (isset($group_name)) {
$new_group = ldap_escape($group_name, "", LDAP_ESCAPE_FILTER); $new_group = ldap_escape($group_name, "", LDAP_ESCAPE_FILTER);
$initial_member = ldap_escape($initial_member, "", LDAP_ESCAPE_FILTER); $initial_member = ldap_escape($initial_member, "", LDAP_ESCAPE_FILTER);
$update_gid_store=FALSE;
$ldap_search_query = "(${LDAP['group_attribute']}=$new_group,${LDAP['group_dn']})"; $ldap_search_query = "(${LDAP['group_attribute']}=$new_group,${LDAP['group_dn']})";
$ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query); $ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query);
@ -584,30 +588,35 @@ function ldap_new_group($ldap_connection,$group_name,$initial_member="") {
if ($result['count'] == 0) { if ($result['count'] == 0) {
$highest_gid = ldap_get_highest_id($ldap_connection,'gid');
$new_gid = $highest_gid + 1;
if ($rfc2307bis_available == FALSE) { $objectclasses = array('top','posixGroup'); } else { $objectclasses = array('top','groupOfUniqueNames','posixGroup'); }
if ($LDAP['group_membership_uses_uid'] == FALSE and $initial_member != "") { $initial_member = "${LDAP['account_attribute']}=$initial_member,${LDAP['user_dn']}"; } if ($LDAP['group_membership_uses_uid'] == FALSE and $initial_member != "") { $initial_member = "${LDAP['account_attribute']}=$initial_member,${LDAP['user_dn']}"; }
$new_group_array=array( 'objectClass' => $objectclasses, $new_group_array=array( 'objectClass' => $LDAP['group_objectclasses'],
'cn' => $new_group, 'cn' => $new_group,
'gidNumber' => $new_gid,
$LDAP['group_membership_attribute'] => $initial_member $LDAP['group_membership_attribute'] => $initial_member
); );
$new_group_array = array_merge($new_group_array,$extra_attributes);
if (!isset($new_group_array["gidnumber"][0]) or !is_numeric($new_group_array["gidnumber"][0])) {
$highest_gid = ldap_get_highest_id($ldap_connection,'gid');
$new_gid = $highest_gid + 1;
$new_group_array["gidnumber"] = $new_gid;
$update_gid_store=TRUE;
}
$group_dn="cn=$new_group,${LDAP['group_dn']}"; $group_dn="cn=$new_group,${LDAP['group_dn']}";
$add_group = @ ldap_add($ldap_connection, $group_dn, $new_group_array); $add_group = @ ldap_add($ldap_connection, $group_dn, $new_group_array);
if (! $add_group ) { if (! $add_group ) {
$this_error="$log_prefix LDAP: unable to add new group (${group_dn}): " . ldap_error($ldap_connection); $this_error="$log_prefix LDAP: unable to add new group (${group_dn}): " . ldap_error($ldap_connection);
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix DEBUG add_group array: ". print_r($new_group_array,true),0); } if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix DEBUG add_group array: ". strip_tags(print_r($new_group_array,true)),0); }
error_log($this_error,0); error_log($this_error,0);
} }
else { else {
error_log("$log_prefix Added new group $group_name",0); error_log("$log_prefix Added new group $group_name",0);
if ($update_gid_store == TRUE) {
$this_gid = fetch_id_stored_in_ldap($ldap_connection,"gid"); $this_gid = fetch_id_stored_in_ldap($ldap_connection,"gid");
if ($this_gid != FALSE) { if ($this_gid != FALSE) {
$update_gid = @ ldap_mod_replace($ldap_connection, "cn=lastGID,${LDAP['base_dn']}", array( 'serialNumber' => $new_gid )); $update_gid = @ ldap_mod_replace($ldap_connection, "cn=lastGID,${LDAP['base_dn']}", array( 'serialNumber' => $new_gid ));
@ -618,6 +627,7 @@ function ldap_new_group($ldap_connection,$group_name,$initial_member="") {
error_log("$log_prefix Unable to update cn=lastGID to $new_gid - this could cause groups to share the same GID.",0); error_log("$log_prefix Unable to update cn=lastGID to $new_gid - this could cause groups to share the same GID.",0);
} }
} }
}
return TRUE; return TRUE;
} }
@ -635,6 +645,37 @@ function ldap_new_group($ldap_connection,$group_name,$initial_member="") {
} }
##################################
function ldap_update_group_attributes($ldap_connection,$group_name,$extra_attributes) {
global $log_prefix, $LDAP, $LDAP_DEBUG;
if (isset($group_name) and (count($extra_attributes) > 0)) {
$group_name = ldap_escape($group_name, "", LDAP_ESCAPE_FILTER);
$group_dn = "${LDAP['group_attribute']}=$group_name,${LDAP['group_dn']}";
$update_group = @ ldap_mod_replace($ldap_connection, $group_dn, $extra_attributes);
if (!$update_group ) {
$this_error="$log_prefix LDAP: unable to update group attributes for group (${group_dn}): " . ldap_error($ldap_connection);
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix DEBUG update group attributes array: ". print_r($extra_attributes,true),0); }
error_log($this_error,0);
return FALSE;
}
else {
error_log("$log_prefix Updated group attributes for $group_name",0);
return TRUE;
}
}
else {
error_log("$log_prefix Update group attributes; group name wasn't set.",0);
return FALSE;
}
}
################################## ##################################
function ldap_delete_group($ldap_connection,$group_name) { function ldap_delete_group($ldap_connection,$group_name) {
@ -685,51 +726,57 @@ function ldap_get_gid_of_group($ldap_connection,$group_name) {
################################## ##################################
function ldap_complete_account_attribute_array() { function ldap_complete_attribute_array($default_attributes,$additional_attributes) {
global $LDAP; if (isset($additional_attributes)) {
$attribute_r = $LDAP['default_attribute_map']; $user_attribute_r = explode(",", $additional_attributes);
$additional_attributes_r = array(); $to_merge = array();
if (isset($LDAP['account_additional_attributes'])) {
$user_attribute_r = explode(",", $LDAP['account_additional_attributes']);
foreach ($user_attribute_r as $this_attr) { foreach ($user_attribute_r as $this_attr) {
$this_r = array(); $this_r = array();
$kv = explode(":", $this_attr); $kv = explode(":", $this_attr);
$attr_name = strtolower(filter_var($kv[0], FILTER_SANITIZE_STRING)); $attr_name = strtolower(filter_var($kv[0], FILTER_SANITIZE_FULL_SPECIAL_CHARS));
$this_r['inputtype'] = "singleinput";
if (substr($attr_name, -1) == '+') {
$this_r['inputtype'] = "multipleinput";
$attr_name = rtrim($attr_name, '+');
}
if (substr($attr_name, -1) == '^') {
$this_r['inputtype'] = "binary";
$attr_name = rtrim($attr_name, '^');
}
if (preg_match('/^[a-zA-Z0-9\-]+$/', $attr_name) == 1) { if (preg_match('/^[a-zA-Z0-9\-]+$/', $attr_name) == 1) {
if (isset($kv[1]) and $kv[1] != "") { if (isset($kv[1]) and $kv[1] != "") {
$this_r['label'] = filter_var($kv[1], FILTER_SANITIZE_STRING); $this_r['label'] = filter_var($kv[1], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
} }
else { else {
$this_r['label'] = $attr_name; $this_r['label'] = $attr_name;
} }
if (isset($kv[2]) and $kv[2] != "") { if (isset($kv[2]) and $kv[2] != "") {
$this_r['default'] = filter_var($kv[2], FILTER_SANITIZE_STRING); $this_r['default'] = filter_var($kv[2], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
} }
$additional_attributes_r[$attr_name] = $this_r; $to_merge[$attr_name] = $this_r;
} }
} }
$attribute_r = array_merge($attribute_r, $additional_attributes_r); $attribute_r = array_merge($default_attributes, $to_merge);
}
if (! array_key_exists($LDAP['account_attribute'], $attribute_r)) {
$attribute_r = array_merge($attribute_r, array($LDAP['account_attribute'] => array("label" => "Account UID")));
}
return($attribute_r); return($attribute_r);
}
else {
return($default_attributes);
}
} }
@ -739,27 +786,25 @@ function ldap_new_account($ldap_connection,$account_r) {
global $log_prefix, $LDAP, $LDAP_DEBUG, $DEFAULT_USER_SHELL, $DEFAULT_USER_GROUP; global $log_prefix, $LDAP, $LDAP_DEBUG, $DEFAULT_USER_SHELL, $DEFAULT_USER_GROUP;
if ( isset($account_r['givenname']) if ( isset($account_r['givenname'][0])
and isset($account_r['sn']) and isset($account_r['sn'][0])
and isset($account_r['cn']) and isset($account_r['cn'][0])
and isset($account_r['uid']) and isset($account_r['uid'][0])
and isset($account_r[$LDAP['account_attribute']]) and isset($account_r[$LDAP['account_attribute']])
and isset($account_r['password'])) { and isset($account_r['password'][0])) {
$account_identifier = $account_r[$LDAP['account_attribute']]; $account_identifier = $account_r[$LDAP['account_attribute']][0];
$ldap_search_query = "(${LDAP['account_attribute']}=" . ldap_escape($account_identifier, "", LDAP_ESCAPE_FILTER) . ",${LDAP['user_dn']})"; $user_dn=$LDAP['user_dn'];
$ldap_search = @ ldap_search($ldap_connection, "${LDAP['user_dn']}", $ldap_search_query); $ldap_search_query = "(${LDAP['account_attribute']}=" . ldap_escape($account_identifier, "", LDAP_ESCAPE_FILTER) . ",$user_dn)";
$ldap_search = @ ldap_search($ldap_connection, $user_dn, $ldap_search_query);
$result = @ ldap_get_entries($ldap_connection, $ldap_search); $result = @ ldap_get_entries($ldap_connection, $ldap_search);
if ($result['count'] == 0) { if ($result['count'] == 0) {
$hashed_pass = ldap_hashed_password($account_r['password']); $hashed_pass = ldap_hashed_password($account_r['password'][0]);
unset($account_r['password']); unset($account_r['password']);
$objectclasses = $LDAP['account_objectclasses']; $objectclasses = $LDAP['account_objectclasses'];
if (isset($LDAP['account_additional_objectclasses']) and $LDAP['account_additional_objectclasses'] != "") {
$objectclasses = array_merge($objectclasses, explode(",", $LDAP['account_additional_objectclasses']));
}
$account_attributes = array('objectclass' => $objectclasses, $account_attributes = array('objectclass' => $objectclasses,
'userpassword' => $hashed_pass, 'userpassword' => $hashed_pass,
@ -784,9 +829,8 @@ function ldap_new_account($ldap_connection,$account_r) {
} }
} }
if (empty($account_attributes['displayname'])) { $account_attributes['displayname'] = $account_attributes['givenname'] . " " . $account_attributes['sn']; }
if (empty($account_attributes['loginshell'])) { $account_attributes['loginshell'] = $DEFAULT_USER_SHELL; } if (empty($account_attributes['loginshell'])) { $account_attributes['loginshell'] = $DEFAULT_USER_SHELL; }
if (empty($account_attributes['homedirectory'])) { $account_attributes['homedirectory'] = "/home/${account_identifier}"; } if (empty($account_attributes['homedirectory'])) { $account_attributes['homedirectory'] = "/home/" . $account_r['uid'][0]; }
$add_account = @ ldap_add($ldap_connection, $add_account = @ ldap_add($ldap_connection,
"${LDAP['account_attribute']}=$account_identifier,${LDAP['user_dn']}", "${LDAP['account_attribute']}=$account_identifier,${LDAP['user_dn']}",
@ -811,13 +855,13 @@ function ldap_new_account($ldap_connection,$account_r) {
} }
return TRUE; return TRUE;
} }
else { else {
ldap_get_option($ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detailed_err); ldap_get_option($ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detailed_err);
error_log("$log_prefix Create account; couldn't create the account for ${account_identifier}: " . ldap_error($ldap_connection) . " -- " . $detailed_err,0); error_log("$log_prefix Create account; couldn't create the account for ${account_identifier}: " . ldap_error($ldap_connection) . " -- " . $detailed_err,0);
} }
} }
else { else {
error_log("$log_prefix Create account; Account for ${account_identifier} already exists",0); error_log("$log_prefix Create account; Account for ${account_identifier} already exists",0);
} }
@ -863,7 +907,7 @@ function ldap_add_member_to_group($ldap_connection,$group_name,$username) {
global $log_prefix, $LDAP, $LDAP_DEBUG; global $log_prefix, $LDAP, $LDAP_DEBUG;
if ($LDAP['rfc2307bis_check_run'] != TRUE) { $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection); } $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection);
$group_dn = "${LDAP['group_attribute']}=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ",${LDAP['group_dn']}"; $group_dn = "${LDAP['group_attribute']}=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ",${LDAP['group_dn']}";
@ -898,7 +942,7 @@ function ldap_delete_member_from_group($ldap_connection,$group_name,$username) {
return FALSE; return FALSE;
} }
else { else {
if ($LDAP['rfc2307bis_check_run'] != TRUE) { $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection); } $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection);
$group_dn = "${LDAP['group_attribute']}=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ",${LDAP['group_dn']}"; $group_dn = "${LDAP['group_attribute']}=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ",${LDAP['group_dn']}";
@ -967,11 +1011,16 @@ function ldap_detect_rfc2307bis($ldap_connection) {
global $log_prefix, $LDAP, $LDAP_DEBUG; global $log_prefix, $LDAP, $LDAP_DEBUG;
$bis_available = FALSE; if (isset($LDAP['rfc2307bis_available'])) {
return $LDAP['rfc2307bis_available'];
}
else {
$LDAP['rfc2307bis_available'] = FALSE;
if ($LDAP['forced_rfc2307bis'] == TRUE) { if ($LDAP['forced_rfc2307bis'] == TRUE) {
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix LDAP RFC2307BIS detection - skipping autodetection because FORCE_RFC2307BIS is TRUE",0); } if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix LDAP RFC2307BIS detection - skipping autodetection because FORCE_RFC2307BIS is TRUE",0); }
$bis_available = TRUE; $LDAP['rfc2307bis_available'] = TRUE;
} }
else { else {
@ -1001,7 +1050,7 @@ function ldap_detect_rfc2307bis($ldap_connection) {
$posixgroup_search = preg_grep("/NAME 'posixGroup'.*AUXILIARY/",$objclass_results[0]['objectclasses']); $posixgroup_search = preg_grep("/NAME 'posixGroup'.*AUXILIARY/",$objclass_results[0]['objectclasses']);
if (count($posixgroup_search) > 0) { if (count($posixgroup_search) > 0) {
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix LDAP RFC2307BIS detection - found AUXILIARY in posixGroup definition which suggests we're using the RFC2307BIS schema" ,0); } if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix LDAP RFC2307BIS detection - found AUXILIARY in posixGroup definition which suggests we're using the RFC2307BIS schema" ,0); }
$bis_available = TRUE; $LDAP['rfc2307bis_available'] = TRUE;
} }
else { else {
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix LDAP RFC2307BIS detection - couldn't find AUXILIARY in the posixGroup definition which suggests we're not using the RFC2307BIS schema. Set FORCE_RFC2307BIS to TRUE if you DO use RFC2307BIS. " ,0); } if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix LDAP RFC2307BIS detection - couldn't find AUXILIARY in the posixGroup definition which suggests we're not using the RFC2307BIS schema. Set FORCE_RFC2307BIS to TRUE if you DO use RFC2307BIS. " ,0); }
@ -1018,10 +1067,10 @@ function ldap_detect_rfc2307bis($ldap_connection) {
} }
} }
$LDAP['rfc2307bis_check_run'] == TRUE; if ($LDAP['rfc2307bis_available'] == TRUE) {
if ($bis_available == TRUE) {
if (!isset($LDAP['group_membership_attribute'])) { $LDAP['group_membership_attribute'] = 'uniquemember'; } if (!isset($LDAP['group_membership_attribute'])) { $LDAP['group_membership_attribute'] = 'uniquemember'; }
if (!isset($LDAP['group_membership_uses_uid'])) { $LDAP['group_membership_uses_uid'] = FALSE; } if (!isset($LDAP['group_membership_uses_uid'])) { $LDAP['group_membership_uses_uid'] = FALSE; }
if (!in_array('groupOfUniqueNames',$LDAP['group_objectclasses'])) { array_push($LDAP['group_objectclasses'], 'groupOfUniqueNames'); }
return TRUE; return TRUE;
} }
else { else {
@ -1030,6 +1079,7 @@ function ldap_detect_rfc2307bis($ldap_connection) {
return FALSE; return FALSE;
} }
}
} }

View File

@ -11,11 +11,13 @@
'log_in' => 'hidden_on_login', 'log_in' => 'hidden_on_login',
'change_password' => 'auth', 'change_password' => 'auth',
'account_manager' => 'admin', 'account_manager' => 'admin',
'log_out' => 'auth'
); );
if ($ACCOUNT_REQUESTS_ENABLED == TRUE) { if ($ACCOUNT_REQUESTS_ENABLED == TRUE) {
$MODULES['request_account'] = 'hidden_on_login'; $MODULES['request_account'] = 'hidden_on_login';
} }
if (!$REMOTE_HTTP_HEADERS_LOGIN) {
$MODULES['log_out'] = 'auth';
}
?> ?>

View File

@ -1,5 +1,4 @@
<?php <?php
#Security level vars #Security level vars
$VALIDATED = FALSE; $VALIDATED = FALSE;
@ -7,6 +6,7 @@ $IS_ADMIN = FALSE;
$IS_SETUP_ADMIN = FALSE; $IS_SETUP_ADMIN = FALSE;
$ACCESS_LEVEL_NAME = array('account','admin'); $ACCESS_LEVEL_NAME = array('account','admin');
unset($USER_ID); unset($USER_ID);
$CURRENT_PAGE=htmlentities($_SERVER['PHP_SELF']);
$SENT_HEADERS = FALSE; $SENT_HEADERS = FALSE;
$SESSION_TIMED_OUT = FALSE; $SESSION_TIMED_OUT = FALSE;
@ -35,15 +35,27 @@ include ("modules.inc.php"); # module definitions
if (substr($SERVER_PATH, -1) != "/") { $SERVER_PATH .= "/"; } if (substr($SERVER_PATH, -1) != "/") { $SERVER_PATH .= "/"; }
$THIS_MODULE_PATH="${SERVER_PATH}${THIS_MODULE}"; $THIS_MODULE_PATH="${SERVER_PATH}${THIS_MODULE}";
validate_passkey_cookie(); $DEFAULT_COOKIE_OPTIONS = array( 'expires' => time()+(60 * $SESSION_TIMEOUT),
'path' => $SERVER_PATH,
'domain' => '',
'secure' => $NO_HTTPS ? FALSE : TRUE,
'samesite' => 'strict'
);
if ($REMOTE_HTTP_HEADERS_LOGIN) {
login_via_headers();
} else {
validate_passkey_cookie();
}
###################################################### ######################################################
function generate_passkey() { function generate_passkey() {
$rnd1 = rand(10000000, (int)100000000000); $rnd1 = mt_rand(10000000, mt_getrandmax());
$rnd2 = rand(10000000, (int)100000000000); $rnd2 = mt_rand(10000000, mt_getrandmax());
$rnd3 = rand(10000000, (int)100000000000); $rnd3 = mt_rand(10000000, mt_getrandmax());
return sprintf("%0x",$rnd1) . sprintf("%0x",$rnd2) . sprintf("%0x",$rnd3); return sprintf("%0x",$rnd1) . sprintf("%0x",$rnd2) . sprintf("%0x",$rnd3);
} }
@ -55,7 +67,7 @@ function set_passkey_cookie($user_id,$is_admin) {
# Create a random value, store it locally and set it in a cookie. # Create a random value, store it locally and set it in a cookie.
global $SESSION_TIMEOUT, $VALIDATED, $USER_ID, $IS_ADMIN, $log_prefix, $SESSION_DEBUG; global $SESSION_TIMEOUT, $VALIDATED, $USER_ID, $IS_ADMIN, $log_prefix, $SESSION_DEBUG, $DEFAULT_COOKIE_OPTIONS;
$passkey = generate_passkey(); $passkey = generate_passkey();
@ -68,16 +80,31 @@ function set_passkey_cookie($user_id,$is_admin) {
} }
$filename = preg_replace('/[^a-zA-Z0-9]/','_', $user_id); $filename = preg_replace('/[^a-zA-Z0-9]/','_', $user_id);
@ file_put_contents("/tmp/$filename","$passkey:$admin_val:$this_time"); @ file_put_contents("/tmp/$filename","$passkey:$admin_val:$this_time");
setcookie('orf_cookie', "$user_id:$passkey", $DEFAULT_COOKIE_OPTIONS);
setcookie('orf_cookie', "$user_id:$passkey", $this_time+(60 * $SESSION_TIMEOUT), '/', '', '', TRUE); $sessto_cookie_opts = $DEFAULT_COOKIE_OPTIONS;
setcookie('sessto_cookie', $this_time+(60 * $SESSION_TIMEOUT), $this_time+7200, '/', '', '', TRUE); $sessto_cookie_opts['expires'] = $this_time+7200;
setcookie('sessto_cookie', $this_time+(60 * $SESSION_TIMEOUT), $sessto_cookie_opts);
if ( $SESSION_DEBUG == TRUE) { error_log("$log_prefix Session: user $user_id validated (IS_ADMIN=${IS_ADMIN}), sent orf_cookie to the browser.",0); } if ( $SESSION_DEBUG == TRUE) { error_log("$log_prefix Session: user $user_id validated (IS_ADMIN=${IS_ADMIN}), sent orf_cookie to the browser.",0); }
$VALIDATED = TRUE; $VALIDATED = TRUE;
} }
######################################################
function login_via_headers() {
global $IS_ADMIN, $USER_ID, $VALIDATED, $LDAP;
//['admins_group'];
$USER_ID = $_SERVER['HTTP_REMOTE_USER'];
$remote_groups = explode(',',$_SERVER['HTTP_REMOTE_GROUPS']);
$IS_ADMIN = in_array($LDAP['admins_group'],$remote_groups);
// users are always validated as we assume, that the auth server does this
$VALIDATED = true;
}
###################################################### ######################################################
function validate_passkey_cookie() { function validate_passkey_cookie() {
@ -85,6 +112,8 @@ function validate_passkey_cookie() {
global $SESSION_TIMEOUT, $IS_ADMIN, $USER_ID, $VALIDATED, $log_prefix, $SESSION_TIMED_OUT, $SESSION_DEBUG; global $SESSION_TIMEOUT, $IS_ADMIN, $USER_ID, $VALIDATED, $log_prefix, $SESSION_TIMED_OUT, $SESSION_DEBUG;
$this_time=time(); $this_time=time();
$VALIDATED = FALSE;
$IS_ADMIN = FALSE;
if (isset($_COOKIE['orf_cookie'])) { if (isset($_COOKIE['orf_cookie'])) {
@ -92,10 +121,7 @@ function validate_passkey_cookie() {
$filename = preg_replace('/[^a-zA-Z0-9]/','_', $user_id); $filename = preg_replace('/[^a-zA-Z0-9]/','_', $user_id);
$session_file = @ file_get_contents("/tmp/$filename"); $session_file = @ file_get_contents("/tmp/$filename");
if (!$session_file) { if (!$session_file) {
$VALIDATED = FALSE; if ($SESSION_DEBUG == TRUE) { error_log("$log_prefix Session: orf_cookie was sent by the client but the session file wasn't found at /tmp/$filename",0); }
unset($USER_ID);
$IS_ADMIN = FALSE;
if ( $SESSION_DEBUG == TRUE) { error_log("$log_prefix Session: orf_cookie was sent by the client but the session file wasn't found at /tmp/$filename",0); }
} }
else { else {
list($f_passkey,$f_is_admin,$f_time) = explode(":",$session_file); list($f_passkey,$f_is_admin,$f_time) = explode(":",$session_file);
@ -103,15 +129,15 @@ function validate_passkey_cookie() {
if ($f_is_admin == 1) { $IS_ADMIN = TRUE; } if ($f_is_admin == 1) { $IS_ADMIN = TRUE; }
$VALIDATED = TRUE; $VALIDATED = TRUE;
$USER_ID=$user_id; $USER_ID=$user_id;
if ( $SESSION_DEBUG == TRUE) { error_log("$log_prefix Setup session: Cookie and session file values match for user ${user_id} - VALIDATED (ADMIN = ${IS_ADMIN})",0); } if ($SESSION_DEBUG == TRUE) { error_log("$log_prefix Setup session: Cookie and session file values match for user ${user_id} - VALIDATED (ADMIN = ${IS_ADMIN})",0); }
set_passkey_cookie($USER_ID,$IS_ADMIN); set_passkey_cookie($USER_ID,$IS_ADMIN);
} }
else { else {
if ( $SESSION_DEBUG == TRUE ) { if ($SESSION_DEBUG == TRUE) {
$this_error="$log_prefix Session: orf_cookie was sent by the client and the session file was found at /tmp/$filename, but"; $this_error="$log_prefix Session: orf_cookie was sent by the client and the session file was found at /tmp/$filename, but";
if (empty($c_passkey)) { $this_error .= " the cookie passkey wasn't set;"; } if (empty($c_passkey)) { $this_error .= " the cookie passkey wasn't set;"; }
if ($c_passkey != $f_passkey) { $this_error .= " the session file passkey didn't match the cookie passkey;"; } if ($c_passkey != $f_passkey) { $this_error .= " the session file passkey didn't match the cookie passkey;"; }
$this_error += " Cookie: ${_COOKIE['orf_cookie']} - Session file contents: $session_file"; $this_error.=" Cookie: ${_COOKIE['orf_cookie']} - Session file contents: $session_file";
error_log($this_error,0); error_log($this_error,0);
} }
} }
@ -119,12 +145,12 @@ function validate_passkey_cookie() {
} }
else { else {
if ( $SESSION_DEBUG == TRUE) { error_log("$log_prefix Session: orf_cookie wasn't sent by the client.",0); } if ($SESSION_DEBUG == TRUE) { error_log("$log_prefix Session: orf_cookie wasn't sent by the client.",0); }
if (isset($_COOKIE['sessto_cookie'])) { if (isset($_COOKIE['sessto_cookie'])) {
$this_session_timeout = $_COOKIE['sessto_cookie']; $this_session_timeout = $_COOKIE['sessto_cookie'];
if ($this_time >= $this_session_timeout) { if ($this_time >= $this_session_timeout) {
$SESSION_TIMED_OUT = TRUE; $SESSION_TIMED_OUT = TRUE;
if ( $SESSION_DEBUG == TRUE) { error_log("$log_prefix Session: The session had timed-out (over $SESSION_TIMEOUT mins idle).",0); } if ($SESSION_DEBUG == TRUE) { error_log("$log_prefix Session: The session had timed-out (over $SESSION_TIMEOUT mins idle).",0); }
} }
} }
} }
@ -138,7 +164,7 @@ function set_setup_cookie() {
# Create a random value, store it locally and set it in a cookie. # Create a random value, store it locally and set it in a cookie.
global $SESSION_TIMEOUT, $IS_SETUP_ADMIN, $log_prefix, $SESSION_DEBUG; global $SESSION_TIMEOUT, $IS_SETUP_ADMIN, $log_prefix, $SESSION_DEBUG, $DEFAULT_COOKIE_OPTIONS;
$passkey = generate_passkey(); $passkey = generate_passkey();
$this_time=time(); $this_time=time();
@ -147,7 +173,7 @@ function set_setup_cookie() {
@ file_put_contents("/tmp/ldap_setup","$passkey:$this_time"); @ file_put_contents("/tmp/ldap_setup","$passkey:$this_time");
setcookie('setup_cookie', "$passkey", $this_time+(60 * $SESSION_TIMEOUT), '/', '', '', TRUE); setcookie('setup_cookie', $passkey, $DEFAULT_COOKIE_OPTIONS);
if ( $SESSION_DEBUG == TRUE) { error_log("$log_prefix Setup session: sent setup_cookie to the client.",0); } if ( $SESSION_DEBUG == TRUE) { error_log("$log_prefix Setup session: sent setup_cookie to the client.",0); }
@ -198,10 +224,15 @@ function log_out($method='normal') {
global $USER_ID, $SERVER_PATH, $DEFAULT_COOKIE_OPTIONS; global $USER_ID, $SERVER_PATH, $DEFAULT_COOKIE_OPTIONS;
$expire_time=time()-20000; $this_time=time();
setcookie('orf_cookie', "", $expire_time, '/', '', '', TRUE); $orf_cookie_opts = $DEFAULT_COOKIE_OPTIONS;
setcookie('sessto_cookie', "", $expire_time, '/', '', '', TRUE); $orf_cookie_opts['expires'] = $this_time-20000;
$sessto_cookie_opts = $DEFAULT_COOKIE_OPTIONS;
$sessto_cookie_opts['expires'] = $this_time-20000;
setcookie('orf_cookie', "", $DEFAULT_COOKIE_OPTIONS);
setcookie('sessto_cookie', "", $DEFAULT_COOKIE_OPTIONS);
$filename = preg_replace('/[^a-zA-Z0-9]/','_', $USER_ID); $filename = preg_replace('/[^a-zA-Z0-9]/','_', $USER_ID);
@ unlink("/tmp/$filename"); @ unlink("/tmp/$filename");
@ -384,7 +415,7 @@ function is_valid_email($email) {
function render_js_username_check(){ function render_js_username_check(){
global $POSIX_REGEX, $ENFORCE_SAFE_SYSTEM_NAMES; global $USERNAME_REGEX, $ENFORCE_SAFE_SYSTEM_NAMES;
if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE) { if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE) {
@ -393,7 +424,7 @@ function render_js_username_check(){
function check_entity_name_validity(name,div_id) { function check_entity_name_validity(name,div_id) {
var check_regex = /$POSIX_REGEX/; var check_regex = /$USERNAME_REGEX/;
if (! check_regex.test(name) ) { if (! check_regex.test(name) ) {
document.getElementById(div_id).classList.add("has-error"); document.getElementById(div_id).classList.add("has-error");
@ -414,22 +445,24 @@ EoCheckJS;
} }
###################################################### ######################################################
function generate_username($fn,$ln) { function generate_username($fn,$ln) {
global $POSIX_USERNAME_FORMAT; global $USERNAME_FORMAT;
$username = $POSIX_USERNAME_FORMAT; $username = $USERNAME_FORMAT;
$username = str_replace('{first_name}',strtolower($fn), $username); $username = str_replace('{first_name}',strtolower($fn), $username);
$username = str_replace('{first_name_initial}',strtolower($fn[0]), $username); $username = str_replace('{first_name_initial}',strtolower($fn[0]), $username);
$username = str_replace('{last_name}',strtolower($ln), $username); $username = str_replace('{last_name}',strtolower($ln), $username);
$username = str_replace('{first_name_initial}',strtolower($ln[0]), $username); $username = str_replace('{last_name_initial}',strtolower($ln[0]), $username);
return $username; return $username;
} }
###################################################### ######################################################
function render_js_username_generator($firstname_field_id,$lastname_field_id,$username_field_id,$username_div_id) { function render_js_username_generator($firstname_field_id,$lastname_field_id,$username_field_id,$username_div_id) {
@ -437,7 +470,7 @@ function render_js_username_generator($firstname_field_id,$lastname_field_id,$us
#Parameters are the IDs of the input fields and username name div in the account creation form. #Parameters are the IDs of the input fields and username name div in the account creation form.
#The div will be set to warning if the username is invalid. #The div will be set to warning if the username is invalid.
global $POSIX_USERNAME_FORMAT, $ENFORCE_SAFE_SYSTEM_NAMES; global $USERNAME_FORMAT, $ENFORCE_SAFE_SYSTEM_NAMES;
$remove_accents=""; $remove_accents="";
if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE) { $remove_accents = ".normalize('NFD').replace(/[\u0300-\u036f]/g, '')"; } if ($ENFORCE_SAFE_SYSTEM_NAMES == TRUE) { $remove_accents = ".normalize('NFD').replace(/[\u0300-\u036f]/g, '')"; }
@ -449,7 +482,7 @@ function render_js_username_generator($firstname_field_id,$lastname_field_id,$us
var first_name = document.getElementById('$firstname_field_id').value; var first_name = document.getElementById('$firstname_field_id').value;
var last_name = document.getElementById('$lastname_field_id').value; var last_name = document.getElementById('$lastname_field_id').value;
var template = '$POSIX_USERNAME_FORMAT'; var template = '$USERNAME_FORMAT';
var actual_username = template; var actual_username = template;
@ -470,6 +503,7 @@ EoRenderJS;
} }
###################################################### ######################################################
function render_js_cn_generator($firstname_field_id,$lastname_field_id,$cn_field_id,$cn_div_id) { function render_js_cn_generator($firstname_field_id,$lastname_field_id,$cn_field_id,$cn_div_id) {
@ -507,6 +541,7 @@ EoRenderCNJS;
} }
###################################################### ######################################################
function render_js_email_generator($username_field_id,$email_field_id) { function render_js_email_generator($username_field_id,$email_field_id) {
@ -532,4 +567,170 @@ EoRenderEmailJS;
} }
######################################################
function render_js_homedir_generator($username_field_id,$homedir_field_id) {
print <<<EoRenderHomedirJS
<script>
var auto_homedir_update = true;
function update_homedir() {
if ( auto_homedir_update == true ) {
var username = document.getElementById('$username_field_id').value;
document.getElementById('$homedir_field_id').value = "/home/" + username;
}
}
</script>
EoRenderHomedirJS;
}
######################################################
function render_dynamic_field_js() {
?>
<script>
function add_field_to(attribute_name,value=null) {
var parent = document.getElementById(attribute_name + '_input_div');
var input_div = document.createElement('div');
window[attribute_name + '_count'] = (window[attribute_name + '_count'] === undefined) ? 1 : window[attribute_name + '_count'] + 1;
var input_field_id = attribute_name + window[attribute_name + '_count'];
var input_div_id = 'div' + '_' + input_field_id;
input_div.className = 'input-group';
input_div.id = input_div_id;
parent.appendChild(input_div);
var input_field = document.createElement('input');
input_field.type = 'text';
input_field.className = 'form-control';
input_field.id = input_field_id;
input_field.name = attribute_name + '[]';
input_field.value = value;
var button_span = document.createElement('span');
button_span.className = 'input-group-btn';
var remove_button = document.createElement('button');
remove_button.type = 'button';
remove_button.className = 'btn btn-default';
remove_button.onclick = function() { var div_to_remove = document.getElementById(input_div_id); div_to_remove.innerHTML = ""; }
remove_button.innerHTML = '-';
input_div.appendChild(input_field);
input_div.appendChild(button_span);
button_span.appendChild(remove_button);
}
</script>
<?php
}
######################################################
function render_attribute_fields($attribute,$label,$values_r,$resource_identifier,$onkeyup="",$inputtype="",$tabindex=null) {
global $THIS_MODULE_PATH;
?>
<div class="form-group" id="<?php print $attribute; ?>_div">
<label for="<?php print $attribute; ?>" class="col-sm-3 control-label"><?php print $label; ?></label>
<div class="col-sm-6" id="<?php print $attribute; ?>_input_div">
<?php if($inputtype == "multipleinput") {
?><div class="input-group">
<input type="text" class="form-control" id="<?php print $attribute; ?>" name="<?php print $attribute; ?>[]" value="<?php if (isset($values_r[0])) { print $values_r[0]; } ?>">
<div class="input-group-btn"><button type="button" class="btn btn-default" onclick="add_field_to('<?php print $attribute; ?>')">+</i></button></div>
</div>
<?php
if (isset($values_r['count']) and $values_r['count'] > 0) {
unset($values_r['count']);
$remaining_values = array_slice($values_r, 1);
print "<script>";
foreach($remaining_values as $this_value) { print "add_field_to('$attribute','$this_value');"; }
print "</script>";
}
}
elseif ($inputtype == "binary") {
$button_text="Browse";
$file_button_action="disabled";
$description="Select a file to upload";
$mimetype="";
if (isset($values_r[0])) {
$this_file_info = new finfo(FILEINFO_MIME_TYPE);
$mimetype = $this_file_info->buffer($values_r[0]);
if (strlen($mimetype) > 23) { $mimetype = substr($mimetype,0,19) . "..."; }
$description="Download $mimetype file (" . human_readable_filesize(strlen($values_r[0])) . ")";
$button_text="Replace file";
if ($resource_identifier != "") {
$this_url="//${_SERVER['HTTP_HOST']}${THIS_MODULE_PATH}/download.php?resource_identifier=${resource_identifier}&attribute=${attribute}";
$file_button_action="onclick=\"window.open('$this_url','_blank');\"";
}
}
if ($mimetype == "image/jpeg") {
$this_image = base64_encode($values_r[0]);
print "<img class='img-thumbnail' src='data:image/jpeg;base64,$this_image'>";
$description="";
}
else {
?>
<button type="button" <?php print $file_button_action; ?> class="btn btn-default" id="<?php print $attribute; ?>-file-info"><?php print $description; ?></button>
<?php } ?>
<label class="btn btn-default">
<?php print $button_text; ?><input <?php if (isset($tabindex)) { ?>tabindex="<?php print $tabindex; ?>" <?php } ?>type="file" style="display:none" onchange="$('#<?php print $attribute; ?>-file-info').text(this.files[0].name)" id="<?php print $attribute; ?>" name="<?php print $attribute; ?>">
</label>
<?php
}
else { ?>
<input <?php if (isset($tabindex)) { ?>tabindex="<?php print $tabindex; ?>" <?php } ?>type="text" class="form-control" id="<?php print $attribute; ?>" name="<?php print $attribute; ?>" value="<?php if (isset($values_r[0])) { print $values_r[0]; } ?>" <?php if ($onkeyup != "") { print "onkeyup=\"$onkeyup\""; } ?>>
<?php
}
?>
</div>
</div>
<?php
}
######################################################
function human_readable_filesize($bytes) {
for($i = 0; ($bytes / 1024) > 0.9; $i++, $bytes /= 1024) {}
return round($bytes, [0,0,1,2,2,3,3,4,4][$i]).['B','kB','MB','GB','TB','PB','EB','ZB','YB'][$i];
}
######################################################
function render_alert_banner($message,$alert_class="success",$timeout=4000) {
?>
<script>window.setTimeout(function() {$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); }); }, $<?php print $timeout; ?>);</script>
<div class="alert alert-<?php print $alert_class; ?>" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center"><?php print $message; ?></p>
</div>
<?php
}
##EoFile
?> ?>

View File

@ -50,7 +50,7 @@ else {
?> ?>
<div class="container"> <div class="container">
<div class="col-sm-8"> <div class="col-sm-8 col-sm-offset-2">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading text-center">Log in</div> <div class="panel-heading text-center">Log in</div>

View File

@ -28,14 +28,14 @@ if($_POST) {
array_push($error_messages, "You didn't enter your first name."); array_push($error_messages, "You didn't enter your first name.");
} }
else { else {
$firstname=filter_var($_POST['firstname'], FILTER_SANITIZE_STRING); $firstname=filter_var($_POST['firstname'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
} }
if (! isset($_POST['lastname']) or $_POST['lastname'] == "") { if (! isset($_POST['lastname']) or $_POST['lastname'] == "") {
array_push($error_messages, "You didn't enter your first name."); array_push($error_messages, "You didn't enter your first name.");
} }
else { else {
$lastname=filter_var($_POST['lastname'], FILTER_SANITIZE_STRING); $lastname=filter_var($_POST['lastname'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
} }
if (isset($_POST['email']) and $_POST['email'] != "") { if (isset($_POST['email']) and $_POST['email'] != "") {
@ -43,7 +43,7 @@ if($_POST) {
} }
if (isset($_POST['notes']) and $_POST['notes'] != "") { if (isset($_POST['notes']) and $_POST['notes'] != "") {
$notes=filter_var($_POST['notes'], FILTER_SANITIZE_STRING); $notes=filter_var($_POST['notes'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
} }
@ -83,22 +83,31 @@ EoT;
include_once "mail_functions.inc.php"; include_once "mail_functions.inc.php";
$sent_email = send_email($ACCOUNT_REQUESTS_EMAIL,"$ORGANISATION_NAME account requests",$mail_subject,$mail_body); $sent_email = send_email($ACCOUNT_REQUESTS_EMAIL,"$ORGANISATION_NAME account requests",$mail_subject,$mail_body);
if ($sent_email) { if ($sent_email) { ?>
$sent_email_message = " Thank you. The request was sent and the administrator will process it as soon as possible.";
}
else {
$sent_email_message = " Unfortunately the request wasn't sent because of a technical problem.";
}
?>
<div class="container"> <div class="container">
<div class="col-sm-8"> <div class="col-sm-6 col-sm-offset-3">
<div class="panel panel-default"> <div class="panel panel-success">
<div class="panel-body"><?php print $sent_email_message; ?></div> <div class="panel-heading">Thank you</div>
<div class="panel-body">
The request was sent and the administrator will process it as soon as possible.
</div>
</div>
</div>
</div>
<?php }
else { ?>
<div class="container">
<div class="col-sm-6 col-sm-offset-3">
<div class="panel panel-danger">
<div class="panel-heading">Error</div>
<div class="panel-body">
Unfortunately the account request wasn't sent because of a technical issue.
</div>
</div> </div>
</div> </div>
</div> </div>
<?php <?php
}
render_footer(); render_footer();
exit(0); exit(0);
@ -106,7 +115,7 @@ EoT;
} }
?> ?>
<div class="container"> <div class="container">
<div class="col-sm-8"> <div class="col-sm-8 col-sm-offset-2">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-body"> <div class="panel-body">