#ifndef PROTON_SSL_H #define PROTON_SSL_H 1 /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @file * * @copybrief ssl * * @addtogroup ssl * @{ */ /** * API for using SSL with the Transport Layer. * * A Transport may be configured to use SSL for encryption and/or authentication. A * Transport can be configured as either an "SSL client" or an "SSL server". An SSL * client is the party that proactively establishes a connection to an SSL server. An SSL * server is the party that accepts a connection request from a remote SSL client. * * This SSL implementation defines the following objects: * @li A top-level object that stores the configuration used by one or more SSL * sessions (pn_ssl_domain_t). * @li A per-connection SSL session object that performs the encryption/authentication * associated with the transport (pn_ssl_t). * * The pn_ssl_domain_t is used to construct an SSL session (pn_ssl_t). The * session "adopts" its configuration from the pn_ssl_domain_t that was used to create it. * For example, pn_ssl_domain_t can be configured as either a "client" or a "server". SSL * sessions constructed from this domain will perform the corresponding role (either * client or server). * * If an SSL session is created without a pn_ssl_domain_t object then a default will be used * (see ::pn_ssl_init()). * * If either an SSL server or client needs to identify itself with the remote node, it * must have its SSL certificate configured (see ::pn_ssl_domain_set_credentials()). * * If either an SSL server or client needs to verify the identity of the remote node, it * must have its database of trusted CAs configured. By default this will be set up to use * the default system database of trusted CA. But this can be changed * (see ::pn_ssl_domain_set_trusted_ca_db()). * * The level of verification required of the remote may be configured (see * ::pn_ssl_domain_set_peer_authentication) * * Support for SSL Client Session resume is provided (see ::pn_ssl_init, * ::pn_ssl_resume_status). */ typedef struct pn_ssl_domain_t pn_ssl_domain_t; /** * @see pn_ssl */ typedef struct pn_ssl_t pn_ssl_t; /** * Determines the type of SSL endpoint. */ typedef enum { PN_SSL_MODE_CLIENT = 1, /**< Local connection endpoint is an SSL client */ PN_SSL_MODE_SERVER /**< Local connection endpoint is an SSL server */ } pn_ssl_mode_t; /** * Indicates whether an SSL session has been resumed. */ typedef enum { PN_SSL_RESUME_UNKNOWN, /**< Session resume state unknown/not supported */ PN_SSL_RESUME_NEW, /**< Session renegotiated - not resumed */ PN_SSL_RESUME_REUSED /**< Session resumed from previous session. */ } pn_ssl_resume_status_t; /** * Tests for SSL implementation present * * @return true if we support SSL, false if not */ PN_EXTERN bool pn_ssl_present( void ); /** * Create an SSL configuration domain * * This method allocates an SSL domain object. This object is used to hold the SSL * configuration for one or more SSL sessions. The SSL session object (pn_ssl_t) is * allocated from this object. * * @param[in] mode the role, client or server, assumed by all SSL sessions created * with this domain. * @return a pointer to the SSL domain, if SSL support is present. */ PN_EXTERN pn_ssl_domain_t *pn_ssl_domain(pn_ssl_mode_t mode); /** * Release an SSL configuration domain * * This method frees an SSL domain object allocated by ::pn_ssl_domain. * @param[in] domain the domain to destroy. */ PN_EXTERN void pn_ssl_domain_free(pn_ssl_domain_t *domain); /** * Set the certificate that identifies the local node to the remote. * * This certificate establishes the identity for the local node for all SSL sessions * created from this domain. It will be sent to the remote if the remote needs to verify * the identity of this node. This may be used for both SSL servers and SSL clients (if * client authentication is required by the server). * * @note This setting effects only those pn_ssl_t objects created after this call * returns. pn_ssl_t objects created before invoking this method will use the domain's * previous setting. * * @param[in] domain the ssl domain that will use this certificate. * @param[in] credential_1 specifier for the file/database containing the identifying * certificate. For Openssl users, this is a PEM file. For Windows SChannel users, this is * the PKCS#12 file or system store. * @param[in] credential_2 an optional key to access the identifying certificate. For * Openssl users, this is an optional PEM file containing the private key used to sign the * certificate. For Windows SChannel users, this is the friendly name of the * self-identifying certificate if there are multiple certificates in the store. * @param[in] password the password used to sign the key, else NULL if key is not * protected. * @return 0 on success */ PN_EXTERN int pn_ssl_domain_set_credentials(pn_ssl_domain_t *domain, const char *credential_1, const char *credential_2, const char *password); /** * Configure the set of trusted CA certificates used by this domain to verify peers. * * If the local SSL client/server needs to verify the identity of the remote, it must * validate the signature of the remote's certificate. This function sets the database of * trusted CAs that will be used to verify the signature of the remote's certificate. * * @note This setting effects only those pn_ssl_t objects created after this call * returns. pn_ssl_t objects created before invoking this method will use the domain's * previous setting. * * @note By default the list of trusted CA certificates will be set to the system default. * What this is is depends on the OS and the SSL implementation used: For OpenSSL the default * will depend on how the OS is set up. When using the Windows SChannel implementation the default * will be the users default trusted certificate store. * * @param[in] domain the ssl domain that will use the database. * @param[in] certificate_db database of trusted CAs, used to authenticate the peer. * @return 0 on success */ PN_EXTERN int pn_ssl_domain_set_trusted_ca_db(pn_ssl_domain_t *domain, const char *certificate_db); /** * Determines the level of peer validation. * * ANONYMOUS_PEER does not require a valid certificate, and permits * use of ciphers that do not provide authentication. * * VERIFY_PEER will only connect to those peers that provide a valid * identifying certificate signed by a trusted CA and are using an * authenticated cipher. * * VERIFY_PEER_NAME is like VERIFY_PEER, but also requires the peer's * identity as contained in the certificate to be valid (see * ::pn_ssl_set_peer_hostname). * * ANONYMOUS_PEER is configured by default. */ typedef enum { PN_SSL_VERIFY_NULL = 0, /**< internal use only */ PN_SSL_VERIFY_PEER, /**< require peer to provide a valid identifying certificate */ PN_SSL_ANONYMOUS_PEER, /**< do not require a certificate nor cipher authorization */ PN_SSL_VERIFY_PEER_NAME /**< require valid certificate and matching name */ } pn_ssl_verify_mode_t; /** * Configure the level of verification used on the peer certificate. * * This method controls how the peer's certificate is validated, if at all. By default, * neither servers nor clients attempt to verify their peers (PN_SSL_ANONYMOUS_PEER). * Once certificates and trusted CAs are configured, peer verification can be enabled. * * @note In order to verify a peer, a trusted CA must be configured. See * ::pn_ssl_domain_set_trusted_ca_db(). * * @note Servers must provide their own certificate when verifying a peer. See * ::pn_ssl_domain_set_credentials(). * * @note This setting effects only those pn_ssl_t objects created after this call * returns. pn_ssl_t objects created before invoking this method will use the domain's * previous setting. * * @param[in] domain the ssl domain to configure. * @param[in] mode the level of validation to apply to the peer * @param[in] trusted_CAs path to a database of trusted CAs that the server will advertise * to the peer client if the server has been configured to verify its peer. * @return 0 on success */ PN_EXTERN int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain, const pn_ssl_verify_mode_t mode, const char *trusted_CAs); /** * Configure the list of permitted TLS protocols * * @param[in] domain the ssl domain to configure. * @param[in] protocols string representing the protocol list. * This list is a space separated string of the allowed TLS protocols, * The current possibilities are TLSv1 TLSv1.1 TLSv1.2 TLSv1.3. None of the earlier SSL * protocols are allowed for security reason. * * @note If this API not called then all the TLS protocols are allowed. The API only acts to * restrict the allowed protocols to the specified set. * @return 0 on success */ PN_EXTERN int pn_ssl_domain_set_protocols(pn_ssl_domain_t *domain, const char *protocols); /** * Configure the list of permitted ciphers * * @note The syntax of the permitted list is undefined and will depend on the * underlying SSL implementation. * * @param[in] domain the ssl domain to configure. * @param[in] ciphers string representing the cipher list * @return 0 on success */ PN_EXTERN int pn_ssl_domain_set_ciphers(pn_ssl_domain_t *domain, const char *ciphers); /** * **Deprecated** - Use ::pn_transport_require_encryption() * * Permit a server to accept connection requests from non-SSL clients. * * This configures the server to "sniff" the incoming client data stream, and dynamically * determine whether SSL/TLS is being used. This option is disabled by default: only * clients using SSL/TLS are accepted. * * @param[in] domain the domain (server) that will accept the client connections. * @return 0 on success */ PN_EXTERN int pn_ssl_domain_allow_unsecured_client(pn_ssl_domain_t *domain); /** * Create a new SSL session object associated with a transport. * * A transport must have an SSL object in order to "speak" SSL over its connection. This * method allocates an SSL object associates it with the transport. * * @param[in] transport the transport that will own the new SSL session. * @return a pointer to the SSL object configured for this transport. Returns NULL if * no SSL session is associated with the transport. */ PN_EXTERN pn_ssl_t *pn_ssl(pn_transport_t *transport); /** * Initialize an SSL session. * * This method configures an SSL object with defaults or the configuration provided by the given * domain. * * @note The default client domain is a secure default generally usable. This uses the system default * certificates and requires peer name verification. * * @note However the default server domain is only really useful for test servers. This is because for * a useful server you *need* to set up certificates to identify it so that clients can connect without * being subject to "man-in-the-middle" attacks - see ::pn_ssl_domain_set_credentials() for details. * * @param[in] ssl the ssl session to configured. * @param[in] domain the ssl domain used to configure the SSL session. If this value is NULL * then use a default domain. This will be a client domain if the ssl object is part of a client transport * and a server domain if the ssl object is part of a server transport. * the transport the pn_ssl_t object * @param[in] session_id if supplied, attempt to resume a previous SSL * session that used the same session_id. If no previous SSL session * is available, a new session will be created using the session_id * and stored for future session restore (see ::::pn_ssl_resume_status). * @return 0 on success, else an error code. */ PN_EXTERN int pn_ssl_init(pn_ssl_t *ssl, pn_ssl_domain_t *domain, const char *session_id); /** * Get the name of the Cipher that is currently in use. * * Gets a text description of the cipher that is currently active, or * returns FALSE if SSL is not active (no cipher). Note that the * cipher in use may change over time due to renegotiation or other * changes to the SSL state. * * @param[in] ssl the ssl client/server to query. * @param[in,out] buffer buffer of size bytes to hold cipher name * @param[in] size maximum number of bytes in buffer. * @return True if cipher name written to buffer, False if no cipher in use. */ PN_EXTERN bool pn_ssl_get_cipher_name(pn_ssl_t *ssl, char *buffer, size_t size); /** * Get the SSF (security strength factor) of the Cipher that is currently in use. * * @param[in] ssl the ssl client/server to query. * @return the ssf, note that 0 means no security. */ PN_EXTERN int pn_ssl_get_ssf(pn_ssl_t *ssl); /** * Get the name of the SSL protocol that is currently in use. * * Gets a text description of the SSL protocol that is currently active, or returns FALSE if SSL * is not active. Note that the protocol may change over time due to renegotiation. * * @param[in] ssl the ssl client/server to query. * @param[in,out] buffer buffer of size bytes to hold the version identifier * @param[in] size maximum number of bytes in buffer. * @return True if the version information was written to buffer, False if SSL connection * not ready. */ PN_EXTERN bool pn_ssl_get_protocol_name(pn_ssl_t *ssl, char *buffer, size_t size); /** * Check whether the state has been resumed. * * Used for client session resume. When called on an active session, indicates whether * the state has been resumed from a previous session. * * @note This is a best-effort service - there is no guarantee that the remote server will * accept the resumed parameters. The remote server may choose to ignore these * parameters, and request a re-negotiation instead. * * @param[in] ssl the ssl session to check * @return status code indicating whether or not the session has been resumed. */ PN_EXTERN pn_ssl_resume_status_t pn_ssl_resume_status(pn_ssl_t *ssl); /** * Set the expected identity of the remote peer. * * By default, SSL will use the hostname associated with the connection that * the transport is bound to (see ::pn_connection_set_hostname). This method * allows the caller to override that default. * * The hostname is used for two purposes: 1) when set on an SSL client, it is sent to the * server during the handshake (if Server Name Indication is supported), and 2) it is used * to check against the identifying name provided in the peer's certificate. If the * supplied name does not exactly match a SubjectAltName (type DNS name), or the * CommonName entry in the peer's certificate, the peer is considered unauthenticated * (potential imposter), and the SSL connection is aborted. * * @note Verification of the hostname is only done if PN_SSL_VERIFY_PEER_NAME is enabled. * See ::pn_ssl_domain_set_peer_authentication. * * @param[in] ssl the ssl session. * @param[in] hostname the expected identity of the remote. Must conform to the syntax as * given in RFC1034, Section 3.5. * @return 0 on success. */ PN_EXTERN int pn_ssl_set_peer_hostname(pn_ssl_t *ssl, const char *hostname); /** * Access the configured peer identity. * * Return the expected identity of the remote peer, as set by ::pn_ssl_set_peer_hostname. * * @param[in] ssl the ssl session. * @param[out] hostname buffer to hold the null-terminated name string. If null, no string * is written. * @param[in,out] bufsize on input set to the number of octets in hostname. On output, set * to the number of octets needed to hold the value of hostname plus a null byte. Zero if * no hostname set. * @return 0 on success. */ PN_EXTERN int pn_ssl_get_peer_hostname(pn_ssl_t *ssl, char *hostname, size_t *bufsize); /** * Get the subject from the peers certificate. * * @param[in] ssl the ssl client/server to query. * @return A null terminated string representing the full subject, * which is valid until the ssl object is destroyed. */ PN_EXTERN const char* pn_ssl_get_remote_subject(pn_ssl_t *ssl); /** * Enumeration identifying the sub fields of the subject field in the ssl certificate. */ typedef enum { PN_SSL_CERT_SUBJECT_COUNTRY_NAME, PN_SSL_CERT_SUBJECT_STATE_OR_PROVINCE, PN_SSL_CERT_SUBJECT_CITY_OR_LOCALITY, PN_SSL_CERT_SUBJECT_ORGANIZATION_NAME, PN_SSL_CERT_SUBJECT_ORGANIZATION_UNIT, PN_SSL_CERT_SUBJECT_COMMON_NAME } pn_ssl_cert_subject_subfield; /** * Enumeration identifying hashing algorithm. */ typedef enum { PN_SSL_SHA1, /* Produces hash that is 20 bytes long */ PN_SSL_SHA256, /* Produces hash that is 32 bytes long */ PN_SSL_SHA512, /* Produces hash that is 64 bytes long */ PN_SSL_MD5 /* Produces hash that is 16 bytes long */ } pn_ssl_hash_alg; /** * Get the fingerprint of the certificate. The certificate fingerprint (as displayed in the Fingerprints section when * looking at a certificate with say the Firefox browser) is the hexadecimal hash of the entire certificate. * The fingerprint is not part of the certificate, rather it is computed from the certificate and can be used to uniquely identify a certificate. * @param[in] ssl0 the ssl client/server to query * @param[in] fingerprint char pointer. The certificate fingerprint (in hex format) will be populated in this array. * If sha1 is the digest name, the fingerprint is 41 characters long (40 + 1 '\0' character), 65 characters long for * sha256 and 129 characters long for sha512 and 33 characters for md5. * @param[in] fingerprint_length - Must be at >= 33 for md5, >= 41 for sha1, >= 65 for sha256 and >=129 for sha512. * @param[in] hash_alg the hash algorithm to use. Must be of type pn_ssl_hash_alg (currently supports sha1, sha256, sha512 and md5) * @return error code - Returns 0 on success. Return a value less than zero if there were any errors. Upon execution of this function, * char *fingerprint will contain the appropriate null terminated hex fingerprint */ PN_EXTERN int pn_ssl_get_cert_fingerprint(pn_ssl_t *ssl0, char *fingerprint, size_t fingerprint_length, pn_ssl_hash_alg hash_alg); /** * Returns a char pointer that contains the value of the sub field of the subject field in the ssl certificate. The subject field usually contains the following sub fields - * C = ISO3166 two character country code * ST = state or province * L = Locality; generally means city * O = Organization - Company Name * OU = Organization Unit - division or unit * CN = CommonName * @param[in] ssl0 the ssl client/server to query * @param[in] field The enumeration pn_ssl_cert_subject_subfield representing the required sub field. * @return A null terminated string which contains the requested sub field value which is valid until the ssl object is destroyed. */ PN_EXTERN const char* pn_ssl_get_remote_subject_subfield(pn_ssl_t *ssl0, pn_ssl_cert_subject_subfield field); /** * @} */ #ifdef __cplusplus } #endif #endif /* ssl.h */