in source/code/shared/tools/scx_ssl_config/scx_ssl_config.cpp [69:340]
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 clientcertFlag ("-c");
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;
bool clientCert = false;
#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 (clientcertFlag == argv[i])
{
clientCert = true;
}
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!)
int rc = 0;
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;
// Upgrade from 2012R2 should update the key ownership to omi:omi
rc = UpdateKeyOwnership(keyPath);
}
}
if (doGenerateCert)
{
rc = DoGenerate(targetPath, startDays, endDays, hostname, domainname, bits, debugMode, clientCert);
// 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);
}