232 lines
6.7 KiB
C++
232 lines
6.7 KiB
C++
#include <iostream>
|
|
#include "dns.h"
|
|
|
|
// NSPR include files
|
|
#include <prerror.h>
|
|
#include <prinit.h>
|
|
#include <prnetdb.h>
|
|
#include <prthread.h>
|
|
#include <nspr.h>
|
|
|
|
// NSS include files
|
|
#include <nss.h>
|
|
#include <pk11pub.h>
|
|
#include <secmod.h>
|
|
#include <ssl.h>
|
|
#include <sslproto.h>
|
|
#include <prio.h>
|
|
|
|
// Qt-dependent Include Files, should come after NSPR / NSS
|
|
#include "ui.h"
|
|
#include "irc.h"
|
|
|
|
NSSInitContext *nssContext;
|
|
SECMODModule *builtInRootsMod;
|
|
|
|
// PK11 Password Function typedef
|
|
typedef char *(*PK11PasswordFunc)(
|
|
PK11SlotInfo *slot,
|
|
PRBool retry,
|
|
void *arg);
|
|
|
|
void init() {
|
|
// NSPR Init
|
|
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
|
|
|
|
// NSS Init
|
|
nssContext =
|
|
NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL, NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
|
|
|
|
if (nssContext == NULL) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "NSSInitContext failed: Error code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
// Ciphers to enable
|
|
static const PRUint16 goodCiphers[] = {
|
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
SSL_NULL_WITH_NULL_NULL // Sentinel value
|
|
};
|
|
|
|
PRBool foundGoodCipher = PR_FALSE;
|
|
for (const PRUint16 *p = goodCiphers; *p != SSL_NULL_WITH_NULL_NULL; ++p) {
|
|
PRInt32 policy;
|
|
if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error: Policy for cipher %u: error %d: %s\n",
|
|
(unsigned) *p, err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
if (policy == SSL_ALLOWED) {
|
|
// Policy allowed this cipher choice
|
|
// fprintf(stderr, "Info: found cipher %x\n", (unsigned) *p);
|
|
foundGoodCipher = PR_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!foundGoodCipher) {
|
|
if (NSS_SetDomesticPolicy() != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error: NSS_SetDomesticPolicy: error %d: %s\n",
|
|
err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
// Initialize trusted certificate store
|
|
char module_name[] = "library=libnssckbi.so name=\"Root Certs\"";
|
|
builtInRootsMod = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE);
|
|
if (builtInRootsMod == NULL || !builtInRootsMod->loaded) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error: Loading built in roots module failed, code %d: %s\n",
|
|
err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void runIrc(void* args) {
|
|
irc* ircInst = (irc *) args;
|
|
ircInst->run();
|
|
}
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
init();
|
|
|
|
PRNetAddr theAddr;
|
|
LookupName((char *) "buyvm.theoks.net", &theAddr);
|
|
|
|
char ipString[80];
|
|
PRStatus status = PR_NetAddrToString(&theAddr, ipString, 75);
|
|
if (status == PR_FAILURE) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error: Converting PRNetAddr to string %d: %s\n",
|
|
err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
PRFileDesc *tcpSocket = PR_OpenTCPSocket(PR_AF_INET6);
|
|
PRFileDesc *model = PR_NewTCPSocket();
|
|
theAddr.ipv6.port = PR_htons(6697);
|
|
theAddr.raw.family = PR_AF_INET6;
|
|
PRFileDesc *nssSocket;
|
|
PRFileDesc *sslModel = SSL_ImportFD(NULL, model);
|
|
|
|
// Set SSL options
|
|
if(SSL_OptionSet(sslModel, SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error disabling SSLv2, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
if(SSL_OptionSet(sslModel, SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error disabling SSLv2 compatible hello, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
if(SSL_OptionSet(sslModel, SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error disabling SSLv3, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
if(SSL_OptionSet(sslModel, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error enabling TLS, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
// Open base TCP connection
|
|
if(PR_Connect(tcpSocket, &theAddr, PR_INTERVAL_NO_TIMEOUT) != PR_SUCCESS) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error opening TCP connection, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
// Wrap TCP connection with SSL layer
|
|
nssSocket = SSL_ImportFD(sslModel, tcpSocket);
|
|
if(nssSocket == nullptr) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error importing TCP Socket to NSS, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
PR_Close(model);
|
|
|
|
// Do the handshake
|
|
if(SSL_ResetHandshake(nssSocket, PR_FALSE) != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Failed resetting handshake, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
if(SSL_SetURL(nssSocket, "buyvm.theoks.net") != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error setting domain for connection, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
if(SSL_ForceHandshake(nssSocket) != SECSuccess) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error forcing handshake, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
ui *uiInstance = new ui(argc, argv);
|
|
|
|
char netBuf[8192];
|
|
|
|
irc *ircInst = new irc(nssSocket, "OKSnet", uiInstance);
|
|
|
|
PRThread* ircThread = PR_CreateThread(PR_SYSTEM_THREAD, runIrc, ircInst, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
|
|
PR_JOINABLE_THREAD, 0);
|
|
|
|
// TEMP: Retreiving test file from HTTP daemon w/ TLS
|
|
// Send the request
|
|
snprintf(netBuf, sizeof(netBuf), "GET /junk/testfile.txt HTTP/1.0\r\nHost: buyvm.theoks.net\r\nUser-Agent: oksirc-testing\r\n\r\n");
|
|
PRInt32 ret = PR_Write(nssSocket, netBuf, strlen(netBuf));
|
|
if(ret < 0) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error writing data to socket, code %d: %s\n", err, PR_ErrorToName(err));
|
|
uiInstance->mainLog->appendPlainText("Error writing data to socket, see stderr.");
|
|
}
|
|
|
|
// Get the response
|
|
ret = PR_Read(nssSocket, netBuf, sizeof(netBuf));
|
|
if(ret < 0) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error reading data from socket, code %d: %s\n", err, PR_ErrorToName(err));
|
|
uiInstance->mainLog->appendPlainText("Error writing data from socket, see stderr.");
|
|
} else {
|
|
printf("%s\n", netBuf);
|
|
uiInstance->mainLog->appendPlainText(netBuf);
|
|
}
|
|
|
|
if(PR_Shutdown(nssSocket, PR_SHUTDOWN_BOTH) != PR_SUCCESS) {
|
|
const PRErrorCode err = PR_GetError();
|
|
fprintf(stderr, "Error shutting down socket, code %d: %s\n", err, PR_ErrorToName(err));
|
|
exit(1);
|
|
}
|
|
|
|
PR_Close(nssSocket);
|
|
|
|
char messageBuf[1024];
|
|
sprintf(messageBuf, "Found IP Address: %s", ipString);
|
|
uiInstance->mainLog->appendPlainText(messageBuf);
|
|
|
|
fprintf(stderr, "argc = %d, strlen(argv[0]) = %d\n", argc, (int)strlen(argv[0]));
|
|
|
|
|
|
int qAppRetCode = uiInstance->exec();
|
|
|
|
// Shutdown of NSS
|
|
SECMOD_DestroyModule(builtInRootsMod);
|
|
NSS_ShutdownContext(nssContext);
|
|
|
|
return qAppRetCode;
|
|
}
|
|
|