~evarlast/ubuntu/utopic/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/mongo/db/cmdline.cpp

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
17
*/
18
18
 
19
 
#include "pch.h"
20
 
#include "cmdline.h"
21
 
#include "commands.h"
22
 
#include "../util/password.h"
23
 
#include "../util/processinfo.h"
24
 
#include "../util/net/listen.h"
25
 
#include "../bson/util/builder.h"
26
 
#include "security_common.h"
 
19
#include "mongo/pch.h"
 
20
 
 
21
#include "mongo/db/cmdline.h"
 
22
 
 
23
#include "mongo/base/status.h"
 
24
#include "mongo/bson/util/builder.h"
 
25
#include "mongo/db/server_parameters.h"
 
26
#include "mongo/util/map_util.h"
27
27
#include "mongo/util/mongoutils/str.h"
 
28
#include "mongo/util/net/listen.h"
 
29
#include "mongo/util/password.h"
 
30
 
28
31
#ifdef _WIN32
29
32
#include <direct.h>
30
 
#else
31
 
#include <sys/types.h>
32
 
#include <sys/wait.h>
33
33
#endif
34
 
#include "globals.h"
35
34
 
36
35
#define MAX_LINE_LENGTH 256
37
36
 
38
37
#include <fstream>
39
 
#include <boost/filesystem/operations.hpp>
40
38
 
41
39
namespace po = boost::program_options;
42
 
namespace fs = boost::filesystem;
43
40
 
44
41
namespace mongo {
45
42
 
46
 
    void setupSignals( bool inFork );
47
 
    string getHostNameCached();
48
 
    static BSONArray argvArray;
49
 
    static BSONObj parsedOpts;
 
43
    static bool _isPasswordArgument(char const* argumentName);
 
44
    static bool _isPasswordSwitch(char const* switchName);
 
45
 
 
46
namespace {
 
47
    BSONArray argvArray;
 
48
    BSONObj parsedOpts;
 
49
}  // namespace
 
50
 
 
51
    BSONArray CmdLine::getArgvArray() {
 
52
        return argvArray;
 
53
    }
 
54
 
 
55
    BSONObj CmdLine::getParsedOpts() {
 
56
        return parsedOpts;
 
57
    }
50
58
 
51
59
    void CmdLine::addGlobalOptions( boost::program_options::options_description& general ,
52
60
                                    boost::program_options::options_description& hidden ,
71
79
        ("port", po::value<int>(&cmdLine.port), portInfoBuilder.str().c_str())
72
80
        ("bind_ip", po::value<string>(&cmdLine.bind_ip), "comma separated list of ip addresses to listen on - all local ips by default")
73
81
        ("maxConns",po::value<int>(), maxConnInfoBuilder.str().c_str())
74
 
        ("objcheck", "inspect client data for validity on receipt")
75
82
        ("logpath", po::value<string>() , "log file to send write to instead of stdout - has to be a file, not directory" )
76
83
        ("logappend" , "append to logpath instead of over-writing" )
77
84
        ("pidfilepath", po::value<string>(), "full path to pidfile (if not set, no pidfile is created)")
78
85
        ("keyFile", po::value<string>(), "private key for cluster authentication")
 
86
        ("setParameter", po::value< std::vector<std::string> >()->composing(),
 
87
                "Set a configurable parameter")
79
88
#ifndef _WIN32
80
89
        ("nounixsocket", "disable listening on unix sockets")
81
90
        ("unixSocketPrefix", po::value<string>(), "alternative directory for UNIX domain sockets (defaults to /tmp)")
90
99
        ("sslOnNormalPorts" , "use ssl on configured ports" )
91
100
        ("sslPEMKeyFile" , po::value<string>(&cmdLine.sslPEMKeyFile), "PEM file for ssl" )
92
101
        ("sslPEMKeyPassword" , new PasswordValue(&cmdLine.sslPEMKeyPassword) , "PEM file password" )
 
102
        ("sslCAFile", po::value<std::string>(&cmdLine.sslCAFile), 
 
103
         "Certificate Authority file for SSL")
 
104
        ("sslCRLFile", po::value<std::string>(&cmdLine.sslCRLFile),
 
105
         "Certificate Revocation List file for SSL")
 
106
        ("sslWeakCertificateValidation", "allow client to connect without presenting a certificate")
 
107
        ("sslFIPSMode", "activate FIPS 140-2 mode at startup")
93
108
#endif
94
109
        ;
95
110
        
96
111
        // Extra hidden options
97
112
        hidden.add_options()
98
 
        ("traceExceptions", "log stack traces for every exception");
 
113
        ("objcheck", "inspect client data for validity on receipt (DEFAULT)")
 
114
        ("noobjcheck", "do NOT inspect client data for validity on receipt")
 
115
        ("traceExceptions", "log stack traces for every exception")
 
116
        ("enableExperimentalIndexStatsCmd", po::bool_switch(&cmdLine.experimental.indexStatsCmdEnabled),
 
117
                "EXPERIMENTAL (UNSUPPORTED). Enable command computing aggregate statistics on indexes.")
 
118
        ("enableExperimentalStorageDetailsCmd", po::bool_switch(&cmdLine.experimental.storageDetailsCmdEnabled),
 
119
                "EXPERIMENTAL (UNSUPPORTED). Enable command computing aggregate statistics on storage.")
 
120
        ;
99
121
    }
100
122
 
101
123
#if defined(_WIN32)
140
162
        return;
141
163
    }
