Compare commits

..

No commits in common. "master" and "release-0.0.5" have entirely different histories.

11 changed files with 43 additions and 214 deletions

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
.env
htmlcov

View File

@ -1,74 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the moderation team at nginx-oss-community@f5.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4,
available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>
For answers to common questions about this code of conduct, see
<https://www.contributor-covenant.org/faq>

View File

@ -1,5 +1,4 @@
ARG PYTHON_VERSION=2 FROM python:2-alpine
FROM python:${PYTHON_VERSION}-alpine
COPY nginx-ldap-auth-daemon.py /usr/src/app/ COPY nginx-ldap-auth-daemon.py /usr/src/app/

View File

@ -1,5 +1,4 @@
ARG PYTHON_VERSION=2 FROM python:2-alpine
FROM python:${PYTHON_VERSION}-alpine
WORKDIR /usr/src/app/ WORKDIR /usr/src/app/
COPY nginx-ldap-auth-daemon.py /usr/src/app/ COPY nginx-ldap-auth-daemon.py /usr/src/app/

View File

@ -1,16 +1,14 @@
# PLEASE note that this project is *not designed or hardened* for production. It is intended as a model for such connector daemons # nginx-ldap-auth
## The nginx-ldap-auth project Reference implementation of method for authenticating users on behalf of servers proxied by NGINX or NGINX Plus
This project provides a reference model implementation of a method for authenticating users on behalf of servers proxied by NGINX or NGINX Plus. ## Description
### Note: ### **Note:** For ease of reading, this document refers to [NGINX Plus](http://www.nginx.com/products/), but it also applies to [open source NGINX](http://www.nginx.org/en). The prerequisite [ngx_http_auth_request_module](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) module is included both in [NGINX Plus packages](http://cs.nginx.com/repo_setup) and [prebuilt open source NGINX binaries](http://nginx.org/en/linux_packages.html).
For ease of reading, this document refers to NGINX Plus, but it also applies to open source NGINX. The prerequisite ngx_http_auth_request_module module is included both in NGINX Plus packages and prebuilt open source NGINX binaries.
### Description: ### The nginx-ldap-auth software is a reference implementation of a method for authenticating users who request protected resources from servers proxied by NGINX Plus. It includes a daemon (*ldap-auth*) that communicates with an authentication server, and a sample daemon that stands in for an actual back-end server during testing, by generating an authentication cookie based on the users credentials. The daemons are written in Python for use with a Lightweight Directory Access Protocol (LDAP) authentication server (OpenLDAP or Microsoft Windows Active Directory 2003 and 2012).
The nginx-ldap-auth software is a reference model implementation of a method for authenticating users who request protected resources from servers proxied by NGINX Plus. It includes a daemon (ldap-auth) that communicates with an authentication server, and a sample daemon that stands in for an actual back-end server during testing, by generating an authentication cookie based on the users credentials. The daemons are written in Python for use with a Lightweight Directory Access Protocol (LDAP) authentication server (OpenLDAP or Microsoft Windows Active Directory 2003 and 2012).
The ldap-auth daemon, which mediates between NGINX Plus and the LDAP server, is intended to serve as a model for "connector" daemons written in other languages, for different authentication systems, or both. NGINX, Inc. Professional Services is available to assist with such adaptations. The ldap-auth daemon, which mediates between NGINX Plus and the LDAP server, is intended to serve as a model for "connector" daemons written in other languages, for different authentication systems, or both. [NGINX, Inc. Professional Services](http://nginx.com/services/) is available to assist with such adaptations.
![NGINX LDAP Architecture](https://cdn-1.wp.nginx.com/wp-content/uploads/2016/02/ldap-auth-components.jpg) ![NGINX LDAP Architecture](https://cdn-1.wp.nginx.com/wp-content/uploads/2016/02/ldap-auth-components.jpg)
@ -34,25 +32,21 @@ To install and configure the reference implementation, perform the following ste
1. On the host where the ldap-auth daemon is to run, install the following additional software. We recommend using the versions that are distributed with the operating system, instead of downloading the software from an open source repository. 1. On the host where the ldap-auth daemon is to run, install the following additional software. We recommend using the versions that are distributed with the operating system, instead of downloading the software from an open source repository.
- Python versions 2 and 3 are supported. - Python version 2. Version 3 is not supported.
- The Python LDAP module, **python-ldap** (created by the [python-ldap.org](http://www.python-ldap.org) open source project). - The Python LDAP module, **python-ldap** (created by the [python-ldap.org](http://www.python-ldap.org) open source project).
1. Copy the following files from your repository clone to the indicated hosts: 1. Copy the following files from your repository clone to the indicated hosts:
- **nginx-ldap-auth.conf** NGINX Plus configuration file, which contains the minimal set of directives for testing the reference implementation. Install on the NGINX Plus host (in the **/etc/nginx/conf.d** directory if using the conventional configuration scheme). To avoid configuration conflicts, remember to move or rename any default configuration files installed with NGINX Plus. - **nginx-ldap-auth.conf** NGINX Plus configuration file, which contains the minimal set of directives for testing the reference implementation. Install on the NGINX Plus host (in the **/etc/nginx/conf.d** directory if using the conventional configuration scheme). To avoid configuration conflicts, remember to move or rename any default configuration files installed with NGINX Plus.
- **nginx-ldap-auth-daemon.py** Python code for the ldap-auth daemon. Install on the host of your choice. - **nginx-ldap-auth-daemon.py** Python code for the ldap-auth daemon. Install on the host of your choice.
Alternatively, use provided Dockerfile to build Docker image: Alternatively, use provided Dockerfile to build Docker image:
``` ```
docker build -t nginx-ldap-auth-daemon . docker build -t nginx-ldap-auth-daemon .
docker run nginx-ldap-auth-daemon docker run nginx-ldap-auth-daemon
``` ```
If you desire to use a container with Python3, you can supply an appropriate build argument:
```
docker build -t nginx-ldap-auth-daemon --build-arg PYTHON_VERSION=3 .
```
- **nginx-ldap-auth-daemon-ctl.sh** Sample shell script for starting and stopping the daemon. Install on the same host as the ldap-auth daemon. - **nginx-ldap-auth-daemon-ctl.sh** Sample shell script for starting and stopping the daemon. Install on the same host as the ldap-auth daemon.
- **backend-sample-app.py** Python code for the daemon that during testing stands in for a real back-end application server. Install on the host of your choice. - **backend-sample-app.py** Python code for the daemon that during testing stands in for a real back-end application server. Install on the host of your choice.
1. Modify the NGINX Plus configuration file as described in [Required Modifications to the NGINX Plus Configuration File](#required-mods) below. For information about customizing your deployment, see [Customization](#customization) below. We recommend running the `nginx -t` command after making your changes to verify that the file is syntactically valid. 1. Modify the NGINX Plus configuration file as described in [Required Modifications to the NGINX Plus Configuration File](#required-mods) below. For information about customizing your deployment, see [Customization](#customization) below. We recommend running the `nginx -t` command after making your changes to verify that the file is syntactically valid.
@ -92,9 +86,6 @@ http {
location = /auth-proxy { location = /auth-proxy {
proxy_pass http://<strong>127.0.0.1</strong>:8888; proxy_pass http://<strong>127.0.0.1</strong>:8888;
proxy_pass_request_body off;
proxy_pass_request_headers off;
proxy_set_header Content-Length "";
proxy_cache <strong>auth_cache</strong>; # Must match the name in the proxy_cache_path directive above proxy_cache <strong>auth_cache</strong>; # Must match the name in the proxy_cache_path directive above
proxy_cache_valid 200 <strong>10m</strong>; proxy_cache_valid 200 <strong>10m</strong>;
@ -132,12 +123,11 @@ proxy_set_header X-Ldap-Template "(&(cn=%(username)s)(memberOf=cn=group1,cn=User
The search filters can be combined from less complex filters using boolean operations and can be rather complex. The search filters can be combined from less complex filters using boolean operations and can be rather complex.
The reference implementation uses cookie-based authentication. If you are using HTTP basic authentication instead, comment out the following directives, and enable the Authorization header as shown: The reference implementation uses cookie-based authentication. If you are using HTTP basic authentication instead, comment out the following directives as shown:
<pre> <pre>
<strong>#</strong>proxy_set_header X-CookieName "nginxauth"; <strong>#</strong>proxy_set_header X-CookieName "nginxauth";
<strong>#</strong>proxy_set_header Cookie nginxauth=$cookie_nginxauth; <strong>#</strong>proxy_set_header Cookie nginxauth=$cookie_nginxauth;
<strong>proxy_set_header Authorization $http_authorization;</strong>
</pre> </pre>
## Customization ## Customization

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
''''which python2 >/dev/null && exec python2 "$0" "$@" # '''
''''which python >/dev/null && exec python "$0" "$@" # ''' ''''which python >/dev/null && exec python "$0" "$@" # '''
# Copyright (C) 2014-2015 Nginx, Inc. # Copyright (C) 2014-2015 Nginx, Inc.
@ -8,29 +9,13 @@
# 1) accepts GET requests on /login and responds with a login form # 1) accepts GET requests on /login and responds with a login form
# 2) accepts POST requests on /login, sets a cookie, and responds with redirect # 2) accepts POST requests on /login, sets a cookie, and responds with redirect
import sys, os, signal, base64, cgi import sys, os, signal, base64, Cookie, cgi, urlparse
if sys.version_info.major == 2: from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from urlparse import urlparse
from Cookie import BaseCookie
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
elif sys.version_info.major == 3:
from urllib.parse import urlparse
from http.cookies import BaseCookie
from http.server import HTTPServer, BaseHTTPRequestHandler
Listen = ('localhost', 9000) Listen = ('localhost', 9000)
import threading import threading
if sys.version_info.major == 2: from SocketServer import ThreadingMixIn
from SocketServer import ThreadingMixIn
elif sys.version_info.major == 3:
from socketserver import ThreadingMixIn
def ensure_bytes(data):
return data if sys.version_info.major == 2 else data.encode("utf-8")
class AuthHTTPServer(ThreadingMixIn, HTTPServer): class AuthHTTPServer(ThreadingMixIn, HTTPServer):
pass pass
@ -38,14 +23,14 @@ class AppHandler(BaseHTTPRequestHandler):
def do_GET(self): def do_GET(self):
url = urlparse(self.path) url = urlparse.urlparse(self.path)
if url.path.startswith("/login"): if url.path.startswith("/login"):
return self.auth_form() return self.auth_form()
self.send_response(200) self.send_response(200)
self.end_headers() self.end_headers()
self.wfile.write(ensure_bytes('Hello, world! Requested URL: ' + self.path + '\n')) self.wfile.write('Hello, world! Requested URL: ' + self.path + '\n')
# send login form html # send login form html
@ -74,7 +59,7 @@ class AppHandler(BaseHTTPRequestHandler):
<tr> <tr>
<td>Username: <input type="text" name="username"/></td> <td>Username: <input type="text" name="username"/></td>
<tr> <tr>
<td>Password: <input type="password" name="password"/></td> <td>Password: <input type="text" name="password"/></td>
<tr> <tr>
<td><input type="submit" value="Login"></td> <td><input type="submit" value="Login"></td>
</table> </table>
@ -85,7 +70,7 @@ class AppHandler(BaseHTTPRequestHandler):
self.send_response(200) self.send_response(200)
self.end_headers() self.end_headers()
self.wfile.write(ensure_bytes(html.replace('TARGET', target))) self.wfile.write(html.replace('TARGET', target))
# processes posted form and sets the cookie with login/password # processes posted form and sets the cookie with login/password
@ -118,10 +103,8 @@ class AppHandler(BaseHTTPRequestHandler):
# and share a key with auth daemon that extracts this information # and share a key with auth daemon that extracts this information
# #
# WARNING WARNING WARNING # WARNING WARNING WARNING
enc = base64.b64encode(ensure_bytes(user + ':' + passwd)) enc = base64.b64encode(user + ':' + passwd)
if sys.version_info.major == 3: self.send_header('Set-Cookie', 'nginxauth=' + enc + '; httponly')
enc = enc.decode()
self.send_header('Set-Cookie', b'nginxauth=' + enc + b'; httponly')
self.send_header('Location', target) self.send_header('Location', target)
self.end_headers() self.end_headers()

View File

@ -1,25 +1,12 @@
#!/bin/sh #!/bin/sh
''''[ -z $LOG ] && export LOG=/dev/stdout # ''' ''''[ -z $LOG ] && export LOG=/dev/stdout # '''
''''which python2 >/dev/null && exec python2 -u "$0" "$@" >> $LOG 2>&1 # '''
''''which python >/dev/null && exec python -u "$0" "$@" >> $LOG 2>&1 # ''' ''''which python >/dev/null && exec python -u "$0" "$@" >> $LOG 2>&1 # '''
# Copyright (C) 2014-2022 Nginx, Inc. # Copyright (C) 2014-2015 Nginx, Inc.
import sys import sys, os, signal, base64, ldap, Cookie, argparse
import os from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import signal
import base64
import ldap
from ldap.filter import escape_filter_chars
import argparse
if sys.version_info.major == 2:
from Cookie import BaseCookie
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
elif sys.version_info.major == 3:
from http.cookies import BaseCookie
from http.server import HTTPServer, BaseHTTPRequestHandler
if not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
#Listen = ('localhost', 8888) #Listen = ('localhost', 8888)
#Listen = "/tmp/auth.sock" # Also uncomment lines in 'Requests are #Listen = "/tmp/auth.sock" # Also uncomment lines in 'Requests are
@ -30,12 +17,7 @@ if not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Requests are processed in separate thread # Requests are processed in separate thread
import threading import threading
from SocketServer import ThreadingMixIn
if sys.version_info.major == 2:
from SocketServer import ThreadingMixIn
elif sys.version_info.major == 3:
from socketserver import ThreadingMixIn
class AuthHTTPServer(ThreadingMixIn, HTTPServer): class AuthHTTPServer(ThreadingMixIn, HTTPServer):
pass pass
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
@ -90,15 +72,14 @@ class AuthHandler(BaseHTTPRequestHandler):
try: try:
auth_decoded = base64.b64decode(auth_header[6:]) auth_decoded = base64.b64decode(auth_header[6:])
if sys.version_info.major == 3: auth_decoded = auth_decoded.decode("utf-8")
user, passwd = auth_decoded.split(':', 1) user, passwd = auth_decoded.split(':', 1)
except: except:
self.auth_failed(ctx) self.auth_failed(ctx)
return True return True
ctx['user'] = user
ctx['pass'] = passwd ctx['pass'] = passwd
ctx['user'] = ldap.filter.escape_filter_chars(user)
# Continue request processing # Continue request processing
return False return False
@ -106,7 +87,7 @@ class AuthHandler(BaseHTTPRequestHandler):
def get_cookie(self, name): def get_cookie(self, name):
cookies = self.headers.get('Cookie') cookies = self.headers.get('Cookie')
if cookies: if cookies:
authcookie = BaseCookie(cookies).get(name) authcookie = Cookie.BaseCookie(cookies).get(name)
if authcookie: if authcookie:
return authcookie.value return authcookie.value
else: else:
@ -236,7 +217,7 @@ class LDAPAuthHandler(AuthHandler):
ldap_obj.bind_s(ctx['binddn'], ctx['bindpasswd'], ldap.AUTH_SIMPLE) ldap_obj.bind_s(ctx['binddn'], ctx['bindpasswd'], ldap.AUTH_SIMPLE)
ctx['action'] = 'preparing search filter' ctx['action'] = 'preparing search filter'
searchfilter = ctx['template'] % {'username': ctx['user']} searchfilter = ctx['template'] % { 'username': ctx['user'] }
self.log_message(('searching on server "%s" with base dn ' + \ self.log_message(('searching on server "%s" with base dn ' + \
'"%s" with filter "%s"') % '"%s" with filter "%s"') %

View File

@ -47,7 +47,6 @@ http {
proxy_pass http://127.0.0.1:8888; proxy_pass http://127.0.0.1:8888;
proxy_pass_request_body off; proxy_pass_request_body off;
proxy_pass_request_headers off;
proxy_set_header Content-Length ""; proxy_set_header Content-Length "";
proxy_cache auth_cache; proxy_cache auth_cache;
proxy_cache_valid 200 10m; proxy_cache_valid 200 10m;
@ -102,9 +101,6 @@ http {
proxy_set_header X-CookieName "nginxauth"; proxy_set_header X-CookieName "nginxauth";
proxy_set_header Cookie nginxauth=$cookie_nginxauth; proxy_set_header Cookie nginxauth=$cookie_nginxauth;
# (Optional) Uncomment if using HTTP basic authentication
#proxy_set_header Authorization $http_authorization;
# (Required if using Microsoft Active Directory as the LDAP server) # (Required if using Microsoft Active Directory as the LDAP server)
# Set the LDAP template by uncommenting the following directive. # Set the LDAP template by uncommenting the following directive.
#proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)"; #proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";

View File

@ -1,16 +1,7 @@
To run tests use supplied Dockerfile.test: To run tests use supplied Dockerfile.test:
```shell docker build -f Dockerfile.test -t my-tag .
docker build -t my-tag -f Dockerfile.test .
```
If you desire to use a container with Python3, you can supply an appropriate
build argument:
```shell
docker build -f Dockerfile.test -t my-tag --build-arg PYTHON_VERSION=3 .
docker run my-tag docker run my-tag
```
To run without Docker: To run without Docker:

View File

@ -105,15 +105,6 @@ http {
proxy_pass http://backend/; proxy_pass http://backend/;
} }
location /query-injection {
auth_request /auth-query-injection;
error_page 401 =200 /login;
proxy_pass http://backend/;
}
location /login { location /login {
proxy_pass http://backend/login; proxy_pass http://backend/login;
@ -230,24 +221,6 @@ http {
proxy_set_header Cookie nginxauth=$cookie_nginxauth; proxy_set_header Cookie nginxauth=$cookie_nginxauth;
} }
location = /auth-query-injection {
internal;
proxy_pass http://127.0.0.1:8888;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Ldap-URL "ldap://127.0.0.1:8083";
proxy_set_header X-Ldap-BaseDN "ou=Users,dc=test,dc=local";
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
proxy_set_header X-Ldap-BindPass "secret";
proxy_set_header X-CookieName "nginxauth";
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
proxy_set_header X-Ldap-Template '(|(&(memberOf=superadmin)(cn=%(username)s))(&(memberOf=admin)(cn=%(username)s)))';
}
} }
} }
@ -348,7 +321,7 @@ EOF
$t->write_file_expand("initial.ldif", <<'EOF'); $t->write_file_expand("initial.ldif", <<'EOF');
dn: dc=test,dc=local dn: dc=test,dc=local
dc: test dc: test
description: Test-OU description: BlaBlaBla
objectClass: dcObject objectClass: dcObject
objectClass: organization objectClass: organization
o: Example, Inc. o: Example, Inc.
@ -360,7 +333,7 @@ objectclass: organizationalunit
dn: cn=user1,ou=Users,dc=test,dc=local dn: cn=user1,ou=Users,dc=test,dc=local
objectclass: inetOrgPerson objectclass: inetOrgPerson
cn: User1 cn: User number one
sn: u1 sn: u1
uid: user1 uid: user1
userpassword: user1secret userpassword: user1secret
@ -370,7 +343,7 @@ ou: Users
dn: cn=user2,ou=Users,dc=test,dc=local dn: cn=user2,ou=Users,dc=test,dc=local
objectclass: inetOrgPerson objectclass: inetOrgPerson
cn: User2 cn: User number one
sn: u2 sn: u2
uid: user2 uid: user2
userpassword: user2secret userpassword: user2secret
@ -380,7 +353,7 @@ ou: Users
dn: cn=user3,ou=Users,dc=test,dc=local dn: cn=user3,ou=Users,dc=test,dc=local
objectclass: inetOrgPerson objectclass: inetOrgPerson
cn: User3 cn: User number one
sn: u3 sn: u3
uid: user3 uid: user3
userpassword: user3secret userpassword: user3secret
@ -405,13 +378,13 @@ objectclass: organizationalunit
dn: ou=more,ou=Users,dc=test,dc=local dn: ou=more,ou=Users,dc=test,dc=local
dc: test dc: test
description: Test-OU description: BlaBlaBla
objectClass: dcObject objectClass: dcObject
objectClass: organizationalUnit objectClass: organizationalUnit
dn: cn=user4, ou=more, ou=Users,dc=test,dc=local dn: cn=user4, ou=more, ou=Users,dc=test,dc=local
objectclass: inetOrgPerson objectclass: inetOrgPerson
cn: User4 cn: User number one
sn: u4 sn: u4
uid: user4 uid: user4
userpassword: user4secret userpassword: user4secret
@ -460,7 +433,7 @@ system("ldapadd -H ldap://127.0.0.1:$p5 -x -D \"cn=root,ou=Users,dc=test,dc=loca
$t->write_file_expand("auth_daemon.sh", <<"EOF"); $t->write_file_expand("auth_daemon.sh", <<"EOF");
AUTHBIN=\$(realpath $AUTHD) AUTHBIN=\$(realpath $AUTHD)
cd $d cd $d
exec coverage run \$AUTHBIN --host 127.0.0.1 \\ exec coverage2 run \$AUTHBIN --host 127.0.0.1 \\
-p %%PORT_8888%% >$d/nginx-ldap-auth-dameon.stdlog 2>&1 -p %%PORT_8888%% >$d/nginx-ldap-auth-dameon.stdlog 2>&1
EOF EOF
@ -468,7 +441,7 @@ $t->run_daemon('/bin/sh', "$d/auth_daemon.sh");
$t->waitforsocket('127.0.0.1:' . port(8888)) $t->waitforsocket('127.0.0.1:' . port(8888))
or die "Can't start auth daemon"; or die "Can't start auth daemon";
$t->plan(22); $t->plan(21);
$t->run(); $t->run();
@ -527,17 +500,10 @@ like(http_get_auth('/ref1', 'user4', 'user4secret'), qr!LOGIN PAGE!,
'server2 user via referral on server1'); 'server2 user via referral on server1');
# unknown user on referred server, result is empty dn # unknown user on referred server, result is empty dn
like(http_get_auth('/ref1', 'unknow_user', 'unknowpassword'), qr!LOGIN PAGE!, like(http_get_auth('/ref1', 'userx', 'blah'), qr!LOGIN PAGE!,
'unknown user with referral on server1'); 'unknown user with referral on server1');
# LDAP Query Injection result in 401
like(http_get_auth('/query-injection', 'user1))(|(cn=user1', 'user1secret'), qr!LOGIN PAGE!,
'Injection Attempt in Username will be escaped and blocked.');
############################################################################### ###############################################################################
sub http_get_auth { sub http_get_auth {

View File

@ -10,4 +10,4 @@ perl ldap-auth.t
testdir=$(find /tmp -name 'nginx-test-*' -print -quit) testdir=$(find /tmp -name 'nginx-test-*' -print -quit)
cd $testdir cd $testdir
coverage html && printf "Coverage report: docker cp <cid>:$testdir/htmlcov <hostdir>\n" coverage2 html && printf "Coverage report: docker cp <cid>:$testdir/htmlcov <hostdir>\n"