/* * Uses the currently set locale to read a pre-defined file and then compares * the output with a reference file that is read with the UTF-8 functions. * These should of course be the same for this test to be successful. * * What encoded file should be read for a certain locale, and which reference file * should be used to test against is handled with a configurations file * that has the name "scxfile_test-locale-map.txt" that consists of multiple * lines like this: * <name of locale> <name of encoded file> <name of reference file> * * The "encoded file" is read with named locale active into an array. * The reference file is read with our own UTF-8 decoding routines, into * another array. These two should result in exactly the same result for this * test to be successful. * * If you're writing a new encoded or reference file, you'll at some point need * to see exactly what it contains byte-for-byte. The this command will be * useful: "od -t x1 <filename>". * * If the current locale is not found in the configuration file, this results * in a warning. */ void TestReadFilesWithPresetCharacterConversion() { bool found = false; std::wifstream locmap("./testfiles/scxfile_test-locale-map.txt"); wstring locName, encodedFileName, referenceFileName; // This is the name of the currently selected locale for the Ctype facet wstring presetLocaleName(SCXLocaleContext::GetCtypeName()); if (presetLocaleName == L"C" || presetLocaleName == L"POSIX") { SCXUNIT_WARNING(L"Testing with C/POSIX locale is meaningless."); } wcout << "\nTesting preset locale " << presetLocaleName << endl; while (locmap) { locmap >> locName >> encodedFileName >> referenceFileName; // Diagnostic output // wcout << "Name " << locName << endl; // wcout << "File " << encodedFileName << endl; // wcout << "File " << referenceFileName << endl; if (locName == presetLocaleName) { // wcout << L"found " << locName << endl; found = true; break; } } if (!found) { SCXUNIT_WARNING(L"Can't find preset locale " + presetLocaleName + L" in locale-map.txt. Please add it and test again."); return; } SCXFilePath encodedFileFP; encodedFileFP.SetDirectory(L"./testfiles/"); encodedFileFP.SetFilename(encodedFileName); SCXFilePath referenceFileFP; referenceFileFP.SetDirectory(L"./testfiles/"); referenceFileFP.SetFilename(referenceFileName); SCXStream::NLFs nlfs; vector<wstring> localLines; vector<wstring> utf8Lines; SCXFile::ReadAllLines(encodedFileFP, localLines, nlfs); SCXFile::ReadAllLinesAsUTF8(referenceFileFP, utf8Lines, nlfs); CPPUNIT_ASSERT_MESSAGE("Failure for preset locale " + locale().name(), localLines == utf8Lines); }
/** Constructor \param[in] id Identifier for the appserver (= install path for the appserver configuration) \param[in] homePath Root install path for the application server \param[in] deps Dependency instance to use */ TomcatAppServerInstance::TomcatAppServerInstance( wstring id, wstring homePath, SCXHandle<TomcatAppServerInstancePALDependencies> deps) : AppServerInstance(id, APP_SERVER_TYPE_TOMCAT), m_deps(deps) { SCXFilePath installPath; SCXFilePath homeFilePath; installPath.SetDirectory(id); SetId(installPath.Get()); m_diskPath = GetId(); homeFilePath.SetDirectory(homePath); m_homePath = homeFilePath.Get(); SCX_LOGTRACE(m_log, wstring(L"TomcatAppServerInstance default constructor - ").append(GetId())); }
/** Read the nodemanager.domains file to get a list of the WebLogic 10g domains associated with the installation. Note: this file is located up the tree in a 'well-known' location. i.e. /opt/Oracle/Middleware/wlserver_10.3/common/nodemanager/nodemanager.domains Example: #Domains and directories created by Configuration Wizard #Tue Apr 12 15:23:12 PDT 2011 base_domain=/opt/Oracle/Middleware/user_projects/domains/base_domain \param[in] nodemanagerDomains File object of the text file to open. \param[out] domains vector that will be populated with list of discovered domains. */ void WebLogicFileReader::ReadNodemanagerDomains( const SCXFilePath& nodemanagerDomains, vector<SCXFilePath>& domains) { string content; try { /* * Parse the INI file. * * After a '#', assume the rest of the line is a comment. * The file should consist of name/value pairs seperated * by an '='. */ SCXHandle<istream> reader = OpenNodemanagerDomains(nodemanagerDomains.Get()); while (SCXStream::IsGood(*reader)) { string buffer; getline(*reader, buffer); size_t effectiveEnd = buffer.size(); size_t commentLocation = buffer.find(INI_COMMENT); if (string::npos != commentLocation) { effectiveEnd = commentLocation; } size_t delimiterLocation = buffer.find(INI_DELIMITER); if (string::npos != delimiterLocation) { string narrowPath = buffer.substr(delimiterLocation + 1); wstring widePath = StrFromUTF8(narrowPath); SCXFilePath domainPath; domainPath.SetDirectory(widePath); domains.push_back(domainPath); } } } catch (SCXFilePathNotFoundException&) { SCX_LOGERROR(m_log, wstring(L"WebLogicFileReader::ReadNodemanagerDomains() - "). append(m_installationPath).append(L" - Could not find file: "). append(nodemanagerDomains.Get())); } catch (SCXUnauthorizedFileSystemAccessException&) { SCX_LOGERROR(m_log, wstring(L"WebLogicFileReader::ReadNodemanagerDomains() - "). append(m_installationPath).append(L" - not authorized to open file: "). append(nodemanagerDomains.Get())); } }
/** From the necessary file, read the domains and return a unique list of potential domains. */ vector<SCXFilePath> WebLogicFileReader::GetDomains() { SCX_LOGTRACE(m_log, L"WebLogicFileReader::GetDomains"); vector<SCXFilePath> domains; // Logic necessary for reading WebLogic 11g domains SCXFilePath domainRegistryXml; domainRegistryXml.SetDirectory(m_installationPath); domainRegistryXml.SetFilename( WEBLOGIC_DOMAIN_REGISTRY_XML_FILENAME); if (DoesDomainRegistryXmlExist(domainRegistryXml)) { ReadDomainRegistryXml(domainRegistryXml, domains); } // Logic necessary for reading WebLogic 10g domains SCXFilePath nodemanagerDomains; nodemanagerDomains.SetDirectory(m_installationPath); nodemanagerDomains.AppendDirectory(WEBLOGIC_NODEMANAGER_DOMAINS_DIRECTORY); nodemanagerDomains.SetFilename(WEBLOGIC_NODEMANAGER_DOMAINS_FILENAME); if (DoesNodemanagerDomainsExist(nodemanagerDomains)) { ReadNodemanagerDomains(nodemanagerDomains, domains); } // There may be duplicates in the list, it is necessary to // sort the list of domains and return only the unique instances. sort(domains.begin(), domains.end(), SortPath()); vector<SCXFilePath>::iterator tmp = unique(domains.begin(), domains.end()); domains.resize(tmp-domains.begin()); SCX_LOGTRACE(m_log, wstring(L"WebLogicFileReader::GetDomains() - "). append(L"Found ").append(StrFrom(domains.size())).append(L" domain(s)")); return domains; }
/** Read a simple XML file to find the locations of the domains for this WebLogic 11g R1 installation. Example: <?xml version="1.0" encoding="UTF-8"?> <domain-registry xmlns="http://xmlns.oracle.com/weblogic/domain-registry"> <domain location="/opt/Oracle/Middleware/user_projects/domains/base_domain"/> </domain-registry> \param[in] domainRegistryXml File object of the XML file to open. \param[out] domains vector that will contain the list of discovered domains. */ void WebLogicFileReader::ReadDomainRegistryXml( const SCXFilePath& domainRegistryXml, vector<SCXFilePath>& domains) { string xml; try { SCXHandle<istream> reader = OpenDomainRegistryXml(domainRegistryXml.Get()); GetStringFromStream(reader, xml); XElementPtr domainRegistryNode; XElement::Load(xml, domainRegistryNode); if (domainRegistryNode->GetName() == WEBLOGIC_DOMAIN_REGISTRY_XML_NODE) { XElementList domainNodes; domainRegistryNode->GetChildren(domainNodes); for (size_t index = 0; index < domainNodes.size(); ++index) { string location; if (domainNodes[index]->GetName() == WEBLOGIC_DOMAIN_XML_NODE && domainNodes[index]->GetAttributeValue(WEBLOGIC_LOCATION_XML_ATTRIBUTE, location)) { wstring wideLocation = StrFromUTF8(location); SCXFilePath domainPath; domainPath.SetDirectory(wideLocation); domains.push_back(domainPath); } } } } catch (SCXFilePathNotFoundException&) { SCX_LOGERROR(m_log, wstring(L"WebLogicFileReader::ReadDomainRegistryXml() - "). append(m_installationPath).append(L" - Could not find file: "). append(domainRegistryXml.Get())); } catch (SCXUnauthorizedFileSystemAccessException&) { SCX_LOGERROR(m_log, wstring(L"WebLogicFileReader::ReadDomainRegistryXml() - "). append(m_installationPath).append(L" - not authorized to open file: "). append(domainRegistryXml.Get())); } catch (XmlException&) { SCX_LOGERROR(m_log, wstring(L"WebLogicFileReader::ReadDomainRegistryXml() - "). append(m_installationPath).append(L" - Could not load XML from file: "). append(domainRegistryXml.Get())); } }
//! Search for an existing filename using case insensitive comparision SCXFilePath SearchExistingFilename(const wstring &directory, const wstring &name) { vector<SCXCoreLib::SCXFilePath> files = SCXDirectory::GetFiles(directory); for (size_t nr = 0; nr < files.size(); nr++) { if (StrCompare(files[nr].GetFilename(), name, true) == 0) { return files[nr]; } } // No existing name found, return the original path SCXFilePath original; original.SetDirectory(directory); original.SetFilename(name); return original; }
void TestFileSystemInfo_SetAttributes() { // Improve code coverage on SCXFileSystemInfo #if defined(SCX_UNIX) SCXFileSystem::Attribute readable = SCXFileSystem::eUserRead; SCXFileSystem::Attribute writable = SCXFileSystem::eUserWrite; #else SCXFileSystem::Attribute readable = SCXFileSystem::eReadable; SCXFileSystem::Attribute writable = SCXFileSystem::eWritable; #endif SCXFileInfo fi(m_path1); SCXFileSystem::Attributes attrRO, attrRW; attrRO.insert(readable); attrRW.insert(readable); attrRW.insert(writable); // Test SCXFileSystemInfo::SetAttributes and SCXFileSystemInfo::isWritable (and make sure it's right!) fi.SetAttributes(attrRO); CPPUNIT_ASSERT(! fi.isWritable()); CPPUNIT_ASSERT(fi.GetAttributes().count(writable) == 0); fi.SetAttributes(attrRW); fi.Refresh(); CPPUNIT_ASSERT(fi.isWritable()); CPPUNIT_ASSERT(fi.GetAttributes().count(writable) != 0); // Create a new "junk" object to test directory - test SCXFileSystemInfo::GetDirectoryPath // (Use operator += to add a filename to pick up an additional test of that operator) SCXFilePath fbad = fi.GetDirectoryPath(); fbad += L"file"; fbad += L".txt"; fbad.SetDirectory(L"/bogus/directory/path"); #if defined(SCX_UNIX) CPPUNIT_ASSERT(fbad.GetDirectory() == L"/bogus/directory/path/"); CPPUNIT_ASSERT(fbad.Get() == L"/bogus/directory/path/file.txt"); #else CPPUNIT_ASSERT(fbad.GetDirectory() == L"\\bogus\\directory\\path\\"); CPPUNIT_ASSERT(fbad.Get() == L"\\bogus\\directory\\path\\file.txt"); #endif // Original path was created without directory - test SCXFileSystemInfo::GetOriginalPath CPPUNIT_ASSERT(fi.GetOriginalPath().GetDirectory() == L""); CPPUNIT_ASSERT(fi.GetFullPath().GetDirectory() != L""); }
/** Constructor \param[in] cell The WebSphere Cell Name \param[in] node The WebSphere Node Name \param[in] profile The WebSphete Profile Name \param[in] installDir The folder where WebSphere is installed \param[in] server The WebSphere Server Name \param[in] deps Dependency instance to use */ WebSphereAppServerInstance::WebSphereAppServerInstance( wstring installDir, wstring cell, wstring node, wstring profile, wstring server, SCXHandle<WebSphereAppServerInstancePALDependencies> deps) : AppServerInstance(installDir, APP_SERVER_TYPE_WEBSPHERE), m_deps(deps) { SCXFilePath installPath; installPath.SetDirectory(installDir); m_diskPath = installPath.Get(); m_cell = cell; m_node = node; m_profile = profile; m_server = server; wstring id = profile; SetId(id.append(L"-").append(cell).append(L"-").append(node).append(L"-").append(server)); SCX_LOGTRACE(m_log, wstring(L"WebSphereAppServerInstance default constructor - ").append(GetId())); }
/** From the necessary XML configuration file, read information about the known instances. The file should be: ${Install}/${Domain}/config/config.xml \param[in] domains List of domains to find instances for \param[out] instances vector to add instances to */ void WebLogicFileReader::GetInstances( const SCXFilePath& domain, vector<SCXHandle<AppServerInstance> >& instances) { SCXFilePath configXml; configXml.SetDirectory(domain.Get()); configXml.AppendDirectory(WEBLOGIC_CONFIG_DIRECTORY); configXml.Append(WEBLOGIC_CONFIG_FILENAME); if (DoesConfigXmlExist(configXml)) { SCX_LOGTRACE(m_log, wstring(L"WebLogicFileReader::GetInstances() - "). append(L"Reading ").append(configXml.Get())); ReadConfigXml(domain, configXml, instances); } else { SCX_LOGTRACE(m_log, wstring(L"WebLogicFileReader::GetInstances() - "). append(L"Expected configuration file '"). append(configXml.Get()).append(L"' does not exist.")); } }
/** Read a simple XML file to find the locations of the both the Admin and Managed servers for a WebLogic 11g R1 installation. Example: <?xml version="1.0" encoding="UTF-8"?> <domain ...> <name>base_domain</name> <domain-version>10.3.2.0</domain-version> <security-configuration ...> ... </security-configuration> <server> <name>AdminServer</name> <ssl> <name>AdminServer</name> <enabled>true</enabled> <listen-port>7012</listen-port> </ssl> <machine>new_UnixMachine_1</machine> <listen-port>7011</listen-port> <listen-address/> </server> <server> <name>new_ManagedServer_1</name> <ssl> <name>new_ManagedServer_1</name> <enabled>true</enabled> <listen-port>7513</listen-port> </ssl> <machine>new_UnixMachine_1</machine> <listen-port>7013</listen-port> <listen-address/> </server> <embedded-ldap> <name>base_domain</name> <credential-encrypted>{AES}RVX+Cadq8XJ5EvV7/1Ta2qGZrJlxve6t5CEa2A9euGUkYOMDTAwAqytymqDBS00Q</credential-encrypted> </embedded-ldap> <configuration-version>10.3.2.0</configuration-version> <machine xsi:type="unix-machineType"> <name>new_UnixMachine_1</name> <node-manager> <name>new_UnixMachine_1</name> <listen-address>localhost</listen-address> <listen-port>5566</listen-port> </node-manager> </machine> <admin-server-name>AdminServer</admin-server-name> </domain> \param[in] domainDir Directory of the domain (needed for build the path to the server \param[in] configXml File object of the XML file to open. \param[out] instances vector that will contain the list of server instances for the given domain. */ void WebLogicFileReader::ReadConfigXml( const SCXFilePath& domainDir, const SCXFilePath& configXml, vector<SCXHandle<AppServerInstance> >& instances) { SCX_LOGTRACE(m_log, L"WebLogicFileReader::ReadConfigXml"); SCX_LOGTRACE(m_log, wstring(L"WebLogicFileReader::ReadConfigXml() - "). append(L"Reading the file: ").append(configXml.Get())); string xml; try { SCXHandle<istream> reader = OpenConfigXml(configXml.Get()); GetStringFromStream(reader, xml); XElementPtr domainNode; XElement::Load(xml, domainNode); if (domainNode->GetName() == WEBLOGIC_DOMAIN_XML_NODE) { string version; ReadConfigXmlForVersion(domainNode, version); string adminServerName; ReadConfigXmlForAdminServerName(domainNode, adminServerName); XElementList serverNodes; domainNode->GetChildren(serverNodes); for (size_t index = 0; index < serverNodes.size(); ++index) { if (serverNodes[index]->GetName() == WEBLOGIC_SERVER_XML_NODE) { bool isAdminServer = false; bool isSslEnabled = false; string name = ""; string httpPort = ""; string httpsPort = ""; XElementList childNodes; serverNodes[index]->GetChildren(childNodes); for (size_t j = 0; j < childNodes.size(); ++j) { /* * <server> * <name>new_ManagedServer_1</name> * <ssl> * <name>new_ManagedServer_1</name> * <enabled>true</enabled> * <listen-port>7513</listen-port> * </ssl> * <machine>new_UnixMachine_1</machine> * <listen-port>7013</listen-port> * <listen-address/> * </server> * */ if (childNodes[j]->GetName() == WEBLOGIC_NAME_XML_NODE) { name = childNodes[j]->GetContent(); isAdminServer = adminServerName == name; } else if (childNodes[j]->GetName() == WEBLOGIC_SSL_XML_NODE) { ReadConfigXmlForSslInformation( childNodes[j], isSslEnabled, httpsPort); } else if (childNodes[j]->GetName() == WEBLOGIC_LISTEN_PORT_XML_NODE) { httpPort = childNodes[j]->GetContent(); } } /* * Having found the server node, * read the children */ wstring wideName = StrFromUTF8(name); SCXFilePath pathOnDisk; pathOnDisk.SetDirectory(domainDir.Get()); pathOnDisk.AppendDirectory(WEBLOGIC_SERVERS_DIRECTORY); pathOnDisk.AppendDirectory(wideName); if (DoesServerDirectoryExist(pathOnDisk)) { SCX_LOGTRACE(m_log, wstring(L"WebLogicFileReader::ReadConfigXml() - "). append(L"Adding instance for ID='").append(pathOnDisk.Get()). append(L"'")); // when the HTTP port is not set for the AdminServer, // default to the default weblogic HTTP port (i.e. 7001) wstring wideHttpPort = StrFromUTF8(httpPort); if(isAdminServer && L"" == wideHttpPort) { wideHttpPort = DEFAULT_WEBLOGIC_HTTP_PORT; } // when the HTTPS port is not set, default to // the default HTTPS port (i.e. 7002) wstring wideHttpsPort = StrFromUTF8(httpsPort); if(L"" == wideHttpsPort) { wideHttpsPort = DEFAULT_WEBLOGIC_HTTPS_PORT; } wstring wideVersion = StrFromUTF8(version); SCXHandle<AppServerInstance> instance( new WebLogicAppServerInstance ( pathOnDisk.GetDirectory())); instance->SetHttpPort(wideHttpPort); instance->SetHttpsPort(wideHttpsPort); instance->SetIsDeepMonitored(false, PROTOCOL_HTTPS); instance->SetIsRunning(false); instance->SetVersion(wideVersion); instance->SetServer( isAdminServer ? WEBLOGIC_SERVER_TYPE_ADMIN : WEBLOGIC_SERVER_TYPE_MANAGED); instances.push_back(instance); } else { SCX_LOGTRACE(m_log, wstring(L"WebLogicFileReader::ReadConfigXml() - "). append(L"The directory (").append(pathOnDisk.Get()). append(L") does not exist on disk, ignoring this instance")); } } } } } catch (SCXFilePathNotFoundException&) { SCX_LOGERROR(m_log, wstring(L"WebLogicFileReader::ReadConfigXml() - "). append(m_installationPath).append(L" - Could not find file: "). append(configXml.Get())); } catch (SCXUnauthorizedFileSystemAccessException&) { SCX_LOGERROR(m_log, wstring(L"WebLogicFileReader::ReadConfigXml() - "). append(m_installationPath).append(L" - not authorized to open file: "). append(configXml.Get())); } catch (XmlException& x) { SCX_LOGERROR(m_log, wstring(L"WebLogicFileReader::ReadConfigXml() - "). append(m_installationPath).append(L" - Could not load XML from file: "). append(configXml.Get())); } }
/** main function. \param argc size of \a argv[] \param argv array of string pointers from the command line. \returns 0 on success, otherwise, 1 on error. Usage: scxgencert [-d domain] [-h hostname] [-g targetpath] [-e days] [-s days] \n -v toggle the debug flag. \n -? print the help message and exit. \n -g targetpath target path where certificates should be written \n -s days days to offset valid start date with \n -e days days to offset valid end date with \n -d domain domain name \n -h host hostname \n -b bits number of key bits (defaults to 2048) Result Code \n -1 an exception has occured \n 0 success \n >1 an error occured while executing the command. */ int main(int argc, char *argv[]) { // commandline switches const string helpFlag ("-?"); const string bitsFlag ("-b"); const string domainFlag ("-d"); const string enddaysFlag ("-e"); const string forceFlag ("-f"); const string generateFlag ("-g"); const string hostFlag ("-h"); const string startdaysFlag ("-s"); const string debugFlag ("-v"); const string testFlag ("-t"); // Undocummented, for testing only // Control variables built from command line arguments (defaulted as needed by SCX) bool debugMode = false; bool testMode = false; bool doGenerateCert = false; wstring targetPath = L"/etc/opt/omi/ssl"; int startDays = -365; int endDays = 7300; #if defined(hpux) && defined(hppa) int bits = 1024; #else int bits = 2048; #endif SCXCoreLib::NameResolver mi; wstring hostname; wstring domainname; wstring specified_hostname; wstring specified_domainname; int i = 1; for (; i < argc; ++i) { if (debugFlag == argv[i]) { debugMode = ! debugMode; wcout << L"Setting debugMode=" << (debugMode ? L"true" :L"false") << endl; } else if (helpFlag == argv[i]) { usage(argv[0], 0); } else if (forceFlag == argv[i]) { doGenerateCert = true; } else if(bitsFlag == argv[i]) { if (++i >= argc) { wcout << L"Enter number of bits." << endl; usage(argv[0], 1); } bits = (int) SCXCoreLib::StrToLong(SCXCoreLib::StrFromUTF8(argv[i])); if (0 == bits || 0 != bits%512) { wcout << L"Bits must be non-zero dividable by 512." << endl; usage(argv[0], 1); } } else if(domainFlag == argv[i]) { if (++i >= argc) { wcout << L"Enter a domain name." << endl; usage(argv[0], 1); } // Some platforms fail to convert if locale is not right (SLES 11 for instance). // Note we do not print domain name because wcout will also fail to // properly convert, displaying a mangled string and further confusing // the user. Using cout is not an option because it will not print a // non-convertible string at all.... try { specified_domainname = SCXCoreLib::StrFromMultibyte(argv[i], true); } catch(const SCXCoreLib::SCXStringConversionException &ex) { wcout << L"Not able to convert domain name. Consider adjusting your locale setting. Exiting." << endl; exit(3); } } else if(hostFlag == argv[i]) { if (++i >= argc) { wcout << "Enter a hostname." << endl; usage(argv[0], 1); } // Host name is expected to be 7 bit so conversion is in most cases a no-op // If it fails prompt user and quit try { specified_hostname = SCXCoreLib::StrFromMultibyte(argv[i], true); } catch(const SCXCoreLib::SCXStringConversionException &e) { wcout << L"Not able to convert host name, \'" << argv[i] << "\'." << endl; wcout << L"Please specify a host name that uses only 7-bit ASCII characters." << endl; exit(4); } } else if (generateFlag == argv[i]) { // Ensure the path argument exists. if (++i >= argc) { wcout << "Enter a target path to generate certificates." << endl; usage(argv[0], 1); } try { targetPath = SCXCoreLib::StrFromMultibyte(argv[i], true); } catch(SCXCoreLib::SCXStringConversionException) { wcout << L"Not able to convert target path, \'" << argv[i] << "\'." << endl; wcout << L"Consider adjusting your locale by changing the LC_CTYPE environment variable." << endl; exit(4); } } else if (startdaysFlag == argv[i]) { // Ensure the value argument exists. if (++i >= argc) { wcout << "Enter a value for start days." << endl; usage(argv[0], 1); } startDays = (int) SCXCoreLib::StrToLong(SCXCoreLib::StrFromUTF8(argv[i])); } else if (enddaysFlag == argv[i]) { // Ensure the value argument exists. if (++i >= argc || SCXCoreLib::StrToLong(SCXCoreLib::StrFromUTF8(argv[i])) == 0) { wcout << "Enter a non-zero value for end days." << endl; usage(argv[0], 1); } endDays = (int) SCXCoreLib::StrToLong(SCXCoreLib::StrFromUTF8(argv[i])); } else if (testFlag == argv[i]) { testMode = true; } else { break; } } // Fail if all arguments are not used. if (i < argc) { wcout << L"Unused arguments:" << endl; for (; i < argc; ++i) { wcout << L"\t" << argv[i] << endl; } wcout << endl; usage(argv[0], 1); } hostname = specified_hostname; domainname = specified_domainname; if(hostname.empty()) { std::string hostname_raw = ""; try { // This can fail because there are string conversions done in GetHostname() hostname = mi.GetHostname(&hostname_raw); } catch(SCXCoreLib::SCXStringConversionException) { // Note: We should never see this because host names are s'pose to be 7 bit ASCII // Can get away with conversion of stdout here because we are dying, and can do it exactly once ... fwide(stdout, -1); cout << "Unable to convert default host name \'" << hostname_raw << "\'." << endl; cout << "This might be caused by a host name that contains UTF-8 characters that are invalid given your current locale." << endl; // MUST exit here, due to fwide() call above ... cannot call fwide() more than once w/out closing/reopening handle exit(3); } catch(SCXCoreLib::SCXErrnoERANGE_Exception &e) { cout << SCXCoreLib::StrToUTF8(e.Where()) << endl << SCXCoreLib::StrToUTF8(e.What()) << endl; exit(3); } } // If the user did not supply a domain name, use default. if(domainname.empty()) { domainname = mi.GetDomainname(); } if(debugMode) { // Show what we would have used - even if user specified specific host/domain wcout << L"Generated hostname: \"" << mi.GetHostname() << L"\" (" << mi.DumpSourceString(mi.GetHostnameSource()) << L")" << endl; wcout << L"Generated domainname: \"" << mi.GetDomainname() << L"\" (" << mi.DumpSourceString(mi.GetDomainnameSource()) << L")" << endl << endl; wcout << L"Using Host Name: " << hostname << endl; wcout << L"Using Domain Name: " << domainname << endl; wcout << L"Start Days: " << startDays << endl; wcout << L"End Days: " << endDays << endl; wcout << L"Cert Length: " << bits << endl; wcout << L"Target Path: " << targetPath << endl << endl; } // We only generate the certificate if "-f" was specified, or if no certificate exists // (Note: If no certificate exists, we should still return a success error code!) if (!doGenerateCert) { SCXFilePath keyPath; keyPath.SetDirectory(targetPath); keyPath.SetFilename(L"omikey.pem"); SCXCoreLib::SCXFileInfo keyInfo(keyPath); if ( ! keyInfo.Exists() ) { doGenerateCert = true; } else { wcerr << L"Certificate not generated - '" << keyPath.Get() << "' exists" << endl; } } int rc = 0; if (doGenerateCert) { rc = DoGenerate(targetPath, startDays, endDays, hostname, domainname, bits, debugMode); // When the domain or host name is specified through the command line we do not allow recovery. // Add an exception to this rule for testing purposes. if ( (specified_domainname.empty() && specified_hostname.empty()) || testMode ) { // When the domain or hostname is not RFC compliant, openssl fails to generate a cerificate. // We will try to fallback. if ( rc == ERROR_CERT_GENERATE ) { wcout << "Hostname or domain likely not RFC compliant, trying fallback: \"localhost.local\"" << endl; rc = DoGenerate(targetPath, startDays, endDays, L"localhost", L"local", bits, debugMode); } } } if (debugMode) { wcout << L"return code = " << rc << endl; } exit(rc); }
/** Generate Key and Certificate \param[in] targetPath Path where the certificates should be written. \param[in] startDays Days to offset valid start date. \param[in] endDays Days to offset valid end date. \param[in] hostname Hostname to put into the certificate. \param[in] domainname Domainname to put into the certificate. \param[in] bits Number of bits in key. \returns Zero on success. */ static int DoGenerate(const wstring & targetPath, int startDays, int endDays, const wstring & hostname, const wstring & domainname, int bits, bool bDebug) { // Output what we'll be using for certificate generation wcout << L"Generating certificate with hostname=\"" << hostname << L"\""; if (domainname.length()) { wcout << L", domainname=\"" << domainname << L"\"" ; } wcout << endl; std::wstring c_certFilename(L"omi-host-"); // Remainder must be generated const std::wstring c_keyFilename(L"omikey.pem"); int rc = 0; // Do not allow an exception to slip out try { // The certificate filename must be something like omi-host-<hostname>.pem; generate it c_certFilename.append(hostname); c_certFilename.append(L".pem"); SCXFilePath keyPath; keyPath.SetDirectory(targetPath); keyPath.SetFilename(c_keyFilename); SCXFilePath certPath; certPath.SetDirectory(targetPath); certPath.SetFilename(c_certFilename); SCXSSLCertificateLocalizedDomain cert(keyPath, certPath, startDays, endDays, hostname, domainname, bits); std::ostringstream debugChatter; debugChatter << endl; try { cert.Generate(debugChatter); } catch(const SCXCoreLib::SCXStringConversionException &ex) { if(bDebug) wcout << debugChatter.str().c_str(); wcerr << endl << "Generation of certificate raised an exception" << endl; wcerr << ex.Where() << endl; wcerr << ex.What() << endl; return 2; } catch(const SCXSSLException &e_ssl) { if(bDebug) { wcout << debugChatter.str().c_str(); debugChatter.str(""); } wcerr << e_ssl.What() << endl; return ERROR_CERT_GENERATE; } catch(const SCXCoreLib::SCXFilePathNotFoundException &ex) { wcerr << endl << "Generation of certificate raised an exception" << endl; wcerr << "Output path \"" << ex.GetPath().Get() << "\" does not exist" << endl; return 4; } if(bDebug) { wcout << debugChatter.str().c_str(); } /* ** We actually have three certificate files in total: ** ** Certificate File: omi-host-<hostname>.pem (public) ** Key File: omi-key.pem (private) ** Soft link: omi.pem (soft link to certificate file, used by openwsman) ** ** ** Create the soft link to point to the certificate file. */ SCXFilePath fpLinkFile; fpLinkFile.SetDirectory(targetPath); fpLinkFile.SetFilename(L"omi.pem"); std::string sLinkFile = SCXCoreLib::StrToMultibyte(fpLinkFile.Get()); std::string sCertFile = SCXCoreLib::StrToMultibyte(certPath.Get()); rc = unlink(sLinkFile.c_str()); if (0 != rc && ENOENT != errno) { throw SCXCoreLib::SCXErrnoFileException(L"unlink", fpLinkFile.Get(), errno, SCXSRCLOCATION); } rc = symlink(sCertFile.c_str(), sLinkFile.c_str()); if (0 != rc) { throw SCXCoreLib::SCXErrnoFileException(L"unlink", fpLinkFile.Get(), errno, SCXSRCLOCATION); } /* ** Finally, make sure the permissions are right: ** The pub key gets 444, the priv key gets 400 */ rc = chmod(sCertFile.c_str(), 00444); if (0 != rc) { throw SCXCoreLib::SCXErrnoFileException(L"chmod", certPath.Get(), errno, SCXSRCLOCATION); } std::string sKeyFile = SCXCoreLib::StrToMultibyte(keyPath.Get()); rc = chmod(sKeyFile.c_str(), 00400); if (0 != rc) { throw SCXCoreLib::SCXErrnoFileException(L"chmod", keyPath.Get(), errno, SCXSRCLOCATION); } } catch(const SCXCoreLib::SCXException & e) { wcout << e.Where() << endl << e.What() << endl; // use -1 to indicate an exception occured. rc = -1; } return rc; }