void censorBSONObjRecursive(const BSONObj& params, // Object we are censoring const std::string& parentPath, // Set if this is a sub object bool isArray, BSONObjBuilder* result) { BSONObjIterator paramsIterator(params); while (paramsIterator.more()) { BSONElement param = paramsIterator.next(); std::string dottedName = (parentPath.empty() ? param.fieldName() : isArray ? parentPath : parentPath + '.' + param.fieldName()); if (param.type() == Array) { BSONObjBuilder subArray(result->subarrayStart(param.fieldName())); censorBSONObjRecursive(param.Obj(), dottedName, true, &subArray); subArray.done(); } else if (param.type() == Object) { BSONObjBuilder subObj(result->subobjStart(param.fieldName())); censorBSONObjRecursive(param.Obj(), dottedName, false, &subObj); subObj.done(); } else if (param.type() == String) { if (_isPasswordArgument(dottedName.c_str())) { result->append(param.fieldName(), "<password>"); } else { result->append(param); } } else { result->append(param); } } }
static bool _isPasswordSwitch(const char* switchName) { if (switchName[0] != '-') return false; size_t i = 1; if (switchName[1] == '-') i = 2; switchName += i; return _isPasswordArgument(switchName); }
bool CmdLine::store( const std::vector<std::string>& argv, boost::program_options::options_description& visible, boost::program_options::options_description& hidden, boost::program_options::positional_options_description& positional, boost::program_options::variables_map ¶ms ) { if (argv.empty()) return false; { // setup binary name cmdLine.binaryName = argv[0]; size_t i = cmdLine.binaryName.rfind( '/' ); if ( i != string::npos ) cmdLine.binaryName = cmdLine.binaryName.substr( i + 1 ); // setup cwd char buffer[1024]; #ifdef _WIN32 verify( _getcwd( buffer , 1000 ) ); #else verify( getcwd( buffer , 1000 ) ); #endif cmdLine.cwd = buffer; } /* don't allow guessing - creates ambiguities when some options are * prefixes of others. allow long disguises and don't allow guessing * to get away with our vvvvvvv trick. */ int style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::options_description all; all.add( visible ); all.add( hidden ); po::store( po::command_line_parser(std::vector<std::string>(argv.begin() + 1, argv.end())) .options( all ) .positional( positional ) .style( style ) .run(), params ); if ( params.count("config") ) { ifstream f( params["config"].as<string>().c_str() ); if ( ! f.is_open() ) { cout << "ERROR: could not read from config file" << endl << endl; cout << visible << endl; return false; } stringstream ss; CmdLine::parseConfigFile( f, ss ); po::store( po::parse_config_file( ss , all ) , params ); f.close(); } po::notify(params); } catch (po::error &e) { cout << "error command line: " << e.what() << endl; cout << "use --help for help" << endl; //cout << visible << endl; return false; } { BSONArrayBuilder b; std::vector<std::string> censoredArgv = argv; censor(&censoredArgv); for (size_t i=0; i < censoredArgv.size(); i++) { b << censoredArgv[i]; } argvArray = b.arr(); } { BSONObjBuilder b; for (po::variables_map::const_iterator it(params.begin()), end(params.end()); it != end; it++){ if (!it->second.defaulted()){ const string& key = it->first; const po::variable_value& value = it->second; const type_info& type = value.value().type(); if (type == typeid(string)){ if (value.as<string>().empty()) b.appendBool(key, true); // boost po uses empty string for flags like --quiet else { if ( _isPasswordArgument(key.c_str()) ) { b.append( key, "<password>" ); } else { b.append( key, value.as<string>() ); } } } else if (type == typeid(int)) b.append(key, value.as<int>()); else if (type == typeid(double)) b.append(key, value.as<double>()); else if (type == typeid(bool)) b.appendBool(key, value.as<bool>()); else if (type == typeid(long)) b.appendNumber(key, (long long)value.as<long>()); else if (type == typeid(unsigned)) b.appendNumber(key, (long long)value.as<unsigned>()); else if (type == typeid(unsigned long long)) b.appendNumber(key, (long long)value.as<unsigned long long>()); else if (type == typeid(vector<string>)) b.append(key, value.as<vector<string> >()); else b.append(key, "UNKNOWN TYPE: " + demangleName(type)); } } parsedOpts = b.obj(); } if (params.count("verbose")) { logLevel = 1; } for (string s = "vv"; s.length() <= 12; s.append("v")) { if (params.count(s)) { logLevel = s.length(); } } if (params.count("quiet")) { cmdLine.quiet = true; } if (params.count("traceExceptions")) { DBException::traceExceptions = true; } if (params.count("maxConns")) { cmdLine.maxConns = params["maxConns"].as<int>(); if ( cmdLine.maxConns < 5 ) { out() << "maxConns has to be at least 5" << endl; return false; } else if ( cmdLine.maxConns > MAX_MAX_CONN ) { out() << "maxConns can't be greater than " << MAX_MAX_CONN << endl; return false; } } if (params.count("objcheck")) { cmdLine.objcheck = true; } if (params.count("noobjcheck")) { if (params.count("objcheck")) { out() << "can't have both --objcheck and --noobjcheck" << endl; return false; } cmdLine.objcheck = false; } if (params.count("bind_ip")) { // passing in wildcard is the same as default behavior; remove and warn if ( cmdLine.bind_ip == "0.0.0.0" ) { cout << "warning: bind_ip of 0.0.0.0 is unnecessary; listens on all ips by default" << endl; cmdLine.bind_ip = ""; } } #ifndef _WIN32 if (params.count("unixSocketPrefix")) { cmdLine.socket = params["unixSocketPrefix"].as<string>(); } if (params.count("nounixsocket")) { cmdLine.noUnixSocket = true; } if (params.count("fork") && !params.count("shutdown")) { cmdLine.doFork = true; } #endif // _WIN32 if (params.count("logpath")) { cmdLine.logpath = params["logpath"].as<string>(); if (cmdLine.logpath.empty()) { cout << "logpath cannot be empty if supplied" << endl; return false; } } cmdLine.logWithSyslog = params.count("syslog"); cmdLine.logAppend = params.count("logappend"); if (!cmdLine.logpath.empty() && cmdLine.logWithSyslog) { cout << "Cant use both a logpath and syslog " << endl; return false; } if (cmdLine.doFork && cmdLine.logpath.empty() && !cmdLine.logWithSyslog) { cout << "--fork has to be used with --logpath or --syslog" << endl; return false; } if (params.count("keyFile")) { cmdLine.keyFile = params["keyFile"].as<string>(); } if ( params.count("pidfilepath")) { cmdLine.pidFile = params["pidfilepath"].as<string>(); } if (params.count("setParameter")) { std::vector<std::string> parameters = params["setParameter"].as<std::vector<std::string> >(); for (size_t i = 0, length = parameters.size(); i < length; ++i) { std::string name; std::string value; if (!mongoutils::str::splitOn(parameters[i], '=', name, value)) { cout << "Illegal option assignment: \"" << parameters[i] << "\"" << endl; return false; } ServerParameter* parameter = mapFindWithDefault( ServerParameterSet::getGlobal()->getMap(), name, static_cast<ServerParameter*>(NULL)); if (NULL == parameter) { cout << "Illegal --option parameter: \"" << name << "\"" << endl; return false; } Status status = parameter->setFromString(value); if (!status.isOK()) { cout << "Bad value for parameter \"" << name << "\": " << status.reason() << endl; return false; } } } #ifdef MONGO_SSL if (params.count("sslWeakCertificateValidation")) { cmdLine.sslWeakCertificateValidation = true; } if (params.count("sslOnNormalPorts")) { cmdLine.sslOnNormalPorts = true; if ( cmdLine.sslPEMKeyFile.size() == 0 ) { log() << "need sslPEMKeyFile" << endl; return false; } if (cmdLine.sslWeakCertificateValidation && cmdLine.sslCAFile.empty()) { log() << "need sslCAFile with sslWeakCertificateValidation" << endl; return false; } } else if (cmdLine.sslPEMKeyFile.size() || cmdLine.sslPEMKeyPassword.size() || cmdLine.sslCAFile.size() || cmdLine.sslCRLFile.size() || cmdLine.sslWeakCertificateValidation) { log() << "need to enable sslOnNormalPorts" << endl; return false; } #endif return true; }