Permalink
Browse files

[ARMT] fixed singing and hashing of messages sent to the remote server

  • Loading branch information...
1 parent 32ff57e commit 1ac224fa45e855229a98e8c0918047aa59a078c0 @gnif committed Sep 4, 2012
Showing with 195 additions and 44 deletions.
  1. +1 −6 armt.cc
  2. +12 −3 common/CCommon.cc
  3. +13 −5 common/CCommon.h
  4. +2 −7 common/CHTTP.cc
  5. +0 −2 common/CHTTP.h
  6. +147 −21 common/CMessageBuilder.cc
  7. +13 −0 common/CMessageBuilder.h
  8. +7 −0 fs/CFSVerifier.cc
View
@@ -62,7 +62,7 @@ bool DISKCHECK(std::iostream &ss)
continue;
/* dont send devices that are not faulting */
- if (it->second->IsOK())
+ if (!it->second->IsOK())
continue;
send = true;
@@ -104,11 +104,6 @@ bool FSCHECK(std::iostream &ss)
return fs.Save(ss);
}
-bool SMARTCHECK(std::iostream &ss)
-{
- return true;
-}
-
int main(int argc, char *argv[])
{
/* must be called first */
View
@@ -26,6 +26,7 @@
#include <string.h>
#include <libgen.h>
#include <unistd.h>
+#include <assert.h>
#include <stdarg.h>
#include <sys/wait.h>
@@ -45,9 +46,11 @@
#include "../utils/megactl.h"
/* static declarations */
-bool CCommon::m_isBE;
-std::string CCommon::m_exePath;
-std::string CCommon::m_basePath;
+bool CCommon::m_isBE;
+std::string CCommon::m_exePath;
+std::string CCommon::m_basePath;
+entropy_context CCommon::m_entropy;
+ctr_drbg_context CCommon::m_drbg;
bool __attribute__((optimize("O0"))) detectBE()
{
@@ -81,8 +84,14 @@ void CCommon::Initialize(const int argc, char* const argv[])
WriteExe("bin/lsscsi" , lsscsi , lsscsi_size );
WriteExe("bin/megactl" , megactl , megactl_size );
WriteExe("bin/megasasctl" , megasasctl , megasasctl_size );
+
+ /* init entropy for SSL/RSA */
+ const char *pers = "ARMT_CHTTPS";
+ entropy_init(&m_entropy);
+ assert(ctr_drbg_init(&m_drbg, entropy_func, &m_entropy, (unsigned char* )pers, strlen(pers)) == 0);
}
+
void CCommon::Trim(std::string &s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
View
@@ -25,6 +25,9 @@
#include <string>
#include <vector>
+#include "polarssl/entropy.h"
+#include "polarssl/ctr_drbg.h"
+
class CCommon
{
public:
@@ -39,8 +42,10 @@ class CCommon
static std::string IntToStr(int value, int base = 10);
static std::string StrToLower(const std::string &string);
- static const std::string &GetExePath () { return m_exePath ; }
- static const std::string &GetBasePath() { return m_basePath; }
+ static const std::string &GetExePath () { return m_exePath ; }
+ static const std::string &GetBasePath() { return m_basePath; }
+ static entropy_context *GetEntropy () { return &m_entropy; }
+ static ctr_drbg_context *GetDRBG () { return &m_drbg ; }
static bool IsFile (const std::string &path);
static bool IsDir (const std::string &path);
@@ -56,9 +61,12 @@ class CCommon
static bool RunCommand(std::string &result, const std::string &cmd, ...) __attribute__ ((sentinel));
private:
- static bool m_isBE;
- static std::string m_exePath;
- static std::string m_basePath;
+ static bool m_isBE;
+ static std::string m_exePath;
+ static std::string m_basePath;
+
+ static entropy_context m_entropy;
+ static ctr_drbg_context m_drbg;
};
#endif // _CCOMMON_H_
View
@@ -24,7 +24,7 @@
#include "polarssl/net.h"
#include <sys/socket.h>
#include <pcrecpp.h>
-
+#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -47,11 +47,6 @@ bool CHTTP::Connect(const std::string &host, const int port, const bool ssl)
if (ssl)
{
- const char *pers = "ARMT_CHTTPS";
- entropy_init(&m_entropy);
- if (ctr_drbg_init(&m_ctr_drbg, entropy_func, &m_entropy, (unsigned char* )pers, strlen(pers)) != 0)
- return false;
-
memset(&m_sslContext, 0, sizeof(m_sslContext));
memset(&m_sslSession, 0, sizeof(m_sslSession));
@@ -61,7 +56,7 @@ bool CHTTP::Connect(const std::string &host, const int port, const bool ssl)
ssl_init (&m_sslContext);
ssl_set_endpoint (&m_sslContext, SSL_IS_CLIENT);
ssl_set_authmode (&m_sslContext, SSL_VERIFY_NONE);
- ssl_set_rng (&m_sslContext, ctr_drbg_random, &m_ctr_drbg);
+ ssl_set_rng (&m_sslContext, ctr_drbg_random, CCommon::GetDRBG());
ssl_set_bio (&m_sslContext, net_recv, &m_sslFD, net_send, &m_sslFD);
ssl_set_ciphersuites(&m_sslContext, ssl_default_ciphersuites);
ssl_set_session (&m_sslContext, 1, 600, &m_sslSession);
View
@@ -63,8 +63,6 @@ class CHTTP
HeaderMap m_headers;
/* polarssl vars */
- entropy_context m_entropy;
- ctr_drbg_context m_ctr_drbg;
ssl_context m_sslContext;
ssl_session m_sslSession;
int m_sslFD;
View
@@ -22,11 +22,16 @@
#include "CCommon.h"
#include "CCompress.h"
+#include <sys/stat.h>
#include <assert.h>
#include <stdint.h>
#include <sstream>
+#include <fstream>
#include <string.h>
-#include "polarssl/md5.h"
+
+#include "polarssl/sha1.h"
+#include "polarssl/base64.h"
+#include "polarssl/x509write.h"
CMessageBuilder::CMessageBuilder(const std::string &host, const unsigned int port) :
m_armthost(host),
@@ -49,9 +54,119 @@ CMessageBuilder::CMessageBuilder(const std::string &host, const unsigned int por
m_http.SetHeader("Host" , host);
m_http.SetHeader("User-Agent" , "ARMT");
m_http.SetHeader("Accept" , "text/plain");
+ m_http.SetHeader("Content-Type" , "application/octet-stream");
m_http.SetHeader("Accept-Encoding", "");
m_http.SetHeader("Connection" , "close");
- m_http.SetHeader("X-ARMT-HOST" , m_hostname);
+
+ InitAuth();
+}
+
+CMessageBuilder::~CMessageBuilder()
+{
+ rsa_free (&m_rsa);
+}
+
+bool CMessageBuilder::SignPayload(const std::string &payload, std::string &signature)
+{
+ /* hash the payload */
+ unsigned char tmp[20];
+ sha1((const unsigned char *)payload.c_str(), payload.length(), tmp);
+
+ /* sign the hash */
+ unsigned char buffer[m_rsa.len];
+ if (rsa_pkcs1_sign(
+ &m_rsa,
+ ctr_drbg_random,
+ CCommon::GetDRBG(),
+ RSA_PRIVATE,
+ SIG_RSA_SHA1,
+ sizeof(tmp),
+ tmp,
+ buffer
+ ) != 0)
+ return false;
+
+ /* base64 encode the signature */
+ signature = Base64Encode(std::string((char *)buffer, sizeof(buffer)));
+ return true;
+}
+
+std::string CMessageBuilder::Base64Encode(const std::string &str)
+{
+ size_t baselen = 0;
+ /* get the baselen */
+ base64_encode(NULL, &baselen, (const unsigned char *)str.c_str(), str.length());
+
+ /* encode the string */
+ unsigned char base[baselen];
+ if (base64_encode(base, &baselen, (const unsigned char *)str.c_str(), str.length()) != 0)
+ return "";
+
+ std::string result;
+ result.assign((char *)base, baselen);
+ return result;
+}
+
+void CMessageBuilder::InitAuth()
+{
+ const std::string certPath = CCommon::GetBasePath() + "/ssl";
+ const std::string rsaFile = certPath + "/private.pem";
+
+ if (!CCommon::IsDir(certPath))
+ assert(mkdir(certPath.c_str(), S_IRWXU) == 0);
+
+ /* init m_rsa */
+ rsa_init(&m_rsa, RSA_PKCS_V15, 0);
+
+ /* check if we have an RSA key, and if not generate one */
+ if (!CCommon::IsFile(rsaFile))
+ {
+ assert(rsa_gen_key(&m_rsa, ctr_drbg_random, CCommon::GetDRBG(), 2048, 65537) == 0);
+
+ /* save the key off */
+ FILE *fp;
+ assert(fp = fopen(rsaFile.c_str(), "w"));
+
+ assert(
+ mpi_write_file("", &m_rsa.N , 16, fp) == 0 &&
+ mpi_write_file("", &m_rsa.E , 16, fp) == 0 &&
+ mpi_write_file("", &m_rsa.D , 16, fp) == 0 &&
+ mpi_write_file("", &m_rsa.P , 16, fp) == 0 &&
+ mpi_write_file("", &m_rsa.Q , 16, fp) == 0 &&
+ mpi_write_file("", &m_rsa.DP, 16, fp) == 0 &&
+ mpi_write_file("", &m_rsa.DQ, 16, fp) == 0 &&
+ mpi_write_file("", &m_rsa.QP, 16, fp) == 0
+ );
+
+ fclose(fp);
+ if (chmod(rsaFile.c_str(), S_IRUSR | S_IWUSR) != 0)
+ {
+ printf("Unable to secure private key\n");
+ unlink(rsaFile.c_str());
+ assert(false);
+ }
+ }
+ else
+ {
+ /* load the private key */
+ FILE *fp;
+ assert(fp = fopen(rsaFile.c_str(), "r"));
+
+ assert(
+ mpi_read_file(&m_rsa.N , 16, fp) == 0 &&
+ mpi_read_file(&m_rsa.E , 16, fp) == 0 &&
+ mpi_read_file(&m_rsa.D , 16, fp) == 0 &&
+ mpi_read_file(&m_rsa.P , 16, fp) == 0 &&
+ mpi_read_file(&m_rsa.Q , 16, fp) == 0 &&
+ mpi_read_file(&m_rsa.DP, 16, fp) == 0 &&
+ mpi_read_file(&m_rsa.DQ, 16, fp) == 0 &&
+ mpi_read_file(&m_rsa.QP, 16, fp) == 0
+ );
+
+ m_rsa.len = mpi_size(&m_rsa.N);
+
+ fclose(fp);
+ }
}
void CMessageBuilder::AppendSegment(const std::string &name, SegmentFn fn)
@@ -62,6 +177,11 @@ void CMessageBuilder::AppendSegment(const std::string &name, SegmentFn fn)
void CMessageBuilder::PackString(std::ostream &ss, const std::string &value)
{
uint16_t len = value.length();
+
+ /* we need to always send in LE */
+ if (CCommon::IsBE())
+ swab(&len, &len, sizeof(len));
+
ss.write((const char *)&len, sizeof(len));
ss << value;
}
@@ -95,38 +215,44 @@ bool CMessageBuilder::Send()
body = compressed.str();
}
+ /* connect to the host */
+ if (!m_http.Connect(m_armthost, m_armtport, true))
+ return false;
+
+ /* encode the public key for transmission */
+ std::string pubkey;
{
- /* hash the body for the header */
- unsigned char tmp[16];
- md5((const unsigned char *)body.c_str(), body.length(), tmp);
- std::string hash;
- for(int i = 0; i < 16; ++i)
- {
- std::string dec = CCommon::IntToStr(tmp[i], 16);
- if(dec.length() < 2)
- dec.insert(0, "0");
- hash.append(dec);
- }
- m_http.SetHeader("X-ARMT-MD5", hash);
+ unsigned char buffer[1024];
+
+ int len = x509_write_pubkey_der(buffer, sizeof(buffer), &m_rsa);
+ if (len <= 0)
+ return false;
+
+ pubkey = Base64Encode(std::string(
+ (char *)buffer + sizeof(buffer) - len - 1, /* the key is in the end of the buffer */
+ len
+ ));
}
+ std::string signature;
+ if (!SignPayload(body, signature))
+ return false;
+
+ m_http.SetHeader("X-ARMT-HOST" , m_hostname);
+ m_http.SetHeader("X-ARMT-IP" , m_http.GetLocalIP());
+ m_http.SetHeader("X-ARMT-PUB" , pubkey);
+ m_http.SetHeader("X-ARMT-SIG" , signature);
m_http.SetHeader("Content-Length", CCommon::IntToStr(body.length()));
/* send the message */
uint16_t error;
CHTTP::HeaderMap headers;
- if (!m_http.Connect(m_armthost, m_armtport, true))
- return false;
-
- /* add the source IP to the header so the monitor knows what machine this is if it is behind a proxy or nat */
- m_http.SetHeader("X-ARMT-IP", m_http.GetLocalIP());
-
if (!m_http.PerformRequest("POST", "/", error, headers, body))
return false;
printf("%d\n", error);
printf("%s\n", body.c_str());
- return true;
+ return error == 202;
}
View
@@ -26,12 +26,22 @@
#include <string>
#include <map>
+#include "polarssl/x509.h"
+#include "polarssl/rsa.h"
+
class CMessageBuilder
{
public:
typedef bool (*SegmentFn)(std::iostream &ss);
CMessageBuilder(const std::string &host, const unsigned int port);
+ ~CMessageBuilder();
+
+ bool SignPayload(const std::string &payload, std::string &signature);
+ std::string Base64Encode(const std::string &str);
+
+ bool LoadCertificate(const std::string &crt);
+ void InitAuth();
void AppendSegment(const std::string &name, SegmentFn fn);
bool Send();
@@ -43,6 +53,9 @@ class CMessageBuilder
std::string m_armthost;
unsigned int m_armtport;
+ /* our key for signing messages */
+ rsa_context m_rsa;
+
std::string m_hostname;
SegmentList m_segments;
CHTTP m_http;
Oops, something went wrong.

0 comments on commit 1ac224f

Please sign in to comment.