#include #include #include #include #include "rsloginhandler.h" #include "util/rsdir.h" #if defined(UBUNTU) || defined(__FreeBSD__) #include GnomeKeyringPasswordSchema my_schema = { GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD, { { "RetroShare SSL Id", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, { NULL, (GnomeKeyringAttributeType)0 } } }; #endif #ifdef __APPLE__ /* OSX Headers */ #include #include #endif /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ /* WINDOWS STRUCTURES FOR DPAPI */ #ifndef WINDOWS_SYS /* UNIX */ #include #else /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ #include #include #include /* class CRYPTPROTECT_PROMPTSTRUCT; */ #ifdef __cplusplus extern "C" { #endif #ifdef WINDOWS_SYS #if defined(__CYGWIN__) typedef struct _CRYPTPROTECT_PROMPTSTRUCT { DWORD cbSize; DWORD dwPromptFlags; HWND hwndApp; LPCWSTR szPrompt; } CRYPTPROTECT_PROMPTSTRUCT, *PCRYPTPROTECT_PROMPTSTRUCT; #endif #endif /* definitions for the two functions */ __declspec (dllimport) extern BOOL WINAPI CryptProtectData( DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptionalEntropy, PVOID pvReserved, /* PVOID prompt, */ /* CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, */ CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut ); __declspec (dllimport) extern BOOL WINAPI CryptUnprotectData( DATA_BLOB* pDataIn, LPWSTR* ppszDataDescr, DATA_BLOB* pOptionalEntropy, PVOID pvReserved, /* PVOID prompt, */ /* CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, */ CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut ); #ifdef __cplusplus } #endif #endif bool RsLoginHandler::getSSLPassword(const std::string& ssl_id,bool enable_gpg_ask_passwd,std::string& ssl_passwd) { // First, see if autologin is available // if(tryAutoLogin(ssl_id,ssl_passwd)) return true ; // If we're not expecting to enter a passwd (e.g. test for autologin before // display of the login window), safely respond false. // if(!enable_gpg_ask_passwd) return false ; return getSSLPasswdFromGPGFile(ssl_id,ssl_passwd) ; } bool RsLoginHandler::tryAutoLogin(const std::string& ssl_id,std::string& ssl_passwd) { std::cerr << "RsTryAutoLogin()" << std::endl; /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS /* UNIX */ #if defined(UBUNTU) || defined(__FreeBSD__) gchar *passwd = NULL; std::cerr << "Using attribute: " << ssl_id << std::endl; if( gnome_keyring_find_password_sync(&my_schema, &passwd,"RetroShare SSL Id",ssl_id.c_str(),NULL) == GNOME_KEYRING_RESULT_OK ) { std::cerr << "Got SSL passwd ********************" /*<< passwd*/ << " from gnome keyring" << std::endl; ssl_passwd = std::string(passwd); return true ; } else { std::cerr << "Could not get passwd from gnome keyring" << std::endl; return false ; } #else /******************** OSX KeyChain stuff *****************************/ #ifdef __APPLE__ std::cerr << "RsTryAutoLogin() OSX Version" << std::endl; //Call SecKeychainFindGenericPassword to get a password from the keychain: void *passwordData = NULL; UInt32 passwordLength = 0; const char *userId = ssl_id.c_str(); UInt32 uidLength = strlen(ssl_id.c_str()); SecKeychainItemRef itemRef = NULL; OSStatus status = SecKeychainFindGenericPassword ( NULL, // default keychain 10, // length of service name "Retroshare", // service name uidLength, // length of account name userId, // account name &passwordLength, // length of password &passwordData, // pointer to password data &itemRef // the item reference ); std::cerr << "RsTryAutoLogin() SecKeychainFindGenericPassword returned: " << status << std::endl; if (status != 0) { std::cerr << "RsTryAutoLogin() Error " << std::endl; /* error */ if (status == errSecItemNotFound) { //Is password on keychain? std::cerr << "RsTryAutoLogin() Error - Looks like password is not in KeyChain " << std::endl; } } else { std::cerr << "RsTryAutoLogin() Password found on KeyChain! " << std::endl; /* load up password to correct location */ ssl_passwd.clear(); ssl_passwd.insert(0, (char*)passwordData, passwordLength); } //Free the data allocated by SecKeychainFindGenericPassword: SecKeychainItemFreeContent ( NULL, //No attribute data to release passwordData //Release data buffer allocated by SecKeychainFindGenericPassword ); if (itemRef) CFRelease(itemRef); return (status == 0); /******************** OSX KeyChain stuff *****************************/ #else /* UNIX, but not UBUNTU or APPLE */ FILE* helpFile = RsDirUtil::rs_fopen(getAutologinFileName(ssl_id).c_str(), "r"); if(helpFile == NULL){ std::cerr << "\nFailed to open help file\n" << std::endl; return false; } /* decrypt help */ int c ; std::string passwd ; while( (c = getc(helpFile)) != EOF ) passwd += (char)c ; const int DAT_LEN = passwd.length(); const int KEY_DAT_LEN = RsInitConfig::load_cert.length(); unsigned char* key_data = (unsigned char*)RsInitConfig::load_cert.c_str(); unsigned char* indata = new unsigned char[DAT_LEN]; unsigned char* outdata = new unsigned char[DAT_LEN]; for(int i=0;iencryptTextToFile(ssl_passwd, getSSLPasswdFileName(ssl_id))) { std::cerr << "Encrypting went ok !" << std::endl; ok= true ; } else { std::cerr << "Encrypting went wrong !" << std::endl; ok= false ; } return ok ; } bool RsLoginHandler::getSSLPasswdFromGPGFile(const std::string& ssl_id,std::string& sslPassword) { // Let's read the password from an encrypted file // Let's check if there's a ssl_passpharese_file that we can decrypt with PGP // FILE *sslPassphraseFile = RsDirUtil::rs_fopen(getSSLPasswdFileName(ssl_id).c_str(), "r"); if (sslPassphraseFile == NULL) { std::cerr << "No password provided, and no sslPassphraseFile : " << getSSLPasswdFileName(ssl_id).c_str() << std::endl; return 0; } fclose(sslPassphraseFile); std::cerr << "opening sslPassphraseFile : " << getSSLPasswdFileName(ssl_id).c_str() << std::endl; std::string plain ; if (AuthGPG::getAuthGPG()->decryptTextFromFile(plain,getSSLPasswdFileName(ssl_id))) { std::cerr << "Decrypting went ok !" << std::endl; sslPassword = plain ; std::cerr << "sslpassword: " << "******************** (length = " << sslPassword.length() << ")" << std::endl; return sslPassword.length() > 0 ; } else { sslPassword = "" ; std::cerr << "Error : decrypting went wrong !" << std::endl; return false; } } std::string RsLoginHandler::getSSLPasswdFileName(const std::string& /*ssl_id*/) { return RsInit::RsConfigKeysDirectory() + "/" + "ssl_passphrase.pgp"; } std::string RsLoginHandler::getAutologinFileName(const std::string& /*ssl_id*/) { return RsInit::RsConfigKeysDirectory() + "/" + "help.dta" ; }