diff options
Diffstat (limited to 'ldap/synctools/passwordsync/passhand.cpp')
| -rw-r--r-- | ldap/synctools/passwordsync/passhand.cpp | 409 |
1 files changed, 354 insertions, 55 deletions
diff --git a/ldap/synctools/passwordsync/passhand.cpp b/ldap/synctools/passwordsync/passhand.cpp index 56cd80ed..32de25bf 100644 --- a/ldap/synctools/passwordsync/passhand.cpp +++ b/ldap/synctools/passwordsync/passhand.cpp @@ -1,127 +1,426 @@ -// --- BEGIN COPYRIGHT BLOCK --- -// Copyright (C) 2005 Red Hat, Inc. -// All rights reserved. -// --- END COPYRIGHT BLOCK --- - // Created: 2-8-2005 // Author(s): Scott Bridges #include "passhand.h" +#include <time.h> + +#define KEY {0xe8, 0xa7, 0x7c, 0xe2, 0x05, 0x63, 0x6a, 0x31} +#define IV {0xe4, 0xbb, 0x3b, 0xd3, 0xc3, 0x71, 0x2e, 0x58} + +void timeStamp(fstream* outFile) +{ + if(outFile->is_open()) + { + char dateBuf[32]; + char timeBuf[32]; + + _strdate(dateBuf); + _strtime(timeBuf); + *outFile << dateBuf << " " << timeBuf << ": "; + } +} PasswordHandler::PasswordHandler() { + outLog.open("./passhand.log", ios::out | ios::app); } PasswordHandler::~PasswordHandler() { + outLog.close(); } int PasswordHandler::SaveSet(char* filename) { + int result = 0; fstream outFile; list<USER_PASS_PAIR>::iterator currentPair; + strstream plainTextStream; + char* cipherTextBuf; + int usernameLen; + int passwordLen; + int plainTextLen; + int cipherTextLen; + int resultTextLen = 0; + int pairCount = userPassPairs.size(); - outFile.open(filename, ios::out | ios::binary); - - if(!outFile.is_open()) + if(outLog.is_open()) { - return -1; + timeStamp(&outLog); + outLog << "SaveSet: saving " << userPassPairs.size() << " entries to file" << endl; } + // Write usernames and passwords to a strstream + plainTextStream.write((char*)&pairCount, sizeof(pairCount)); for(currentPair = userPassPairs.begin(); currentPair != userPassPairs.end(); currentPair++) { - outFile.write((char*)¤tPair->username.Length, sizeof(currentPair->username.Length)); - outFile.write((char*)currentPair->username.Buffer, currentPair->username.Length); + // Usernames + usernameLen = strlen(currentPair->username) + 1; + plainTextStream.write((char*)&usernameLen, sizeof(usernameLen)); + plainTextStream.write(currentPair->username, usernameLen); + + // Passwords + passwordLen = strlen(currentPair->password) + 1; + plainTextStream.write((char*)&passwordLen, sizeof(passwordLen)); + plainTextStream.write(currentPair->password, passwordLen); + } + + + plainTextLen = plainTextStream.tellp() - plainTextStream.tellg(); + // cipherTextBuf length must be at least plainTextLen + 8 + cipherTextLen = plainTextLen + 8; + + cipherTextBuf = (char*)malloc(cipherTextLen); - outFile.write((char*)¤tPair->password.Length, sizeof(currentPair->password.Length)); - outFile.write((char*)currentPair->password.Buffer, currentPair->password.Length); + if(encrypt(plainTextStream.str(), plainTextLen, cipherTextBuf, cipherTextLen, &resultTextLen) != 0) + { + result = -1; + goto exit; } - // ToDo: Zero out memory. + // Write cipher text to file + outFile.open(filename, ios::out | ios::binary); + if(!outFile.is_open()) + { + result = -1; + goto exit; + } + outFile.write(cipherTextBuf, resultTextLen); + outFile.close(); + + // ToDo: zero out memory + userPassPairs.clear(); - return 0; +exit: + return result; } int PasswordHandler::LoadSet(char* filename) { + int result = 0; + int i; fstream inFile; USER_PASS_PAIR newPair; - - inFile.open(filename, ios::in | ios::binary); + strstream* plainTextStream; + char* cipherTextBuf; + char* plainTextBuf; + int usernameLen; + int passwordLen; + int plainTextLen; + int cipherTextLen; + int resultTextLen = 0; + int pairCount; + // Read in cipher text from file + inFile.open(filename, ios::in | ios::binary); if(!inFile.is_open()) { - return -1; + result = -1; + goto exit; } + // Determine file size + inFile.seekg(0, ios::end); + cipherTextLen = inFile.tellg(); + inFile.seekg(0, ios::beg); + // plainTextLen length must be at least cipherTextLen + plainTextLen = cipherTextLen; + + cipherTextBuf = (char*)malloc(cipherTextLen); + plainTextBuf = (char*)malloc(plainTextLen); - while(!inFile.eof()) + inFile.read(cipherTextBuf, cipherTextLen); + inFile.close(); + + if(decrypt(cipherTextBuf, cipherTextLen, plainTextBuf, plainTextLen, &resultTextLen) != 0) { - inFile.read((char*)&newPair.username.Length, sizeof(newPair.username.Length)); - newPair.username.Buffer = (unsigned short*)malloc(newPair.username.Length); - inFile.read((char*)newPair.username.Buffer, newPair.username.Length); - newPair.username.MaximumLength = newPair.username.Length; + result = -1; + goto exit; + } - inFile.read((char*)&newPair.password.Length, sizeof(newPair.password.Length)); - newPair.password.Buffer = (unsigned short*)malloc(newPair.password.Length); - inFile.read((char*)newPair.password.Buffer, newPair.password.Length); - newPair.password.MaximumLength = newPair.password.Length; + plainTextStream = new strstream(plainTextBuf, resultTextLen); - if(!inFile.eof()) - { - userPassPairs.push_back(newPair); - } + plainTextStream->read((char*)&pairCount, sizeof(pairCount)); + + // Read usernames and passwords from a strstream + for(i = 0; i < pairCount; i++) + { + // Username + plainTextStream->read((char*)&usernameLen, sizeof(usernameLen)); + newPair.username = (char*)malloc(usernameLen); + plainTextStream->read((char*)newPair.username, usernameLen); + + // Password + plainTextStream->read((char*)&passwordLen, sizeof(passwordLen)); + newPair.password = (char*)malloc(passwordLen); + plainTextStream->read((char*)newPair.password, passwordLen); + + userPassPairs.push_back(newPair); } - return 0; + delete plainTextStream; + + if(outLog.is_open()) + { + timeStamp(&outLog); + outLog << "LoadSet: "<< userPassPairs.size() << " entries loaded from file" << endl; + } + +exit: + return result; } -int PasswordHandler::PushUserPass(PUNICODE_STRING username, PUNICODE_STRING password) +int PasswordHandler::PushUserPass(char* username, char* password) { USER_PASS_PAIR newPair; - newPair.username.Length = username->Length; - newPair.username.Buffer = (unsigned short*)malloc(username->Length); - memcpy(newPair.username.Buffer, username->Buffer, username->Length); - newPair.username.MaximumLength = newPair.username.Length; + newPair.username = (char*)malloc(strlen(username) + 1); + strcpy(newPair.username, username); - newPair.password.Length = password->Length; - newPair.password.Buffer = (unsigned short*)malloc(password->Length); - memcpy(newPair.password.Buffer, password->Buffer, password->Length); - newPair.password.MaximumLength = newPair.password.Length; + newPair.password = (char*)malloc(strlen(password) + 1); + strcpy(newPair.password, password); userPassPairs.push_back(newPair); + if(outLog.is_open()) + { + timeStamp(&outLog); + outLog << "PushUserPass: pushed user password pair, new length " << userPassPairs.size() << endl; + } + return 0; } -int PasswordHandler::PeekUserPass(PUNICODE_STRING username, PUNICODE_STRING password) +int PasswordHandler::PeekUserPass(char* username, char* password) { + int result = 0; list<USER_PASS_PAIR>::iterator currentPair; - if(userPassPairs.size() == 0) + if(userPassPairs.size() < 1) { - return -1; + result = -1; + goto exit; } currentPair = userPassPairs.begin(); + strcpy(username, currentPair->username); + strcpy(password, currentPair->password); - username->Length = currentPair->username.Length; - username->Buffer = (unsigned short*)malloc(username->Length); - memcpy(username->Buffer, currentPair->username.Buffer, username->Length); - username->MaximumLength = username->Length; - - password->Length = currentPair->password.Length; - password->Buffer = (unsigned short*)malloc(password->Length); - memcpy(password->Buffer, currentPair->password.Buffer, password->Length); - password->MaximumLength = password->Length; + if(outLog.is_open()) + { + timeStamp(&outLog); + outLog << "PeekUserPass: current length " << userPassPairs.size() << endl; + } - return 0; +exit: + return result; } int PasswordHandler::PopUserPass() { - // ToDo: Zero out memory. + // ToDo: zero out memory. + userPassPairs.pop_front(); + if(outLog.is_open()) + { + timeStamp(&outLog); + outLog << "PopUserPass: popped user password pair, new length " << userPassPairs.size() << endl; + } + return 0; } + + +int PasswordHandler::encrypt(char* plainTextBuf, int plainTextLen, char* cipherTextBuf, int cipherTextLen, int* resultTextLen) +{ + int result = 0; + SECStatus rv1, rv2, rv3; + PK11SlotInfo* slot = NULL; + PK11SymKey* SymKey = NULL; + SECItem* SecParam = NULL; + PK11Context* EncContext = NULL; + unsigned char gKey[] = KEY; + unsigned char gIV[] = IV; + PK11SymKey* key = NULL; + SECItem keyItem; + SECItem ivItem; + CK_MECHANISM_TYPE cipherMech = CKM_DES_CBC_PAD; + int offset; + int tempTextLen; + + // Initialize NSS + rv1 = NSS_NoDB_Init("."); + if(rv1 != SECSuccess) + { + result = PR_GetError(); + goto exit; + } + + // Get a key slot + slot = PK11_GetInternalKeySlot(); + if(slot == NULL) + { + result = PR_GetError(); + goto exit; + } + + // Generate a symmetric key + keyItem.data = gKey; + keyItem.len = sizeof(gKey); + SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL); + if(SymKey == NULL) + { + result = PR_GetError(); + goto exit; + } + + // Set up the PKCS11 encryption paramters + ivItem.data = gIV; + ivItem.len = sizeof(gIV); + SecParam = PK11_ParamFromIV(cipherMech, &ivItem); + if(SecParam == NULL) + { + if(SymKey != NULL) + { + PK11_FreeSymKey(SymKey); + } + result = PR_GetError(); + goto exit; + } + + // ToDo: check parameters + + + // Encrypt + tempTextLen = 0; + EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, SymKey, SecParam); + rv2 = PK11_CipherOp(EncContext, (unsigned char*)cipherTextBuf, &tempTextLen, cipherTextLen, (unsigned char*)plainTextBuf, plainTextLen); + offset = tempTextLen; + rv3 = PK11_DigestFinal(EncContext, (unsigned char*)cipherTextBuf + offset, (unsigned int*)&tempTextLen, cipherTextLen - offset); + *resultTextLen = offset + tempTextLen; + + // Clean up + PK11_DestroyContext(EncContext, PR_TRUE); + PK11_FreeSymKey(SymKey); + SECITEM_FreeItem(SecParam, PR_TRUE); + + if((rv2 != SECSuccess) || (rv2 != SECSuccess)) + { + result = PR_GetError(); + goto exit; + } + +exit: + if(outLog.is_open()) + { + if(result == 0) + { + timeStamp(&outLog); + outLog << "encrypt: success" << endl; + } + else + { + timeStamp(&outLog); + outLog << "encrypt: failure" << endl; + } + } + + return result; +} + +int PasswordHandler::decrypt(char* cipherTextBuf, int cipherTextLen, char* plainTextBuf, int plainTextLen, int* resultTextLen) +{ + int result = 0; + SECStatus rv1, rv2, rv3; + PK11SlotInfo* slot = NULL; + PK11SymKey* SymKey = NULL; + SECItem* SecParam = NULL; + PK11Context* EncContext = NULL; + unsigned char gKey[] = KEY; + unsigned char gIV[] = IV; + PK11SymKey* key = NULL; + SECItem keyItem; + SECItem ivItem; + CK_MECHANISM_TYPE cipherMech = CKM_DES_CBC_PAD; + int offset; + int tempTextLen; + + // Initialize NSS + rv1 = NSS_NoDB_Init("."); + if(rv1 != SECSuccess) + { + result = PR_GetError(); + goto exit; + } + + // Get a key slot + slot = PK11_GetInternalKeySlot(); + if(slot == NULL) + { + result = PR_GetError(); + goto exit; + } + + // Generate a symmetric key + keyItem.data = gKey; + keyItem.len = sizeof(gKey); + SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL); + if(SymKey == NULL) + { + result = PR_GetError(); + goto exit; + } + + // Set up the PKCS11 encryption paramters + ivItem.data = gIV; + ivItem.len = sizeof(gIV); + SecParam = PK11_ParamFromIV(cipherMech, &ivItem); + if(SecParam == NULL) + { + if(SymKey != NULL) + { + PK11_FreeSymKey(SymKey); + } + result = PR_GetError(); + goto exit; + } + + // ToDo: check parameters + + + // Decrypt + tempTextLen = 0; + EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_DECRYPT, SymKey, SecParam); + rv2 = PK11_CipherOp(EncContext, (unsigned char*)plainTextBuf, &tempTextLen, plainTextLen, (unsigned char*)cipherTextBuf, cipherTextLen); + offset = tempTextLen; + rv3 = PK11_DigestFinal(EncContext, (unsigned char*)plainTextBuf + offset, (unsigned int*)&tempTextLen, plainTextLen - offset); + *resultTextLen = offset + tempTextLen; + + // Clean up + PK11_DestroyContext(EncContext, PR_TRUE); + PK11_FreeSymKey(SymKey); + SECITEM_FreeItem(SecParam, PR_TRUE); + + if((rv2 != SECSuccess) || (rv2 != SECSuccess)) + { + result = PR_GetError(); + goto exit; + } + +exit: + if(outLog.is_open()) + { + if(result == 0) + { + timeStamp(&outLog); + outLog << "decrypt: success" << endl; + } + else + { + timeStamp(&outLog); + outLog << "decrypt: failure" << endl; + } + } + + return result; +} |
