/** * Copyright (C) 2018-present MongoDB, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the Server Side Public License, version 1, * as published by MongoDB, Inc. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Server Side Public License for more details. * * You should have received a copy of the Server Side Public License * along with this program. If not, see * . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the Server Side Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ #pragma once #include #include #include "mongo/base/disallow_copying.h" #include "mongo/base/status.h" #include "mongo/base/string_data.h" #include "mongo/stdx/functional.h" namespace mongo { /** * Base class for the client side of a SASL authentication conversation. * * To use, create an instance, then use setParameter() to configure the authentication * parameters. Once all parameters are set, call initialize() to initialize the client state * machine. Finally, use repeated calls to step() to generate messages to send to the server * and process server responses. * * The required parameters vary by mechanism, but all mechanisms require parameterServiceName, * parameterServiceHostname, parameterMechanism and parameterUser. All of the required * parameters must be UTF-8 encoded strings with no embedded NUL characters. The * parameterPassword parameter is not constrained. */ class SaslClientSession { MONGO_DISALLOW_COPYING(SaslClientSession); public: typedef stdx::function SaslClientSessionFactoryFn; static SaslClientSessionFactoryFn create; /** * Identifiers of parameters used to configure a SaslClientSession. */ enum Parameter { parameterServiceName = 0, parameterServiceHostname, parameterServiceHostAndPort, parameterMechanism, parameterUser, parameterPassword, numParameters // Must be last }; SaslClientSession(); virtual ~SaslClientSession(); /** * Sets the parameter identified by "id" to "value". * * The value of "id" must be one of the legal values of Parameter less than numParameters. * May be called repeatedly for the same value of "id", with the last "value" replacing * previous values. * * The session object makes and owns a copy of the data in "value". */ virtual void setParameter(Parameter id, StringData value); /** * Returns true if "id" identifies a parameter previously set by a call to setParameter(). */ virtual bool hasParameter(Parameter id); /** * Returns the value of a previously set parameter. * * If parameter "id" was never set, returns an empty StringData. Note that a parameter may * be explicitly set to StringData(), so use hasParameter() to distinguish those cases. * * The session object owns the storage behind the returned StringData, which will remain * valid until setParameter() is called with the same value of "id", or the session object * goes out of scope. */ virtual StringData getParameter(Parameter id); /** * Initializes a session for use. * * Call exactly once, after setting any parameters you intend to set via setParameter(). */ virtual Status initialize() = 0; /** * Takes one step of the SASL protocol on behalf of the client. * * Caller should provide data from the server side of the conversation in "inputData", or an * empty StringData() if none is available. If the client should make a response to the * server, stores the response into "*outputData". * * Returns Status::OK() on success. Any other return value indicates a failed * authentication, though the specific return value may provide insight into the cause of * the failure (e.g., ProtocolError, AuthenticationFailed). * * In the event that this method returns Status::OK(), consult the value of isDone() to * determine if the conversation has completed. When step() returns Status::OK() and * isDone() returns true, authentication has completed successfully. */ virtual Status step(StringData inputData, std::string* outputData) = 0; /** * Returns true if the authentication completed successfully. */ virtual bool isDone() const = 0; private: /** * Buffer object that owns data for a single parameter. */ struct DataBuffer { std::unique_ptr data; size_t size; }; /// Buffers for each of the settable parameters. DataBuffer _parameters[numParameters]; }; } // namespace mongo