Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
R
re6stnet
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
2
Issues
2
List
Boards
Labels
Milestones
Merge Requests
4
Merge Requests
4
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
re6stnet
Commits
e1060631
Commit
e1060631
authored
Jun 14, 2024
by
Tom Niget
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wip: add lots of type hints and fix some python 2 migration bugs
parent
7aa7a526
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
108 additions
and
96 deletions
+108
-96
re6st/cache.py
re6st/cache.py
+14
-13
re6st/cli/node.py
re6st/cli/node.py
+2
-2
re6st/ctl.py
re6st/ctl.py
+2
-2
re6st/debug.py
re6st/debug.py
+6
-6
re6st/plib.py
re6st/plib.py
+6
-6
re6st/registry.py
re6st/registry.py
+29
-26
re6st/tests/test_unit/test_registry.py
re6st/tests/test_unit/test_registry.py
+7
-5
re6st/tests/tools.py
re6st/tests/tools.py
+2
-2
re6st/tunnel.py
re6st/tunnel.py
+9
-6
re6st/upnpigd.py
re6st/upnpigd.py
+2
-2
re6st/utils.py
re6st/utils.py
+12
-11
re6st/x509.py
re6st/x509.py
+17
-15
No files found.
re6st/cache.py
View file @
e1060631
...
@@ -5,7 +5,7 @@ from . import utils, version, x509
...
@@ -5,7 +5,7 @@ from . import utils, version, x509
class
Cache
:
class
Cache
:
def
__init__
(
self
,
db_path
,
registry
,
cert
:
x509
.
Cert
,
db_size
=
200
):
def
__init__
(
self
,
db_path
:
str
,
registry
,
cert
:
x509
.
Cert
,
db_size
=
200
):
self
.
_prefix
=
cert
.
prefix
self
.
_prefix
=
cert
.
prefix
self
.
_db_size
=
db_size
self
.
_db_size
=
db_size
self
.
_decrypt
=
cert
.
decrypt
self
.
_decrypt
=
cert
.
decrypt
...
@@ -50,7 +50,7 @@ class Cache:
...
@@ -50,7 +50,7 @@ class Cache:
self
.
warnProtocol
()
self
.
warnProtocol
()
logging
.
info
(
"Cache initialized."
)
logging
.
info
(
"Cache initialized."
)
def
_open
(
self
,
path
)
:
def
_open
(
self
,
path
:
str
)
->
sqlite3
.
Connection
:
db
=
sqlite3
.
connect
(
path
,
isolation_level
=
None
)
db
=
sqlite3
.
connect
(
path
,
isolation_level
=
None
)
db
.
text_factory
=
str
db
.
text_factory
=
str
db
.
execute
(
"PRAGMA synchronous = OFF"
)
db
.
execute
(
"PRAGMA synchronous = OFF"
)
...
@@ -147,7 +147,7 @@ class Cache:
...
@@ -147,7 +147,7 @@ class Cache:
logging
.
warning
(
"There's a new version of re6stnet:"
logging
.
warning
(
"There's a new version of re6stnet:"
" you should update."
)
" you should update."
)
def
getDh
(
self
,
path
):
def
getDh
(
self
,
path
:
str
):
# We'd like to do a full check here but
# We'd like to do a full check here but
# from OpenSSL import SSL
# from OpenSSL import SSL
# SSL.Context(SSL.TLSv1_METHOD).load_tmp_dh(path)
# SSL.Context(SSL.TLSv1_METHOD).load_tmp_dh(path)
...
@@ -179,11 +179,11 @@ class Cache:
...
@@ -179,11 +179,11 @@ class Cache:
logging
.
trace
(
"- %s: %s%s"
,
prefix
,
address
,
logging
.
trace
(
"- %s: %s%s"
,
prefix
,
address
,
' (blacklisted)'
if
_try
else
''
)
' (blacklisted)'
if
_try
else
''
)
def
cacheMinimize
(
self
,
size
):
def
cacheMinimize
(
self
,
size
:
int
):
with
self
.
_db
:
with
self
.
_db
:
self
.
_cacheMinimize
(
size
)
self
.
_cacheMinimize
(
size
)
def
_cacheMinimize
(
self
,
size
):
def
_cacheMinimize
(
self
,
size
:
int
):
a
=
self
.
_db
.
execute
(
a
=
self
.
_db
.
execute
(
"SELECT peer FROM volatile.stat ORDER BY try, RANDOM() LIMIT ?,-1"
,
"SELECT peer FROM volatile.stat ORDER BY try, RANDOM() LIMIT ?,-1"
,
(
size
,)).
fetchall
()
(
size
,)).
fetchall
()
...
@@ -192,26 +192,27 @@ class Cache:
...
@@ -192,26 +192,27 @@ class Cache:
q
(
"DELETE FROM peer WHERE prefix IN (?)"
,
a
)
q
(
"DELETE FROM peer WHERE prefix IN (?)"
,
a
)
q
(
"DELETE FROM volatile.stat WHERE peer IN (?)"
,
a
)
q
(
"DELETE FROM volatile.stat WHERE peer IN (?)"
,
a
)
def
connecting
(
self
,
prefix
,
connecting
):
def
connecting
(
self
,
prefix
:
str
,
connecting
:
int
):
# TODO: is `connecting` a bool?
self
.
_db
.
execute
(
"UPDATE volatile.stat SET try=? WHERE peer=?"
,
self
.
_db
.
execute
(
"UPDATE volatile.stat SET try=? WHERE peer=?"
,
(
connecting
,
prefix
))
(
connecting
,
prefix
))
def
resetConnecting
(
self
):
def
resetConnecting
(
self
):
self
.
_db
.
execute
(
"UPDATE volatile.stat SET try=0"
)
self
.
_db
.
execute
(
"UPDATE volatile.stat SET try=0"
)
def
getAddress
(
self
,
prefix
)
:
def
getAddress
(
self
,
prefix
:
str
)
->
bool
:
r
=
self
.
_db
.
execute
(
"SELECT address FROM peer, volatile.stat"
r
=
self
.
_db
.
execute
(
"SELECT address FROM peer, volatile.stat"
" WHERE prefix=? AND prefix=peer AND try=0"
,
" WHERE prefix=? AND prefix=peer AND try=0"
,
(
prefix
,)).
fetchone
()
(
prefix
,)).
fetchone
()
return
r
and
r
[
0
]
return
r
and
r
[
0
]
@
property
@
property
def
my_address
(
self
):
def
my_address
(
self
)
->
str
:
for
x
,
in
self
.
_db
.
execute
(
"SELECT address FROM peer WHERE prefix=''"
):
for
x
,
in
self
.
_db
.
execute
(
"SELECT address FROM peer WHERE prefix=''"
):
return
x
return
x
@
my_address
.
setter
@
my_address
.
setter
def
my_address
(
self
,
value
):
def
my_address
(
self
,
value
:
str
):
if
value
:
if
value
:
with
self
.
_db
as
db
:
with
self
.
_db
as
db
:
db
.
execute
(
"INSERT OR REPLACE INTO peer VALUES ('', ?)"
,
db
.
execute
(
"INSERT OR REPLACE INTO peer VALUES ('', ?)"
,
...
@@ -234,10 +235,10 @@ class Cache:
...
@@ -234,10 +235,10 @@ class Cache:
#return self._db.execute(__sql, (self._prefix, failed))
#return self._db.execute(__sql, (self._prefix, failed))
r
=
self
.
_db
.
execute
(
__sql
,
(
self
.
_prefix
,
failed
))
r
=
self
.
_db
.
execute
(
__sql
,
(
self
.
_prefix
,
failed
))
return
r
return
r
def
getPeerCount
(
self
,
failed
=
0
,
__sql
=
_get_peer_sql
%
"COUNT(*)"
):
def
getPeerCount
(
self
,
failed
=
0
,
__sql
=
_get_peer_sql
%
"COUNT(*)"
)
->
int
:
return
self
.
_db
.
execute
(
__sql
,
(
self
.
_prefix
,
failed
)).
next
()[
0
]
return
self
.
_db
.
execute
(
__sql
,
(
self
.
_prefix
,
failed
)).
next
()[
0
]
def
getBootstrapPeer
(
self
):
def
getBootstrapPeer
(
self
)
->
tuple
[
str
,
str
]
:
logging
.
info
(
'Getting Boot peer...'
)
logging
.
info
(
'Getting Boot peer...'
)
try
:
try
:
bootpeer
=
self
.
_registry
.
getBootstrapPeer
(
self
.
_prefix
)
bootpeer
=
self
.
_registry
.
getBootstrapPeer
(
self
.
_prefix
)
...
@@ -251,7 +252,7 @@ class Cache:
...
@@ -251,7 +252,7 @@ class Cache:
return
prefix
,
address
return
prefix
,
address
logging
.
warning
(
'Buggy registry sent us our own address'
)
logging
.
warning
(
'Buggy registry sent us our own address'
)
def
addPeer
(
self
,
prefix
,
address
,
set_preferred
=
False
):
def
addPeer
(
self
,
prefix
:
str
,
address
:
str
,
set_preferred
=
False
):
logging
.
debug
(
'Adding peer %s: %s'
,
prefix
,
address
)
logging
.
debug
(
'Adding peer %s: %s'
,
prefix
,
address
)
with
self
.
_db
:
with
self
.
_db
:
q
=
self
.
_db
.
execute
q
=
self
.
_db
.
execute
...
@@ -275,7 +276,7 @@ class Cache:
...
@@ -275,7 +276,7 @@ class Cache:
q
(
"INSERT OR REPLACE INTO peer VALUES (?,?)"
,
(
prefix
,
address
))
q
(
"INSERT OR REPLACE INTO peer VALUES (?,?)"
,
(
prefix
,
address
))
q
(
"INSERT OR REPLACE INTO volatile.stat VALUES (?,0)"
,
(
prefix
,))
q
(
"INSERT OR REPLACE INTO volatile.stat VALUES (?,0)"
,
(
prefix
,))
def
getCountry
(
self
,
ip
)
:
def
getCountry
(
self
,
ip
:
str
)
->
str
:
try
:
try
:
return
self
.
_registry
.
getCountry
(
self
.
_prefix
,
ip
).
decode
()
return
self
.
_registry
.
getCountry
(
self
.
_prefix
,
ip
).
decode
()
except
socket
.
error
as
e
:
except
socket
.
error
as
e
:
...
...
re6st/cli/node.py
View file @
e1060631
...
@@ -273,12 +273,12 @@ def main():
...
@@ -273,12 +273,12 @@ def main():
raise
EnvironmentError
(
"%r failed with error %u
\
n
%s"
raise
EnvironmentError
(
"%r failed with error %u
\
n
%s"
%
(
' '
.
join
(
cmd
),
p
.
returncode
,
stderr
))
%
(
' '
.
join
(
cmd
),
p
.
returncode
,
stderr
))
return
stdout
return
stdout
def
ip4
(
object
,
*
args
):
def
ip4
(
object
:
str
,
*
args
):
args
=
[
'ip'
,
'-4'
,
object
,
'add'
]
+
list
(
args
)
args
=
[
'ip'
,
'-4'
,
object
,
'add'
]
+
list
(
args
)
call
(
args
)
call
(
args
)
args
[
3
]
=
'del'
args
[
3
]
=
'del'
cleanup
.
append
(
lambda
:
subprocess
.
call
(
args
))
cleanup
.
append
(
lambda
:
subprocess
.
call
(
args
))
def
ip
(
object
,
*
args
):
def
ip
(
object
:
str
,
*
args
):
args
=
[
'ip'
,
'-6'
,
object
,
'add'
]
+
list
(
args
)
args
=
[
'ip'
,
'-6'
,
object
,
'add'
]
+
list
(
args
)
call
(
args
)
call
(
args
)
args
[
3
]
=
'del'
args
[
3
]
=
'del'
...
...
re6st/ctl.py
View file @
e1060631
...
@@ -171,7 +171,7 @@ class Babel:
...
@@ -171,7 +171,7 @@ class Babel:
_decode
=
None
_decode
=
None
def
__init__
(
self
,
socket_path
,
handler
,
network
):
def
__init__
(
self
,
socket_path
:
str
,
handler
,
network
:
str
):
self
.
socket_path
=
socket_path
self
.
socket_path
=
socket_path
self
.
handler
=
handler
self
.
handler
=
handler
self
.
network
=
network
self
.
network
=
network
...
@@ -304,7 +304,7 @@ class iterRoutes:
...
@@ -304,7 +304,7 @@ class iterRoutes:
_waiting
=
True
_waiting
=
True
def
__new__
(
cls
,
control_socket
,
network
):
def
__new__
(
cls
,
control_socket
:
str
,
network
:
str
):
self
=
object
.
__new__
(
cls
)
self
=
object
.
__new__
(
cls
)
c
=
Babel
(
control_socket
,
self
,
network
)
c
=
Babel
(
control_socket
,
self
,
network
)
c
.
request_dump
()
c
.
request_dump
()
...
...
re6st/debug.py
View file @
e1060631
...
@@ -3,30 +3,30 @@ import errno, os, socket, stat, threading
...
@@ -3,30 +3,30 @@ import errno, os, socket, stat, threading
class
Socket
:
class
Socket
:
def
__init__
(
self
,
socket
):
def
__init__
(
self
,
socket
:
socket
.
socket
):
# In case that the default timeout is not None.
# In case that the default timeout is not None.
socket
.
settimeout
(
None
)
socket
.
settimeout
(
None
)
self
.
_socket
=
socket
self
.
_socket
=
socket
self
.
_buf
=
''
self
.
_buf
=
b
''
def
close
(
self
):
def
close
(
self
):
self
.
_socket
.
close
()
self
.
_socket
.
close
()
def
write
(
self
,
data
):
def
write
(
self
,
data
:
bytes
):
self
.
_socket
.
send
(
data
)
self
.
_socket
.
send
(
data
)
def
readline
(
self
):
def
readline
(
self
)
->
bytes
:
recv
=
self
.
_socket
.
recv
recv
=
self
.
_socket
.
recv
data
=
self
.
_buf
data
=
self
.
_buf
while
True
:
while
True
:
i
=
1
+
data
.
find
(
'
\
n
'
)
i
=
1
+
data
.
find
(
b
'
\
n
'
)
if
i
:
if
i
:
self
.
_buf
=
data
[
i
:]
self
.
_buf
=
data
[
i
:]
return
data
[:
i
]
return
data
[:
i
]
d
=
recv
(
4096
)
d
=
recv
(
4096
)
data
+=
d
data
+=
d
if
not
d
:
if
not
d
:
self
.
_buf
=
''
self
.
_buf
=
b
''
return
data
return
data
def
flush
(
self
):
def
flush
(
self
):
...
...
re6st/plib.py
View file @
e1060631
...
@@ -9,7 +9,7 @@ ovpn_server = os.path.join(here, 'ovpn-server')
...
@@ -9,7 +9,7 @@ ovpn_server = os.path.join(here, 'ovpn-server')
ovpn_client
=
os
.
path
.
join
(
here
,
'ovpn-client'
)
ovpn_client
=
os
.
path
.
join
(
here
,
'ovpn-client'
)
ovpn_log
:
Optional
[
str
]
=
None
ovpn_log
:
Optional
[
str
]
=
None
def
openvpn
(
iface
,
encrypt
,
*
args
,
**
kw
)
:
def
openvpn
(
iface
:
str
,
encrypt
,
*
args
,
**
kw
)
->
utils
.
Popen
:
args
=
[
'openvpn'
,
args
=
[
'openvpn'
,
'--dev-type'
,
'tap'
,
'--dev-type'
,
'tap'
,
'--dev'
,
iface
,
'--dev'
,
iface
,
...
@@ -28,7 +28,7 @@ def openvpn(iface, encrypt, *args, **kw):
...
@@ -28,7 +28,7 @@ def openvpn(iface, encrypt, *args, **kw):
ovpn_link_mtu_dict
=
{
'udp4'
:
1432
,
'udp6'
:
1450
}
ovpn_link_mtu_dict
=
{
'udp4'
:
1432
,
'udp6'
:
1450
}
def
server
(
iface
,
max_clients
,
dh_path
,
fd
,
port
,
proto
,
encrypt
,
*
args
,
**
kw
)
:
def
server
(
iface
:
str
,
max_clients
:
int
,
dh_path
:
str
,
fd
:
int
,
port
:
int
,
proto
:
str
,
encrypt
:
bool
,
*
args
,
**
kw
)
->
utils
.
Popen
:
if
proto
==
'udp'
:
if
proto
==
'udp'
:
proto
=
'udp4'
proto
=
'udp4'
client_script
=
'%s %s'
%
(
ovpn_server
,
fd
)
client_script
=
'%s %s'
%
(
ovpn_server
,
fd
)
...
@@ -49,7 +49,7 @@ def server(iface, max_clients, dh_path, fd, port, proto, encrypt, *args, **kw):
...
@@ -49,7 +49,7 @@ def server(iface, max_clients, dh_path, fd, port, proto, encrypt, *args, **kw):
*
args
,
pass_fds
=
[
fd
],
**
kw
)
*
args
,
pass_fds
=
[
fd
],
**
kw
)
def
client
(
iface
,
address_list
,
encrypt
,
*
args
,
**
kw
)
:
def
client
(
iface
:
str
,
address_list
:
list
[
tuple
[
str
,
int
,
str
]],
encrypt
:
bool
,
*
args
,
**
kw
)
->
utils
.
Popen
:
remote
=
[
'--nobind'
,
'--client'
]
remote
=
[
'--nobind'
,
'--client'
]
# XXX: We'd like to pass <connection> sections at command-line.
# XXX: We'd like to pass <connection> sections at command-line.
link_mtu
=
set
()
link_mtu
=
set
()
...
@@ -65,8 +65,8 @@ def client(iface, address_list, encrypt, *args, **kw):
...
@@ -65,8 +65,8 @@ def client(iface, address_list, encrypt, *args, **kw):
return
openvpn
(
iface
,
encrypt
,
*
remote
,
**
kw
)
return
openvpn
(
iface
,
encrypt
,
*
remote
,
**
kw
)
def
router
(
ip
,
ip4
,
rt6
,
hello_interval
,
log_path
,
state_path
,
pidfile
,
def
router
(
ip
:
tuple
[
str
,
int
],
ip4
,
rt6
:
tuple
[
str
,
bool
,
bool
],
hello_interval
:
int
,
log_path
:
str
,
state_path
:
str
,
pidfile
:
str
,
control_socket
,
default
,
hmac
,
*
args
,
**
kw
)
:
control_socket
:
str
,
default
:
str
,
hmac
:
tuple
[
bytes
|
None
,
bytes
|
None
],
*
args
,
**
kw
)
->
utils
.
Popen
:
network
,
gateway
,
has_ipv6_subtrees
=
rt6
network
,
gateway
,
has_ipv6_subtrees
=
rt6
network_mask
=
int
(
network
[
network
.
index
(
'/'
)
+
1
:])
network_mask
=
int
(
network
[
network
.
index
(
'/'
)
+
1
:])
ip
,
n
=
ip
ip
,
n
=
ip
...
@@ -83,7 +83,7 @@ def router(ip, ip4, rt6, hello_interval, log_path, state_path, pidfile,
...
@@ -83,7 +83,7 @@ def router(ip, ip4, rt6, hello_interval, log_path, state_path, pidfile,
'-C'
,
'redistribute local deny'
,
'-C'
,
'redistribute local deny'
,
'-C'
,
'redistribute ip %s/%s eq %s'
%
(
ip
,
n
,
n
)]
'-C'
,
'redistribute ip %s/%s eq %s'
%
(
ip
,
n
,
n
)]
if
hmac_sign
:
if
hmac_sign
:
def
key
(
cmd
,
id
:
str
,
value
):
def
key
(
cmd
:
list
[
str
],
id
:
str
,
value
:
bytes
):
cmd
+=
'-C'
,
(
'key type blake2s128 id %s value %s'
%
cmd
+=
'-C'
,
(
'key type blake2s128 id %s value %s'
%
(
id
,
binascii
.
hexlify
(
value
).
decode
()))
(
id
,
binascii
.
hexlify
(
value
).
decode
()))
key
(
cmd
,
'sign'
,
hmac_sign
)
key
(
cmd
,
'sign'
,
hmac_sign
)
...
...
re6st/registry.py
View file @
e1060631
...
@@ -22,10 +22,13 @@ import base64, hmac, hashlib, http.client, inspect, json, logging
...
@@ -22,10 +22,13 @@ import base64, hmac, hashlib, http.client, inspect, json, logging
import
mailbox
,
os
,
platform
,
random
,
select
,
smtplib
,
socket
,
sqlite3
import
mailbox
,
os
,
platform
,
random
,
select
,
smtplib
,
socket
,
sqlite3
import
string
,
sys
,
threading
,
time
,
weakref
,
zlib
import
string
,
sys
,
threading
,
time
,
weakref
,
zlib
from
collections
import
defaultdict
,
deque
from
collections
import
defaultdict
,
deque
from
collections.abc
import
Iterator
from
datetime
import
datetime
from
datetime
import
datetime
from
http.server
import
HTTPServer
,
BaseHTTPRequestHandler
from
http.server
import
HTTPServer
,
BaseHTTPRequestHandler
from
email.mime.text
import
MIMEText
from
email.mime.text
import
MIMEText
from
operator
import
itemgetter
from
operator
import
itemgetter
from
typing
import
Tuple
from
OpenSSL
import
crypto
from
OpenSSL
import
crypto
from
urllib.parse
import
urlparse
,
unquote
,
urlencode
from
urllib.parse
import
urlparse
,
unquote
,
urlencode
from
.
import
ctl
,
tunnel
,
utils
,
version
,
x509
from
.
import
ctl
,
tunnel
,
utils
,
version
,
x509
...
@@ -139,10 +142,10 @@ class RegistryServer:
...
@@ -139,10 +142,10 @@ class RegistryServer:
if
self
.
geoip_db
:
if
self
.
geoip_db
:
from
geoip2
import
database
,
errors
from
geoip2
import
database
,
errors
country
=
database
.
Reader
(
self
.
geoip_db
).
country
country
=
database
.
Reader
(
self
.
geoip_db
).
country
def
geoiplookup
(
ip
)
:
def
geoiplookup
(
ip
:
str
)
->
Tuple
[
str
,
str
]
:
try
:
try
:
req
=
country
(
ip
)
req
=
country
(
ip
)
return
req
.
country
.
iso_code
.
encode
(),
req
.
continent
.
code
.
encode
()
return
req
.
country
.
iso_code
,
req
.
continent
.
code
except
(
errors
.
AddressNotFoundError
,
ValueError
):
except
(
errors
.
AddressNotFoundError
,
ValueError
):
return
'*'
,
'*'
return
'*'
,
'*'
self
.
_geoiplookup
=
geoiplookup
self
.
_geoiplookup
=
geoiplookup
...
@@ -245,7 +248,7 @@ class RegistryServer:
...
@@ -245,7 +248,7 @@ class RegistryServer:
def
babel_dump
(
self
):
def
babel_dump
(
self
):
self
.
_wait_dump
=
False
self
.
_wait_dump
=
False
def
iterCert
(
self
):
def
iterCert
(
self
)
->
Iterator
[
Tuple
[
crypto
.
X509
,
str
,
str
]]
:
for
prefix
,
email
,
cert
in
self
.
db
.
execute
(
for
prefix
,
email
,
cert
in
self
.
db
.
execute
(
"SELECT * FROM cert WHERE cert IS NOT NULL"
):
"SELECT * FROM cert WHERE cert IS NOT NULL"
):
try
:
try
:
...
@@ -357,7 +360,7 @@ class RegistryServer:
...
@@ -357,7 +360,7 @@ class RegistryServer:
assert
len
(
key
)
==
len
(
sign
)
assert
len
(
key
)
==
len
(
sign
)
return
key
+
sign
return
key
+
sign
def
getCert
(
self
,
client_prefix
)
:
def
getCert
(
self
,
client_prefix
:
str
)
->
bytes
:
assert
self
.
lock
.
locked
()
assert
self
.
lock
.
locked
()
cert
=
self
.
db
.
execute
(
"SELECT cert FROM cert"
cert
=
self
.
db
.
execute
(
"SELECT cert FROM cert"
" WHERE prefix=? AND cert IS NOT NULL"
,
(
client_prefix
,)).
fetchone
()
" WHERE prefix=? AND cert IS NOT NULL"
,
(
client_prefix
,)).
fetchone
()
...
@@ -366,19 +369,19 @@ class RegistryServer:
...
@@ -366,19 +369,19 @@ class RegistryServer:
return
cert
[
0
]
return
cert
[
0
]
@
rpc_private
@
rpc_private
def
isToken
(
self
,
token
):
def
isToken
(
self
,
token
:
str
):
with
self
.
lock
:
with
self
.
lock
:
if
self
.
db
.
execute
(
"SELECT 1 FROM token WHERE token = ?"
,
if
self
.
db
.
execute
(
"SELECT 1 FROM token WHERE token = ?"
,
(
token
,)).
fetchone
():
(
token
,)).
fetchone
():
return
b"1"
return
b"1"
@
rpc_private
@
rpc_private
def
deleteToken
(
self
,
token
):
def
deleteToken
(
self
,
token
:
str
):
with
self
.
lock
:
with
self
.
lock
:
self
.
db
.
execute
(
"DELETE FROM token WHERE token = ?"
,
(
token
,))
self
.
db
.
execute
(
"DELETE FROM token WHERE token = ?"
,
(
token
,))
@
rpc_private
@
rpc_private
def
addToken
(
self
,
email
,
token
)
:
def
addToken
(
self
,
email
:
str
,
token
:
str
|
None
)
->
str
:
prefix_len
=
self
.
config
.
prefix_length
prefix_len
=
self
.
config
.
prefix_length
if
not
prefix_len
:
if
not
prefix_len
:
raise
HTTPError
(
http
.
client
.
FORBIDDEN
)
raise
HTTPError
(
http
.
client
.
FORBIDDEN
)
...
@@ -506,7 +509,7 @@ class RegistryServer:
...
@@ -506,7 +509,7 @@ class RegistryServer:
q
(
"UPDATE cert SET cert = 'reserved' WHERE prefix = ?"
,
(
prefix
,))
q
(
"UPDATE cert SET cert = 'reserved' WHERE prefix = ?"
,
(
prefix
,))
@
rpc
@
rpc
def
requestCertificate
(
self
,
token
,
req
,
location
=
''
,
ip
=
''
):
def
requestCertificate
(
self
,
token
:
str
|
None
,
req
:
bytes
,
location
:
str
=
''
,
ip
:
str
=
''
):
logging
.
debug
(
"Requesting certificate with token %s"
,
token
)
logging
.
debug
(
"Requesting certificate with token %s"
,
token
)
req
=
crypto
.
load_certificate_request
(
crypto
.
FILETYPE_PEM
,
req
)
req
=
crypto
.
load_certificate_request
(
crypto
.
FILETYPE_PEM
,
req
)
with
self
.
lock
:
with
self
.
lock
:
...
@@ -580,7 +583,7 @@ class RegistryServer:
...
@@ -580,7 +583,7 @@ class RegistryServer:
return
cert
return
cert
@
rpc
@
rpc
def
renewCertificate
(
self
,
cn
)
:
def
renewCertificate
(
self
,
cn
:
str
)
->
bytes
:
with
self
.
lock
:
with
self
.
lock
:
with
self
.
db
as
db
:
with
self
.
db
as
db
:
pem
=
self
.
getCert
(
cn
)
pem
=
self
.
getCert
(
cn
)
...
@@ -596,16 +599,16 @@ class RegistryServer:
...
@@ -596,16 +599,16 @@ class RegistryServer:
cert
.
get_subject
(),
cert
.
get_pubkey
(),
not_after
)
cert
.
get_subject
(),
cert
.
get_pubkey
(),
not_after
)
@
rpc
@
rpc
def
getCa
(
self
):
def
getCa
(
self
)
->
bytes
:
return
crypto
.
dump_certificate
(
crypto
.
FILETYPE_PEM
,
self
.
cert
.
ca
)
return
crypto
.
dump_certificate
(
crypto
.
FILETYPE_PEM
,
self
.
cert
.
ca
)
@
rpc
@
rpc
def
getDh
(
self
,
cn
)
:
def
getDh
(
self
,
cn
:
str
)
->
bytes
:
with
open
(
self
.
config
.
dh
)
as
f
:
with
open
(
self
.
config
.
dh
,
"rb"
)
as
f
:
return
f
.
read
()
return
f
.
read
()
@
rpc
@
rpc
def
getNetworkConfig
(
self
,
cn
)
:
def
getNetworkConfig
(
self
,
cn
:
str
)
->
bytes
:
with
self
.
lock
:
with
self
.
lock
:
cert
=
self
.
getCert
(
cn
)
cert
=
self
.
getCert
(
cn
)
config
=
self
.
network_config
.
copy
()
config
=
self
.
network_config
.
copy
()
...
@@ -615,7 +618,7 @@ class RegistryServer:
...
@@ -615,7 +618,7 @@ class RegistryServer:
v
and
base64
.
b64encode
(
x509
.
encrypt
(
cert
,
v
)).
decode
(
"ascii"
)
v
and
base64
.
b64encode
(
x509
.
encrypt
(
cert
,
v
)).
decode
(
"ascii"
)
return
zlib
.
compress
(
json
.
dumps
(
config
).
encode
(
"utf-8"
))
return
zlib
.
compress
(
json
.
dumps
(
config
).
encode
(
"utf-8"
))
def
_queryAddress
(
self
,
peer
)
->
str
:
def
_queryAddress
(
self
,
peer
:
str
)
->
str
:
logging
.
info
(
"Querying address for %s/%s %r"
,
int
(
peer
,
2
),
len
(
peer
),
peer
)
logging
.
info
(
"Querying address for %s/%s %r"
,
int
(
peer
,
2
),
len
(
peer
),
peer
)
self
.
sendto
(
peer
,
1
)
self
.
sendto
(
peer
,
1
)
s
=
self
.
sock
,
s
=
self
.
sock
,
...
@@ -632,12 +635,12 @@ class RegistryServer:
...
@@ -632,12 +635,12 @@ class RegistryServer:
int
(
peer
,
2
),
len
(
peer
))
int
(
peer
,
2
),
len
(
peer
))
@
rpc
@
rpc
def
getCountry
(
self
,
cn
,
address
)
->
bytes
:
def
getCountry
(
self
,
cn
:
str
,
address
:
str
)
->
bytes
|
None
:
country
=
self
.
_geoiplookup
(
address
)[
0
]
country
=
self
.
_geoiplookup
(
address
)[
0
]
return
None
if
country
==
'*'
else
country
.
encode
()
return
None
if
country
==
'*'
else
country
.
encode
()
@
rpc
@
rpc
def
getBootstrapPeer
(
self
,
cn
)
:
def
getBootstrapPeer
(
self
,
cn
:
str
)
->
bytes
|
None
:
logging
.
info
(
"Answering bootstrap peer for %s"
,
cn
)
logging
.
info
(
"Answering bootstrap peer for %s"
,
cn
)
with
self
.
peers_lock
:
with
self
.
peers_lock
:
age
,
peers
=
self
.
peers
age
,
peers
=
self
.
peers
...
@@ -672,7 +675,7 @@ class RegistryServer:
...
@@ -672,7 +675,7 @@ class RegistryServer:
return
x509
.
encrypt
(
cert
,
msg
.
encode
())
return
x509
.
encrypt
(
cert
,
msg
.
encode
())
@
rpc_private
@
rpc_private
def
revoke
(
self
,
cn_or_serial
):
def
revoke
(
self
,
cn_or_serial
:
int
|
str
):
with
self
.
lock
,
self
.
db
:
with
self
.
lock
,
self
.
db
:
q
=
self
.
db
.
execute
q
=
self
.
db
.
execute
try
:
try
:
...
@@ -693,12 +696,12 @@ class RegistryServer:
...
@@ -693,12 +696,12 @@ class RegistryServer:
q
(
"INSERT INTO crl VALUES (?,?)"
,
(
serial
,
not_after
))
q
(
"INSERT INTO crl VALUES (?,?)"
,
(
serial
,
not_after
))
self
.
updateNetworkConfig
()
self
.
updateNetworkConfig
()
def
newHMAC
(
self
,
i
,
key
=
None
):
def
newHMAC
(
self
,
i
:
int
,
key
:
bytes
=
None
):
if
key
is
None
:
if
key
is
None
:
key
=
os
.
urandom
(
16
)
key
=
os
.
urandom
(
16
)
self
.
setConfig
(
BABEL_HMAC
[
i
],
key
)
self
.
setConfig
(
BABEL_HMAC
[
i
],
key
)
def
delHMAC
(
self
,
i
):
def
delHMAC
(
self
,
i
:
int
):
self
.
db
.
execute
(
"DELETE FROM config WHERE name=?"
,
(
BABEL_HMAC
[
i
],))
self
.
db
.
execute
(
"DELETE FROM config WHERE name=?"
,
(
BABEL_HMAC
[
i
],))
@
rpc_private
@
rpc_private
...
@@ -725,7 +728,7 @@ class RegistryServer:
...
@@ -725,7 +728,7 @@ class RegistryServer:
self
.
sendto
(
self
.
prefix
,
0
)
self
.
sendto
(
self
.
prefix
,
0
)
@
rpc_private
@
rpc_private
def
getNodePrefix
(
self
,
email
)
:
def
getNodePrefix
(
self
,
email
:
str
)
->
str
|
None
:
with
self
.
lock
,
self
.
db
:
with
self
.
lock
,
self
.
db
:
try
:
try
:
cert
,
=
next
(
self
.
db
.
execute
(
"SELECT cert FROM cert WHERE email = ?"
,
cert
,
=
next
(
self
.
db
.
execute
(
"SELECT cert FROM cert WHERE email = ?"
,
...
@@ -736,7 +739,7 @@ class RegistryServer:
...
@@ -736,7 +739,7 @@ class RegistryServer:
return
x509
.
subnetFromCert
(
certificate
)
return
x509
.
subnetFromCert
(
certificate
)
@
rpc_private
@
rpc_private
def
getIPv6Address
(
self
,
email
)
:
def
getIPv6Address
(
self
,
email
:
str
)
->
str
:
cn
=
self
.
getNodePrefix
(
email
)
cn
=
self
.
getNodePrefix
(
email
)
if
cn
:
if
cn
:
return
utils
.
ipFromBin
(
return
utils
.
ipFromBin
(
...
@@ -744,7 +747,7 @@ class RegistryServer:
...
@@ -744,7 +747,7 @@ class RegistryServer:
+
utils
.
binFromSubnet
(
cn
))
+
utils
.
binFromSubnet
(
cn
))
@
rpc_private
@
rpc_private
def
getIPv4Information
(
self
,
email
)
:
def
getIPv4Information
(
self
,
email
:
str
)
->
bytes
|
None
:
peer
=
self
.
getNodePrefix
(
email
)
peer
=
self
.
getNodePrefix
(
email
)
if
peer
:
if
peer
:
peer
=
utils
.
binFromSubnet
(
peer
)
peer
=
utils
.
binFromSubnet
(
peer
)
...
@@ -763,7 +766,7 @@ class RegistryServer:
...
@@ -763,7 +766,7 @@ class RegistryServer:
return
msg
.
split
(
','
)[
0
].
encode
()
return
msg
.
split
(
','
)[
0
].
encode
()
@
rpc_private
@
rpc_private
def
versions
(
self
):
def
versions
(
self
)
->
str
:
with
self
.
peers_lock
:
with
self
.
peers_lock
:
self
.
request_dump
()
self
.
request_dump
()
peers
=
{
prefix
peers
=
{
prefix
...
@@ -789,7 +792,7 @@ class RegistryServer:
...
@@ -789,7 +792,7 @@ class RegistryServer:
return
json
.
dumps
(
peer_dict
)
return
json
.
dumps
(
peer_dict
)
@
rpc_private
@
rpc_private
def
topology
(
self
):
def
topology
(
self
)
->
str
:
logging
.
info
(
"Computing topology"
)
logging
.
info
(
"Computing topology"
)
p
=
lambda
p
:
'%s/%s'
%
(
int
(
p
,
2
),
len
(
p
))
p
=
lambda
p
:
'%s/%s'
%
(
int
(
p
,
2
),
len
(
p
))
peers
=
deque
((
p
(
self
.
prefix
),))
peers
=
deque
((
p
(
self
.
prefix
),))
...
@@ -829,7 +832,7 @@ class RegistryClient:
...
@@ -829,7 +832,7 @@ class RegistryClient:
_hmac
=
None
_hmac
=
None
user_agent
=
"re6stnet/%s, %s"
%
(
version
.
version
,
platform
.
platform
())
user_agent
=
"re6stnet/%s, %s"
%
(
version
.
version
,
platform
.
platform
())
def
__init__
(
self
,
url
,
cert
:
x509
.
Cert
=
None
,
auto_close
=
True
):
def
__init__
(
self
,
url
:
str
,
cert
:
x509
.
Cert
=
None
,
auto_close
=
True
):
self
.
cert
=
cert
self
.
cert
=
cert
self
.
auto_close
=
auto_close
self
.
auto_close
=
auto_close
url_parsed
=
urlparse
(
url
)
url_parsed
=
urlparse
(
url
)
...
@@ -839,7 +842,7 @@ class RegistryClient:
...
@@ -839,7 +842,7 @@ class RegistryClient:
)[
scheme
](
unquote
(
host
),
timeout
=
60
)
)[
scheme
](
unquote
(
host
),
timeout
=
60
)
self
.
_path
=
path
.
rstrip
(
'/'
)
self
.
_path
=
path
.
rstrip
(
'/'
)
def
__getattr__
(
self
,
name
):
def
__getattr__
(
self
,
name
:
str
):
getcallargs
=
getattr
(
RegistryServer
,
name
).
getcallargs
getcallargs
=
getattr
(
RegistryServer
,
name
).
getcallargs
def
rpc
(
*
args
,
**
kw
)
->
bytes
:
def
rpc
(
*
args
,
**
kw
)
->
bytes
:
kw
=
getcallargs
(
*
args
,
**
kw
)
kw
=
getcallargs
(
*
args
,
**
kw
)
...
...
re6st/tests/test_unit/test_registry.py
View file @
e1060631
...
@@ -11,11 +11,13 @@ import hashlib
...
@@ -11,11 +11,13 @@ import hashlib
import
time
import
time
import
tempfile
import
tempfile
from
argparse
import
Namespace
from
argparse
import
Namespace
from
sqlite3
import
Cursor
from
OpenSSL
import
crypto
from
OpenSSL
import
crypto
from
mock
import
Mock
,
patch
from
mock
import
Mock
,
patch
from
pathlib
import
Path
from
pathlib
import
Path
from
re6st
import
registry
from
re6st
import
registry
,
x509
from
re6st.tests.tools
import
*
from
re6st.tests.tools
import
*
from
re6st.tests
import
DEMO_PATH
from
re6st.tests
import
DEMO_PATH
...
@@ -23,7 +25,7 @@ from re6st.tests import DEMO_PATH
...
@@ -23,7 +25,7 @@ from re6st.tests import DEMO_PATH
# TODO test for request_dump, requestToken, getNetworkConfig, getBoostrapPeer
# TODO test for request_dump, requestToken, getNetworkConfig, getBoostrapPeer
# getIPV4Information, versions
# getIPV4Information, versions
def
load_config
(
filename
=
"registry.json"
)
:
def
load_config
(
filename
:
str
=
"registry.json"
)
->
Namespace
:
with
open
(
filename
)
as
f
:
with
open
(
filename
)
as
f
:
config
=
json
.
load
(
f
)
config
=
json
.
load
(
f
)
config
[
"dh"
]
=
DEMO_PATH
/
"dh2048.pem"
config
[
"dh"
]
=
DEMO_PATH
/
"dh2048.pem"
...
@@ -37,13 +39,13 @@ def load_config(filename="registry.json"):
...
@@ -37,13 +39,13 @@ def load_config(filename="registry.json"):
return
Namespace
(
**
config
)
return
Namespace
(
**
config
)
def
get_cert
(
cur
,
prefix
):
def
get_cert
(
cur
:
Cursor
,
prefix
:
str
):
res
=
cur
.
execute
(
res
=
cur
.
execute
(
"SELECT cert FROM cert WHERE prefix=?"
,
(
prefix
,)).
fetchone
()
"SELECT cert FROM cert WHERE prefix=?"
,
(
prefix
,)).
fetchone
()
return
res
[
0
]
return
res
[
0
]
def
insert_cert
(
cur
,
ca
,
prefix
,
not_after
=
None
,
email
=
None
):
def
insert_cert
(
cur
:
Cursor
,
ca
:
x509
.
Cert
,
prefix
:
str
,
not_after
=
None
,
email
=
None
):
key
,
csr
=
generate_csr
()
key
,
csr
=
generate_csr
()
cert
=
generate_cert
(
ca
.
ca
,
ca
.
key
,
csr
,
prefix
,
insert_cert
.
serial
,
not_after
)
cert
=
generate_cert
(
ca
.
ca
,
ca
.
key
,
csr
,
prefix
,
insert_cert
.
serial
,
not_after
)
cur
.
execute
(
"INSERT INTO cert VALUES (?,?,?)"
,
(
prefix
,
email
,
cert
))
cur
.
execute
(
"INSERT INTO cert VALUES (?,?,?)"
,
(
prefix
,
email
,
cert
))
...
@@ -54,7 +56,7 @@ def insert_cert(cur, ca, prefix, not_after=None, email=None):
...
@@ -54,7 +56,7 @@ def insert_cert(cur, ca, prefix, not_after=None, email=None):
insert_cert
.
serial
=
0
insert_cert
.
serial
=
0
def
delete_cert
(
cur
,
prefix
):
def
delete_cert
(
cur
:
Cursor
,
prefix
:
str
):
cur
.
execute
(
"DELETE FROM cert WHERE prefix = ?"
,
(
prefix
,))
cur
.
execute
(
"DELETE FROM cert WHERE prefix = ?"
,
(
prefix
,))
...
...
re6st/tests/tools.py
View file @
e1060631
...
@@ -92,10 +92,10 @@ def create_ca_file(pkey_file, cert_file, serial=0x120010db80042):
...
@@ -92,10 +92,10 @@ def create_ca_file(pkey_file, cert_file, serial=0x120010db80042):
return
key
,
cert
return
key
,
cert
def
prefix2cn
(
prefix
)
:
def
prefix2cn
(
prefix
:
str
)
->
str
:
return
"%u/%u"
%
(
int
(
prefix
,
2
),
len
(
prefix
))
return
"%u/%u"
%
(
int
(
prefix
,
2
),
len
(
prefix
))
def
serial2prefix
(
serial
)
:
def
serial2prefix
(
serial
:
int
)
->
str
:
return
bin
(
serial
)[
2
:].
rjust
(
16
,
'0'
)
return
bin
(
serial
)[
2
:].
rjust
(
16
,
'0'
)
# pkey: private key
# pkey: private key
...
...
re6st/tunnel.py
View file @
e1060631
...
@@ -2,6 +2,9 @@ import errno, json, logging, os, platform, random, socket
...
@@ -2,6 +2,9 @@ import errno, json, logging, os, platform, random, socket
import
subprocess
,
struct
,
sys
,
time
,
weakref
import
subprocess
,
struct
,
sys
,
time
,
weakref
from
collections
import
defaultdict
,
deque
from
collections
import
defaultdict
,
deque
from
bisect
import
bisect
,
insort
from
bisect
import
bisect
,
insort
from
collections.abc
import
Iterator
,
Sequence
from
typing
import
Callable
from
OpenSSL
import
crypto
from
OpenSSL
import
crypto
from
.
import
ctl
,
plib
,
utils
,
version
,
x509
from
.
import
ctl
,
plib
,
utils
,
version
,
x509
...
@@ -21,7 +24,7 @@ proto_dict = {
...
@@ -21,7 +24,7 @@ proto_dict = {
proto_dict
[
'tcp'
]
=
proto_dict
[
'tcp4'
]
proto_dict
[
'tcp'
]
=
proto_dict
[
'tcp4'
]
proto_dict
[
'udp'
]
=
proto_dict
[
'udp4'
]
proto_dict
[
'udp'
]
=
proto_dict
[
'udp4'
]
def
resolve
(
ip
,
port
,
proto
)
:
def
resolve
(
ip
,
port
,
proto
:
str
)
->
tuple
[
socket
.
AddressFamily
|
None
,
Iterator
[
str
]]
:
try
:
try
:
family
,
proto
=
proto_dict
[
proto
]
family
,
proto
=
proto_dict
[
proto
]
except
KeyError
:
except
KeyError
:
...
@@ -31,16 +34,16 @@ def resolve(ip, port, proto):
...
@@ -31,16 +34,16 @@ def resolve(ip, port, proto):
class
MultiGatewayManager
(
dict
):
class
MultiGatewayManager
(
dict
):
def
__init__
(
self
,
gateway
):
def
__init__
(
self
,
gateway
:
Callable
[[
str
],
str
]
):
self
.
_gw
=
gateway
self
.
_gw
=
gateway
def
_route
(
self
,
cmd
,
dest
,
gw
):
def
_route
(
self
,
cmd
:
str
,
dest
:
str
,
gw
:
str
):
if
gw
:
if
gw
:
cmd
=
'ip'
,
'-4'
,
'route'
,
cmd
,
'%s/32'
%
dest
,
'via'
,
gw
cmd
=
'ip'
,
'-4'
,
'route'
,
cmd
,
'%s/32'
%
dest
,
'via'
,
gw
logging
.
trace
(
'%r'
,
cmd
)
logging
.
trace
(
'%r'
,
cmd
)
subprocess
.
check_call
(
cmd
)
subprocess
.
check_call
(
cmd
)
def
add
(
self
,
dest
,
route
):
def
add
(
self
,
dest
:
str
,
route
:
bool
):
try
:
try
:
self
[
dest
][
1
]
+=
1
self
[
dest
][
1
]
+=
1
except
KeyError
:
except
KeyError
:
...
@@ -48,7 +51,7 @@ class MultiGatewayManager(dict):
...
@@ -48,7 +51,7 @@ class MultiGatewayManager(dict):
self
[
dest
]
=
[
gw
,
0
]
self
[
dest
]
=
[
gw
,
0
]
self
.
_route
(
'add'
,
dest
,
gw
)
self
.
_route
(
'add'
,
dest
,
gw
)
def
remove
(
self
,
dest
):
def
remove
(
self
,
dest
:
str
):
gw
,
count
=
self
[
dest
]
gw
,
count
=
self
[
dest
]
if
count
:
if
count
:
self
[
dest
][
1
]
=
count
-
1
self
[
dest
][
1
]
=
count
-
1
...
@@ -665,7 +668,7 @@ class TunnelManager(BaseTunnelManager):
...
@@ -665,7 +668,7 @@ class TunnelManager(BaseTunnelManager):
def
__init__
(
self
,
control_socket
,
cache
,
cert
,
openvpn_args
,
def
__init__
(
self
,
control_socket
,
cache
,
cert
,
openvpn_args
,
timeout
,
client_count
,
iface_list
,
conf_country
,
address
,
timeout
,
client_count
,
iface_list
,
conf_country
,
address
,
ip_changed
,
remote_gateway
,
disable_proto
,
neighbour_list
=
()):
ip_changed
,
remote_gateway
:
Callable
[[
str
],
str
],
disable_proto
:
Sequence
[
str
]
,
neighbour_list
=
()):
super
(
TunnelManager
,
self
).
__init__
(
control_socket
,
super
(
TunnelManager
,
self
).
__init__
(
control_socket
,
cache
,
cert
,
conf_country
,
address
)
cache
,
cert
,
conf_country
,
address
)
self
.
ovpn_args
=
openvpn_args
self
.
ovpn_args
=
openvpn_args
...
...
re6st/upnpigd.py
View file @
e1060631
...
@@ -17,7 +17,7 @@ class Forwarder:
...
@@ -17,7 +17,7 @@ class Forwarder:
_lcg_n
=
0
_lcg_n
=
0
@
classmethod
@
classmethod
def
_getExternalPort
(
cls
):
def
_getExternalPort
(
cls
)
->
int
:
# Since _refresh() does not test all ports in a row, we prefer to
# Since _refresh() does not test all ports in a row, we prefer to
# return random ports to maximize the chance to find a free port.
# return random ports to maximize the chance to find a free port.
# A linear congruential generator should be random enough, without
# A linear congruential generator should be random enough, without
...
@@ -35,7 +35,7 @@ class Forwarder:
...
@@ -35,7 +35,7 @@ class Forwarder:
self
.
_u
.
discoverdelay
=
200
self
.
_u
.
discoverdelay
=
200
self
.
_rules
=
[]
self
.
_rules
=
[]
def
__getattr__
(
self
,
name
):
def
__getattr__
(
self
,
name
:
str
):
wrapped
=
getattr
(
self
.
_u
,
name
)
wrapped
=
getattr
(
self
.
_u
,
name
)
def
wrapper
(
*
args
,
**
kw
):
def
wrapper
(
*
args
,
**
kw
):
try
:
try
:
...
...
re6st/utils.py
View file @
e1060631
import
argparse
,
errno
,
fcntl
,
hashlib
,
logging
,
os
,
select
as
_select
import
argparse
,
errno
,
fcntl
,
hashlib
,
logging
,
os
,
select
as
_select
import
shlex
,
signal
,
socket
,
sqlite3
,
struct
,
subprocess
import
shlex
,
signal
,
socket
,
sqlite3
,
struct
,
subprocess
import
sys
,
textwrap
,
threading
,
time
,
traceback
import
sys
,
textwrap
,
threading
,
time
,
traceback
from
typing
import
Optional
from
collections.abc
import
Iterator
,
Mapping
from
typing
import
Optional
,
Callable
# PY3: It will be even better to use Popen(pass_fds=...),
# PY3: It will be even better to use Popen(pass_fds=...),
# and then socket.SOCK_CLOEXEC will be useless.
# and then socket.SOCK_CLOEXEC will be useless.
...
@@ -46,7 +47,7 @@ class FileHandler(logging.FileHandler):
...
@@ -46,7 +47,7 @@ class FileHandler(logging.FileHandler):
if
self
.
lock
.
acquire
(
False
):
if
self
.
lock
.
acquire
(
False
):
self
.
release
()
self
.
release
()
def
setupLog
(
log_level
,
filenam
e
=
None
,
**
kw
):
def
setupLog
(
log_level
:
int
,
filename
:
str
|
Non
e
=
None
,
**
kw
):
if
log_level
and
filename
:
if
log_level
and
filename
:
makedirs
(
os
.
path
.
dirname
(
filename
))
makedirs
(
os
.
path
.
dirname
(
filename
))
handler
=
FileHandler
(
filename
)
handler
=
FileHandler
(
filename
)
...
@@ -192,7 +193,7 @@ def setCloexec(fd):
...
@@ -192,7 +193,7 @@ def setCloexec(fd):
flags
=
fcntl
.
fcntl
(
fd
,
fcntl
.
F_GETFD
)
flags
=
fcntl
.
fcntl
(
fd
,
fcntl
.
F_GETFD
)
fcntl
.
fcntl
(
fd
,
fcntl
.
F_SETFD
,
flags
|
fcntl
.
FD_CLOEXEC
)
fcntl
.
fcntl
(
fd
,
fcntl
.
F_SETFD
,
flags
|
fcntl
.
FD_CLOEXEC
)
def
select
(
R
,
W
,
T
):
def
select
(
R
:
Mapping
,
W
:
Mapping
,
T
):
try
:
try
:
r
,
w
,
_
=
_select
.
select
(
R
,
W
,
(),
r
,
w
,
_
=
_select
.
select
(
R
,
W
,
(),
max
(
0
,
min
(
T
)[
0
]
-
time
.
time
())
if
T
else
None
)
max
(
0
,
min
(
T
)[
0
]
-
time
.
time
())
if
T
else
None
)
...
@@ -216,15 +217,15 @@ def makedirs(*args):
...
@@ -216,15 +217,15 @@ def makedirs(*args):
if
e
.
errno
!=
errno
.
EEXIST
:
if
e
.
errno
!=
errno
.
EEXIST
:
raise
raise
def
binFromIp
(
ip
)
:
def
binFromIp
(
ip
:
str
)
->
str
:
return
binFromRawIp
(
socket
.
inet_pton
(
socket
.
AF_INET6
,
ip
))
return
binFromRawIp
(
socket
.
inet_pton
(
socket
.
AF_INET6
,
ip
))
def
binFromRawIp
(
ip
)
:
def
binFromRawIp
(
ip
:
bytes
)
->
str
:
ip1
,
ip2
=
struct
.
unpack
(
'>QQ'
,
ip
)
ip1
,
ip2
=
struct
.
unpack
(
'>QQ'
,
ip
)
return
bin
(
ip1
)[
2
:].
rjust
(
64
,
'0'
)
+
bin
(
ip2
)[
2
:].
rjust
(
64
,
'0'
)
return
bin
(
ip1
)[
2
:].
rjust
(
64
,
'0'
)
+
bin
(
ip2
)[
2
:].
rjust
(
64
,
'0'
)
def
ipFromBin
(
ip
,
suffix
=
''
)
:
def
ipFromBin
(
ip
:
str
,
suffix
=
''
)
->
str
:
suffix_len
=
128
-
len
(
ip
)
suffix_len
=
128
-
len
(
ip
)
if
suffix_len
>
0
:
if
suffix_len
>
0
:
ip
+=
suffix
.
rjust
(
suffix_len
,
'0'
)
ip
+=
suffix
.
rjust
(
suffix_len
,
'0'
)
...
@@ -233,11 +234,11 @@ def ipFromBin(ip, suffix=''):
...
@@ -233,11 +234,11 @@ def ipFromBin(ip, suffix=''):
return
socket
.
inet_ntop
(
socket
.
AF_INET6
,
return
socket
.
inet_ntop
(
socket
.
AF_INET6
,
struct
.
pack
(
'>QQ'
,
int
(
ip
[:
64
],
2
),
int
(
ip
[
64
:],
2
)))
struct
.
pack
(
'>QQ'
,
int
(
ip
[:
64
],
2
),
int
(
ip
[
64
:],
2
)))
def
dump_address
(
address
)
:
def
dump_address
(
address
:
str
)
->
str
:
return
';'
.
join
(
map
(
','
.
join
,
address
))
return
';'
.
join
(
map
(
','
.
join
,
address
))
# Yield ip, port, protocol, and country if it is in the address
# Yield ip, port, protocol, and country if it is in the address
def
parse_address
(
address_list
)
:
def
parse_address
(
address_list
:
str
)
->
Iterator
[
tuple
[
str
,
str
,
str
,
str
]]
:
for
address
in
address_list
.
split
(
';'
):
for
address
in
address_list
.
split
(
';'
):
try
:
try
:
a
=
address
.
split
(
','
)
a
=
address
.
split
(
','
)
...
@@ -247,17 +248,17 @@ def parse_address(address_list):
...
@@ -247,17 +248,17 @@ def parse_address(address_list):
logging
.
warning
(
"Failed to parse node address %r (%s)"
,
logging
.
warning
(
"Failed to parse node address %r (%s)"
,
address
,
e
)
address
,
e
)
def
binFromSubnet
(
subnet
)
:
def
binFromSubnet
(
subnet
:
str
)
->
str
:
p
,
l
=
subnet
.
split
(
'/'
)
p
,
l
=
subnet
.
split
(
'/'
)
return
bin
(
int
(
p
))[
2
:].
rjust
(
int
(
l
),
'0'
)
return
bin
(
int
(
p
))[
2
:].
rjust
(
int
(
l
),
'0'
)
def
newHmacSecret
()
:
def
_newHmacSecret
()
->
Callable
[[
Optional
[
int
]],
bytes
]
:
"""returns bytes"""
"""returns bytes"""
from
random
import
getrandbits
as
g
from
random
import
getrandbits
as
g
pack
=
struct
.
Struct
(
">QQI"
).
pack
pack
=
struct
.
Struct
(
">QQI"
).
pack
assert
len
(
pack
(
0
,
0
,
0
))
==
HMAC_LEN
assert
len
(
pack
(
0
,
0
,
0
))
==
HMAC_LEN
return
lambda
x
=
None
:
pack
(
g
(
64
)
if
x
is
None
else
x
,
g
(
64
),
g
(
32
))
return
lambda
x
=
None
:
pack
(
g
(
64
)
if
x
is
None
else
x
,
g
(
64
),
g
(
32
))
newHmacSecret
=
newHmacSecret
()
newHmacSecret
=
_
newHmacSecret
()
### Integer serialization
### Integer serialization
# - supports values from 0 to 0x202020202020201f
# - supports values from 0 to 0x202020202020201f
...
...
re6st/x509.py
View file @
e1060631
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import
calendar
,
hashlib
,
hmac
,
logging
,
os
,
struct
,
subprocess
,
threading
,
time
import
calendar
,
hashlib
,
hmac
,
logging
,
os
,
struct
,
subprocess
,
threading
,
time
from
typing
import
Callable
,
Any
from
OpenSSL
import
crypto
from
OpenSSL
import
crypto
from
cryptography.hazmat.primitives
import
hashes
from
cryptography.hazmat.primitives
import
hashes
from
cryptography.hazmat.primitives.asymmetric
import
padding
from
cryptography.hazmat.primitives.asymmetric
import
padding
...
@@ -9,29 +11,29 @@ from cryptography.x509 import load_pem_x509_certificate
...
@@ -9,29 +11,29 @@ from cryptography.x509 import load_pem_x509_certificate
from
.
import
utils
from
.
import
utils
from
.version
import
protocol
from
.version
import
protocol
def
newHmacSecret
():
def
newHmacSecret
()
->
bytes
:
return
utils
.
newHmacSecret
(
int
(
time
.
time
()
*
1000000
))
return
utils
.
newHmacSecret
(
int
(
time
.
time
()
*
1000000
))
def
networkFromCa
(
ca
)
:
def
networkFromCa
(
ca
:
crypto
.
X509
)
->
str
:
# TODO: will be ca.serial_number after migration to cryptography
# TODO: will be ca.serial_number after migration to cryptography
return
bin
(
ca
.
get_serial_number
())[
3
:]
return
bin
(
ca
.
get_serial_number
())[
3
:]
def
subnetFromCert
(
cert
)
:
def
subnetFromCert
(
cert
:
crypto
.
X509
)
->
str
:
return
cert
.
get_subject
().
CN
return
cert
.
get_subject
().
CN
def
notBefore
(
cert
)
:
def
notBefore
(
cert
:
crypto
.
X509
)
->
int
:
return
calendar
.
timegm
(
time
.
strptime
(
cert
.
get_notBefore
().
decode
(),
'%Y%m%d%H%M%SZ'
))
return
calendar
.
timegm
(
time
.
strptime
(
cert
.
get_notBefore
().
decode
(),
'%Y%m%d%H%M%SZ'
))
def
notAfter
(
cert
)
:
def
notAfter
(
cert
:
crypto
.
X509
)
->
int
:
return
calendar
.
timegm
(
time
.
strptime
(
cert
.
get_notAfter
().
decode
(),
'%Y%m%d%H%M%SZ'
))
return
calendar
.
timegm
(
time
.
strptime
(
cert
.
get_notAfter
().
decode
(),
'%Y%m%d%H%M%SZ'
))
def
openssl
(
*
args
,
fds
=
[])
:
def
openssl
(
*
args
:
str
,
fds
=
[])
->
utils
.
Popen
:
return
utils
.
Popen
((
'openssl'
,)
+
args
,
return
utils
.
Popen
((
'openssl'
,)
+
args
,
stdin
=
subprocess
.
PIPE
,
stdin
=
subprocess
.
PIPE
,
stdout
=
subprocess
.
PIPE
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
pass_fds
=
fds
)
stderr
=
subprocess
.
PIPE
,
pass_fds
=
fds
)
def
encrypt
(
cert
,
data
:
bytes
)
->
bytes
:
def
encrypt
(
cert
:
bytes
,
data
:
bytes
)
->
bytes
:
assert
isinstance
(
data
,
bytes
)
assert
isinstance
(
data
,
bytes
)
r
,
w
=
os
.
pipe
()
r
,
w
=
os
.
pipe
()
try
:
try
:
...
@@ -46,10 +48,10 @@ def encrypt(cert, data: bytes) -> bytes:
...
@@ -46,10 +48,10 @@ def encrypt(cert, data: bytes) -> bytes:
raise
subprocess
.
CalledProcessError
(
p
.
returncode
,
'openssl'
,
err
)
raise
subprocess
.
CalledProcessError
(
p
.
returncode
,
'openssl'
,
err
)
return
out
return
out
def
fingerprint
(
cert
,
alg
=
'sha1'
):
def
fingerprint
(
cert
:
crypto
.
X509
,
alg
=
'sha1'
):
return
hashlib
.
new
(
alg
,
crypto
.
dump_certificate
(
crypto
.
FILETYPE_ASN1
,
cert
))
return
hashlib
.
new
(
alg
,
crypto
.
dump_certificate
(
crypto
.
FILETYPE_ASN1
,
cert
))
def
maybe_renew
(
path
,
cert
,
info
,
renew
,
force
=
False
)
:
def
maybe_renew
(
path
:
str
,
cert
:
crypto
.
X509
,
info
:
str
,
renew
:
Callable
[[],
Any
],
force
=
False
)
->
tuple
[
crypto
.
X509
,
int
]
:
from
.registry
import
RENEW_PERIOD
from
.registry
import
RENEW_PERIOD
while
True
:
while
True
:
if
force
:
if
force
:
...
@@ -93,7 +95,7 @@ class NewSessionError(Exception):
...
@@ -93,7 +95,7 @@ class NewSessionError(Exception):
class
Cert
:
class
Cert
:
def
__init__
(
self
,
ca
,
key
,
cert
=
None
):
def
__init__
(
self
,
ca
:
str
,
key
:
str
,
cert
:
str
|
None
=
None
):
self
.
ca_path
=
ca
self
.
ca_path
=
ca
self
.
cert_path
=
cert
self
.
cert_path
=
cert
self
.
key_path
=
key
self
.
key_path
=
key
...
@@ -111,24 +113,24 @@ class Cert:
...
@@ -111,24 +113,24 @@ class Cert:
self
.
cert
=
self
.
loadVerify
(
f
.
read
().
encode
())
self
.
cert
=
self
.
loadVerify
(
f
.
read
().
encode
())
@
property
@
property
def
prefix
(
self
):
def
prefix
(
self
)
->
str
:
return
utils
.
binFromSubnet
(
subnetFromCert
(
self
.
cert
))
return
utils
.
binFromSubnet
(
subnetFromCert
(
self
.
cert
))
@
property
@
property
def
network
(
self
):
def
network
(
self
)
->
str
:
return
networkFromCa
(
self
.
ca
)
return
networkFromCa
(
self
.
ca
)
@
property
@
property
def
subject_serial
(
self
):
def
subject_serial
(
self
)
->
int
:
return
int
(
self
.
cert
.
get_subject
().
serialNumber
)
return
int
(
self
.
cert
.
get_subject
().
serialNumber
)
@
property
@
property
def
openvpn_args
(
self
):
def
openvpn_args
(
self
)
->
tuple
[
str
,
...]
:
return
(
'--ca'
,
self
.
ca_path
,
return
(
'--ca'
,
self
.
ca_path
,
'--cert'
,
self
.
cert_path
,
'--cert'
,
self
.
cert_path
,
'--key'
,
self
.
key_path
)
'--key'
,
self
.
key_path
)
def
maybeRenew
(
self
,
registry
,
crl
):
def
maybeRenew
(
self
,
registry
,
crl
)
->
int
:
self
.
cert
,
next_renew
=
maybe_renew
(
self
.
cert_path
,
self
.
cert
,
self
.
cert
,
next_renew
=
maybe_renew
(
self
.
cert_path
,
self
.
cert
,
"Certificate"
,
lambda
:
registry
.
renewCertificate
(
self
.
prefix
),
"Certificate"
,
lambda
:
registry
.
renewCertificate
(
self
.
prefix
),
self
.
cert
.
get_serial_number
()
in
crl
)
self
.
cert
.
get_serial_number
()
in
crl
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment