Пример #1
0
// -----------------------------------------------------------------------------
// CSdpOriginField::ExternalizeL
// Externalizes the field back to string
// -----------------------------------------------------------------------------
//	
void CSdpOriginField::ExternalizeL(
    RWriteStream& aStream ) const
    {
    __TEST_INVARIANT;

    // <username>    
    aStream.WriteUint32L( UserName().Length() );
	aStream.WriteL( UserName(), UserName().Length() );
    // <session id>
    aStream.WriteUint32L( OriginFieldPtrs().SessionId().Length() );
    aStream.WriteL( OriginFieldPtrs().SessionId(),
    				OriginFieldPtrs().SessionId().Length() );
    // <version>
    aStream.WriteUint32L( OriginFieldPtrs().SessionVersion().Length() );
    aStream.WriteL( OriginFieldPtrs().SessionVersion(),
    				OriginFieldPtrs().SessionVersion().Length() );
    // <network type>
    aStream.WriteUint32L( iNetType.DesC().Length() );
    aStream.WriteL( iNetType.DesC() );
    // <address type>
    aStream.WriteUint32L( iAddressType.DesC().Length() );
    aStream.WriteL( iAddressType.DesC() );    
    // <address>
    aStream.WriteUint32L( iAddress.Length() );
    aStream.WriteL( iAddress );
    }
Пример #2
0
// -----------------------------------------------------------------------------
// CSdpOriginField::CloneL
// Creates an exact copy of the origin field
// -----------------------------------------------------------------------------
//
EXPORT_C CSdpOriginField* CSdpOriginField::CloneL() const
	{
	__TEST_INVARIANT;

    CSdpOriginField* obj = 0;

    if ( InetAddress() )
        {
        // Clones instance with TInetAddr
        TInetAddr addr( *InetAddress() );        
        obj = CSdpOriginField::NewLC( UserName(), KDummyValue,
        							  KDummyValue, addr );
        }
    else
        {
        // Clones instance with Internet address as a standard string               
        obj = CSdpOriginField::NewLC( UserName(), KDummyValue, KDummyValue,
                                      iNetType, iAddressType,  Address() );        
        }

	// Set the real values
	obj->OriginFieldPtrs().SetSessionIdL( OriginFieldPtrs().SessionId() );
	obj->OriginFieldPtrs().SetSessionVersionL(
		OriginFieldPtrs().SessionVersion() );
	CleanupStack::Pop( obj );
		
	__ASSERT_DEBUG( *this == *obj, User::Panic( KSdpCodecPanicCat, 
                                                KSdpCodecPanicInternal ) );
	return obj;
	}
StatusWith<bool> SaslPLAINServerConversation::step(StringData inputData, std::string* outputData) {
    // Expecting user input on the form: user\0user\0pwd
    std::string input = inputData.toString();
    std::string pwd = "";

    try {
        _user = input.substr(0, inputData.find('\0'));
        pwd = input.substr(inputData.find('\0', _user.size() + 1) + 1);
    } catch (std::out_of_range& exception) {
        return StatusWith<bool>(ErrorCodes::AuthenticationFailed,
                                mongoutils::str::stream()
                                    << "Incorrectly formatted PLAIN client message");
    }

    User* userObj;
    // The authentication database is also the source database for the user.
    Status status =
        _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().acquireUser(
            _saslAuthSession->getOpCtxt(),
            UserName(_user, _saslAuthSession->getAuthenticationDatabase()),
            &userObj);

    if (!status.isOK()) {
        return StatusWith<bool>(status);
    }

    const User::CredentialData creds = userObj->getCredentials();
    _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().releaseUser(userObj);

    std::string authDigest = createPasswordDigest(_user, pwd);

    if (!creds.password.empty()) {
        // Handle schemaVersion26Final (MONGODB-CR/SCRAM mixed mode)
        if (authDigest != creds.password) {
            return StatusWith<bool>(ErrorCodes::AuthenticationFailed,
                                    mongoutils::str::stream() << "Incorrect user name or password");
        }
    } else {
        // Handle schemaVersion28SCRAM (SCRAM only mode)
        unsigned char storedKey[scram::hashSize];
        unsigned char serverKey[scram::hashSize];

        scram::generateSecrets(
            authDigest,
            reinterpret_cast<const unsigned char*>(base64::decode(creds.scram.salt).c_str()),
            16,
            creds.scram.iterationCount,
            storedKey,
            serverKey);
        if (creds.scram.storedKey !=
            base64::encode(reinterpret_cast<const char*>(storedKey), scram::hashSize)) {
            return StatusWith<bool>(ErrorCodes::AuthenticationFailed,
                                    mongoutils::str::stream() << "Incorrect user name or password");
        }
    }

    *outputData = "";

    return StatusWith<bool>(true);
}
Пример #4
0
bool CmdSaslStart::run(OperationContext* txn,
                       const std::string& db,
                       BSONObj& cmdObj,
                       int options,
                       std::string& ignored,
                       BSONObjBuilder& result) {
    Client* client = Client::getCurrent();
    AuthenticationSession::set(client, std::unique_ptr<AuthenticationSession>());

    std::string mechanism;
    if (!extractMechanism(cmdObj, &mechanism).isOK()) {
        return false;
    }

    SaslAuthenticationSession* session =
        SaslAuthenticationSession::create(AuthorizationSession::get(client), db, mechanism);

    std::unique_ptr<AuthenticationSession> sessionGuard(session);

    session->setOpCtxt(txn);

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

    if (session->isDone()) {
        audit::logAuthentication(client,
                                 session->getMechanism(),
                                 UserName(session->getPrincipalId(), db),
                                 status.code());
    } else {
        AuthenticationSession::swap(client, sessionGuard);
    }
    return status.isOK();
}
Пример #5
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();
    }
    Status parseAndValidateRemoveUserCommand(const BSONObj& cmdObj,
                                             const std::string& dbname,
                                             UserName* parsedUserName,
                                             BSONObj* parsedWriteConcern) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert("removeUser");
        validFieldNames.insert("writeConcern");

        Status status = _checkNoExtraFields(cmdObj, "removeUser", validFieldNames);
        if (!status.isOK()) {
            return status;
        }

        std::string user;
        status = bsonExtractStringField(cmdObj, "removeUser", &user);
        if (!status.isOK()) {
            return status;
        }

        status = _extractWriteConcern(cmdObj, parsedWriteConcern);
        if (!status.isOK()) {
            return status;
        }

        *parsedUserName = UserName(user, dbname);
        return Status::OK();
    }
Пример #7
0
 DatabaseTagTestFixtureClass()
     : DatabaseTestFixtureClass("database_tag")
     , DatabaseTag() {
     DatabaseTag.Schema = UNICODE_STRING_SIMPLE("database_tag");
     DatabaseTag.Host = UNICODE_STRING_SIMPLE("127.0.0.1");
     DatabaseTag.User = t4p::CharToIcu(UserName().c_str());
     DatabaseTag.Password = t4p::CharToIcu(Password().c_str());
 }
Пример #8
0
bool TCred::CanControl(TCred &cred) const {
    if (IsRootUser() || Uid == cred.Uid)
        return true;

    if (cred.IsMemberOf(PORTO_CONT_GROUP_NAME))
        return true;

    return cred.IsMemberOf(UserName(Uid) + CONT_SUFFIX);
}
Пример #9
0
    bool CmdAuthenticate::authenticateX509(const string& dbname,
                                           BSONObj& cmdObj, 
                                           string& errmsg, 
                                           BSONObjBuilder& result) {
        if(dbname != "$external") {
            errmsg = "X.509 authentication must always use the $external database.";
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }

        std::string user = cmdObj.getStringField("user");
        ClientBasic *client = ClientBasic::getCurrent();
        AuthorizationSession* authorizationSession = client->getAuthorizationSession();
        StringData subjectName = client->port()->getX509SubjectName();
        
        if (user != subjectName) {
            errmsg = "There is no x.509 client certificate matching the user.";
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }
        else {
            StringData srvSubjectName = getSSLManager()->getSubjectName();
            StringData srvClusterId = srvSubjectName.substr(0, srvSubjectName.find("/CN")+1);
            StringData peerClusterId = subjectName.substr(0, subjectName.find("/CN")+1);

            // Handle internal cluster member 
            if (srvClusterId == peerClusterId) {
                authorizationSession->grantInternalAuthorization(UserName(user, "$external"));
            }
            // Handle normal client authentication
            else {
                Principal* principal = new Principal(UserName(user, "$external"));
                principal->setImplicitPrivilegeAcquisition(true);
                authorizationSession->addAuthorizedPrincipal(principal);
            }
            result.append( "dbname" , dbname );
            result.append( "user" , user );
            return true;
        }
    }
    Status parseUserRoleManipulationCommand(const BSONObj& cmdObj,
                                            const StringData& cmdName,
                                            const std::string& dbname,
                                            AuthorizationManager* authzManager,
                                            UserName* parsedUserName,
                                            vector<RoleName>* parsedRoleNames,
                                            BSONObj* parsedWriteConcern) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert(cmdName.toString());
        validFieldNames.insert("roles");
        validFieldNames.insert("writeConcern");

        Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames);
        if (!status.isOK()) {
            return status;
        }

        status = _extractWriteConcern(cmdObj, parsedWriteConcern);
        if (!status.isOK()) {
            return status;
        }

        std::string userNameStr;
        status = bsonExtractStringField(cmdObj, cmdName, &userNameStr);
        if (!status.isOK()) {
            return status;
        }
        *parsedUserName = UserName(userNameStr, dbname);

        BSONElement rolesElement;
        status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement);
        if (!status.isOK()) {
            return status;
        }

        status = _extractRoleNamesFromBSONArray(BSONArray(rolesElement.Obj()),
                                                dbname,
                                                authzManager,
                                                parsedRoleNames);
        if (!status.isOK()) {
            return status;
        }

        if (!parsedRoleNames->size()) {
            return Status(ErrorCodes::BadValue,
                          mongoutils::str::stream() << cmdName << " command requires a non-empty" <<
                                  " roles array");
        }
        return Status::OK();
    }
    MysqlResourceFinderFixtureClass()
        : DatabaseTestFixtureClass("sql_resource_finder")
        , SqliteTestFixtureClass(t4p::ResourceSqlSchemaAsset())
        , DatabaseTag()
        , Fetcher(SqliteTestFixtureClass::Session)
        , Finder(SqliteTestFixtureClass::Session) {
        DatabaseTag.Driver = t4p::DatabaseTagClass::MYSQL;
        DatabaseTag.Schema = UNICODE_STRING_SIMPLE("sql_resource_finder");

        // user name, pwd are #defines come from the premake script premake_opts.lua
        DatabaseTag.Host = UNICODE_STRING_SIMPLE("127.0.0.1");
        DatabaseTag.User = t4p::CharToIcu(UserName().c_str());
        DatabaseTag.Password = t4p::CharToIcu(Password().c_str());
    }
Пример #12
0
    MONGO_INITIALIZER_WITH_PREREQUISITES(SetupInternalSecurityUser, MONGO_NO_PREREQUISITES)(
            InitializerContext* context) {

        User* user = new User(UserName("__system", "local"));

        user->incrementRefCount(); // Pin this user so the ref count never drops below 1.
        ActionSet allActions;
        allActions.addAllActions();
        PrivilegeVector privileges;
        RoleGraph::generateUniversalPrivileges(&privileges);
        user->addPrivileges(privileges);
        internalSecurity.user = user;

        return Status::OK();
    }
Пример #13
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();
    }
    StatusWith<bool> SaslPLAINServerConversation::step(const StringData& inputData, 
                                                       std::string* outputData) {
        // Expecting user input on the form: user\0user\0pwd
        std::string input = inputData.toString();
        std::string pwd = "";
 
        try {
            _user = input.substr(0, inputData.find('\0'));
            pwd = input.substr(inputData.find('\0', _user.size()+1)+1);
        }
        catch (std::out_of_range& exception) {
            return StatusWith<bool>(ErrorCodes::AuthenticationFailed,
                mongoutils::str::stream() << "Incorrectly formatted PLAIN client message");
        }

        User* userObj;
        // The authentication database is also the source database for the user.
        Status status = _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().
                acquireUser(_saslAuthSession->getOpCtxt(),
                            UserName(_user, _saslAuthSession->getAuthenticationDatabase()),
                            &userObj);

        if (!status.isOK()) {
            return StatusWith<bool>(status);
        }

        const User::CredentialData creds = userObj->getCredentials();
        _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().
                releaseUser(userObj);

        std::string authDigest = createPasswordDigest(_user, pwd);
 
        if (authDigest != creds.password) {
            return StatusWith<bool>(ErrorCodes::AuthenticationFailed,
                mongoutils::str::stream() << "Incorrect user name or password");
        }

        *outputData = "";

        return StatusWith<bool>(true);
    }
Пример #15
0
bool CmdSaslContinue::run(OperationContext* opCtx,
                          const std::string& db,
                          const BSONObj& cmdObj,
                          BSONObjBuilder& result) {
    Client* client = Client::getCurrent();
    std::unique_ptr<AuthenticationSession> sessionGuard;
    AuthenticationSession::swap(client, sessionGuard);

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

    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) {
        return appendCommandStatus(
            result,
            Status(ErrorCodes::ProtocolError,
                   "Attempt to switch database target during SASL authentication."));
    }

    session->setOpCtxt(opCtx);

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

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

    return status.isOK();
}
Пример #16
0
// -----------------------------------------------------------------------------
// CSdpOriginField::operator ==
// Checks if two origin fields are equal
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CSdpOriginField::operator == (
    const CSdpOriginField& aObj) const
	{
	__TEST_INVARIANT;

    TBool equalFields = EFalse;

    // Check that username, session ID and address type match before
    // going to internet address       
    if ( ( UserName().CompareF( aObj.UserName() ) == 0 ) &&
         ( SessionId() == aObj.SessionId() ) &&
         ( AddressType() == aObj.AddressType() ) &&
         ( Version() == aObj.Version() ) &&
         ( NetType() == aObj.NetType() ) )
        {
        if ( InetAddress() && aObj.InetAddress() )
            {            
            if ( (*InetAddress()).Match( *aObj.InetAddress() ) )
                {
                equalFields = ETrue;
                }
            }
        else if ( !InetAddress() && !aObj.InetAddress() )            
            {
            if ( iAddress.CompareF( aObj.Address() ) == 0 )
                {
                equalFields = ETrue;
                }
            }                
        else
            {
            // These two are not the same
            }
        }   
        
    return equalFields;
	}
Пример #17
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {
            UpdateUserArgs args;
            Status status = _parseAndValidateInput(cmdObj, &args);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            // TODO: This update will have to change once we're using the new v2 user
            // storage format.
            BSONObjBuilder setBuilder;
            if (args.hasPassword) {
                std::string password = DBClientWithCommands::createPasswordDigest(
                        args.userName, args.clearTextPassword);
                setBuilder.append("pwd", password);
            }
            if (args.hasExtraData) {
                setBuilder.append("extraData", args.extraData);
            }
            BSONObj updateObj = BSON("$set" << setBuilder.obj());

            status = getGlobalAuthorizationManager()->updatePrivilegeDocument(
                    UserName(args.userName, dbname), updateObj);

            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            return true;
        }
    Status parseCreateOrUpdateUserCommands(const BSONObj& cmdObj,
                                           const StringData& cmdName,
                                           const std::string& dbname,
                                           CreateOrUpdateUserArgs* parsedArgs) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert(cmdName.toString());
        validFieldNames.insert("customData");
        validFieldNames.insert("digestPassword");
        validFieldNames.insert("pwd");
        validFieldNames.insert("roles");
        validFieldNames.insert("writeConcern");

        Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames);
        if (!status.isOK()) {
            return status;
        }

        status = _extractWriteConcern(cmdObj, &parsedArgs->writeConcern);
        if (!status.isOK()) {
            return status;
        }

        BSONObjBuilder userObjBuilder;

        // Parse user name
        std::string userName;
        status = bsonExtractStringField(cmdObj, cmdName, &userName);
        if (!status.isOK()) {
            return status;
        }

        parsedArgs->userName = UserName(userName, dbname);

        // Parse password
        if (cmdObj.hasField("pwd")) {
            std::string password;
            status = bsonExtractStringField(cmdObj, "pwd", &password);
            if (!status.isOK()) {
                return status;
            }
            if (password.empty()) {
                return Status(ErrorCodes::BadValue, "User passwords must not be empty");
            }

            bool digestPassword; // True if the server should digest the password
            status = bsonExtractBooleanFieldWithDefault(cmdObj,
                                                        "digestPassword",
                                                        true,
                                                        &digestPassword);
            if (!status.isOK()) {
                return status;
            }

            if (digestPassword) {
                parsedArgs->hashedPassword = auth::createPasswordDigest(userName, password);
            } else {
                parsedArgs->hashedPassword = password;
            }
            parsedArgs->hasHashedPassword = true;
        }

        // Parse custom data
        if (cmdObj.hasField("customData")) {
            BSONElement element;
            status = bsonExtractTypedField(cmdObj, "customData", Object, &element);
            if (!status.isOK()) {
                return status;
            }
            parsedArgs->customData = element.Obj();
            parsedArgs->hasCustomData = true;
        }

        // Parse roles
        if (cmdObj.hasField("roles")) {
            BSONElement rolesElement;
            status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement);
            if (!status.isOK()) {
                return status;
            }
            status = parseRoleNamesFromBSONArray(BSONArray(rolesElement.Obj()),
                                                 dbname,
                                                 &parsedArgs->roles);
            if (!status.isOK()) {
                return status;
            }
            parsedArgs->hasRoles = true;
        }

        return Status::OK();
    }
    Status parseCreateOrUpdateUserCommands(const BSONObj& cmdObj,
                                           const StringData& cmdName,
                                           const std::string& dbname,
                                           CreateOrUpdateUserArgs* parsedArgs) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert(cmdName.toString());
        validFieldNames.insert("customData");
        validFieldNames.insert("pwd");
        validFieldNames.insert("roles");
        validFieldNames.insert("writeConcern");

        Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames);
        if (!status.isOK()) {
            return status;
        }

        status = _extractWriteConcern(cmdObj, &parsedArgs->writeConcern);
        if (!status.isOK()) {
            return status;
        }

        BSONObjBuilder userObjBuilder;

        // Parse user name
        std::string userName;
        status = bsonExtractStringField(cmdObj, cmdName, &userName);
        if (!status.isOK()) {
            return status;
        }

        parsedArgs->userName = UserName(userName, dbname);

        // Parse password
        if (cmdObj.hasField("pwd")) {
            std::string clearTextPassword;
            status = bsonExtractStringField(cmdObj, "pwd", &clearTextPassword);
            if (!status.isOK()) {
                return status;
            }

            parsedArgs->hashedPassword = auth::createPasswordDigest(userName, clearTextPassword);
            parsedArgs->hasHashedPassword = true;
        }

        // Parse custom data
        if (cmdObj.hasField("customData")) {
            BSONElement element;
            status = bsonExtractTypedField(cmdObj, "customData", Object, &element);
            if (!status.isOK()) {
                return status;
            }
            parsedArgs->customData = element.Obj();
            parsedArgs->hasCustomData = true;
        }

        // Parse roles
        if (cmdObj.hasField("roles")) {
            BSONElement rolesElement;
            status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement);
            if (!status.isOK()) {
                return status;
            }
            status = _extractRoleDataFromBSONArray(rolesElement, dbname, &parsedArgs->roles);
            if (!status.isOK()) {
                return status;
            }
            parsedArgs->hasRoles = true;
        }

        return Status::OK();
    }
Пример #20
0
/*
 *******************************************************************
 * Function: int BehaviourFunction( const CKBehaviorContext& behaviorContext )
 *
 * Description : The execution function is the function that will be called 
 *               during the process loop of the behavior engine, if the behavior 
 *               is defined as using an execution function. This function is not 
 *               called if the behavior is defined as a graph. This function is the 
 *               heart of the behavior: it should compute the essence of the behavior, 
 *               in an incremental way. The minimum amount of computing should be 
 *               done at each call, to leave time for the other behaviors to run. 
 *               The function receives the delay in milliseconds that has elapsed 
 *               since the last behavioral process, and should rely on this value to 
 *               manage the amount of effect it has on its computation, if the effect 
 *               of this computation relies on time.
 *
 * Parameters :
 *    behaviourContext    r   Behavior context reference, which gives access to 
 *                            frequently used global objects ( context, level, manager, etc... )
 *
 * Returns : int, If it is done, it should return CKBR_OK. If it returns 
 *                CKBR_ACTIVATENEXTFRAME, the behavior will again be called 
 *                during the next process loop.
 *
 *******************************************************************
 */
int GBLPFCreate::BehaviourFunction( const CKBehaviorContext& behaviorContext )
{
    CKBehavior *behaviour=behaviorContext.Behavior;
    CKContext *context = behaviorContext.Context;
    CGBLCOError returnValue(CGBLCOError::EGBLCOErrorType::GBLCO_OK);
    CKBOOL newTeam = true;
    CKERROR check;

    behaviour->ActivateInput(EGBLCreateBehInputs::In, false);

      
    //newTeam = behaviour->IsInputParameterEnabled(EGBLCreateParamInputs::Teamname);
    
    CGBLUserID NewPlayerId;
    CGBLTeamID TeamId;
    
    CGBLProfileManager *pm = (CGBLProfileManager *)context->GetManagerByGuid(GBLProfileManagerGUID);
    
    int buf;
    check  = behaviour->GetInputParameterValue(EGBLCreateParamInputs::LAEID, &buf);
    if(check  != CK_OK|| buf==0)
    {
        newTeam = false;
    }
    CGBLLAEID LAEID(buf);
    XString TeamName((CKSTRING)behaviour->GetInputParameterReadDataPtr(EGBLCreateParamInputs::Teamname));                
    CGBLProfileManager::EGBLUserType  userType;
    behaviour->GetInputParameterValue(EGBLCreateParamInputs::Type, &userType);
    XString UserName((CKSTRING) behaviour->GetInputParameterReadDataPtr(EGBLCreateParamInputs::Username));
    
    
    if(newTeam)
    {
        returnValue = pm->CreateTeamProfile(&TeamId, LAEID, TeamName);
    }
    else   
    {
        returnValue = pm->CreatePlayerProfile(&NewPlayerId, userType, UserName);
    }
    
    
    if ((int)returnValue == CGBLCOError::EGBLCOErrorType::GBLCO_OK)
    {
        
        if (newTeam)//activate output with TeamId
        {
            behaviour->SetOutputParameterValue(EGBLCreateParamOutputs::ProfileId, &TeamId);
        }
        else //acitvate output  with PlayerId
        {
            behaviour->SetOutputParameterValue(EGBLCreateParamOutputs::ProfileId, &NewPlayerId);
        }
        behaviour->ActivateOutput(EGBLCreateBehOutputs::Success, true);
    }
    else
    {
        CKParameterOut *pOut = behaviour->GetOutputParameter(EGBLCreateParamOutputs::ErrorCode);
        CGBLCOError::EGBLCOErrorType tType = CGBLCOError::EGBLCOErrorType::GBLCO_OK ;
        switch((CGBLCOError::EGBLCOErrorType)returnValue)
        {
        case 0:
            tType = CGBLCOError::EGBLCOErrorType::GBLCO_OK;
            break;
        case 1:
            tType = CGBLCOError::EGBLCOErrorType::GBLCO_FATAL;
            break;
        case 2:
             tType = CGBLCOError::EGBLCOErrorType::GBLCO_LOCAL;
            break;
        case 3:
            tType = CGBLCOError::EGBLCOErrorType::GBLCO_LOCAL;
            break;
        }
        
        
		const char*errorString = returnValue;
        TGBLError::SetTGBLError(pOut, tType,returnValue, (CKSTRING)errorString);

        //behaviour->SetOutputParameterValue(EGBLCreateParamOutputs::ErrorCode, &returnValue);
        behaviour->ActivateOutput(EGBLCreateBehOutputs::Error, true);
    }
    return CKBR_OK;
}
    /*
     * Parse client-first-message of the form:
     * n,a=authzid,n=encoded-username,r=client-nonce
     *
     * Generate server-first-message on the form:
     * r=client-nonce|server-nonce,s=user-salt,i=iteration-count
     *
     * NOTE: we are ignoring the authorization ID part of the message
     */
    StatusWith<bool> SaslSCRAMSHA1ServerConversation::_firstStep(std::vector<string>& input,
                                                                 std::string* outputData) {
#ifndef MONGO_SSL
        return StatusWith<bool>(ErrorCodes::InternalError,
            "The server is not compiled with SSL support");
#else
        std::string authzId = "";

        if (input.size() == 4) {
            /* The second entry a=authzid is optional. If provided it will be
             * validated against the encoded username.
             *
             * The two allowed input forms are:
             * n,,n=encoded-username,r=client-nonce
             * n,a=authzid,n=encoded-username,r=client-nonce
             */
            if (!str::startsWith(input[1], "a=") || input[1].size() < 3) {
                return StatusWith<bool>(ErrorCodes::BadValue, mongoutils::str::stream() <<
                    "Incorrect SCRAM-SHA-1 authzid: " << input[1]);
            }
            authzId = input[1].substr(2);
            input.erase(input.begin() + 1);
        }

        if (input.size() != 3) {
            return StatusWith<bool>(ErrorCodes::BadValue, mongoutils::str::stream() <<
                "Incorrect number of arguments for first SCRAM-SHA-1 client message, got " <<
                input.size() << " expected 4");
        }
        else if (input[0] != "n") {
            return StatusWith<bool>(ErrorCodes::BadValue, mongoutils::str::stream() <<
                "Incorrect SCRAM-SHA-1 client message prefix: " << input[0]);
        }
        else if (!str::startsWith(input[1], "n=") || input[1].size() < 3) {
            return StatusWith<bool>(ErrorCodes::BadValue, mongoutils::str::stream() <<
                "Incorrect SCRAM-SHA-1 user name: " << input[1]);
        }
        else if(!str::startsWith(input[2], "r=") || input[2].size() < 6) {
            return StatusWith<bool>(ErrorCodes::BadValue, mongoutils::str::stream() <<
                "Incorrect SCRAM-SHA-1 client nonce: " << input[2]);
        }

        // add client-first-message-bare to _authMessage
        _authMessage += input[1] + "," + input[2] + ",";

        _user = input[1].substr(2);
        if (!authzId.empty() && _user != authzId) {
            return StatusWith<bool>(ErrorCodes::BadValue, mongoutils::str::stream() <<
                "SCRAM-SHA-1 user name " << _user << " does not match authzid " << authzId);
        }

        decodeSCRAMUsername(_user);
        std::string clientNonce = input[2].substr(2);

        // The authentication database is also the source database for the user.
        User* userObj;
        Status status = _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().
                acquireUser(_saslAuthSession->getOpCtxt(),
                            UserName(_user, _saslAuthSession->getAuthenticationDatabase()),
                            &userObj);

        if (!status.isOK()) {
            return StatusWith<bool>(status);
        }

        _creds = userObj->getCredentials();
        _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().
                releaseUser(userObj);

        // Generate SCRAM credentials on the fly for mixed MONGODB-CR/SCRAM mode.
        if (_creds.scram.salt.empty() && !_creds.password.empty()) {
            BSONObj scramCreds = scram::generateCredentials(_creds.password);
            _creds.scram.iterationCount = scramCreds["iterationCount"].Int();
            _creds.scram.salt = scramCreds["salt"].String();
            _creds.scram.storedKey = scramCreds["storedKey"].String();
            _creds.scram.serverKey = scramCreds["serverKey"].String();
        }

        // Generate server-first-message
        // Create text-based nonce as base64 encoding of a binary blob of length multiple of 3
        const int nonceLenQWords = 3;
        uint64_t binaryNonce[nonceLenQWords];

        scoped_ptr<SecureRandom> sr(SecureRandom::create());

        binaryNonce[0] = sr->nextInt64();
        binaryNonce[1] = sr->nextInt64();
        binaryNonce[2] = sr->nextInt64();

        _nonce = clientNonce +
            base64::encode(reinterpret_cast<char*>(binaryNonce), sizeof(binaryNonce));
        StringBuilder sb;
        sb << "r=" << _nonce <<
              ",s=" << _creds.scram.salt <<
              ",i=" << _creds.scram.iterationCount;
        *outputData = sb.str();

        // add server-first-message to authMessage
        _authMessage += *outputData + ",";

        return StatusWith<bool>(false);
#endif // MONGO_SSL
    }
    Status parseAndValidateUpdateUserCommand(const BSONObj& cmdObj,
                                             const std::string& dbname,
                                             AuthorizationManager* authzManager,
                                             BSONObj* parsedUpdateObj,
                                             UserName* parsedUserName,
                                             BSONObj* parsedWriteConcern) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert("updateUser");
        validFieldNames.insert("customData");
        validFieldNames.insert("pwd");
        validFieldNames.insert("roles");
        validFieldNames.insert("writeConcern");

        Status status = _checkNoExtraFields(cmdObj, "updateUser", validFieldNames);
        if (!status.isOK()) {
            return status;
        }

        status = _extractWriteConcern(cmdObj, parsedWriteConcern);
        if (!status.isOK()) {
            return status;
        }

        BSONObjBuilder updateSetBuilder;

        // Parse user name
        std::string userName;
        status = bsonExtractStringField(cmdObj, "updateUser", &userName);
        if (!status.isOK()) {
            return status;
        }
        *parsedUserName = UserName(userName, dbname);

        // Parse password
        if (cmdObj.hasField("pwd")) {
            std::string clearTextPassword;
            status = bsonExtractStringField(cmdObj, "pwd", &clearTextPassword);
            if (!status.isOK()) {
                return status;
            }

            std::string password = auth::createPasswordDigest(userName, clearTextPassword);
            updateSetBuilder.append("credentials.MONGODB-CR", password);
        }


        // Parse custom data
        if (cmdObj.hasField("customData")) {
            BSONElement element;
            status = bsonExtractTypedField(cmdObj, "customData", Object, &element);
            if (!status.isOK()) {
                return status;
            }
            updateSetBuilder.append("customData", element.Obj());
        }

        // Parse roles
        if (cmdObj.hasField("roles")) {
            BSONElement rolesElement;
            Status status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement);
            if (!status.isOK()) {
                return status;
            }

            BSONArray modifiedRolesObj;
            status = _validateAndModifyRolesArray(rolesElement,
                                                  dbname,
                                                  authzManager,
                                                  true,
                                                  &modifiedRolesObj);
            if (!status.isOK()) {
                return status;
            }

            updateSetBuilder.append("roles", modifiedRolesObj);
        }

        BSONObj updateSet = updateSetBuilder.obj();
        if (updateSet.isEmpty()) {
            return Status(ErrorCodes::UserModificationFailed,
                          "Must specify at least one field to update in updateUser");
        }

        *parsedUpdateObj = BSON("$set" << updateSet);
        return Status::OK();
    }
StatusWith<bool> SaslPLAINServerConversation::step(StringData inputData, std::string* outputData) {
    if (_saslAuthSession->getAuthenticationDatabase() == "$external") {
        return Status(ErrorCodes::AuthenticationFailed,
                      "PLAIN mechanism must be used with internal users");
    }

    // Expecting user input on the form: [authz-id]\0authn-id\0pwd
    std::string input = inputData.toString();

    SecureAllocatorAuthDomain::SecureString pwd = "";
    try {
        size_t firstNull = inputData.find('\0');
        if (firstNull == std::string::npos) {
            return Status(
                ErrorCodes::AuthenticationFailed,
                str::stream()
                    << "Incorrectly formatted PLAIN client message, missing first NULL delimiter");
        }
        size_t secondNull = inputData.find('\0', firstNull + 1);
        if (secondNull == std::string::npos) {
            return Status(
                ErrorCodes::AuthenticationFailed,
                str::stream()
                    << "Incorrectly formatted PLAIN client message, missing second NULL delimiter");
        }

        std::string authorizationIdentity = input.substr(0, firstNull);
        _user = input.substr(firstNull + 1, (secondNull - firstNull) - 1);
        if (_user.empty()) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "Incorrectly formatted PLAIN client message, empty username");
        } else if (!authorizationIdentity.empty() && authorizationIdentity != _user) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "SASL authorization identity must match authentication identity");
        }
        pwd = SecureAllocatorAuthDomain::SecureString(input.substr(secondNull + 1).c_str());
        if (pwd->empty()) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "Incorrectly formatted PLAIN client message, empty password");
        }
    } catch (std::out_of_range& exception) {
        return Status(ErrorCodes::AuthenticationFailed,
                      mongoutils::str::stream() << "Incorrectly formatted PLAIN client message");
    }

    User* userObj;
    // The authentication database is also the source database for the user.
    Status status =
        _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().acquireUser(
            _saslAuthSession->getOpCtxt(),
            UserName(_user, _saslAuthSession->getAuthenticationDatabase()),
            &userObj);

    if (!status.isOK()) {
        return StatusWith<bool>(status);
    }

    const User::CredentialData creds = userObj->getCredentials();
    _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().releaseUser(userObj);

    std::string authDigest = createPasswordDigest(_user, pwd->c_str());

    if (!creds.password.empty()) {
        // Handle schemaVersion26Final (MONGODB-CR/SCRAM mixed mode)
        if (authDigest != creds.password) {
            return StatusWith<bool>(ErrorCodes::AuthenticationFailed,
                                    mongoutils::str::stream() << "Incorrect user name or password");
        }
    } else {
        // Handle schemaVersion28SCRAM (SCRAM only mode)
        std::string decodedSalt = base64::decode(creds.scram.salt);
        scram::SCRAMSecrets secrets = scram::generateSecrets(scram::SCRAMPresecrets(
            authDigest,
            std::vector<std::uint8_t>(reinterpret_cast<const std::uint8_t*>(decodedSalt.c_str()),
                                      reinterpret_cast<const std::uint8_t*>(decodedSalt.c_str()) +
                                          16),
            creds.scram.iterationCount));
        if (creds.scram.storedKey !=
            base64::encode(reinterpret_cast<const char*>(secrets->storedKey.data()),
                           secrets->storedKey.size())) {
            return StatusWith<bool>(ErrorCodes::AuthenticationFailed,
                                    mongoutils::str::stream() << "Incorrect user name or password");
        }
    }

    *outputData = "";

    return StatusWith<bool>(true);
}
StatusWith<bool> SaslPLAINServerConversation::step(StringData inputData, std::string* outputData) {
    if (_saslAuthSession->getAuthenticationDatabase() == "$external") {
        return Status(ErrorCodes::AuthenticationFailed,
                      "PLAIN mechanism must be used with internal users");
    }

    // Expecting user input on the form: [authz-id]\0authn-id\0pwd
    std::string input = inputData.toString();

    SecureAllocatorAuthDomain::SecureString pwd = "";
    try {
        size_t firstNull = inputData.find('\0');
        if (firstNull == std::string::npos) {
            return Status(
                ErrorCodes::AuthenticationFailed,
                str::stream()
                    << "Incorrectly formatted PLAIN client message, missing first NULL delimiter");
        }
        size_t secondNull = inputData.find('\0', firstNull + 1);
        if (secondNull == std::string::npos) {
            return Status(
                ErrorCodes::AuthenticationFailed,
                str::stream()
                    << "Incorrectly formatted PLAIN client message, missing second NULL delimiter");
        }

        std::string authorizationIdentity = input.substr(0, firstNull);
        _user = input.substr(firstNull + 1, (secondNull - firstNull) - 1);
        if (_user.empty()) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "Incorrectly formatted PLAIN client message, empty username");
        } else if (!authorizationIdentity.empty() && authorizationIdentity != _user) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "SASL authorization identity must match authentication identity");
        }
        pwd = SecureAllocatorAuthDomain::SecureString(input.substr(secondNull + 1).c_str());
        if (pwd->empty()) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "Incorrectly formatted PLAIN client message, empty password");
        }
    } catch (std::out_of_range&) {
        return Status(ErrorCodes::AuthenticationFailed,
                      mongoutils::str::stream() << "Incorrectly formatted PLAIN client message");
    }

    User* userObj;
    // The authentication database is also the source database for the user.
    Status status =
        _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().acquireUser(
            _saslAuthSession->getOpCtxt(),
            UserName(_user, _saslAuthSession->getAuthenticationDatabase()),
            &userObj);

    if (!status.isOK()) {
        return status;
    }

    const auto creds = userObj->getCredentials();
    _saslAuthSession->getAuthorizationSession()->getAuthorizationManager().releaseUser(userObj);

    *outputData = "";
    const auto sha256Status = trySCRAM<SHA256Block>(creds, pwd->c_str());
    if (!sha256Status.isOK()) {
        return sha256Status;
    }
    if (sha256Status.getValue()) {
        return true;
    }

    const auto authDigest = createPasswordDigest(_user, pwd->c_str());
    const auto sha1Status = trySCRAM<SHA1Block>(creds, authDigest);
    if (!sha1Status.isOK()) {
        return sha1Status;
    }
    if (sha1Status.getValue()) {
        return true;
    }

    return Status(ErrorCodes::AuthenticationFailed, str::stream() << "No credentials available.");
}
StatusWith<std::tuple<bool, std::string>> SASLPlainServerMechanism::stepImpl(
    OperationContext* opCtx, StringData inputData) {
    if (_authenticationDatabase == "$external") {
        return Status(ErrorCodes::AuthenticationFailed,
                      "PLAIN mechanism must be used with internal users");
    }

    AuthorizationManager* authManager = AuthorizationManager::get(opCtx->getServiceContext());

    // Expecting user input on the form: [authz-id]\0authn-id\0pwd
    std::string input = inputData.toString();

    SecureAllocatorAuthDomain::SecureString pwd = "";
    try {
        size_t firstNull = inputData.find('\0');
        if (firstNull == std::string::npos) {
            return Status(
                ErrorCodes::AuthenticationFailed,
                str::stream()
                    << "Incorrectly formatted PLAIN client message, missing first NULL delimiter");
        }
        size_t secondNull = inputData.find('\0', firstNull + 1);
        if (secondNull == std::string::npos) {
            return Status(
                ErrorCodes::AuthenticationFailed,
                str::stream()
                    << "Incorrectly formatted PLAIN client message, missing second NULL delimiter");
        }

        std::string authorizationIdentity = input.substr(0, firstNull);
        ServerMechanismBase::_principalName =
            input.substr(firstNull + 1, (secondNull - firstNull) - 1);
        if (ServerMechanismBase::_principalName.empty()) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "Incorrectly formatted PLAIN client message, empty username");
        } else if (!authorizationIdentity.empty() &&
                   authorizationIdentity != ServerMechanismBase::_principalName) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "SASL authorization identity must match authentication identity");
        }
        pwd = SecureAllocatorAuthDomain::SecureString(input.substr(secondNull + 1).c_str());
        if (pwd->empty()) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "Incorrectly formatted PLAIN client message, empty password");
        }
    } catch (std::out_of_range&) {
        return Status(ErrorCodes::AuthenticationFailed,
                      str::stream() << "Incorrectly formatted PLAIN client message");
    }

    // The authentication database is also the source database for the user.
    auto swUser = authManager->acquireUser(
        opCtx, UserName(ServerMechanismBase::_principalName, _authenticationDatabase));

    if (!swUser.isOK()) {
        return swUser.getStatus();
    }

    auto userObj = std::move(swUser.getValue());
    const auto creds = userObj->getCredentials();

    const auto sha256Status = trySCRAM<SHA256Block>(creds, pwd->c_str());
    if (!sha256Status.isOK()) {
        return sha256Status.getStatus();
    }
    if (sha256Status.getValue()) {
        return std::make_tuple(true, std::string());
    }

    const auto authDigest = createPasswordDigest(ServerMechanismBase::_principalName, pwd->c_str());
    const auto sha1Status = trySCRAM<SHA1Block>(creds, authDigest);
    if (!sha1Status.isOK()) {
        return sha1Status.getStatus();
    }
    if (sha1Status.getValue()) {
        return std::make_tuple(true, std::string());
    }

    return Status(ErrorCodes::AuthenticationFailed, str::stream() << "No credentials available.");


    return std::make_tuple(true, std::string());
}
Пример #26
0
    void WriteBackListener::run() {

        int secsToSleep = 0;
        scoped_ptr<ChunkVersion> lastNeededVersion;
        int lastNeededCount = 0;
        bool needsToReloadShardInfo = false;

        while ( ! inShutdown() ) {

            if ( ! Shard::isAShardNode( _addr ) ) {
                LOG(1) << _addr << " is not a shard node" << endl;
                sleepsecs( 60 );
                continue;
            }

            try {
                if (needsToReloadShardInfo) {
                    // It's possible this shard was removed
                    Shard::reloadShardInfo();
                    needsToReloadShardInfo = false;
                }

                ScopedDbConnection conn(_addr);

                BSONObj result;

                {
                    BSONObjBuilder cmd;
                    cmd.appendOID( "writebacklisten" , &serverID ); // Command will block for data
                    if ( ! conn->runCommand( "admin" , cmd.obj() , result ) ) {
                        result = result.getOwned();
                        log() <<  "writebacklisten command failed!  "  << result << endl;
                        conn.done();
                        continue;
                    }

                }
                conn.done();

                LOG(1) << "writebacklisten result: " << result << endl;

                BSONObj data = result.getObjectField( "data" );
                if ( data.getBoolField( "writeBack" ) ) {
                    string ns = data["ns"].valuestrsafe();

                    ConnectionIdent cid( "" , 0 );
                    OID wid;
                    if ( data["connectionId"].isNumber() && data["id"].type() == jstOID ) {
                        string s = "";
                        if ( data["instanceIdent"].type() == String )
                            s = data["instanceIdent"].String();
                        cid = ConnectionIdent( s , data["connectionId"].numberLong() );
                        wid = data["id"].OID();
                    }
                    else {
                        warning() << "mongos/mongod version mismatch (1.7.5 is the split)" << endl;
                    }

                    int len; // not used, but needed for next call
                    Message msg( (void*)data["msg"].binData( len ) , false );
                    massert( 10427 ,  "invalid writeback message" , msg.header()->valid() );

                    DBConfigPtr db = grid.getDBConfig( ns );
                    ChunkVersion needVersion = ChunkVersion::fromBSON( data, "version" );

                    //
                    // TODO: Refactor the sharded strategy to correctly handle all sharding state changes itself,
                    // we can't rely on WBL to do this for us b/c anything could reset our state in-between.
                    // We should always reload here for efficiency when possible, but staleness is also caught in the
                    // loop below.
                    //

                    ChunkManagerPtr manager;
                    ShardPtr primary;
                    db->getChunkManagerOrPrimary( ns, manager, primary );

                    ChunkVersion currVersion;
                    if( manager ) currVersion = manager->getVersion();

                    LOG(1) << "connectionId: " << cid << " writebackId: " << wid << " needVersion : " << needVersion.toString()
                           << " mine : " << currVersion.toString() << endl;

                    LOG(1) << msg.toString() << endl;

                    //
                    // We should reload only if we need to update our version to be compatible *and* we
                    // haven't already done so.  This avoids lots of reloading when we remove/add a sharded collection
                    //

                    bool alreadyReloaded = lastNeededVersion &&
                                           lastNeededVersion->isEquivalentTo( needVersion );

                    if( alreadyReloaded ){

                        LOG(1) << "wbl already reloaded config information for version "
                               << needVersion << ", at version " << currVersion << endl;
                    }
                    else if( lastNeededVersion ) {

                        log() << "new version change detected to " << needVersion.toString()
                              << ", " << lastNeededCount << " writebacks processed at "
                              << lastNeededVersion->toString() << endl;

                        lastNeededCount = 0;
                    }

                    //
                    // Set our lastNeededVersion for next time
                    //

                    lastNeededVersion.reset( new ChunkVersion( needVersion ) );
                    lastNeededCount++;

                    //
                    // Determine if we should reload, if so, reload
                    //

                    bool shouldReload = ! needVersion.isWriteCompatibleWith( currVersion ) &&
                                        ! alreadyReloaded;

                    if( shouldReload && currVersion.isSet()
                                     && needVersion.isSet()
                                     && currVersion.hasCompatibleEpoch( needVersion ) )
                    {

                        //
                        // If we disagree about versions only, reload the chunk manager
                        //

                        db->getChunkManagerIfExists( ns, true );
                    }
                    else if( shouldReload ){

                        //
                        // If we disagree about anything else, reload the full db
                        //

                        warning() << "reloading config data for " << db->getName() << ", "
                                  << "wanted version " << needVersion.toString()
                                  << " but currently have version " << currVersion.toString() << endl;

                        db->reload();
                    }

                    // do request and then call getLastError
                    // we have to call getLastError so we can return the right fields to the user if they decide to call getLastError

                    BSONObj gle;
                    int attempts = 0;
                    while ( true ) {
                        attempts++;

                        try {

                            Request r( msg , 0 );
                            r.init();

                            r.d().reservedField() |= Reserved_FromWriteback;

                            ClientInfo * ci = r.getClientInfo();
                            if (AuthorizationManager::isAuthEnabled()) {
                                ci->getAuthorizationSession()->grantInternalAuthorization(
                                        UserName("_writebackListener", "local"));
                            }
                            ci->noAutoSplit();

                            r.process( attempts );

                            ci->newRequest(); // this so we flip prev and cur shards

                            BSONObjBuilder b;
                            string errmsg;
                            if ( ! ci->getLastError( "admin",
                                                     BSON( "getLastError" << 1 ),
                                                     b,
                                                     errmsg,
                                                     true ) )
                            {
                                b.appendBool( "commandFailed" , true );
                                if( ! b.hasField( "errmsg" ) ){

                                    b.append( "errmsg", errmsg );
                                    gle = b.obj();
                                }
                                else if( errmsg.size() > 0 ){

                                    // Rebuild GLE object with errmsg
                                    // TODO: Make this less clumsy by improving GLE interface
                                    gle = b.obj();

                                    if( gle["errmsg"].type() == String ){

                                        BSONObj gleNoErrmsg =
                                                gle.filterFieldsUndotted( BSON( "errmsg" << 1 ),
                                                                          false );
                                        BSONObjBuilder bb;
                                        bb.appendElements( gleNoErrmsg );
                                        bb.append( "errmsg", gle["errmsg"].String() +
                                                             " ::and:: " +
                                                             errmsg );
                                        gle = bb.obj().getOwned();
                                    }
                                }
                            }
                            else{
                                gle = b.obj();
                            }

                            if ( gle["code"].numberInt() == 9517 ) {

                                log() << "new version change detected, "
                                      << lastNeededCount << " writebacks processed previously" << endl;

                                lastNeededVersion.reset();
                                lastNeededCount = 1;

                                log() << "writeback failed because of stale config, retrying attempts: " << attempts << endl;
                                LOG(1) << "writeback error : " << gle << endl;

                                //
                                // Bringing this in line with the similar retry logic elsewhere
                                //
                                // TODO: Reloading the chunk manager may not help if we dropped a
                                // collection, but we don't actually have that info in the writeback
                                // error
                                //

                                if( attempts <= 2 ){
                                    db->getChunkManagerIfExists( ns, true );
                                }
                                else{
                                    versionManager.forceRemoteCheckShardVersionCB( ns );
                                    sleepsecs( attempts - 1 );
                                }

                                uassert( 15884, str::stream()
                                         << "Could not reload chunk manager after "
                                         << attempts << " attempts.", attempts <= 4 );

                                continue;
                            }

                            ci->clearSinceLastGetError();
                        }
                        catch ( DBException& e ) {
                            error() << "error processing writeback: " << e << endl;
                            BSONObjBuilder b;
                            e.getInfo().append( b, "err", "code" );
                            gle = b.obj();
                        }

                        break;
                    }

                    {
                        scoped_lock lk( _seenWritebacksLock );
                        WBStatus& s = _seenWritebacks[cid];
                        s.id = wid;
                        s.gle = gle;
                    }
                }
                else if ( result["noop"].trueValue() ) {
                    // no-op
                }
                else {
                    log() << "unknown writeBack result: " << result << endl;
                }

                secsToSleep = 0;
                continue;
            }
            catch ( std::exception& e ) {
                // Attention! Do not call any method that would throw an exception
                // (or assert) in this block.

                if ( inShutdown() ) {
                    // we're shutting down, so just clean up
                    return;
                }

                log() << "WriteBackListener exception : " << e.what() << endl;

                needsToReloadShardInfo = true;
            }
            catch ( ... ) {
                log() << "WriteBackListener uncaught exception!" << endl;
            }
            secsToSleep++;
            sleepsecs(secsToSleep);
            if ( secsToSleep > 10 )
                secsToSleep = 0;
        }

        log() << "WriteBackListener exiting : address no longer in cluster " << _addr;

    }
Пример #27
0
    bool CmdAuthenticate::authenticateCR(const string& dbname, 
                                         BSONObj& cmdObj, 
                                         string& errmsg, 
                                         BSONObjBuilder& result) {
        
        string user = cmdObj.getStringField("user");

        if (!_areNonceAuthenticateCommandsEnabled) {
            // SERVER-8461, MONGODB-CR must be enabled for authenticating the internal user, so that
            // cluster members may communicate with each other.
            if (dbname != StringData("local", StringData::LiteralTag()) ||
                user != internalSecurity.user) {
                errmsg = _nonceAuthenticateCommandsDisabledMessage;
                result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
                return false;
            }
        }

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

        if( user.empty() || key.empty() || received_nonce.empty() ) {
            log() << "field missing/wrong type in received authenticate command "
                  << dbname
                  << endl;
            errmsg = "auth fails";
            sleepmillis(10);
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }

        stringstream digestBuilder;

        {
            bool reject = false;
            ClientBasic *client = ClientBasic::getCurrent();
            AuthenticationSession *session = client->getAuthenticationSession();
            if (!session || session->getType() != AuthenticationSession::SESSION_TYPE_MONGO) {
                reject = true;
                LOG(1) << "auth: No pending nonce" << endl;
            }
            else {
                nonce64 nonce = static_cast<MongoAuthenticationSession*>(session)->getNonce();
                digestBuilder << hex << nonce;
                reject = digestBuilder.str() != received_nonce;
                if ( reject ) {
                    LOG(1) << "auth: Authentication failed for " << dbname << '$' << user << endl;
                }
            }
            client->resetAuthenticationSession(NULL);

            if ( reject ) {
                log() << "auth: bad nonce received or getnonce not called. could be a driver bug or a security attack. db:" << dbname << endl;
                errmsg = "auth fails";
                sleepmillis(30);
                result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
                return false;
            }
        }

        BSONObj userObj;
        string pwd;
        Status status = getGlobalAuthorizationManager()->getPrivilegeDocument(
                dbname, UserName(user, dbname), &userObj);
        if (!status.isOK()) {
            log() << status.reason() << std::endl;
            errmsg = "auth fails";
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }
        pwd = userObj["pwd"].String();

        md5digest d;
        {
            digestBuilder << user << 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 ) {
            log() << "auth: key mismatch " << user << ", ns:" << dbname << endl;
            errmsg = "auth fails";
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }

        AuthorizationSession* authorizationSession =
            ClientBasic::getCurrent()->getAuthorizationSession();
        Principal* principal = new Principal(UserName(user, dbname));
        principal->setImplicitPrivilegeAcquisition(true);
        authorizationSession->addAuthorizedPrincipal(principal);

        result.append( "dbname" , dbname );
        result.append( "user" , user );
        return true;
    }
