... | ... | @@ -866,7 +866,74 @@ starts with the `!` string). |
|
|
|
|
|
### Web interface
|
|
|
|
|
|
TODO: document web interfac; what it can and cannot do and how it works.
|
|
|
The web interface is shipped as part of the userdir-ldap-cgi Debian
|
|
|
package, built from the [userdir-ldap-cgi source code](https://gitweb.torproject.org/admin/userdir-ldap-cgi.git/). The web
|
|
|
interface is written in Perl, using the builtin CGI module and [WML][]
|
|
|
templates. It handles password and settings changes for users,
|
|
|
although some settings (like sudo passwords) require an extra
|
|
|
confirmation by OpenPGP-signed message through the email gateway. It
|
|
|
also lists machines known by LDAP.
|
|
|
|
|
|
The web interface also ships documentation in the form of HTML pages
|
|
|
rendered through [WML][] templates.
|
|
|
|
|
|
The web interface binds to the LDAP database as the logged in user (or
|
|
|
anonymously, for some listings and searches) and therefore doesn't
|
|
|
enjoy any special privilege in itself.
|
|
|
|
|
|
Each "dynamic" page is a standalone CGI script, although it uses some
|
|
|
common code from `Util.pm` to load settings, format some strings, deal
|
|
|
with authentication tokens and passwords.
|
|
|
|
|
|
The main page is the `search.cgi` interface, which allows users to
|
|
|
perform a search in the user database, based on a subset of LDAP
|
|
|
fields. This script uses the `searchform.wml` template.
|
|
|
|
|
|
The login form (`login.cgi`) binds with the LDAP database using the
|
|
|
provided user/password. A "hack" is present to "upgrade" the user's
|
|
|
passwords to MD5, presumably it was in cleartext
|
|
|
before. Authentication persistence is done through an authentication
|
|
|
token (`authtoken` in the URL), which consists of a MD5 "*encoded
|
|
|
username and a key to decrypt the password stored on disk, the
|
|
|
authtoken is protected from modification by an HMAC*". In practice, it
|
|
|
seems the user's password is stored on disk, encrypted with a Blowfish
|
|
|
cipher in CBC mode (from `Crypt::CBC`), with a 10 bytes (80 bits) key,
|
|
|
while the HMAC is based on SHA1 (from `Digest::HMAC_SHA1`). The tokens
|
|
|
are stored in `/var/cache/userdir-ldap/web-cookies/` with one file per
|
|
|
user, named after a salted MD5 hash of the username.
|
|
|
|
|
|
Although the user/password pair is not stored directly in the user's
|
|
|
browser cookies or history, the authentication token effectively acts
|
|
|
as a valid user/password to make changes to the LDAP user database. It
|
|
|
could be abused to authenticate as an LDAP user and change their
|
|
|
password, for example.
|
|
|
|
|
|
The login form uses the `login.wml` template.
|
|
|
|
|
|
The `logout.cgi` interface, fortunately, allows users to clear this
|
|
|
on-disk data, invalidating possibly leaked tokens.
|
|
|
|
|
|
The `update.cgi` interface is what processes actual changes requested
|
|
|
by users. It will extract the actual LDAP user and password from the
|
|
|
on-disk encrypted token and bind with that username and password. It
|
|
|
does some processing of the form to massage it into a proper LDAP
|
|
|
update, running some password quality checks using a wrapper around
|
|
|
[cracklib](https://github.com/cracklib/cracklib) called `password-qualify-check` which, essentially,
|
|
|
looks at a word list, the GECOS fields and the old password. Partial
|
|
|
updates are possible: if (say) the `rtcPassword` fields don't match
|
|
|
but the `userPassword` fields do, the latter will be performed because
|
|
|
it is done first. It is here that unconfirmed `sudo` passwords are set
|
|
|
as well. It's the user's responsability to send the challenge response
|
|
|
by signed OpenPGP email afterwards. This script uses the `update.wml`
|
|
|
template.
|
|
|
|
|
|
The `machines.cgi` script will list servers registered in the LDAP in
|
|
|
a table. It binds to the LDAP server anonymously and searches for all
|
|
|
hosts. It uses the `hostinfo.wml` template.
|
|
|
|
|
|
Finally the `fetchkey.cgi` script will load a public key from the
|
|
|
`keyrings` configuration setting based on the provided fingerprint and
|
|
|
dump it in plain text.
|
|
|
|
|
|
### Interactions with Puppet
|
|
|
|
... | ... | @@ -1137,7 +1204,9 @@ TODO: next steps for LDAP: |
|
|
* old cryptographic primitives: SHA-1 is used to hash `sudo`
|
|
|
passwords, MD5 is used to hash user passwords, those hashes are
|
|
|
communicated over OpenPGP_encrypted email but stored in LDAP in
|
|
|
cleartext
|
|
|
cleartext. There is a "hack" present in the web interface to
|
|
|
enforce MD5 passwords on logins, and the mail interface also has
|
|
|
MD5 hardcoded for password resets.
|
|
|
|
|
|
* rolls its own crypto: ud-ldap ships its own wrapper around GnuPG,
|
|
|
implementing the (somewhat arcane) commandline dialect. it has not
|
... | ... | @@ -1147,9 +1216,12 @@ TODO: next steps for LDAP: |
|
|
standard OpenPGP/MIME messages and is hard to use for users
|
|
|
|
|
|
* the web interface is showing its age: it's made of old Perl CGI
|
|
|
scripts that uses a custom template format built on top of [WML](https://en.wikipedia.org/wiki/Website_Meta_Language)
|
|
|
scripts that uses a custom template format built on top of [WML][]
|
|
|
with custom pattern replacement, without any other framework than
|
|
|
Perl's builtin `CGI` module
|
|
|
Perl's builtin `CGI` module. it uses in-URL tokens which could be
|
|
|
vulnerable to XSS attacks.
|
|
|
|
|
|
[WML]: https://en.wikipedia.org/wiki/Website_Meta_Language
|
|
|
|
|
|
* large technical debt: ud-ldap is written in (old) Python 2, Perl
|
|
|
and shell, which makes it hard to maintain. it will at least need
|
... | ... | |