Beispiel #1
0
    bool CmdSaslStart::run(OperationContext* txn,
                           const std::string& db,
                           BSONObj& cmdObj,
                           int options,
                           std::string& ignored,
                           BSONObjBuilder& result,
                           bool fromRepl) {

        ClientBasic* client = ClientBasic::getCurrent();
        client->resetAuthenticationSession(NULL);

        SaslAuthenticationSession* session = 
            SaslAuthenticationSession::create(client->getAuthorizationSession());
        
        boost::scoped_ptr<AuthenticationSession> sessionGuard(session);

        session->setOpCtxt(txn);

        Status status = doSaslStart(session, db, cmdObj, &result);
        addStatus(status, &result);

        if (session->isDone()) {
            audit::logAuthentication(
                    client,
                    session->getMechanism(),
                    UserName(session->getPrincipalId(), db),
                    status.code());
        }
        else {
            client->swapAuthenticationSession(sessionGuard);
        }
        return status.isOK();
    }
Beispiel #2
0
    bool CmdSaslContinue::run(OperationContext* txn,
                              const std::string& db,
                              BSONObj& cmdObj,
                              int options,
                              std::string& ignored,
                              BSONObjBuilder& result,
                              bool fromRepl) {

        ClientBasic* client = ClientBasic::getCurrent();
        boost::scoped_ptr<AuthenticationSession> sessionGuard(NULL);
        client->swapAuthenticationSession(sessionGuard);

        if (!sessionGuard || sessionGuard->getType() != AuthenticationSession::SESSION_TYPE_SASL) {
            addStatus(Status(ErrorCodes::ProtocolError, "No SASL session state found"), &result);
            return false;
        }

        SaslAuthenticationSession* session =
            static_cast<SaslAuthenticationSession*>(sessionGuard.get());

        // Authenticating the __system@local user to the admin database on mongos is required
        // by the auth passthrough test suite.
        if (session->getAuthenticationDatabase() != db && !Command::testCommandsEnabled) {
            addStatus(Status(ErrorCodes::ProtocolError,
                             "Attempt to switch database target during SASL authentication."),
                      &result);
            return false;
        }

        session->setOpCtxt(txn);

        Status status = doSaslContinue(session, cmdObj, &result);
        addStatus(status, &result);

        if (session->isDone()) {
            audit::logAuthentication(
                    client,
                    session->getMechanism(),
                    UserName(session->getPrincipalId(), db),
                    status.code());
        }
        else {
            client->swapAuthenticationSession(sessionGuard);
        }

        return status.isOK();
    }
    Status CmdAuthenticate::_authenticateCR(const UserName& user, const BSONObj& cmdObj) {

        if (user == internalSecurity.user->getName() &&
            serverGlobalParams.clusterAuthMode == "x509") {
            return Status(ErrorCodes::AuthenticationFailed,
                          "Mechanism x509 is required for internal cluster authentication");
        }

        if (!_areNonceAuthenticateCommandsEnabled) {
            // SERVER-8461, MONGODB-CR must be enabled for authenticating the internal user, so that
            // cluster members may communicate with each other.
            if (user != internalSecurity.user->getName()) {
                return Status(ErrorCodes::BadValue, _nonceAuthenticateCommandsDisabledMessage);
            }
        }

        string key = cmdObj.getStringField("key");
        string received_nonce = cmdObj.getStringField("nonce");

        if( user.getUser().empty() || key.empty() || received_nonce.empty() ) {
            sleepmillis(10);
            return Status(ErrorCodes::ProtocolError,
                          "field missing/wrong type in received authenticate command");
        }

        stringstream digestBuilder;

        {
            ClientBasic *client = ClientBasic::getCurrent();
            boost::scoped_ptr<AuthenticationSession> session;
            client->swapAuthenticationSession(session);
            if (!session || session->getType() != AuthenticationSession::SESSION_TYPE_MONGO) {
                sleepmillis(30);
                return Status(ErrorCodes::ProtocolError, "No pending nonce");
            }
            else {
                nonce64 nonce = static_cast<MongoAuthenticationSession*>(session.get())->getNonce();
                digestBuilder << hex << nonce;
                if (digestBuilder.str() != received_nonce) {
                    sleepmillis(30);
                    return Status(ErrorCodes::AuthenticationFailed, "Received wrong nonce.");
                }
            }
        }

        User* userObj;
        Status status = getGlobalAuthorizationManager()->acquireUser(user, &userObj);
        if (!status.isOK()) {
            // Failure to find the privilege document indicates no-such-user, a fact that we do not
            // wish to reveal to the client.  So, we return AuthenticationFailed rather than passing
            // through the returned status.
            return Status(ErrorCodes::AuthenticationFailed, status.toString());
        }
        string pwd = userObj->getCredentials().password;
        getGlobalAuthorizationManager()->releaseUser(userObj);

        md5digest d;
        {
            digestBuilder << user.getUser() << pwd;
            string done = digestBuilder.str();

            md5_state_t st;
            md5_init(&st);
            md5_append(&st, (const md5_byte_t *) done.c_str(), done.size());
            md5_finish(&st, d);
        }

        string computed = digestToString( d );

        if ( key != computed ) {
            return Status(ErrorCodes::AuthenticationFailed, "key mismatch");
        }

        AuthorizationSession* authorizationSession =
            ClientBasic::getCurrent()->getAuthorizationSession();
        status = authorizationSession->addAndAuthorizeUser(user);
        if (!status.isOK()) {
            return status;
        }

        return Status::OK();
    }