diff --git a/confluent_osdeploy/utils/clortho.c b/confluent_osdeploy/utils/clortho.c index 94918189..97d63472 100644 --- a/confluent_osdeploy/utils/clortho.c +++ b/confluent_osdeploy/utils/clortho.c @@ -36,7 +36,8 @@ unsigned char* genpasswd(int len) { int main(int argc, char* argv[]) { int sock, ret; char slen; - unsigned char currlen, currtype; + unsigned char currtype; + size_t currlen; unsigned char* passwd; unsigned char* cryptedpass; unsigned char* macaddr; @@ -107,10 +108,18 @@ int main(int argc, char* argv[]) { ret = read(sock, buffer, 2); while (buffer[0] != 255) { currtype = buffer[0]; - currlen = buffer[1]; + if (currtype & 0b10000000) { + currlen = buffer[1] << 8 & buffer[2]; + } else { + currlen = buffer[1]; + } memset(buffer, 0, MAXPACKET); + if (currlen > 1000) { + fprintf(stderr, "Received oversized message\n"); + exit(1); + } if (currlen) { - ret = read(sock, buffer, currlen); // Max is 255, well under MAX_PACKET + ret = read(sock, buffer, currlen); // Max is 1000, well under MAX_PACKET } if (currtype == 2) { dprintf(sock, "\x03%c", currlen); @@ -118,6 +127,10 @@ int main(int argc, char* argv[]) { slen = strlen(cryptedpass) & 0xff; dprintf(sock, "\x04%c%s", slen, cryptedpass); ret = write(sock, "\x00\x00", 2); + } else if (currtype == 128) { + printf("SEALED:%s", buffer); + printf("\n"); + exit(0); } else if (currtype == 5) { printf("%s", passwd); printf("\n"); diff --git a/confluent_server/confluent/config/attributes.py b/confluent_server/confluent/config/attributes.py index 5f10e1be..7c5506aa 100644 --- a/confluent_server/confluent/config/attributes.py +++ b/confluent_server/confluent/config/attributes.py @@ -129,6 +129,14 @@ node = { 'Generally this is not directly modified, but is modified ' 'by the "nodedeploy" command'), }, + 'deployment.sealedapikey': { + 'description': 'This attribute is used by some images to save a sealed ' + 'version of a node apikey, so that a subsequent run with ' + 'same TPM2 will use the TPM2 to protect the API key rather ' + 'than local network verification. If this is set, then ' + 'an api key request will receive this if the api key grant ' + 'is not armed', + }, #'id': { # 'description': ('Numeric identifier for node') #}, diff --git a/confluent_server/confluent/credserver.py b/confluent_server/confluent/credserver.py index f6632d00..7e2040ce 100644 --- a/confluent_server/confluent/credserver.py +++ b/confluent_server/confluent/credserver.py @@ -23,6 +23,15 @@ import eventlet.green.socket as socket import eventlet.greenpool import os +# cred grant tlvs: +# 0, 0 - null +# 1, len, +# 2, len, token - echo request +# 3, len, token - echo reply +# 4, len, crypted - crypted apikey +# 5, 0, accept key +# 128, len, len, key - sealed key + class CredServer(object): def __init__(self): self.cfm = cfm.ConfigManager(None) @@ -38,11 +47,20 @@ class CredServer(object): client.close() return nodename = util.stringify(client.recv(tlv[1])) - tlv = bytearray(client.recv(2)) - apiarmed = self.cfm.get_node_attributes(nodename, 'deployment.apiarmed') + tlv = bytearray(client.recv(2)) # should always be null + apiarmed = self.cfm.get_node_attributes(nodename, + ['deployment.apiarmed', 'deployment.sealedapikey']) apiarmed = apiarmed.get(nodename, {}).get('deployment.apiarmed', {}).get( 'value', None) if not apiarmed: + if apiarmed.get(nodename, {}).get( + 'deployment.sealedapikey', {}).get('value', None): + sealed = apiarmed[nodename]['deployment.sealedapikey'][ + 'value'] + if not isintance(sealed, bytes): + sealed = sealed.encode('utf8') + reply = b'\x80' + struct.pack('>H', len(sealed) + 1) + sealed + b'\x00' + client.send(reply) client.close() return if apiarmed not in ('once', 'continuous'): diff --git a/confluent_server/confluent/selfservice.py b/confluent_server/confluent/selfservice.py index 7e286a41..b8f45265 100644 --- a/confluent_server/confluent/selfservice.py +++ b/confluent_server/confluent/selfservice.py @@ -256,6 +256,8 @@ def handle_request(env, start_response): else: start_response('500 Error', (('Content-Type', 'text/plain'),)) yield 'No pending profile detected, unable to accept status update' + elif env['PATH_INFO'] == '/self/savetoken': + print(repr(reqbody)) else: start_response('404 Not Found', ()) yield 'Not found'