mirror of
https://github.com/certbot/certbot.git
synced 2026-06-04 22:33:00 -04:00
initial checkin of client and server that can talk to each other!
This commit is contained in:
parent
6dcfdcecda
commit
b70d4c8215
5 changed files with 158 additions and 0 deletions
8
webserver/Makefile
Normal file
8
webserver/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
deploy: chocolate_protocol_pb2.py chocolate.py
|
||||
scp chocolate_protocol.proto chocolate.py ${CHOCOLATESERVER}: && ssh ${CHOCOLATESERVER} protoc chocolate_protocol.proto --python_out=.
|
||||
|
||||
chocolate_protocol_pb2.py: chocolate_protocol.proto
|
||||
protoc chocolate_protocol.proto --python_out=.
|
||||
|
||||
clean:
|
||||
rm -f chocolate_protocol_pb2.pyc
|
||||
|
|
@ -1,2 +1,13 @@
|
|||
In this directory are tools that will run on webservers for sysadmins to
|
||||
automatically obtain their certs
|
||||
|
||||
|
||||
Set CHOCOLATESERVER environment variable for "make deploy" and client.py!
|
||||
|
||||
|
||||
chocolate.py - server-side, requires web.py (python-webpy), PyCrypto (python-crypto)
|
||||
probably wants to run under a web server like lighttpd with fastcgi
|
||||
|
||||
client.py - experimental tool for making requests and parsing replies
|
||||
|
||||
chocolate_protocol.proto - protocol definition; needs protobuf-compiler
|
||||
|
|
|
|||
39
webserver/chocolate.py
Executable file
39
webserver/chocolate.py
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import web
|
||||
from Crypto.Hash import SHA256, HMAC
|
||||
from chocolate_protocol_pb2 import chocolatemessage
|
||||
from google.protobuf.message import DecodeError
|
||||
|
||||
def hmac(k, m):
|
||||
return HMAC.new(k, m, SHA256).hexdigest()
|
||||
|
||||
urls = (
|
||||
'.*', 'index'
|
||||
)
|
||||
|
||||
class index:
|
||||
def GET(self):
|
||||
web.header("Content-type", "text/html")
|
||||
return "Hello, world! This server only accepts POST requests."
|
||||
|
||||
def POST(self):
|
||||
web.header("Content-type", "text/html")
|
||||
web.setcookie("chocolate", hmac("foo", "bar"),
|
||||
secure=True) # , httponly=True)
|
||||
m = chocolatemessage()
|
||||
r = chocolatemessage()
|
||||
r.chocolateversion = 1
|
||||
try:
|
||||
m.ParseFromString(web.data())
|
||||
except DecodeError:
|
||||
r.failure.cause = r.BadRequest
|
||||
else:
|
||||
if m.chocolateversion != 1:
|
||||
r.failure.cause = r.UnsupportedVersion
|
||||
if m.debug: return "SAW MESSAGE: %s\n" % str(r)
|
||||
else: return r.SerializeToString()
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = web.application(urls, globals())
|
||||
app.run()
|
||||
80
webserver/chocolate_protocol.proto
Normal file
80
webserver/chocolate_protocol.proto
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
message chocolatemessage {
|
||||
required int32 chocolateversion = 1;
|
||||
/* required string session? */
|
||||
|
||||
message SigningRequest {
|
||||
required int64 timestamp = 2;
|
||||
required string nonce = 3;
|
||||
required string csr = 4;
|
||||
required string sig = 5;
|
||||
optional string clientpuzzle = 6;
|
||||
/* server can specify difficulty? */
|
||||
}
|
||||
|
||||
enum FailureReason {
|
||||
UnsupportedVersion = 0;
|
||||
AbandonedRequest = 1;
|
||||
ServerOutage = 2;
|
||||
ServerGone = 3;
|
||||
StaleRequest = 4;
|
||||
BadSignature = 5;
|
||||
BadCSR = 6;
|
||||
BadRequest = 7;
|
||||
/* Unauthenticated = ?; */
|
||||
NeedClientPuzzle = 8;
|
||||
CannotIssueThatName = 9;
|
||||
UnsafeKey = 10;
|
||||
ChallengeFailed = 11;
|
||||
ChallengeTimeout = 12;
|
||||
}
|
||||
|
||||
message Failure {
|
||||
required FailureReason cause = 1;
|
||||
optional string URI = 2;
|
||||
/* reference to which SigningRequest this relates to? */
|
||||
}
|
||||
|
||||
message Proceed {
|
||||
/* possibly URI should be replaced with session ID? */
|
||||
required string timestamp = 1;
|
||||
required string URI = 2;
|
||||
optional int32 polldelay = 3;
|
||||
}
|
||||
|
||||
enum ChallengeType {
|
||||
DomainValidate = 0;
|
||||
EmailValidate = 1;
|
||||
Payment = 2;
|
||||
}
|
||||
|
||||
message Challenge {
|
||||
required ChallengeType type = 1;
|
||||
required int32 challengeid = 2;
|
||||
optional string name = 3;
|
||||
optional string data = 4;
|
||||
optional string URI = 5;
|
||||
optional bool succeeded = 6;
|
||||
/* from server: true if server ACK success,
|
||||
false if server NAK success,
|
||||
omit if server doesn't know if client
|
||||
has attempted yet.
|
||||
|
||||
from client: true if claiming to be done,
|
||||
false if unable,
|
||||
omit if client hasn't attempted yet. */
|
||||
}
|
||||
|
||||
message Success {
|
||||
required string certificate = 1; /* Repeated string certificate? */
|
||||
}
|
||||
|
||||
optional SigningRequest request = 2;
|
||||
optional Failure failure = 3;
|
||||
optional Proceed proceed = 4;
|
||||
repeated Challenge challenge = 5;
|
||||
repeated Challenge completedchallenge = 6;
|
||||
optional Success success = 7;
|
||||
|
||||
optional bool debug = 8; /* Causes server to return text instead of
|
||||
message! */
|
||||
}
|
||||
20
webserver/client.py
Normal file
20
webserver/client.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from chocolate_protocol_pb2 import chocolatemessage
|
||||
import urllib2, os, sys
|
||||
|
||||
try:
|
||||
upstream = "https://%s/chocolate.py" % os.environ["CHOCOLATESERVER"]
|
||||
except KeyError:
|
||||
print "Please set the environment variable CHOCOLATESERVER to the hostname"
|
||||
print "of a server that speaks this protocol."
|
||||
sys.exit(1)
|
||||
|
||||
def do(m):
|
||||
u = urllib2.urlopen(upstream, m.SerializeToString())
|
||||
return u.read()
|
||||
|
||||
def decode(m):
|
||||
return str(chocolatemessage.FromString(m))
|
||||
|
||||
m = chocolatemessage()
|
||||
Loading…
Reference in a new issue