[WIP] new account

This commit is contained in:
AJ ONeal 2019-03-21 02:07:57 -06:00
parent a5c448902e
commit 7f49650c48
1 changed files with 94 additions and 6 deletions

View File

@ -404,8 +404,78 @@ controllers.newNonce = function (req, res) {
};
controllers.newAccount = function (req, res) {
controllers._requireNonce(req, res, function () {
// TODO clean up error messages to be similar to ACME
// check if there's a public key
if (!req.jws || !req.jws.header.kid || !req.jws.header.jwk) {
res.statusCode = 422;
res.send({ error: { message: "jws body was not present or could not be validated" } });
return;
}
// TODO mx record email validation
if (!Array.isArray(req.body.contact) || !req.body.contact.length) {
// req.body.contact: [ 'mailto:email' ]
res.statusCode = 422;
res.send({ error: { message: "jws signed payload should contain a valid mailto:email in the contact array" } });
}
if (!req.body.termsOfServiceAgreed) {
// req.body.termsOfServiceAgreed: true
res.statusCode = 422;
res.send({ error: { message: "jws signed payload should have termsOfServiceAgreed: true" } });
}
// We verify here regardless of whether or not it was verified before,
// because it needs to be signed by the presenter of the public key,
// not just a trusted key
return verifyJws(req.jws.header.jwk, req.jws).then(function (verified) {
if (!verified) {
res.statusCode = 422;
res.send({ error: { message: "jws body was not present or could not be validated" } });
return;
}
// Note: we can get any number of account requests
// and these need to be stored for some space of time
// to await verification.
// we'll have to expire them somehow and prevent DoS
// check if this account already exists
DB.accounts.some(function (/*jwk*/) {
// calculate thumbprint from jwk
// find a key with matching jwk
});
// TODO fail if onlyReturnExisting is not false
// req.body.onlyReturnExisting: false
res.statusCode = 500;
res.end("not implemented yet");
res.send({
error: { message: "not implemented" },
"id": 0, // 5937234,
"key": req.jws.header.jwk, // TODO trim to basics
/*{
"kty": "EC",
"crv": "P-256",
"x": "G7kuV4JiqZs-GztrzpsmUM7Raf9tDUELWt5O337sTqw",
"y": "n5SFz9z2i-ZF_zu5aoS9t9O8y_g2qfonXv3Cna2e39k"
},*/
"contact": req.body.contact, // [ "mailto:john.doe@gmail.com" ],
// I'm not sure if we have the real IP through telebit's network wrapper at this point
// TODO we also need to set X-Forwarded-Addr as a proxy
"initialIp": req.connection.remoteAddress, //"128.187.116.28",
"createdAt": (new Date()).toISOString(), // "2018-04-17T21:29:10.833305103Z",
"status": "invalid" //"valid"
});
/*
Cache-Control: max-age=0, no-cache, no-store
Content-Type: application/json
Expires: Tue, 17 Apr 2018 21:29:10 GMT
Link: <https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf>;rel="terms-of-service"
Location: https://acme-staging-v02.api.letsencrypt.org/acme/acct/5937234
Pragma: no-cache
Replay-nonce: DKxX61imF38y_qkKvVcnWyo9oxQlHll0t9dMwGbkcxw
*/
});
});
};
@ -472,6 +542,7 @@ function jwtEggspress(req, res, next) {
}
// TODO verify if possible
console.warn("[warn] JWT is not verified yet");
next();
}
@ -487,11 +558,14 @@ function verifyJws(jwk, jws) {
}
function jwsEggspress(req, res, next) {
// Check to see if this looks like a JWS
// TODO check header application/jose+json ??
if (!req.body || !(req.body.protected && req.body.payload && req.body.signature)) {
next();
return;
}
// Decode it a bit
req.jws = req.body;
req.jws.header = JSON.parse(Buffer.from(req.jws.protected, 'base64'));
req.body = Buffer.from(req.jws.payload, 'base64');
@ -499,27 +573,40 @@ function jwsEggspress(req, res, next) {
req.body = JSON.parse(req.body);
}
// Check if this is a key we already trust
var vjwk;
DB.pubs.some(function (jwk) {
if (jwk.kid === req.jws.header.kid) {
vjwk = jwk;
}
});
// Check if there aren't any keys that we trust
// and this has signed itself, then make it a key we trust
// (TODO: move this all to the new account function)
if ((0 === DB.pubs.length && req.jws.header.jwk)) {
vjwk = req.jws.header.jwk;
if (!vjwk.kid) { throw Error("Impossible: no key id"); }
}
// Don't verify if it can't be verified
if (!vjwk) {
next();
return;
}
// Run the verification
return verifyJws(vjwk, req.jws).then(function (verified) {
if (true !== verified) {
return;
}
// Mark as verified
req.jws.verified = verified;
if (0 !== DB.pubs.length) {
return;
}
return keystore.set(vjwk.kid + '.pub.jwk.json', vjwk);
// (double check) DO NOT save if there are existing pubs
if (0 !== DB.pubs.length) { return; }
return keystore.set(vjwk.kid + PUBEXT, vjwk);
}).then(function () {
next();
});
@ -1414,6 +1501,7 @@ state.net = state.net || {
var DB = {};
DB.pubs = [];
DB.accounts = [];
var token;
var tokenname = "access_token.jwt";
try {