Commit 5539f577 authored by Joanne Hugé's avatar Joanne Hugé

Add communities

parent f1e95660
...@@ -7,3 +7,4 @@ hello 4 ...@@ -7,3 +7,4 @@ hello 4
client-count 2 client-count 2
tunnel-refresh 100 tunnel-refresh 100
ipv4 10.42.0.0/16 8 ipv4 10.42.0.0/16 8
community registry/community.conf
...@@ -45,6 +45,9 @@ def main(): ...@@ -45,6 +45,9 @@ def main():
_('--anonymous', action='store_true', _('--anonymous', action='store_true',
help="Request an anonymous certificate. No email is required but the" help="Request an anonymous certificate. No email is required but the"
" registry may deliver a longer prefix.") " registry may deliver a longer prefix.")
_('--country',
help="Specify country for the community assignment (default:"
" country is detected based on IP in X-Forwarded-For header")
config = parser.parse_args() config = parser.parse_args()
if config.dir: if config.dir:
os.chdir(config.dir) os.chdir(config.dir)
...@@ -141,7 +144,8 @@ def main(): ...@@ -141,7 +144,8 @@ def main():
# to avoid using our token for nothing. # to avoid using our token for nothing.
cert_fd = os.open(cert_path, os.O_CREAT | os.O_WRONLY, 0666) cert_fd = os.open(cert_path, os.O_CREAT | os.O_WRONLY, 0666)
print "Requesting certificate ..." print "Requesting certificate ..."
cert = s.requestCertificate(token, req) cert = s.requestCertificate(token, req, country=config.country) \
if config.country else s.requestCertificate(token, req)
if not cert: if not cert:
token_advice = None token_advice = None
sys.exit("Error: invalid or expired token") sys.exit("Error: invalid or expired token")
......
...@@ -110,6 +110,8 @@ def main(): ...@@ -110,6 +110,8 @@ def main():
help="Reject nodes that are too old. Current is %s." % version.protocol) help="Reject nodes that are too old. Current is %s." % version.protocol)
_('--authorized-origin', action='append', default=['127.0.0.1', '::1'], _('--authorized-origin', action='append', default=['127.0.0.1', '::1'],
help="Authorized IPs to access origin-restricted RPC.") help="Authorized IPs to access origin-restricted RPC.")
_('--community',
help="File containing community configuration")
_ = parser.add_argument_group('routing').add_argument _ = parser.add_argument_group('routing').add_argument
_('--hello', type=int, default=15, _('--hello', type=int, default=15,
......
...@@ -68,6 +68,13 @@ class RegistryServer(object): ...@@ -68,6 +68,13 @@ class RegistryServer(object):
self.sessions = {} self.sessions = {}
self.sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) self.sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
# Community
self.community_map = {}
if config.community:
with open(config.community, 'r') as f:
self.community_map = {country: prefix
for country, prefix in [l[:-1].split(' ') for l in f]}
# Database initializing # Database initializing
db_dir = os.path.dirname(self.config.db) db_dir = os.path.dirname(self.config.db)
db_dir and utils.makedirs(db_dir) db_dir and utils.makedirs(db_dir)
...@@ -88,6 +95,10 @@ class RegistryServer(object): ...@@ -88,6 +95,10 @@ class RegistryServer(object):
"prefix TEXT PRIMARY KEY NOT NULL", "prefix TEXT PRIMARY KEY NOT NULL",
"email TEXT", "email TEXT",
"cert TEXT") "cert TEXT")
for c in self.community_map:
self.db.execute(
"INSERT OR IGNORE INTO cert VALUES (?,null,null)", (self.community_map[c],))
if not self.community_map:
self.db.execute("INSERT OR IGNORE INTO cert VALUES ('',null,null)") self.db.execute("INSERT OR IGNORE INTO cert VALUES ('',null,null)")
utils.sqliteCreateTable(self.db, "crl", utils.sqliteCreateTable(self.db, "crl",
"serial INTEGER PRIMARY KEY NOT NULL", "serial INTEGER PRIMARY KEY NOT NULL",
...@@ -279,6 +290,8 @@ class RegistryServer(object): ...@@ -279,6 +290,8 @@ class RegistryServer(object):
request.headers.get("X-Forwarded-For") or request.headers.get("X-Forwarded-For") or
request.headers.get("host"), request.headers.get("host"),
request.headers.get("user-agent")) request.headers.get("user-agent"))
if 'ip' in kw:
kw['ip'] = request.headers.get("X-Forwarded-For") or request.headers.get("host")
try: try:
result = m(**kw) result = m(**kw)
except HTTPError, e: except HTTPError, e:
...@@ -385,12 +398,13 @@ class RegistryServer(object): ...@@ -385,12 +398,13 @@ class RegistryServer(object):
s.sendmail(self.email, email, msg.as_string()) s.sendmail(self.email, email, msg.as_string())
s.quit() s.quit()
def newPrefix(self, prefix_len): def newPrefix(self, prefix_len, country=''):
max_len = 128 - len(self.network) max_len = 128 - len(self.network)
assert 0 < prefix_len <= max_len assert 0 < prefix_len <= max_len
try: try:
prefix, = self.db.execute("""SELECT prefix FROM cert WHERE length(prefix) <= ? AND cert is null prefix, = self.db.execute("""SELECT prefix FROM cert WHERE length(prefix) <= ? AND cert is null
ORDER BY length(prefix) DESC""", (prefix_len,)).next() AND prefix LIKE ? ORDER BY length(prefix) DESC""",
(prefix_len, self.community_map.get(country, '') + '%')).next()
except StopIteration: except StopIteration:
logging.error('No more free /%u prefix available', prefix_len) logging.error('No more free /%u prefix available', prefix_len)
raise raise
...@@ -401,10 +415,10 @@ class RegistryServer(object): ...@@ -401,10 +415,10 @@ class RegistryServer(object):
if len(prefix) < max_len or '1' in prefix: if len(prefix) < max_len or '1' in prefix:
return prefix return prefix
self.db.execute("UPDATE cert SET cert = 'reserved' WHERE prefix = ?", (prefix,)) self.db.execute("UPDATE cert SET cert = 'reserved' WHERE prefix = ?", (prefix,))
return self.newPrefix(prefix_len) return self.newPrefix(prefix_len, country)
@rpc @rpc
def requestCertificate(self, token, req): def requestCertificate(self, token, req, country='', ip=''):
req = crypto.load_certificate_request(crypto.FILETYPE_PEM, req) req = crypto.load_certificate_request(crypto.FILETYPE_PEM, req)
with self.lock: with self.lock:
with self.db: with self.db:
...@@ -424,7 +438,9 @@ class RegistryServer(object): ...@@ -424,7 +438,9 @@ class RegistryServer(object):
if not prefix_len: if not prefix_len:
raise HTTPError(httplib.FORBIDDEN) raise HTTPError(httplib.FORBIDDEN)
email = None email = None
prefix = self.newPrefix(prefix_len) country = country if country else self._geoiplookup(ip)
prefix = self.newPrefix(prefix_len,
country if country in self.community_map else '_')
self.db.execute("UPDATE cert SET email = ? WHERE prefix = ?", self.db.execute("UPDATE cert SET email = ? WHERE prefix = ?",
(email, prefix)) (email, prefix))
if self.prefix is None: if self.prefix is None:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment