/***********************************************\ * Common functions (simple SSL toolkit) * * (C) 2005 Digithell, Inc. (Pavel Strachota) * * file: service.cc * \***********************************************/ #include #include #include #include "include/strings.h" #include "service.h" using namespace std; // the certificate verification depth (common for client and server) const int VERIFY_DEPTH=3; static const int PRNG_seed_length = 1024; int Seed_PRNG() /* seed the SSL cryptographic PseudoRandom Number Generator: return codes: 0 success -1 error Seeding the PRNG is not a trivial task as it is difficult to gather enough independent information that can be considered to be random. In this simple program, we will use the UNIX device /dev/urandom , which however won't be available on other OS like Windows. One had better use /dev/random which provides more entropy in the random information, but its "contents" are not always available and depend on user actions (mouse movement etc...). NOTE: OpenSSL seeds the PRNG automatically using /dev/urandom, thus this is here just for completeness. At least, we get an error message when the PRNG could not be seeded at all. */ { if (RAND_load_file("/dev/urandom", PRNG_seed_length)>0) return(0); // returns number of bytes loaded => nonzero is success return(1); } void ReportError(char * error_string, bool is_fatal) { if(is_fatal) { cerr << "Fatal error: "<< error_string << endl; exit(1); } else cerr << "Error: "<< error_string << endl; } void ReportSSLError(char * error_string, bool is_fatal) // reports an user error message followed by the SSL error queue listing. // (call this after a call to an OpenSSL function that caused an error. { cerr << (is_fatal?"Fatal error: ":"Error: ") << error_string << endl << " ----- OpenSSL error report follows -----" << endl; ERR_print_errors_fp(stderr); cerr << " ----------------------------------------" << endl; if(is_fatal) exit(1); } void InitSSL() { SSL_load_error_strings(); // human-readable error messages SSL_library_init(); // initialize library if(Seed_PRNG()) ReportError("PRNG could not be seeded properly.",false); } int LoadPassphrase(char * buf, int size, int flag, void * userdata) /* loads the pass phrase needed for the private key from file. (the whole first line is treated as the passphrase) This is an SSL callback function. The password length in bytes must be returned !!! */ { char buffer[1024]; int length; fstream passwdf; passwdf.open(PASSFILE,ios::in); if(!passwdf) ReportError("Could not open the passphrase file."); passwdf.getline(buffer,sizeof(buffer)); passwdf.close(); cout << "SSL Callback: Loaded private key password from file." << endl; length=len(buffer); if(length >= size) ReportError("The pass phrase is too long."); set(buf,buffer); return(length); } int VerifyCert(int verify_status, X509_STORE_CTX * store) // the certificate verification filter callback. This is called for every certificate // in the certificate chain during verification. { char data[256]; X509 *cert = X509_STORE_CTX_get_current_cert(store); cout << "/------- Verifying certificate: -------\\" << endl; X509_NAME_oneline(X509_get_issuer_name(cert), data, 256); cout << "Issuer: " << data << endl; X509_NAME_oneline(X509_get_subject_name(cert), data, 256); cout << "Subject: " << data << endl; if(!verify_status) { int depth = X509_STORE_CTX_get_error_depth(store); int err = X509_STORE_CTX_get_error(store); cout << "Error verifying certificate at depth" << depth << endl; cout << "Error no. " << err << X509_verify_cert_error_string(err) << endl; } cout << "\\--------------------------------------/" << endl; return(verify_status); }