#ifndef __AUTHN_CANLXX_H__ #define __AUTHN_CANLXX_H__ #include #include #include #include #include #include #include #include /// \mainpage Introduction /// /// \section overview Overview /// /// The API consists of classes allowing for X.509 certificate creation, validation, /// SSL/TLS connection management. Implementation is based on OpenSSL and provides /// limited access to underlying OpenSSL objects for extensibility purposes. /// /// All classes are nested inside AuthN namespace and are separated by /// by functionality. This API mostly provides basic classes for performing basic /// operations. There is very limited hierarchy available. For specific functionality /// users are urged to extend existing functionality by inheriting own classes /// from those provided by this API. For this purpose provided classes have only /// limited amount of private members and also expose internal OpenSSL objects. /// /// Following is short description of purpose of defined classes. For more /// information pease see full description of classes and their members. /// /// \section context_class The Context class /// /// This class provides a way to tune automatic behavior of other classes making /// tools built on top of them suitable for different environments - client /// or service, secure or relaxed. It acts as bag of attributes which is accepted /// by constructors of otther classes. /// /// \section credenials_class The Credentials class /// /// This and related classes - CredentialsRequest, CACredentialsRequest, /// ProxyCredentialsRequest - provide in-memory storage and management capability /// of managing X.509 certificates and private keys. User can extract and manipulate /// attributes of X.509 certificate and generate new certificates. /// /// \section io_class The IO class /// /// This and inheriting classes are implementing TLS/SSL communication over /// various media. Implemented are TCP, third-party socket and OpenSSL BIO. /// /// \section validator_class The Validator class /// /// This class implementis method for performing Credentials validation. /// The validation is performed according to assigned options. For more /// specific and more complex validation functionality of this class may /// by extended by user. /// /// \section rules Common usage rules /// /// Because this API does not throw exception to report failure in /// constructor following approach is adopted. If constructor /// fails created object is marked as invalid. Validity of each object - /// except Status - can be checked by casting it to boolean or /// by performing ! operation. /// /// Unless specifically stated otherwise all failing methods /// leave valid objects in valid and - if possible - unchanged state. /// /// Following memory management rules are adopted in this API. /// /// 1. Owner of object is code which created it. Objects created /// by API are deleted by API. Objects created by user code /// must be deleted by user code. /// /// 2. Whenever possible objects are passed by references. Objects /// passed to methods by reference are either used only during /// execution of those methods or copy is made for later use. /// In case object's reference is needed out of scope of method /// execution it is clearly stated in description of method and /// required lifetime is always defined. /// /// 3. Passing by pointers is not used for objects defined by this API. /// /// All methods of all classes are thread-safe. User code can freely /// call any method of any object from multiple threads unless stated /// otherwise in description of method. But care must always be taken /// concerning memory management (like concurently using and /// destroying object in separate threads). namespace AuthN { namespace OpenSSL { class CertContext; class KeyContext; class CSRContext; }; class Context; class Credentials; class CredentialsRequest; class Validator; class IO; /// Result of execution. /// This class represents result of every call. Every API method reports /// result by returning object of this class. No method will throw exception /// (for compatibility reasons). All results are resported only through Status. /// Zero is only positive numeric code. Other codes represent some failures. /// Actual values are mostly not defined and are used only internally. Some /// special cases may have codes defined in corresponding classes. class Status { public: /// Constructor with success as default. Status(int code = 0); /// Constructor which assigns human readable description of error. Status(int code, const std::string& description); /// Casting to int returns error code. operator int(void) const { return code_; }; /// Getter method for obtaining error code. int GetCode(void) const { return code_; }; /// Comparison of results by code. bool operator==(const Status& s) const { return (code_==s.code_); }; /// Returns (hopefuly) user-friendly description /// Description is meant for reporting errors to humans std::string GetDescription(void) const { return description_; }; /// Returns true if result is positive operator bool(void) { return (code_==0); }; /// Returns true if result represent failure bool operator!(void) { return (code_!=0); }; private: int code_; std::string description_; }; /// This class defines environment in which other classes are functioning. /// Type of context may affect various decisions made during authentication /// and validation procedures as well as during initialization of default values. /// It also holds information needed for establishing valid X.509 environement. /// This object does not hold credentials themselves, only information /// useful to retrieving/detecting them. class Context { public: /// Set of predefined ways to specify authentication attributes. typedef enum { /// Nothing is predefined. /// No values are initialiized and created object is marked invalid. EmptyContext, /// Collects information needed for user tool. /// 1. Environment variable X509_USER_PROXY is used to set CertPath /// and KeyPath. /// 2. If X509_USER_PROXY is missing then environment variables /// X509_USER_CERT and X509_USER_KEY are used to set CertPath /// and KeyPath accordingly. /// 3. If any of previous variables are missing then corresponding /// values are set to default ~/.emi/usercert.pem and ~/.emi/userkey.pem. /// 4. Environment variable X509_CERT_DIR is used to set CAPath. /// 5. If X509_CERT_DIR is missing then CAPath is set to default value /// /etc/grid-security/certificates. /// 6. Environment variable X509_CRL_DIR is used to set CAPath. /// 7. If X509_CRL_DIR is missing then X509_CERT_DIR is used. /// 8. If X509_CERT_DIR is missing too then CRLPath is set to default value /// /etc/grid-security/certificates. /// 9. Presence of corresponding files/directories and their permissions /// are checked. /// 10. If all checks passed then object is marked as valid. ClientFullContext, /// Like ClientFullContext but does not fail if anything is missing. /// Step 9 is not performed and object is always valid. ClientMinimalContext, /// Set paths to values needed for running server. /// 1. No environment variables are used. /// 2. CertPath is set to /etc/grid-security/hostcert.pem. /// 3. KeyPath is set to /etc/grid-security/hostkey.pem. /// 4. CAPath is set to /etc/grid-security/certificates. /// 5. CRLPath is set to /etc/grid-security/certificates. /// 6. Presence of corresponding files/directories and their permissions /// are checked. /// 7. If all checks passed then object is marked as valid. ServiceFullContext, /// Like ServiceFullContext but does not fail if anything is missing. /// Step 6 is not performed and object is always valid. ServiceMinimalContext } ContextType; typedef enum { LogDebug = 0, LogVerbose = 1, LogInfo = 2, LogWarning = 3, LogError = 4, LogFatal = 5 } LogLevel; /// Constructor sets paths and defaults according to specified ContextType. /// During object initialization constructor scans application environment /// and picks proper values. If specified algorithm failed object gets invalid mark. Context(ContextType env = EmptyContext); virtual ~Context(void); /// Returns true if object is valid. /// Object is valid if constructor passed without failures and no EmptyContext /// was requested. If object is not valid then modifying its content by using /// one of Set*() methods switches it to valid. virtual operator bool(void) const; /// Returns true if object is invalid. virtual bool operator!(void) const; /// Returns status of last operation. AuthN::Status GetStatus(void) const; /// Makes copy of this object. /// Returned object is created using new operation and its ownership /// is transfered to calling code. That object must be destroyed using /// delete operation. virtual Context& Copy(void) const; /// Returns path to directory containing CA certificates. std::string GetCAPath(void) const; /// Sets path to directory containing CA certificates. /// Those are certificates of CAs which are accepted for authentication. void SetCAPath(const std::string& path); /// Returns path to directory containing set of CRLs. std::string GetCRLPath(void) const; /// Sets path to directory containing set of CRLs. void SetCRLPath(const std::string& path); /// Sets path to X.509 credentials and optionally private key. /// If 'keypath' is empty then no private key is specified in Context. void SetCredentials(const std::string& certpath,const std::string& keypath); /// Sets path to X.509 credentials and private key contained in same file (aka proxy). void SetCredentials(const std::string& certpath); /// Returns path to X.509 certificate std::string GetCertPath(void) const; /// Returns path to X.509 private key std::string GetKeyPath(void) const; /// Method to be called when some object needs user provided password. /// Usually that is needed for decrypting private key. /// This implementation always returns empty password and hence /// suitable for using in service context. /// Rewrite it by inheriting from Context class to provide /// own way to retrieve password. /// Here type will contain human readable name of type of object /// to be decrypted and source will describe location of it. /// Provided implementation drops type and source and returns empty string. virtual std::string Password(const std::string& type, const std::string& source); /// Method to be called when some object needs user provided password. /// Here message should be presented to user before entering password. /// Provided implementation drops the message and returns empty string. virtual std::string Password(const std::string& message); /// Method to be called when something need to be communicated to user. /// Here message should be presented to user. Provided implementation /// drops the message. virtual void Message(const std::string& message); /// Method to be called when something need to be stored into log. /// Here message should be passed to logging facilities and level /// defines verbosity level of the message. Provided implementation /// drops the message. virtual void Log(LogLevel level ,const std::string& message); /// Method to be called when something need to be stored into log. /// Here format and successive arguments should be processed in printf() /// way and passed to logging facilities and level defines verbosity /// level of the message. Provided implementation uses vsnprintf to /// process format and then calls LogCallback. void LogFormat(LogLevel level, const std::string& format, ...); bool valid_; std::string capath_; std::string crlpath_; std::vector crlfiles_; std::string certpath_; std::string keypath_; std::string nssdbpath_; Status last_error_; }; /// Performs validation while accepting credentials class Validator { public: /* /// Bit-field for turning on/off various validation procedures. /// If simultaneously flags are set for same validation procedure with different /// strictness most strict is applied. typedef int ValidationMode; /// Perform all know validations const ValidationMode ValidationFull; // = (0xffffffff) /// Do not perform any validations const ValidationMode ValidationNone; // = (0xffffffff) /// Do not to check against CRLs const ValidationMode ValidationCRLNone; // = (0<<0) /// Do check against CRLs and require valid CRL for every used CAs const ValidationMode ValidationCRLMandatory; // = (1<<0) /// Do check against CRL only if CRL is present and valid const ValidationMode ValidationCRLIfValid; // = (2<<0) /// Do check against CRL only if CRL is present (use outdated CRLs too) const ValidationMode ValidationCRLIfPresent; // = (4<<0) /// Do not check for credentials namespace limitation const ValidationMode ValidationNamespaceNone; // = (0<<3) /// Do check and require at least one known credentials namespace limitation for every used CA const ValidationMode ValidationNamespaceCheck; // = (1<<3) /// Do check for credentials namespace limitation if information present const ValidationMode ValidationNamespaceLax; // = (2<<3) /// Do not allow proxy credentials const ValidationMode ValidationProxyDisallow; // = (0<<5) /// Do allow proxy credentials const ValidationMode ValidationProxyAllow; // = (1<<5) /// Turn in all basic validation procedures. /// Those not covered by previous flags const ValidationMode ValidationBasic; // = (1<<6) */ enum ValidationMode { /// Perform all know validations ValidationFull = (0xffffffff), /// Do not perform any validations ValidationNone = 0x00, /// Do not to check against CRLs ValidationCRLNone = 0x01, /// Do check against CRLs and require valid CRL for every used CAs ValidationCRLMandatory = 0x02, /// Do check against CRL only if CRL is present and valid ValidationCRLIfValid = 0x04, /// Do check against CRL only if CRL is present (use outdated CRLs too) ValidationCRLIfPresent = 0x08, /// Do check against OCSP servers and require OCSP server information ValidationOCSPMandatory = 0x10, /// Do check against OCSP servers only if OCSP server information is present ValidationOCSPIfPresent = 0x20, /// Do not check for credentials namespace limitation ValidationNamespaceNone = 0x40, /// Do check and require at lest one known credentials namespace limitation for every used CA ValidationNamespaceCheck = 0x80, /// Do check for credentials namespace limitation if information present ValidationNamespaceLax = 0x100, /// Do not allow proxy credentials ValidationProxyDisallow = 0x200, /// Do allow proxy credentials ValidationProxyAllow = 0x400, /// Turn in all basic validation procedures. /// Those not covered by previous flags ValidationBasic = 0x800 }; /// Constructor creates object with default validation mode // for that context. Copy of provided Context - made by Copy() // method - is stored in Validator. Validator(const AuthN::Context& ctx); /// Constructor creates object with specified validation mode. /// Mode is specified by ORed Validate* flags. /// Copy of provided Context - made by Copy() // method - is stored in Validator. Validator(const AuthN::Context& ctx, ValidationMode mode); virtual ~Validator(void); /// Returns true if object is valid virtual operator bool(void) const; /// Returns true if object is invalid virtual bool operator!(void) const; /// Returns status of last operation. AuthN::Status GetStatus(void) const; /// Makes copy of this object. /// Returned object is created using new operation and its ownership /// is tansfered to calling code. That object must be destroyed using /// delete operation. virtual Validator& Copy(void) const; /// Returns current validation mode. ValidationMode Mode(void) const; /// Changes validation mode. /// It accepts mode made of Validate* values ORed together. void SetMode(ValidationMode mode); /// Returns reference to associated context. /// This points directly to internally stored Context and /// must not be accessed after Validator is destroyed. const AuthN::Context& GetContext(void) const; /// Associates new context. /// Internally stored Context object is destroyed. Copy of passed /// 'env' is made for later usage. void SetContext(const AuthN::Context& env); /// Performs validation. /// This implementation performs validations defined by Validate* flags. /// For more validation steps and additional validation modes one can write /// own impelementation by inheriting from Validator class. virtual Status Validate(Credentials& cred); protected: Context* context_; ValidationMode mode_; Status last_error_; }; /// Represents X.509 credentials. /// It holds binary content of credentials. class Credentials { public: /// Certificate extension in generic format. class Extension { public: /// Flag specifies if extension is critical. bool critical; /// oid of extension in textual representation according to RFC3061. std::string oid; /// Memory blob containing extension. std::string value; }; protected: bool valid_; OpenSSL::CertContext* certctx_; //EVP_PKEY* priv_key_; //X509* cert_; //STACK_OF(X509)* cert_chain_; Context* context_; Validator* validator_; Status last_error_; // Hiding few methods here because normally those should not be called // by external code. Credentials(void); Credentials(const Credentials& arg); Credentials& operator=(const Credentials& arg); AuthN::Status Assign(const Credentials& arg); //AuthN::Status Assign(const X509* cert, const STACK_OF(X509)* chain, const EVP_PKEY* key); public: /// Creates new Credentials object with associated context. /// According to content of 'ctx' object specified credentials are loaded /// and stored inside created object. Assigning empty or invalid /// 'ctx' creates empty Credentials object. Copy of Context is /// also stored inside Credentials for later usage. Credentials(const AuthN::Context& ctx); virtual ~Credentials(void); /// Returns true if object is valid. virtual operator bool(void) const { return valid_; }; /// Returns true if object is invalid. virtual bool operator!(void) const { return !valid_; }; /// Returns status of last operation. AuthN::Status GetStatus(void) const; /// Makes copy of this object. /// Returned object is created using new operation and its ownership /// is tansfered to calling code. That object must be destroyed using /// delete operation. virtual Credentials& Copy(void) const; /// Assigns new credentials content. /// Copies of provided credentials are stored inside object. Not all /// arguments need to be provided. Those missing must be set to NULL. /// Passed objects are copied for storing inside this object. /// If method fails negative Status is returned. //AuthN::Status Assign(X509 *cert, const STACK_OF(X509)* chain, const EVP_PKEY *key); /// Assigns new credentials content. /// Credentials parts are loaded from specified streams. Method detects /// when arguments are representing same stream and loads proxy credential. /// Empty stream may be provided if any part is not avaialble. /// If any of supplied objects is encrypted password callback of assigned /// Context will be used. /// If method fails negative Status is returned. AuthN::Status Assign(std::istream& cert, std::istream& chain, std::istream& key); /// Assigns new credentials content. /// Credentials parts are loaded from specified strings. Method detects /// when arguments are representing same string and loads proxy credential. /// Empty string may be provided if any part is not avaialble. /// If any of supplied objects is encrypted password callback of assigned /// Context will be used. /// If method fails negative Status is returned. AuthN::Status Assign(const std::string& cert, const std::string& chain = "", const std::string& key = ""); /// Returns pointer to stored credentials. /// Returned pointer points to object stored inside this instance and /// must not be accessed after this instance is destroyed or certificate /// replaced or destroyed. //X509* GetCertificate(void) const; /// Fills string containing textual representation of certificate in PEM format. void GetCertificate(std::string& str) const; /// Outputs textual representation of certificate into provided stream in PEM format. void GetCertificate(std::ostream& o) const; /// Returns pointer to stored credentials chain. /// Returned pointer points to object stored inside this instance and /// must not be accessed after this instance is destroyed or any element /// of chain is replaced or destroyed. //STACK_OF(X509)* GetChain(void) const; /// Returns string containing textual representation of certificates chain in PEM format. void GetChain(std::string& str) const; /// Outputs textual representation of certificate into provided stream in PEM format. void GetChain(std::ostream& o) const; /// Returns pointer to private key. /// Returned pointer points to object stored inside this instance and /// must not be accessed after this instance is destroyed or key replaced /// or destroyed. //EVP_PKEY* GetPrivateKey(void) const; /// Fills 'str' with textual representation of private key in PEM format. /// If encrypt is set to true password callback of assigned Context /// will be used to obtain encryption password. void GetPrivateKey(std::string& str, bool encrypt = false) const; /// Outputs textual representation of private key into provided stream in PEM format. /// If encrypt is set to true password callback of assigned Context /// will be used to obtain encryption password. void GetPrivateKey(std::ostream& o, bool encrypt = false) const; /// Validates credentials using assigned Validator. /// If validation fails or other error occurs negative Status is returned. AuthN::Status Validate(void); /// Signs certificate request. /// Signed certificate along with needed certificate chain is stored in /// 'out' argument. The conf_file argument is the location of configuration /// file, specifically speaking the configuration file is openssl.cnf. /// Depending on type of associated credentials this /// method will produce either ordinary certificate or proxy certificate. /// Only validation steps related to signing procedure are performed. /// Validation of involved credentials is not done. /// If method fails negative Status is returned. AuthN::Status Sign(CredentialsRequest& request, Credentials& out, const std::string& conf_file = ""); /// Outputs textual representation of Subject Name. /// Output is generated in format defined in RFC2253. std::string GetSubjectName(void) const; /// Outputs textual representation of Subject Name of identity certificate. /// Output is generated in format defined in RFC2253. /// Identity certificate is first non-proxy certificate in a chain. /// If identity can't be established outputs empty string. std::string GetIdentityName(void) const; /// Outputs textual representation of Issuer Name of certificate. /// Output is generated in format defined in RFC2253. /// Position defines which certificate in a chain to use. /// 0 corresponds to main certificate itself. /// If there is no certificate at specified position outputs empty string. std::string GetIssuerName(int position = 0) const; /// Fills 'cert' with information representing certificate in stored chain. /// The 'position' defines which certificate to use. The 0 value corresponds /// to main certificate itself. /// If method fails - for example if position is out of range - negative /// Status is returned. AuthN::Status GetChainCert(Credentials& cert, int position = 1) const; /// Returns validity start time in seconds since epoch. time_t GetValidFrom(void) const; /// Returns validity end time in seconds since epoch. time_t GetValidTill(void) const; /// Returns true if credential is self-signed. bool GetSelfSigned(void) const; /// Returns true if credential is CA. bool GetCA(void) const; /// Returns true if credential contains proxy. bool GetProxy(void) const; /// Returns true if credential contains limited proxy. /// This is only relevant for proxy credentials. bool GetProxyLimited(void) const; /// Retreives policy of proxy. /// Policy of last proxy in chain which is also main credential /// is filled in 'policy'. /// Returns false if this object does not represent proxy. bool GetProxyPolicy(Extension& policy) const; /// Retrieves extension by its position in internal list. /// If succeeded extension is filled into 'ext'. /// Returns false if extension does not exist (pos out of range). bool GetExtension(int pos, Extension& ext) const; /// Retrieves extension by predefined name (for known extensions) /// Names are to be defined. Oids can be used as names. /// If succeeded extension is filled into 'ext'. /// Returns false if extension does not exist. bool GetExtension(const std::string& name, Extension& ext) const; /// Retrieves attributes by predefined name /// Here term attribute is used to denote any additional information /// stored in certificate - not Attribute Certificate only. The purpose /// of this method is to extract complex information from certificate /// in a way known to implementation. /// Information is returned in format which depends on value of /// 'name'. But in any case format must be suitable for immediate /// processing without knowledge of how attributes are encoded inside /// credentials. Example of such information is VOMS FQANs/attributes /// encoded in Attribute Certificates stored inside X.509 Certificates. /// The attributes are retrieved only from main certificate - not /// from certificates chain. /// Note: attribute names and their content to be defined later. /// Returns false if extension does not exist or is not known. bool GetAttributes(const std::string& name, std::list& attrs) const; /// Associates new context. /// Internally stored Context object is destroyed. Copy of passed /// 'env' is made for later usage. void SetContext(const AuthN::Context& env); /// Returns reference to associated Context. /// It points to internal Context object and must not be used /// after Credentials is destroyed or Context is replaced. const AuthN::Context& GetContext(void) const; /// Assigns validator /// Assigned validator will be used by Validate() method. /// Copy of Validator is stored inside Credentials. void SetValidator(const AuthN::Validator& validator); /// Returns reference to associated Validator. /// It points to internal Validator object and must not be used /// after Credentials object is destroyed. const AuthN::Validator& GetValidator(void) const; friend class Validator; friend class IONetwork; friend class IOSocket; }; /// This is a helper class to make it possible to use Credentials class for /// generating X.509 credentials and proxies. It can also be used for /// implementing remote delegation and signing services. // TODO: combine pib_key_ into req_. Remove dependency on openssl // configuration file. class CredentialsRequest { protected: Context* context_; OpenSSL::CSRContext* csrctx_; OpenSSL::KeyContext* keyctx_; std::string subject_name_; time_t valid_from_; time_t valid_till_; std::map extensions; Status last_error_; CredentialsRequest(void); CredentialsRequest(const CredentialsRequest& arg); CredentialsRequest& operator=(const CredentialsRequest& arg); Status Assign(const CredentialsRequest& arg); //AuthN::Status Assign(X509_REQ* req, const EVP_PKEY* pub, const EVP_PKEY* priv); public: /// Creates new credentials request with associated context /// Copy of Context is also stored inside CredentialsRequest for later usage. CredentialsRequest(const AuthN::Context& ctx); virtual ~CredentialsRequest(void); /// Returns true if object is valid virtual operator bool(void) const { return (csrctx_ != NULL); }; /// Returns true if object is invalid virtual bool operator!(void) const { return (csrctx_ == NULL); }; /// Returns status of last operation. AuthN::Status GetStatus(void) const; /// Makes copy of this object. /// Returned object is created using new operation and its ownership /// is transfered to calling code. That object must be destroyed using /// delete operation. virtual CredentialsRequest& Copy(void) const; /// Generates pair of private/public keys with specified strength. /// If method fails negative Status is returned. AuthN::Status MakeKeys(int bits); virtual AuthN::Status MakeRequest(void); /// Loads private and public keys from OpenSSL structures. /// Copies of specified objects are made for internal use. /// If method fails negative Status is returned. //AuthN::Status AssignKeys(const EVP_PKEY* priv); /// Loads private and public keys from streams in textual representation in PEM format. /// If any of supplied objects is encrypted password callback of assigned /// Context will be used. /// If method fails negative Status is returned. AuthN::Status AssignKeys(std::istream& priv); /// Loads private and public keys from strings in textual representation in PEM format. /// If any of supplied objects is encrypted password callback of assigned /// Context will be used. /// If method fails negative Status is returned. AuthN::Status AssignKeys(const std::string& priv); /// Loads request and optional private key from OpenSSL structures. /// Copies of specified objects are made for internal use. /// If method fails negative Status is returned. //AuthN::Status AssignRequest(X509_REQ* req, const EVP_PKEY* priv); /// Loads request and optional private key from streams in textual representation in PEM format. /// If method fails negative Status is returned. AuthN::Status AssignRequest(std::istream& req, std::istream& priv); /// Loads request and optional private key from strings in textual representation in PEM format. /// If method fails negative Status is returned. AuthN::Status AssignRequest(const std::string& req, const std::string& priv); /// Returns assigned subject name in format defined in RFC2253. std::string GetSubjectName(void) const; /// Assigns subject name for request /// Subject Name must be in format defined in RFC2253. /// Failure is returned if parsing failed. AuthN::Status SetSubjectName(const std::string sn); /// Returns validity start time in seconds since epoch. time_t GetValidFrom(void) const; /// Assigns validity start time in seconds since epoch. void SetValidFrom(time_t sec); /// Returns validity end time in seconds since epoch. time_t GetValidTill(void) const; /// Assigns validity end time in seconds since epoch. void SetValidTill(time_t sec); /// Retrieves extension by its position in internal list. /// If succeeded extension is filled into 'ext'. /// Returns false if extension does not exist (pos out of range). AuthN::Status GetExtension(int pos, Credentials::Extension& ext) const; /// Retrieves extension by predefined name (for known extensions) /// Names are to be defined. Oids can be used as names. /// If succeeded extension is filled into 'ext'. /// Returns false if extension does not exist. AuthN::Status GetExtension(const std::string& name, Credentials::Extension& ext) const; /// Adds extension to be included in final credentials. /// If needed existing extension is replaced. /// Note the extension to be added is only supposed to be /// the one in asn1 coded format, not in the human readable format. /// therefore, for example, "Digital Signature, Key Encipherment" /// can not be put as the extension to be added, unless it is encoded. AuthN::Status AddExtension(Credentials::Extension& ext); /// Returns attributes by predefined name. /// For more information see Credentials::GetAttributes(). AuthN::Status GetAttributes(const std::string& name, std::list& attrs) const; /// Inserts attributes into request. /// For more information see Credentials::GetAttributes(). /// Existing attributes are not removed. /// False is returned if attribute is not applicable due to some reason or /// if not known. AuthN::Status AddAttributes(const std::string& name, const std::string& attrs); /// Returns pointer to public key. /// Returned pointer points to object stored inside this instance and /// must not be used after this instance is destroyed. //const EVP_PKEY* GetPublicKey(void) const; /// Outputs textual representation of public key into string in PEM format. AuthN::Status GetPublicKey(std::string& str) const; /// Outputs textual representation of public key into provided stream in PEM format. AuthN::Status GetPublicKey(std::ostream& o) const; /// Returns pointer to private key. /// Returned pointer points to object stored inside this instance and /// must not be used after this instance is destroyed. //const EVP_PKEY* GetPrivateKey(void) const; /// Outputs textual representation of private key into string in PEM format. /// If encrypt is set to true password callback of assigned Context /// will be used to obtain encryption password. AuthN::Status GetPrivateKey(std::string& str, bool encrypt = false) const; /// Outputs textual representation of private key into provided stream in PEM format. /// If encrypt is set to true password callback of assigned Context /// will be used to obtain encryption password. AuthN::Status GetPrivateKey(std::ostream& o, bool encrypt = false) const; /// Returns pointer to X.509 request. /// Returned pointer points to object stored inside this instance and /// must not be used after this instance is destroyed. //const X509_REQ* GetRequest(void) const; /// Returns string containing textual representation of credentials request in PEM format. AuthN::Status GetRequest(std::string& str) const; /// Outputs textual representation of credentials request into provided stream in PEM format. AuthN::Status GetRequest(std::ostream& o) const; friend class Credentials; }; // Special case of CredentialsRequest for generating CA credentials. class CACredentialsRequest: public CredentialsRequest { private: OpenSSL::CertContext* certctx_; public: /// Creates new credentials request with associated context. /// Copy of Context is also stored inside CredentialsRequest for later usage. CACredentialsRequest(const AuthN::Context& ctx); virtual ~CACredentialsRequest(void); /// Makes copy of this object. /// Returned object is created using new operation and its ownership /// is tansfered to calling code. That object must be destroyed using /// delete operation. virtual CredentialsRequest& Copy(void) const; virtual AuthN::Status MakeRequest(void); /// Assigns new certificate content. /// Copies of provided certificate is stored inside object. /// Passed objects are copied for storing inside this object. /// If method fails negative Status is returned. //AuthN::Status Assign(X509* cert); AuthN::Status Assign(const std::string& cert); /// Returns pointer to stored credentials. /// Returned pointer points to object stored inside this instance and /// must not be accessed after this instance is destroyed or certificate /// replaced or destroyed. //const X509* GetCertificate(void) const; /// Fills string with textual representation of certificate in PEM format. AuthN::Status GetCertificate(std::string& str); /// Outputs textual representation of certificate into provided stream in PEM format. AuthN::Status GetCertificate(std::ostream& o); }; /// Special case of CredentialsRequest for generating proxy credentials. class ProxyCredentialsRequest: public CredentialsRequest { private: bool limited_; public: /// Creates new credentials request with associated context. /// Copy of Context is also stored inside CredentialsRequest for later usage. ProxyCredentialsRequest(const AuthN::Context& ctx); virtual ~ProxyCredentialsRequest(void); /// Makes copy of this object. /// Returned object is created using new operation and its ownership /// is tansfered to calling code. That object must be destroyed using /// delete operation. virtual CredentialsRequest& Copy(void) const; /// Returns true if request is for limited proxy. bool GetLimited(void); /// Sets if request is for limited proxy. void SetLimited(bool); /// Returns current policy of proxy. AuthN::Status GetPolicy(Credentials::Extension& policy); /// Assigns policy of proxy. /// Member 'critical' of 'policy' object is ignored. AuthN::Status SetPolicy(const Credentials::Extension& policy); }; /// Represents authenticated connection. /// This is a base class for performing authenticated connectiion. /// Implementaions are supposed to override WireWrite(), WireRead and /// WireClose() methods to make classes classes capable of using /// some transfer layer. class IO { public: /// Failure code for Status representing not implemented operation. static const int NotImplemented; /// Failure code for Status representing timeout. /// This failure must be especially expected when using 0 timeout. static const int CommunicationTimeout; /// Creates neutral object with Context attached. /// NOTE: Is Context enough to distinguish between server and client endpoints? IO(const AuthN::Context& ctx); virtual ~IO(void); /// Returns true if object is valid. virtual operator bool(void) const; /// Returns true if object is invalid. virtual bool operator!(void) const; /// Assigns credentials to be used during connection. /// Copy of provided Creddentials is kept inside IO object. void SetOwnCredentials(const AuthN::Credentials& cred); /// Returns reference to assigned credentials. /// Returned reference points to object stored inside IO object /// and must not be used after desctruction of this object. const AuthN::Credentials& GetOwnCredentials(void) const; /// Returns reference to remote credentials. /// Returned reference points to object stored inside IO object /// and must not be used after desctruction of this object. const AuthN::Credentials& GetPeerCredentials(void) const; /// Assigns validator to be used for validating connection and remote credentials. /// copy of provided Validator is kept inside this IO for later usage. void SetValidator(const AuthN::Validator& validator); /// Returns reference to assigned validator. const AuthN::Validator& GetValidator(void) const; /// Read no more than size bytes into buffer. /// Returns positive status if no failures happened. On exit size /// variable contains number of read bytes. This number may be 0 in /// case of timeout. /// In case of error negative status is returned. AuthN::Status Read(void *buffer, size_t& size); /// Read no more than size bytes into buffer. /// If size == 0 then read as much as available. /// In case of error negative status is returned. AuthN::Status Read(std::string& buffer, size_t size = 0); /// Write size bytes from buffer. /// Returns positive result only if whole buffer content is written. /// In case of error negative status is returned. AuthN::Status Write(const void *buffer, size_t size); /// Write whole buffer. /// Returns positive result only if whole buffer content is written. /// In case of error negative status is returned. AuthN::Status Write(const std::string& buffer); /// Closes associated connection. /// In case of error negative status is returned. It is still safe to /// destroy object even if Close() failed. AuthN::Status Close(void); /// Sets timeout for communication operations in milliseconds. /// Value -1 sets timeout to infinite. 0 means there must /// some kind of polling implemented. void SetTimeout(int ms); /// Returns current timeout for communication operations in milliseconds. int GetTimeout(void); /// Returns status of last operation. AuthN::Status GetStatus(void) const; protected: /// This method must implement real write over communication layer. /// It can be rewritten by inheriting class in order to implement /// different communication layer. virtual AuthN::Status WireWrite(const void *buffer, size_t size); /// This method must implement real read over communication layer. /// It can be rewritten by inheriting class in order to implement /// different communication layer. virtual AuthN::Status WireRead(void *buffer, size_t& size); /// This method must implement real close over communication layer. /// It can be rewritten by inheriting class in order to implement /// different communication layer. virtual AuthN::Status WireClose(void); bool valid_; int timeout_; Status last_error_; Validator* validator_; Credentials* node_; Credentials* peer_; Context* context_; }; /// Implementation of IO for communication through TCP/IP network. class IONetwork: public IO { public: IONetwork(const AuthN::Context& ctx); virtual ~IONetwork(void); /// Establishes connection to specified TCP location. /// Assigned timeout is used while waiting for connection established. /// In case of error negative status is returned. AuthN::Status Connect(const std::string& host, int port); /// Wait and accept connection at specified TCP/IP port and host interface. /// If host is empty then socket is bound to all available interfaces. /// If port is set to 0 then socket is bound to arbitrary port. /// Returned object represents established connection and has same Context /// and Validator associated. This IO object keeps listening on specified /// port and interface even after method exits. /// In case of error invalid object is returned. Error description can /// be obtained by using GetStatus() method. AuthN::IO& Accept(const std::string& host, int port); /// Returns true if object is valid. virtual operator bool(void) const; /// Returns true if object is invalid. virtual bool operator!(void) const; protected: virtual AuthN::Status WireWrite(const void *buffer, size_t size); virtual AuthN::Status WireRead(void *buffer, size_t& size); virtual AuthN::Status WireClose(void); SSL_CTX* ctx_; BIO* bio_; }; /* /// Implementation of IO for communication through OpenSSL BIO. class IOBIO: public IO { public: IOBIO(const AuthN::Context& ctx); /// Establishes connection through already connected BIO object. /// Provided BIO object is used during whole lifetime of /// this object and must not be destroyed during that time range. /// BIO object will *not* be destoyed/freed in destructor and /// by Close() method. /// In case of error negative status is returned. AuthN::Status Connect(::BIO *bio); /// Performs action equal to accept through already connected BIO object. /// If returned status is positive this IO object represents new connection /// This BIO object socket will *not* be destoyed/freed in destructor /// and by Close() method. /// In case of error negative status is returned. AuthN::Status Accept(::BIO *bio); /// Returns true if object is valid. virtual operator bool(void) const; /// Returns true if object is invalid. virtual bool operator!(void) const; protected: virtual AuthN::Status WireWrite(const void *buffer, size_t size); virtual AuthN::Status WireRead(void *buffer, size_t& size); virtual AuthN::Status WireClose(void); }; */ /// Implementation of IO for communication through socket handle. class IOSocket: public IO { public: IOSocket(const AuthN::Context& ctx); ~IOSocket(void); /// Establishes connection through already connected socket. /// Provided socket will not be closed in destructor and by Close() method. /// In case of error negative Status is returned. AuthN::Status Connect(int socket); /// Performs action equal to accept through already connected socket /// If returned status is positive this IO object represents new connection. /// This socket will not be closed in destructor and by Close() method. /// In case of error negative Status is returned. AuthN::Status Accept(int socket); /// Returns true if object is valid. virtual operator bool(void) const; /// Returns true if object is invalid. virtual bool operator!(void) const; protected: virtual AuthN::Status WireWrite(const void *buffer, size_t size); virtual AuthN::Status WireRead(void *buffer, size_t& size); virtual AuthN::Status WireClose(void); SSL_CTX* ctx_; BIO* bio_; }; } // namespace AuthN #endif // __AUTHN_CANLXX_H__