Skip to content

Commit 258c20c

Browse files
committed
Initial import
0 parents  commit 258c20c

File tree

6 files changed

+1299
-0
lines changed

6 files changed

+1299
-0
lines changed

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Redistribution and use in source and binary forms, with or without
2+
modification, are permitted provided that the following conditions
3+
are met:
4+
1. Redistributions of source code must retain the above copyright
5+
notice, this list of conditions and the following disclaimer.
6+
2. Redistributions in binary form must reproduce the above copyright
7+
notice, this list of conditions and the following disclaimer in the
8+
documentation and/or other materials provided with the distribution.
9+
10+
THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
11+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13+
ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
14+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
15+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20+
SUCH DAMAGE.

bugs.txt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
2+
state management/nginx machinery
3+
- all requests to digest-protected pages are funneled through a single mutex accessing an
4+
rbtree of recently issued nonce values. the logic for evicting saved nonces from the tree
5+
over time is fairly simple, but what is unclear to me is how to schedule these garbage
6+
collection runs.
7+
8+
the cleanup hook on the request's pool seems like a good candidate since it won't block the
9+
request that triggered it. perhaps with an atomic flag in the shm segment preventing traffic
10+
jams of cleanup?
11+
12+
- a larger unknown (to me) is the performance characteristics of tree maintenance over the
13+
tree sizes (also unknown) likely to be seen in production use. it would be good to have
14+
some solid numbers on which to base shm-size and eviction defaults.
15+
16+
- there's a fair amount of painful parsing code devoted to unpacking the key/value fields
17+
in the Authorize header. i have to believe i'm just unaware of an nginx built-in of some
18+
sort that will do this part for me. however the docs only led me to a string-level
19+
representation of the header.
20+
21+
- there should be a directive letting you specify that only particular users in a realm may
22+
log in. how to handle wildcards though; maybe "*" or "any"? "_" or "none"?
23+
24+
25+
rfc 2617
26+
- currently lacks backward compatibility with clients that don't provide `qop' fields in
27+
the Authorize header. according to the rfc the server should work without it, but is it
28+
worth supporting the less secure version of an already not-bulletproof authentication
29+
scheme?
30+
31+
- should the 401 response also offer a basic auth option if that module is also enabled
32+
for a given location block? is there a way for one module to read another's config to
33+
detect the overlap? or is this a module-loading-order issue (c.f., the way the fancy_index
34+
module inserts itself before the built-in autoindex module in its HTTP_MODULES config var)?
35+
36+
- the opaque field is not used when generating challenges, nor is it validated when included
37+
in an authentication request. is this a significant omission? the spec makes it seem as
38+
though it only exists as a convenience to stash state in, but i could believe some software
39+
out there depends upon it...
40+
41+
general (in)security
42+
- i followed the model of the auth_basic module which pages through the password file's
43+
contents on every request. i know from experience that it's impossible for me to write that
44+
sliding-window-through-a-buffer routine without a creating at least a couple off-by-one
45+
errors and non-terminated strings. it would be nice to find them.
46+
47+
- also as a result of the auth_basic-inspired character-by-character verification of the
48+
auth credentials, the current implementation could be vulnerable to timing attacks (since
49+
it returns as soon as it finds a match). the simplest solution to this would seem to be adding
50+
a sleep(random()) delaying the response by a few (dozen? hundred?) milliseconds. i presume the
51+
non-blocking way to do this would be to use a timer?
52+
53+
- OOM conditions in the shm segment are not handled at all well at the moment leading to an
54+
easy DOS attack. valid nonces are added to the shm and expired seconds or minutes later.
55+
Once the shm is full no new nonces can be remembered and all auth attempts will fail until
56+
enough space has been claimed through expiration. It's unclear to me whether it's possible
57+
to realloc the shm segment to a larger size after config-time (or if additional segments
58+
could be alloc'd to allow for a bank-switching solution). If the amount of memory really is
59+
finite, then that argues for either more aggressive eviction in lomem conditions or for
60+
moving the state storage to the filesystem. Could nginx's file caching machinery be used
61+
for managing expiration?
62+

config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# -*- mode:sh; -*-
2+
ngx_addon_name=ngx_http_auth_digest_module
3+
HTTP_MODULES="$HTTP_MODULES ngx_http_auth_digest_module"
4+
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_auth_digest_module.c"

htdigest.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env python
2+
# encoding: utf-8
3+
"""
4+
htdigest.py
5+
6+
A barebones stand-in for the apache htdigest tool. It lacks the -c switch of the
7+
original and doesn't handle comments or blank lines. Caveat sysadmin...
8+
9+
Created by Christian Swinehart on 2011-10-30.
10+
Copyright (c) 2011 Samizdat Drafting Co. All rights reserved.
11+
"""
12+
13+
from __future__ import with_statement
14+
import sys
15+
import os
16+
from hashlib import md5
17+
from getpass import getpass
18+
19+
class Passwd(object):
20+
def __init__(self, pth):
21+
super(Passwd, self).__init__()
22+
self.pth = os.path.abspath(pth)
23+
self.creds = []
24+
if not os.path.exists(self.pth):
25+
while True:
26+
resp = raw_input('%s does not exist. Create it? (y/n) '%self.pth).lower()
27+
if resp == 'y': break
28+
if resp == 'n': sys.exit(1)
29+
else:
30+
with file(self.pth) as f:
31+
for line in f.readlines():
32+
self.creds.append(line.strip().split(":"))
33+
34+
def update(self, username, realm):
35+
user_matches = [c for c in self.creds if c[0]==username and c[1]==realm]
36+
if user_matches:
37+
password = getpass('Change password for "%s" to: '%username)
38+
else:
39+
password = getpass('Password for new user "%s": '%username)
40+
if password != getpass('Please repeat the password: '):
41+
print "Passwords didn't match. %s unchanged."%self.pth
42+
sys.exit(1)
43+
44+
pw_hash = md5(':'.join([username,realm,password])).hexdigest()
45+
if user_matches:
46+
user_matches[0][2] = pw_hash
47+
else:
48+
self.creds.append([username, realm, pw_hash])
49+
50+
new_passwd = "\n".join(":".join(cred) for cred in self.creds)
51+
with file(self.pth,'w') as f:
52+
f.write(new_passwd)
53+
54+
if __name__ == '__main__':
55+
if len(sys.argv) != 4:
56+
print "usage: htdigest.py passwdfile username 'realm name'"
57+
sys.exit(1)
58+
fn,user,realm = sys.argv[1:4]
59+
60+
passwd = Passwd(fn)
61+
passwd.update(user,realm)
62+

0 commit comments

Comments
 (0)