2
* Copyright (C) 2004-2011 See the AUTHORS file for details.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 2 as published
6
* by the Free Software Foundation.
15
#include <openssl/ssl.h>
16
#endif /* HAVE_LIBSSL */
19
#include <sys/types.h>
22
// Required with GCC 4.3+ if openssl is disabled
26
using std::stringstream;
32
void CUtils::GenerateCert(FILE *pOut, const CString& sHost) {
33
EVP_PKEY *pKey = NULL;
35
X509_NAME *pName = NULL;
39
u_int iSeed = time(NULL);
40
int serial = (rand_r(&iSeed) % 9999);
42
RSA *pRSA = RSA_generate_key(2048, 0x10001, NULL, NULL);
43
if ((pKey = EVP_PKEY_new())) {
44
if (!EVP_PKEY_assign_RSA(pKey, pRSA)) {
49
PEM_write_RSAPrivateKey(pOut, pRSA, NULL, NULL, 0, NULL, NULL);
51
if (!(pCert = X509_new())) {
56
X509_set_version(pCert, 2);
57
ASN1_INTEGER_set(X509_get_serialNumber(pCert), serial);
58
X509_gmtime_adj(X509_get_notBefore(pCert), 0);
59
X509_gmtime_adj(X509_get_notAfter(pCert), (long)60*60*24*days*years);
60
X509_set_pubkey(pCert, pKey);
62
pName = X509_get_subject_name(pCert);
64
const char *pLogName = getenv("LOGNAME");
65
const char *pHostName = NULL;
68
pHostName = sHost.c_str();
72
pHostName = getenv("HOSTNAME");
80
pHostName = "host.unknown";
83
CString sEmailAddr = pLogName;
85
sEmailAddr += pHostName;
87
X509_NAME_add_entry_by_txt(pName, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0);
88
X509_NAME_add_entry_by_txt(pName, "ST", MBSTRING_ASC, (unsigned char *)"SomeState", -1, -1, 0);
89
X509_NAME_add_entry_by_txt(pName, "L", MBSTRING_ASC, (unsigned char *)"SomeCity", -1, -1, 0);
90
X509_NAME_add_entry_by_txt(pName, "O", MBSTRING_ASC, (unsigned char *)"SomeCompany", -1, -1, 0);
91
X509_NAME_add_entry_by_txt(pName, "OU", MBSTRING_ASC, (unsigned char *)pLogName, -1, -1, 0);
92
X509_NAME_add_entry_by_txt(pName, "CN", MBSTRING_ASC, (unsigned char *)pHostName, -1, -1, 0);
93
X509_NAME_add_entry_by_txt(pName, "emailAddress", MBSTRING_ASC, (unsigned char *)sEmailAddr.c_str(), -1, -1, 0);
95
X509_set_subject_name(pCert, pName);
96
X509_set_issuer_name(pCert, pName);
98
if (!X509_sign(pCert, pKey, EVP_sha1())) {
104
PEM_write_X509(pOut, pCert);
109
#endif /* HAVE_LIBSSL */
111
CString CUtils::GetIP(unsigned long addr) {
113
memset((char*) szBuf, 0, 16);
115
if (addr >= (1 << 24)) {
117
ip[0] = addr >> 24 & 255;
118
ip[1] = addr >> 16 & 255;
119
ip[2] = addr >> 8 & 255;
121
sprintf(szBuf, "%lu.%lu.%lu.%lu", ip[0], ip[1], ip[2], ip[3]);
127
unsigned long CUtils::GetLongIP(const CString& sIP) {
132
i = sscanf(sIP.c_str(), "%3[0-9].%3[0-9].%3[0-9].%3[0-9]",
133
ip[0], ip[1], ip[2], ip[3]);
137
// Beware that atoi("200") << 24 would overflow and turn negative!
138
ret = atol(ip[0]) << 24;
139
ret += atol(ip[1]) << 16;
140
ret += atol(ip[2]) << 8;
141
ret += atol(ip[3]) << 0;
146
// If you change this here and in GetSaltedHashPass(),
147
// don't forget CUser::HASH_DEFAULT!
148
const CString CUtils::sDefaultHash = "sha256";
149
CString CUtils::GetSaltedHashPass(CString& sSalt) {
153
CString pass1 = CUtils::GetPass("Enter Password");
154
CString pass2 = CUtils::GetPass("Confirm Password");
156
if (!pass1.Equals(pass2, true)) {
157
CUtils::PrintError("The supplied passwords did not match");
158
} else if (pass1.empty()) {
159
CUtils::PrintError("You can not use an empty password");
161
// Construct the salted pass
162
return SaltedSHA256Hash(pass1, sSalt);
167
CString CUtils::GetSalt() {
168
return CString::RandomString(20);
171
CString CUtils::SaltedMD5Hash(const CString& sPass, const CString& sSalt) {
172
return CString(sPass + sSalt).MD5();
175
CString CUtils::SaltedSHA256Hash(const CString& sPass, const CString& sSalt) {
176
return CString(sPass + sSalt).SHA256();
179
CString CUtils::GetPass(const CString& sPrompt) {
180
PrintPrompt(sPrompt);
181
#ifdef HAVE_GETPASSPHRASE
182
return getpassphrase("");
188
bool CUtils::GetBoolInput(const CString& sPrompt, bool bDefault) {
189
return CUtils::GetBoolInput(sPrompt, &bDefault);
192
bool CUtils::GetBoolInput(const CString& sPrompt, bool *pbDefault) {
193
CString sRet, sDefault;
196
sDefault = (*pbDefault) ? "yes" : "no";
200
GetInput(sPrompt, sRet, sDefault, "yes/no");
202
if (sRet.Equals("y") || sRet.Equals("yes")) {
204
} else if (sRet.Equals("n") || sRet.Equals("no")) {
210
bool CUtils::GetNumInput(const CString& sPrompt, unsigned int& uRet, unsigned int uMin, unsigned int uMax, unsigned int uDefault) {
215
CString sDefault = (uDefault != (unsigned int) ~0) ? CString(uDefault) : "";
218
if (uMax != (unsigned int) ~0) {
219
sHint = CString(uMin) + " to " + CString(uMax);
220
} else if (uMin > 0) {
221
sHint = CString(uMin) + " and up";
225
GetInput(sPrompt, sNum, sDefault, sHint);
230
uRet = sNum.ToUInt();
232
if ((uRet >= uMin && uRet <= uMax)) {
236
CUtils::PrintError("Number must be " + sHint);
242
bool CUtils::GetInput(const CString& sPrompt, CString& sRet, const CString& sDefault, const CString& sHint) {
245
sExtra += (!sHint.empty()) ? (" (" + sHint + ")") : "";
246
sExtra += (!sDefault.empty()) ? (" [" + sDefault + "]") : "";
248
PrintPrompt(sPrompt + sExtra);
250
memset(szBuf, 0, 1024);
251
if (fgets(szBuf, 1024, stdin) == NULL) {
252
// Reading failed (Error? EOF?)
253
PrintError("Error while reading from stdin. Exiting...");
258
if (sInput.Right(1) == "\n") {
262
if (sInput.empty()) {
268
return !sRet.empty();
271
void CUtils::PrintError(const CString& sMessage) {
272
if (CDebug::StdoutIsTTY())
273
fprintf(stdout, "\033[1m\033[34m[\033[31m ** \033[34m]\033[39m\033[22m %s\n", sMessage.c_str());
275
fprintf(stdout, "%s\n", sMessage.c_str());
279
void CUtils::PrintPrompt(const CString& sMessage) {
280
if (CDebug::StdoutIsTTY())
281
fprintf(stdout, "\033[1m\033[34m[\033[33m ?? \033[34m]\033[39m\033[22m %s: ", sMessage.c_str());
283
fprintf(stdout, "[ ?? ] %s: ", sMessage.c_str());
287
void CUtils::PrintMessage(const CString& sMessage, bool bStrong) {
288
if (CDebug::StdoutIsTTY()) {
290
fprintf(stdout, "\033[1m\033[34m[\033[33m ** \033[34m]\033[39m\033[22m \033[1m%s\033[22m\n",
293
fprintf(stdout, "\033[1m\033[34m[\033[33m ** \033[34m]\033[39m\033[22m %s\n",
296
fprintf(stdout, "%s\n", sMessage.c_str());
301
void CUtils::PrintAction(const CString& sMessage) {
302
if (CDebug::StdoutIsTTY())
303
fprintf(stdout, "\033[1m\033[34m[\033[32m \033[34m]\033[39m\033[22m %s... ", sMessage.c_str());
305
fprintf(stdout, "%s... ", sMessage.c_str());
309
void CUtils::PrintStatus(bool bSuccess, const CString& sMessage) {
310
if (CDebug::StdoutIsTTY()) {
311
if (!sMessage.empty()) {
313
fprintf(stdout, "%s", sMessage.c_str());
315
fprintf(stdout, "\033[1m\033[34m[\033[31m %s \033[34m]"
316
"\033[39m\033[22m", sMessage.c_str());
320
fprintf(stdout, "\r");
323
fprintf(stdout, "\033[1m\033[34m[\033[32m ok \033[34m]\033[39m\033[22m\n");
325
fprintf(stdout, "\033[1m\033[34m[\033[31m !! \033[34m]\033[39m\033[22m\n");
329
fprintf(stdout, "%s\n", sMessage.c_str());
331
if (!sMessage.empty()) {
332
fprintf(stdout, "[ %s ]", sMessage.c_str());
335
fprintf(stdout, "\n");
342
bool CTable::AddColumn(const CString& sName) {
343
for (unsigned int a = 0; a < m_vsHeaders.size(); a++) {
344
if (m_vsHeaders[a].Equals(sName)) {
349
m_vsHeaders.push_back(sName);
350
m_msuWidths[sName] = sName.size();
355
unsigned int CTable::AddRow() {
356
// Don't add a row if no headers are defined
357
if (m_vsHeaders.empty()) {
358
return (unsigned int) -1;
361
// Add a vector with enough space for each column
362
push_back(vector<CString>(m_vsHeaders.size()));
366
bool CTable::SetCell(const CString& sColumn, const CString& sValue, unsigned int uRowIdx) {
367
if (uRowIdx == (unsigned int) ~0) {
375
unsigned int uColIdx = GetColumnIndex(sColumn);
377
if (uColIdx == (unsigned int) -1)
380
(*this)[uRowIdx][uColIdx] = sValue;
382
if (m_msuWidths[sColumn] < sValue.size())
383
m_msuWidths[sColumn] = sValue.size();
388
bool CTable::GetLine(unsigned int uIdx, CString& sLine) const {
399
for (unsigned int a = 0; a < m_vsHeaders.size(); a++) {
400
ssRet.width(GetColumnWidth(a));
401
ssRet << std::left << m_vsHeaders[a];
402
ssRet << ((a == m_vsHeaders.size() -1) ? " |" : " | ");
407
} else if ((uIdx == 0) || (uIdx == 2) || (uIdx == (size() +3))) {
411
for (unsigned int a = 0; a < m_vsHeaders.size(); a++) {
412
ssRet.width(GetColumnWidth(a));
413
ssRet << std::left << "-";
414
ssRet << ((a == m_vsHeaders.size() -1) ? "-+" : "-+-");
423
const vector<CString>& mRow = (*this)[uIdx];
427
for (unsigned int c = 0; c < m_vsHeaders.size(); c++) {
428
ssRet.width(GetColumnWidth(c));
429
ssRet << std::left << mRow[c];
430
ssRet << ((c == m_vsHeaders.size() -1) ? " |" : " | ");
441
unsigned int CTable::GetColumnIndex(const CString& sName) const {
442
for (unsigned int i = 0; i < m_vsHeaders.size(); i++) {
443
if (m_vsHeaders[i] == sName)
447
DEBUG("CTable::GetColumnIndex(" + sName + ") failed");
449
return (unsigned int) -1;
452
unsigned int CTable::GetColumnWidth(unsigned int uIdx) const {
453
if (uIdx >= m_vsHeaders.size()) {
457
const CString& sColName = m_vsHeaders[uIdx];
458
map<CString, unsigned int>::const_iterator it = m_msuWidths.find(sColName);
460
if (it == m_msuWidths.end()) {
461
// AddColumn() and SetCell() should make sure that we get a value :/
467
void CTable::Clear() {
474
CBlowfish::CBlowfish(const CString & sPassword, int iEncrypt, const CString & sIvec) {
475
m_iEncrypt = iEncrypt;
476
m_ivec = (unsigned char *)calloc(sizeof(unsigned char), 8);
479
if (sIvec.length() >= 8) {
480
memcpy(m_ivec, sIvec.data(), 8);
483
BF_set_key(&m_bkey, sPassword.length(), (unsigned char *)sPassword.data());
486
CBlowfish::~CBlowfish() {
490
//! output must be freed
491
unsigned char *CBlowfish::MD5(const unsigned char *input, u_int ilen) {
492
unsigned char *output = (unsigned char *)malloc(MD5_DIGEST_LENGTH);
493
::MD5(input, ilen, output);
497
//! returns an md5 of the CString (not hex encoded)
498
CString CBlowfish::MD5(const CString & sInput, bool bHexEncode) {
500
unsigned char *data = MD5((const unsigned char *)sInput.data(), sInput.length());
503
sRet.append((const char *)data, MD5_DIGEST_LENGTH);
505
for (int a = 0; a < MD5_DIGEST_LENGTH; a++) {
506
sRet += g_HexDigits[data[a] >> 4];
507
sRet += g_HexDigits[data[a] & 0xf];
515
//! output must be the same size as input
516
void CBlowfish::Crypt(unsigned char *input, unsigned char *output, u_int ibytes) {
517
BF_cfb64_encrypt(input, output, ibytes, &m_bkey, m_ivec, &m_num, m_iEncrypt);
521
unsigned char * CBlowfish::Crypt(unsigned char *input, u_int ibytes) {
522
unsigned char *buff = (unsigned char *)malloc(ibytes);
523
Crypt(input, buff, ibytes);
527
CString CBlowfish::Crypt(const CString & sData) {
528
unsigned char *buff = Crypt((unsigned char *)sData.data(), sData.length());
530
sOutput.append((const char *)buff, sData.length());
535
#endif // HAVE_LIBSSL