142
164
 
143
 
#ifndef _WIN32
144
 
    // support for exit value propagation with fork
145
 
    void launchSignal( int sig ) {
146
 
        if ( sig == SIGUSR2 ) {
147
 
            pid_t cur = getpid();
148
 
            
149
 
            if ( cur == cmdLine.parentProc || cur == cmdLine.leaderProc ) {
150
 
                // signal indicates successful start allowing us to exit
151
 
                _exit(0);
152
 
            } 
153
 
        }
154
 
    }
155
 
 
156
 
    void setupLaunchSignals() {
157
 
        verify( signal(SIGUSR2 , launchSignal ) != SIG_ERR );
158
 
    }
159
 
 
160
 
 
161
 
    void CmdLine::launchOk() {
162
 
        if ( cmdLine.doFork ) {
163
 
            // killing leader will propagate to parent
164
 
            verify( kill( cmdLine.leaderProc, SIGUSR2 ) == 0 );
165
 
        }
166
 
    }
167
 
#endif
168
 
 
169
 
    bool CmdLine::store( int argc , char ** argv ,
 
165
    bool CmdLine::store( const std::vector<std::string>& argv,
170
166
                         boost::program_options::options_description& visible,
171
167
                         boost::program_options::options_description& hidden,
172
168
                         boost::program_options::positional_options_description& positional,
173
169
                         boost::program_options::variables_map &params ) {
174
170
 
175
171
 
 
172
        if (argv.empty())
 
173
            return false;
 
174
 
176
175
        {
177
176
            // setup binary name
178
177
            cmdLine.binaryName = argv[0];
206
205
            all.add( visible );
207
206
            all.add( hidden );
208
207
 
209
 
            po::store( po::command_line_parser(argc, argv)
 
208
            po::store( po::command_line_parser(std::vector<std::string>(argv.begin() + 1,
 
209
                                                                        argv.end()))
210
210
                       .options( all )
211
211
                       .positional( positional )
212
212
                       .style( style )
236
236
            return false;
237
237
        }
238
238
 
239
 
        if (params.count("verbose")) {
240
 
            logLevel = 1;
241
 
        }
242
 
 
243
 
        for (string s = "vv"; s.length() <= 12; s.append("v")) {
244
 
            if (params.count(s)) {
245
 
                logLevel = s.length();
246
 
            }
247
 
        }
248
 
 
249
 
        if (params.count("quiet")) {
250
 
            cmdLine.quiet = true;
251
 
        }
252
 
 
253
 
        if (params.count("traceExceptions")) {
254
 
            DBException::traceExceptions = true;
255
 
        }
256
 
 
257
 
        if ( params.count( "maxConns" ) ) {
258
 
            int newSize = params["maxConns"].as<int>();
259
 
            if ( newSize < 5 ) {
260
 
                out() << "maxConns has to be at least 5" << endl;
261
 
                ::_exit( EXIT_BADOPTIONS );
262
 
            }
263
 
            else if ( newSize >= 10000000 ) {
264
 
                out() << "maxConns can't be greater than 10000000" << endl;
265
 
                ::_exit( EXIT_BADOPTIONS );
266
 
            }
267
 
            connTicketHolder.resize( newSize );
268
 
        }
269
 
 
270
 
        if (params.count("objcheck")) {
271
 
            cmdLine.objcheck = true;
272
 
        }
273
 
 
274
 
        if (params.count("bind_ip")) {
275
 
            // passing in wildcard is the same as default behavior; remove and warn
276
 
            if ( cmdLine.bind_ip ==  "0.0.0.0" ) {
277
 
                cout << "warning: bind_ip of 0.0.0.0 is unnecessary; listens on all ips by default" << endl;
278
 
                cmdLine.bind_ip = "";
279
 
            }
280
 
        }
281
 
 
282
 
        string logpath;
283
 
 
284
 
#ifndef _WIN32
285
 
        if (params.count("unixSocketPrefix")) {
286
 
            cmdLine.socket = params["unixSocketPrefix"].as<string>();
287
 
            if (!fs::is_directory(cmdLine.socket)) {
288
 
                cout << cmdLine.socket << " must be a directory" << endl;
289
 
                ::_exit(-1);
290
 
            }
291
 
        }
292
 
 
293
 
        if (params.count("nounixsocket")) {
294
 
            cmdLine.noUnixSocket = true;
295
 
        }
296
 
 
297
 
        if (params.count("fork") && !params.count("shutdown")) {
298
 
            cmdLine.doFork = true;
299
 
            if ( ! params.count( "logpath" ) && ! params.count( "syslog" ) ) {
300
 
                cout << "--fork has to be used with --logpath or --syslog" << endl;
301
 
                ::_exit(EXIT_BADOPTIONS);
302
 
            }
303
 
 
304
 
            if ( params.count( "logpath" ) ) {
305
 
                // test logpath
306
 
                logpath = params["logpath"].as<string>();
307
 
                verify( logpath.size() );
308
 
                if ( logpath[0] != '/' ) {
309
 
                    logpath = cmdLine.cwd + "/" + logpath;
310
 
                }
311
 
                bool exists = boost::filesystem::exists( logpath );
312
 
                FILE * test = fopen( logpath.c_str() , "a" );
313
 
                if ( ! test ) {
314
 
                    cout << "can't open [" << logpath << "] for log file: " << errnoWithDescription() << endl;
315
 
                    ::_exit(-1);
316
 
                }
317
 
                fclose( test );
318
 
                // if we created a file, unlink it (to avoid confusing log rotation code)
319
 
                if ( ! exists ) {
320
 
                    unlink( logpath.c_str() );
321
 
                }
322
 
            }
323
 
 
324
 
            cout.flush();
325
 
            cerr.flush();
326
 
            
327
 
            cmdLine.parentProc = getpid();
328
 
            
329
 
            // facilitate clean exit when child starts successfully
330
 
            setupLaunchSignals();
331
 
 
332
 
            pid_t c = fork();
333
 
            if ( c ) {
334
 
                int pstat;
335
 
                waitpid(c, &pstat, 0);
336
 
 
337
 
                if ( WIFEXITED(pstat) ) {
338
 
                    if ( ! WEXITSTATUS(pstat) ) {
339
 
                        cout << "child process started successfully, parent exiting" << endl;
340
 
                    }
341
 
 
342
 
                    _exit( WEXITSTATUS(pstat) );
343
 
                }
344
 
 
345
 
                _exit(50);
346
 
            }
347
 
 
348
 
            if ( chdir("/") < 0 ) {
349
 
                cout << "Cant chdir() while forking server process: " << strerror(errno) << endl;
350
 
                ::_exit(-1);
351
 
            }
352
 
            setsid();
353
 
            
354
 
            cmdLine.leaderProc = getpid();
355
 
 
356
 
            pid_t c2 = fork();
357
 
            if ( c2 ) {
358
 
                int pstat;
359
 
                cout << "forked process: " << c2 << endl;
360
 
                waitpid(c2, &pstat, 0);
361
 
 
362
 
                if ( WIFEXITED(pstat) ) {
363
 
                    _exit( WEXITSTATUS(pstat) );
364
 
                }
365
 
 
366
 
                _exit(51);
367
 
            }
368
 
 
369
 
            // stdout handled in initLogging
370
 
            //fclose(stdout);
371
 
            //freopen("/dev/null", "w", stdout);
372
 
 
373
 
            fclose(stderr);
374
 
            fclose(stdin);
375
 
 
376
 
            FILE* f = freopen("/dev/null", "w", stderr);
377
 
            if ( f == NULL ) {
378
 
                cout << "Cant reassign stderr while forking server process: " << strerror(errno) << endl;
379
 
                ::_exit(-1);
380
 
            }
381
 
 
382
 
            f = freopen("/dev/null", "r", stdin);
383
 
            if ( f == NULL ) {
384
 
                cout << "Cant reassign stdin while forking server process: " << strerror(errno) << endl;
385
 
                ::_exit(-1);
386
 
            }
387
 
        }
388
 
        setupSignals( true );
389
 
 
390
 
        if (params.count("syslog")) {
391
 
            StringBuilder sb;
392
 
            sb << cmdLine.binaryName << "." << cmdLine.port;
393
 
            Logstream::useSyslog( sb.str().c_str() );
394
 
        }
395
 
#endif
396
 
        if (params.count("logpath") && !params.count("shutdown")) {
397
 
            if ( params.count("syslog") ) {
398
 
                cout << "Cant use both a logpath and syslog " << endl;
399
 
                ::_exit(EXIT_BADOPTIONS);
400
 
            }
401
 
            
402
 
            if ( logpath.size() == 0 )
403
 
                logpath = params["logpath"].as<string>();
404
 
            uassert( 10033 ,  "logpath has to be non-zero" , logpath.size() );
405
 
            initLogging( logpath , params.count( "logappend" ) );
406
 
        }
407
 
 
408
 
        if ( params.count("pidfilepath")) {
409
 
            writePidFile( params["pidfilepath"].as<string>() );
410
 
        }
411
 
 
412
 
        if (params.count("keyFile")) {
413
 
            const string f = params["keyFile"].as<string>();
414
 
 
415
 
            if (!setUpSecurityKey(f)) {
416
 
                // error message printed in setUpPrivateKey
417
 
                ::_exit(EXIT_BADOPTIONS);
418
 
            }
419
 
 
420
 
            cmdLine.keyFile = true;
421
 
            noauth = false;
422
 
        }
423
 
        else {
424
 
            cmdLine.keyFile = false;
425
 
        }
426
 
 
427
 
#ifdef MONGO_SSL
428
 
        if (params.count("sslOnNormalPorts") ) {
429
 
            cmdLine.sslOnNormalPorts = true;
430
 
 
431
 
            if ( cmdLine.sslPEMKeyPassword.size() == 0 ) {
432
 
                log() << "need sslPEMKeyPassword" << endl;
433
 
                ::_exit(EXIT_BADOPTIONS);
434
 
            }
435
 
            
436
 
            if ( cmdLine.sslPEMKeyFile.size() == 0 ) {
437
 
                log() << "need sslPEMKeyFile" << endl;
438
 
                ::_exit(EXIT_BADOPTIONS);
439
 
            }
440
 
            
441
 
            cmdLine.sslServerManager = new SSLManager( false );
442
 
            if ( ! cmdLine.sslServerManager->setupPEM( cmdLine.sslPEMKeyFile , cmdLine.sslPEMKeyPassword ) ) {
443
 
                ::_exit(EXIT_BADOPTIONS);
444
 
            }
445
 
        }
446
 
        else if ( cmdLine.sslPEMKeyFile.size() || cmdLine.sslPEMKeyPassword.size() ) {
447
 
            log() << "need to enable sslOnNormalPorts" << endl;
448
 
            ::_exit(EXIT_BADOPTIONS);
449
 
        }
450
 
#endif
451
 
        
 
239
        {
 
240
            BSONArrayBuilder b;
 
241
            std::vector<std::string> censoredArgv = argv;
 
242
            censor(&censoredArgv);
 
243
            for (size_t i=0; i < censoredArgv.size(); i++) {
 
244
                b << censoredArgv[i];
 
245
            }
 
246
            argvArray = b.arr();
 
247
        }
 
248
 
452
249
        {
453
250
            BSONObjBuilder b;
454
251
            for (po::variables_map::const_iterator it(params.begin()), end(params.end()); it != end; it++){
461
258
                        if (value.as<string>().empty())
462
259
                            b.appendBool(key, true); // boost po uses empty string for flags like --quiet
463
260
                        else {
464
 
                            if ( key == "servicePassword" || key == "sslPEMKeyPassword" ) {
 
261
                            if ( _isPasswordArgument(key.c_str()) ) {
465
262
                                b.append( key, "<password>" );
466
263
                            }
467
264
                            else {
490
287
            parsedOpts = b.obj();
491
288
        }
492
289
 
493
 
        {
494
 
            BSONArrayBuilder b;
495
 
            for (int i=0; i < argc; i++) {
496
 
                b << argv[i];
497
 
                if ( mongoutils::str::equals(argv[i], "--sslPEMKeyPassword")
498
 
                     || mongoutils::str::equals(argv[i], "-sslPEMKeyPassword")
499
 
                     || mongoutils::str::equals(argv[i], "--servicePassword")
500
 
                     || mongoutils::str::equals(argv[i], "-servicePassword")) {
501
 
                    b << "<password>";
502
 
                    i++;
503
 
 
504
 
                    // hide password from ps output
505
 
                    char* arg = argv[i];
506
 
                    while (*arg) {
507
 
                        *arg++ = 'x';
508
 
                    }
509
 
                }
510
 
            }
511
 
            argvArray = b.arr();
512
 
        }
 
290
        if (params.count("verbose")) {
 
291
            logLevel = 1;
 
292
        }
 
293
 
 
294
        for (string s = "vv"; s.length() <= 12; s.append("v")) {
 
295
            if (params.count(s)) {
 
296
                logLevel = s.length();
 
297
            }
 
298
        }
 
299
 
 
300
        if (params.count("quiet")) {
 
301
            cmdLine.quiet = true;
 
302
        }
 
303
 
 
304
        if (params.count("traceExceptions")) {
 
305
            DBException::traceExceptions = true;
 
306
        }
 
307
 
 
308
        if (params.count("maxConns")) {
 
309
            cmdLine.maxConns = params["maxConns"].as<int>();
 
310
 
 
311
            if ( cmdLine.maxConns < 5 ) {
 
312
                out() << "maxConns has to be at least 5" << endl;
 
313
                return false;
 
314
            }
 
315
            else if ( cmdLine.maxConns > MAX_MAX_CONN ) {
 
316
                out() << "maxConns can't be greater than " << MAX_MAX_CONN << endl;
 
317
                return false;
 
318
            }
 
319
        }
 
320
 
 
321
        if (params.count("objcheck")) {
 
322
            cmdLine.objcheck = true;
 
323
        }
 
324
        if (params.count("noobjcheck")) {
 
325
            if (params.count("objcheck")) {
 
326
                out() << "can't have both --objcheck and --noobjcheck" << endl;
 
327
                return false;
 
328
            }
 
329
            cmdLine.objcheck = false;
 
330
        }
 
331
 
 
332
        if (params.count("bind_ip")) {
 
333
            // passing in wildcard is the same as default behavior; remove and warn
 
334
            if ( cmdLine.bind_ip ==  "0.0.0.0" ) {
 
335
                cout << "warning: bind_ip of 0.0.0.0 is unnecessary; listens on all ips by default" << endl;
 
336
                cmdLine.bind_ip = "";
 
337
            }
 
338
        }
 
339
 
 
340
#ifndef _WIN32
 
341
        if (params.count("unixSocketPrefix")) {
 
342
            cmdLine.socket = params["unixSocketPrefix"].as<string>();
 
343
        }
 
344
 
 
345
        if (params.count("nounixsocket")) {
 
346
            cmdLine.noUnixSocket = true;
 
347
        }
 
348
 
 
349
        if (params.count("fork") && !params.count("shutdown")) {
 
350
            cmdLine.doFork = true;
 
351
        }
 
352
#endif  // _WIN32
 
353
 
 
354
        if (params.count("logpath")) {
 
355
            cmdLine.logpath = params["logpath"].as<string>();
 
356
            if (cmdLine.logpath.empty()) {
 
357
                cout << "logpath cannot be empty if supplied" << endl;
 
358
                return false;
 
359
            }
 
360
        }
 
361
 
 
362
        cmdLine.logWithSyslog = params.count("syslog");
 
363
        cmdLine.logAppend = params.count("logappend");
 
364
        if (!cmdLine.logpath.empty() && cmdLine.logWithSyslog) {
 
365
            cout << "Cant use both a logpath and syslog " << endl;
 
366
            return false;
 
367
        }
 
368
 
 
369
        if (cmdLine.doFork && cmdLine.logpath.empty() && !cmdLine.logWithSyslog) {
 
370
            cout << "--fork has to be used with --logpath or --syslog" << endl;
 
371
            return false;
 
372
        }
 
373
 
 
374
        if (params.count("keyFile")) {
 
375
            cmdLine.keyFile = params["keyFile"].as<string>();
 
376
        }
 
377
 
 
378
        if ( params.count("pidfilepath")) {
 
379
            cmdLine.pidFile = params["pidfilepath"].as<string>();
 
380
        }
 
381
 
 
382
        if (params.count("setParameter")) {
 
383
            std::vector<std::string> parameters =
 
384
                params["setParameter"].as<std::vector<std::string> >();
 
385
            for (size_t i = 0, length = parameters.size(); i < length; ++i) {
 
386
                std::string name;
 
387
                std::string value;
 
388
                if (!mongoutils::str::splitOn(parameters[i], '=', name, value)) {
 
389
                    cout << "Illegal option assignment: \"" << parameters[i] << "\"" << endl;
 
390
                    return false;
 
391
                }
 
392
                ServerParameter* parameter = mapFindWithDefault(
 
393
                        ServerParameterSet::getGlobal()->getMap(),
 
394
                        name,
 
395
                        static_cast<ServerParameter*>(NULL));
 
396
                if (NULL == parameter) {
 
397
                    cout << "Illegal --setParameter parameter: \"" << name << "\"" << endl;
 
398
                    return false;
 
399
                }
 
400
                if (!parameter->allowedToChangeAtStartup()) {
 
401
                    cout << "Cannot use --setParameter to set \"" << name << "\" at startup" <<
 
402
                        endl;
 
403
                    return false;
 
404
                }
 
405
                Status status = parameter->setFromString(value);
 
406
                if (!status.isOK()) {
 
407
                    cout << "Bad value for parameter \"" << name << "\": " << status.reason()
 
408
                         << endl;
 
409
                    return false;
 
410
                }
 
411
            }
 
412
        }
 
413
 
 
414
#ifdef MONGO_SSL
 
415
        if (params.count("sslWeakCertificateValidation")) {
 
416
            cmdLine.sslWeakCertificateValidation = true;
 
417
        }
 
418
        if (params.count("sslOnNormalPorts")) {
 
419
            cmdLine.sslOnNormalPorts = true;
 
420
            if ( cmdLine.sslPEMKeyFile.size() == 0 ) {
 
421
                log() << "need sslPEMKeyFile with sslOnNormalPorts" << endl;
 
422
                return false;
 
423
            }
 
424
            if (cmdLine.sslWeakCertificateValidation &&
 
425
                cmdLine.sslCAFile.empty()) {
 
426
                log() << "need sslCAFile with sslWeakCertificateValidation" << endl;
 
427
                return false;
 
428
            }
 
429
            if (!cmdLine.sslCRLFile.empty() &&
 
430
                cmdLine.sslCAFile.empty()) {
 
431
                log() << "need sslCAFile with sslCRLFile" << endl;
 
432
                return false;
 
433
            }
 
434
            if (params.count("sslFIPSMode")) {
 
435
                cmdLine.sslFIPSMode = true;
 
436
            }
 
437
        }
 
438
        else if (cmdLine.sslPEMKeyFile.size() || 
 
439
                 cmdLine.sslPEMKeyPassword.size() ||
 
440
                 cmdLine.sslCAFile.size() ||
 
441
                 cmdLine.sslCRLFile.size() ||
 
442
                 cmdLine.sslWeakCertificateValidation ||
 
443
                 cmdLine.sslFIPSMode) {
 
444
            log() << "need to enable sslOnNormalPorts" << endl;
 
445
            return false;
 
446
        }
 
447
#endif
513
448
 
514
449
        return true;
515
450
    }
516
451
 
 
452
    static bool _isPasswordArgument(const char* argumentName) {
 
453
        static const char* const passwordArguments[] = {
 
454
            "sslPEMKeyPassword",
 
455
            "servicePassword",
 
456
            NULL  // Last entry sentinel.
 
457
        };
 
458
        for (const char* const* current = passwordArguments; *current; ++current) {
 
459
            if (mongoutils::str::equals(argumentName, *current))
 
460
                return true;
 
461
        }
 
462
        return false;
 
463
    }
 
464
 
 
465
    static bool _isPasswordSwitch(const char* switchName) {
 
466
        if (switchName[0] != '-')
 
467
            return false;
 
468
        size_t i = 1;
 
469
        if (switchName[1] == '-')
 
470
            i = 2;
 
471
        switchName += i;
 
472
 
 
473
        return _isPasswordArgument(switchName);
 
474
    }
 
475
 
 
476
    static void _redact(char* arg) {
 
477
        for (; *arg; ++arg)
 
478
            *arg = 'x';
 
479
    }
 
480
 
 
481
    void CmdLine::censor(std::vector<std::string>* args) {
 
482
        for (size_t i = 0; i < args->size(); ++i) {
 
483
            std::string& arg = args->at(i);
 
484
            const std::string::iterator endSwitch = std::find(arg.begin(), arg.end(), '=');
 
485
            std::string switchName(arg.begin(), endSwitch);
 
486
            if (_isPasswordSwitch(switchName.c_str())) {
 
487
                if (endSwitch == arg.end()) {
 
488
                    if (i + 1 < args->size()) {
 
489
                        args->at(i + 1) = "<password>";
 
490
                    }
 
491
                }
 
492
                else {
 
493
                    arg = switchName + "=<password>";
 
494
                }
 
495
            }
 
496
        }
 
497
    }
 
498
 
 
499
    void CmdLine::censor(int argc, char** argv) {
 
500
        // Algorithm:  For each arg in argv:
 
501
        //   Look for an equal sign in arg; if there is one, temporarily nul it out.
 
502
        //   check to see if arg is a password switch.  If so, overwrite the value
 
503
        //     component with xs.
 
504
        //   restore the nul'd out equal sign, if any.
 
505
        for (int i = 0; i < argc; ++i) {
 
506
 
 
507
            char* const arg = argv[i];
 
508
            char* const firstEqSign = strchr(arg, '=');
 
509
            if (NULL != firstEqSign) {
 
510
                *firstEqSign = '\0';
 
511
            }
 
512
 
 
513
            if (_isPasswordSwitch(arg)) {
 
514
                if (NULL == firstEqSign) {
 
515
                    if (i + 1 < argc) {
 
516
                        _redact(argv[i + 1]);
 
517
                    }
 
518
                }
 
519
                else {
 
520
                    _redact(firstEqSign + 1);
 
521
                }
 
522
            }
 
523
 
 
524
            if (NULL != firstEqSign) {
 
525
                *firstEqSign = '=';
 
526
            }
 
527
        }
 
528
    }
 
529
 
517
530
    void printCommandLineOpts() {
518
531
        log() << "options: " << parsedOpts << endl;
519
532
    }
520
 
 
521
 
    void ignoreSignal( int sig ) {}
522
 
 
523
 
    static void rotateLogsOrDie(int sig) {
524
 
        fassert(16176, rotateLogs());
525
 
    }
526
 
 
527
 
    void setupCoreSignals() {
528
 
#if !defined(_WIN32)
529
 
        verify( signal(SIGUSR1 , rotateLogsOrDie ) != SIG_ERR );
530
 
        verify( signal(SIGHUP , ignoreSignal ) != SIG_ERR );
531
 
#endif
532
 
    }
533
 
 
534
 
    class CmdGetCmdLineOpts : Command {
535
 
    public:
536
 
        CmdGetCmdLineOpts(): Command("getCmdLineOpts") {}
537
 
        void help(stringstream& h) const { h << "get argv"; }
538
 
        virtual LockType locktype() const { return NONE; }
539
 
        virtual bool adminOnly() const { return true; }
540
 
        virtual bool slaveOk() const { return true; }
541
 
 
542
 
        virtual bool run(const string&, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
543
 
            result.append("argv", argvArray);
544
 
            result.append("parsed", parsedOpts);
545
 
            return true;
546
 
        }
547
 
 
548
 
    } cmdGetCmdLineOpts;
549
 
 
550
 
    string prettyHostName() {
551
 
        StringBuilder s;
552
 
        s << getHostNameCached();
553
 
        if( cmdLine.port != CmdLine::DefaultDBPort )
554
 
            s << ':' << mongo::cmdLine.port;
555
 
        return s.str();
556
 
    }
557
 
 
558
 
    casi< map<string,ParameterValidator*> * > pv_all (NULL);
559
 
 
560
 
    ParameterValidator::ParameterValidator( const string& name ) : _name( name ) {
561
 
        if ( ! pv_all)
562
 
            pv_all.ref() = new map<string,ParameterValidator*>();
563
 
        (*pv_all.ref())[_name] = this;
564
 
    }
565
 
    
566
 
    ParameterValidator * ParameterValidator::get( const string& name ) {
567
 
        map<string,ParameterValidator*>::const_iterator i = pv_all.get()->find( name );
568
 
        if ( i == pv_all.get()->end() )
569
 
            return NULL;
570
 
        return i->second;
571
 
    }
572
 
 
573
533
}