mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-06 00:13:33 +00:00
Added cert generation helper for Diagnostic Agent use
This commit is contained in:
@@ -1670,6 +1670,92 @@ duk_ret_t ILibDuktape_MeshAgent_ServerInfo(duk_context *ctx)
|
||||
return(1);
|
||||
}
|
||||
|
||||
duk_ret_t ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent(duk_context *ctx)
|
||||
{
|
||||
char *rootSubject = (char*)duk_require_string(ctx, 0);
|
||||
char tmp[UTIL_SHA384_HASHSIZE];
|
||||
struct util_cert tmpCert;
|
||||
|
||||
duk_push_this(ctx);
|
||||
MeshAgentHostContainer *agent = (MeshAgentHostContainer*)Duktape_GetPointerProperty(ctx, -1, MESH_AGENT_PTR);
|
||||
duk_push_object(ctx);
|
||||
|
||||
#ifdef WIN32
|
||||
PCCERT_CONTEXT certCtx = NULL;
|
||||
char *certCtx_data = NULL;
|
||||
if (wincrypto_open_ex(TRUE, rootSubject, &certCtx) == 0) // Force certificate re-generation
|
||||
{
|
||||
int l;
|
||||
do {
|
||||
// Finish off work with our own certificate
|
||||
l = wincrypto_getcert_ex(&certCtx_data, certCtx);
|
||||
if (l > 0)
|
||||
{
|
||||
util_from_cer(certCtx_data, l, &tmpCert);
|
||||
util_keyhash(tmpCert, tmp);
|
||||
if (((int*)tmp)[0] == 0) { wincrypto_close_ex(certCtx); wincrypto_open_ex(1, rootSubject, &certCtx); }
|
||||
}
|
||||
} while (l != 0 && ((int*)tmp)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
|
||||
|
||||
if (l > 0)
|
||||
{
|
||||
// Save the root cert in CER format
|
||||
duk_push_object(ctx); // [object][root]
|
||||
char *rootBuffer = duk_push_fixed_buffer(ctx, l); // [object][root][buffer]
|
||||
duk_push_buffer_object(ctx, -1, 0, l, DUK_BUFOBJ_NODEJS_BUFFER); // [object][root][buffer][nodeBuffer]
|
||||
duk_put_prop_string(ctx, -3, "der"); // [object][root][buffer]
|
||||
duk_pop(ctx); // [object][root]
|
||||
duk_put_prop_string(ctx, -2, "root"); // [object]
|
||||
memcpy_s(rootBuffer, l, certCtx_data, l);
|
||||
|
||||
// Generate a new TLS certificate & save it.
|
||||
l = wincrypto_mkCert(rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &certCtx_data);
|
||||
|
||||
duk_push_object(ctx); // [object][tls]
|
||||
char *buffer = duk_push_fixed_buffer(ctx, l); // [object][tls][buffer]
|
||||
duk_push_buffer_object(ctx, -1, 0, l, DUK_BUFOBJ_NODEJS_BUFFER); // [object][tls][buffer][nodeBuffer]
|
||||
duk_put_prop_string(ctx, -3, "pfx"); // [object][tls][buffer]
|
||||
duk_pop(ctx); // [object][tls]
|
||||
duk_push_string(ctx, "hidden"); duk_put_prop_string(ctx, -2, "passphrase");
|
||||
duk_put_prop_string(ctx, -2, "tls"); // [object]
|
||||
memcpy_s(buffer, l, certCtx_data, l);
|
||||
util_free(certCtx_data);
|
||||
return(1);
|
||||
}
|
||||
|
||||
// wincrypto error
|
||||
return(ILibDuktape_Error(ctx, "Error Generating Certificates using WinCrypto"));
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
// Generate a new self-signed root certificate for this node using OpenSSL
|
||||
do
|
||||
{
|
||||
if (util_mkCert(NULL, &(tmpCert), 3072, 10000, "MeshNodeCertificate", CERTIFICATE_ROOT, NULL) == 0)
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "Error Generating Certificates using OpenSSL"));
|
||||
}
|
||||
util_keyhash(tmpCert, tmp);
|
||||
} while (((int*)tmp)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
|
||||
|
||||
duk_push_object(ctx); // [object][root]
|
||||
char *pfx = NULL;
|
||||
int pfxLen = util_to_p12(tmpCert, "hidden", &pfx);
|
||||
char *jspfx = duk_push_fixed_buffer(ctx, pfxLen); // [object][root][buffer]
|
||||
duk_push_buffer_object(ctx, -1, 0, pfxLen, DUK_BUFOBJ_NODEJS_BUFFER); // [object][root][buffer][nodeBuffer]
|
||||
duk_put_prop_string(ctx, -3, "pfx"); // [object][root][buffer]
|
||||
duk_pop(ctx); // [object][root]
|
||||
duk_push_string(ctx, "hidden"); duk_put_prop_string(ctx, -2, "passphrase");
|
||||
duk_put_prop_string(ctx, -2, "root"); // [object]
|
||||
|
||||
memcpy_s(jspfx, pfxLen, pfx, pfxLen);
|
||||
util_free(pfx);
|
||||
util_freecert(&tmpCert);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
void ILibDuktape_MeshAgent_PUSH(duk_context *ctx, void *chain)
|
||||
{
|
||||
MeshAgentHostContainer *agent;
|
||||
@@ -1715,6 +1801,7 @@ void ILibDuktape_MeshAgent_PUSH(duk_context *ctx, void *chain)
|
||||
// Always use the root cert for agent authentication
|
||||
duk_push_pointer(ctx, &agent->selfcert);
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_MeshAgent_Cert_NonLeaf);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "GenerateAgentCertificate", ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent, 1);
|
||||
#endif
|
||||
|
||||
ILibDuktape_EventEmitter_CreateEventEx(emitter, "Ready");
|
||||
|
||||
@@ -125,14 +125,21 @@ int __fastcall wincrypto_isopen()
|
||||
return (wincrypto_hProv != NULL && wincrypto_hCertStore != NULL && wincrypto_certCtx != NULL);
|
||||
}
|
||||
|
||||
void __fastcall wincrypto_close()
|
||||
void __fastcall wincrypto_close_ex(PCCERT_CONTEXT certCtx)
|
||||
{
|
||||
if (wincrypto_certCtx != NULL) { CertFreeCertificateContext(wincrypto_certCtx); wincrypto_certCtx = NULL; }
|
||||
if (wincrypto_hProv != NULL) { NCryptFreeObject(wincrypto_hProv); wincrypto_hProv = NULL; }
|
||||
if (wincrypto_hCertStore != NULL) { CertCloseStore(wincrypto_hCertStore, 0); wincrypto_hCertStore = NULL; }
|
||||
if (certCtx != NULL)
|
||||
{
|
||||
CertFreeCertificateContext(certCtx);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wincrypto_certCtx != NULL) { CertFreeCertificateContext(wincrypto_certCtx); wincrypto_certCtx = NULL; }
|
||||
if (wincrypto_hProv != NULL) { NCryptFreeObject(wincrypto_hProv); wincrypto_hProv = NULL; }
|
||||
if (wincrypto_hCertStore != NULL) { CertCloseStore(wincrypto_hCertStore, 0); wincrypto_hCertStore = NULL; }
|
||||
}
|
||||
}
|
||||
|
||||
int __fastcall wincrypto_open(int newcert, char *rootSubject)
|
||||
int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT *certCtx)
|
||||
{
|
||||
DWORD KeyLength = 3072;
|
||||
NCRYPT_KEY_HANDLE hKeyNode = NULL;
|
||||
@@ -172,9 +179,10 @@ int __fastcall wincrypto_open(int newcert, char *rootSubject)
|
||||
|
||||
akeyLen = sprintf_s(akeycontainer, sizeof(akeycontainer), "%s_privatekey", rootSubject);
|
||||
if (mbstowcs_s(&wkeyLen, (wchar_t*)wkeycontainer, sizeof(wkeycontainer) / 2, (char*)akeycontainer, 64) != 0) { return(1); } // Error creating privatekey container name
|
||||
if (certCtx == NULL) { certCtx = &wincrypto_certCtx; }
|
||||
|
||||
ZeroMemory(&exts, sizeof(exts));
|
||||
wincrypto_close();
|
||||
wincrypto_close_ex(*certCtx);
|
||||
|
||||
// Open the best CNG possible
|
||||
while (providerName == NULL && wincrypto_CngProviders[r] != NULL) {
|
||||
@@ -299,7 +307,7 @@ int __fastcall wincrypto_open(int newcert, char *rootSubject)
|
||||
error:
|
||||
// Clean up
|
||||
if (hKeyNode != NULL) NCryptFreeObject(hKeyNode);
|
||||
wincrypto_close();
|
||||
wincrypto_close_ex(*certCtx);
|
||||
return 1;
|
||||
|
||||
end:
|
||||
@@ -479,11 +487,19 @@ end:
|
||||
}
|
||||
|
||||
// Get the X509 certificate including the public key (Direct reference, no need to free this).
|
||||
int __fastcall wincrypto_getcert(char** data)
|
||||
int __fastcall wincrypto_getcert_ex(char** data, PCCERT_CONTEXT certCtx)
|
||||
{
|
||||
if (wincrypto_certCtx == NULL) { *data = NULL; return 0; }
|
||||
*data = (char*)wincrypto_certCtx->pbCertEncoded;
|
||||
return (int)wincrypto_certCtx->cbCertEncoded;
|
||||
if (certCtx != NULL)
|
||||
{
|
||||
*data = (char*)certCtx->pbCertEncoded;
|
||||
return (int)certCtx->cbCertEncoded;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wincrypto_certCtx == NULL) { *data = NULL; return 0; }
|
||||
*data = (char*)wincrypto_certCtx->pbCertEncoded;
|
||||
return (int)wincrypto_certCtx->cbCertEncoded;
|
||||
}
|
||||
}
|
||||
|
||||
// Create an X509, RSA 3027bit certificate with the MeshAgent certificate as signing root.
|
||||
|
||||
@@ -23,15 +23,18 @@ void __fastcall wincrypto_setregistryA(char* name, char* value);
|
||||
int __fastcall wincrypto_getregistry(LPCWSTR name, char** value);
|
||||
int __fastcall wincrypto_getregistryA(char* name, char** value);
|
||||
int __fastcall wincrypto_isopen();
|
||||
void __fastcall wincrypto_close();
|
||||
int __fastcall wincrypto_open(int newcert, char *rootSubject);
|
||||
void __fastcall wincrypto_close_ex(PCCERT_CONTEXT certCtx);
|
||||
#define wincrypto_close() wincrypto_close_ex(NULL)
|
||||
#define wincrypto_open(newCert, rootSubject) wincrypto_open_ex(newCert, rootSubject, NULL)
|
||||
int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT *certCtx);
|
||||
void __fastcall wincrypto_random(int length, char* result);
|
||||
int __fastcall wincrypto_md5(char* data, int datalen, char* result);
|
||||
int __fastcall wincrypto_sha256(char* data, int datalen, char* result);
|
||||
int __fastcall wincrypto_sha384(char* data, int datalen, char* result);
|
||||
int __fastcall wincrypto_sign(char* data, int len, char** signature);
|
||||
int __fastcall wincrypto_decrypt(char* encdata, int encdatalen, char** data);
|
||||
int __fastcall wincrypto_getcert(char** data);
|
||||
#define wincrypto_getcert(data) wincrypto_getcert_ex(data, NULL)
|
||||
int __fastcall wincrypto_getcert_ex(char** data, PCCERT_CONTEXT certCtx);
|
||||
int __fastcall wincrypto_mkCert(char* rootSubject, wchar_t* subject, int certtype, wchar_t* password, char** data); // certtype: 1=Root, 2=Server, 3=Client
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user