Пример #28
0
 const string& GetUserName(void) const
 {
     return UserName();
 }
    Status parseAndValidateUpdateUserCommand(const BSONObj& cmdObj,
                                             const std::string& dbname,
                                             AuthorizationManager* authzManager,
                                             BSONObj* parsedUpdateObj,
                                             UserName* parsedUserName) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert("updateUser");
        validFieldNames.insert("customData");
        validFieldNames.insert("pwd");
        validFieldNames.insert("roles");
        validFieldNames.insert("writeConcern");

        // Iterate through all fields in command object and make sure there are no unexpected
        // ones.
        for (BSONObjIterator iter(cmdObj); iter.more(); iter.next()) {
            StringData fieldName = (*iter).fieldNameStringData();
            if (!validFieldNames.count(fieldName.toString())) {
                return Status(ErrorCodes::BadValue,
                              mongoutils::str::stream() << "\"" << fieldName << "\" is not "
                                      "a valid argument to createUser");
            }
        }

        BSONObjBuilder updateSetBuilder;

        // Parse user name
        std::string userName;
        Status status = bsonExtractStringField(cmdObj, "updateUser", &userName);
        if (!status.isOK()) {
            return status;
        }
        *parsedUserName = UserName(userName, dbname);

        // Parse password
        if (cmdObj.hasField("pwd")) {
            std::string clearTextPassword;
            status = bsonExtractStringField(cmdObj, "pwd", &clearTextPassword);
            if (!status.isOK()) {
                return status;
            }

            std::string password = auth::createPasswordDigest(userName, clearTextPassword);
            updateSetBuilder.append("credentials.MONGODB-CR", password);
        }


        // Parse custom data
        if (cmdObj.hasField("customData")) {
            BSONElement element;
            status = bsonExtractTypedField(cmdObj, "customData", Object, &element);
            if (!status.isOK()) {
                return status;
            }
            updateSetBuilder.append("customData", element.Obj());
        }

        // Parse roles
        if (cmdObj.hasField("roles")) {
            BSONElement rolesElement;
            Status status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement);
            if (!status.isOK()) {
                return status;
            }

            BSONArray modifiedRolesObj;
            status = _validateAndModifyRolesArray(rolesElement,
                                                  dbname,
                                                  authzManager,
                                                  &modifiedRolesObj);
            if (!status.isOK()) {
                return status;
            }

            updateSetBuilder.append("roles", modifiedRolesObj);
        }

        BSONObj updateSet = updateSetBuilder.obj();
        if (updateSet.isEmpty()) {
            return Status(ErrorCodes::UserModificationFailed,
                          "Must specify at least one field to update in updateUser");
        }

        *parsedUpdateObj = BSON("$set" << updateSet);
        return Status::OK();
    }