From: Roger Meier Date: Sun, 4 May 2014 20:34:44 +0000 (+0200) Subject: THRIFT-2512 lib/${language}/README.md X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=4fba9d2c3c57684950ffe70979de77bb18973d05;p=common%2Fthrift.git THRIFT-2512 lib/${language}/README.md Client: cpp doc cosmetics --- diff --git a/lib/cpp/README.md b/lib/cpp/README.md index e57fdd44..c578223f 100755 --- a/lib/cpp/README.md +++ b/lib/cpp/README.md @@ -127,138 +127,143 @@ OS's. *NIX named pipes only support 1:1 client-server connection. # Thrift/SSL -1. Scope +## Scope - This SSL only supports blocking mode socket I/O. It can only be used with - TSimpleServer, TThreadedServer, and TThreadPoolServer. +This SSL only supports blocking mode socket I/O. It can only be used with +TSimpleServer, TThreadedServer, and TThreadPoolServer. -2. Implementation +## Implementation - There're two main classes TSSLSocketFactory and TSSLSocket. Instances of - TSSLSocket are always created from TSSLSocketFactory. +There're two main classes TSSLSocketFactory and TSSLSocket. Instances of +TSSLSocket are always created from TSSLSocketFactory. - PosixSSLThreadFactory creates PosixSSLThread. The only difference from the - PthreadThread type is that it cleanups OpenSSL error queue upon exiting - the thread. Ideally, OpenSSL APIs should only be called from PosixSSLThread. +PosixSSLThreadFactory creates PosixSSLThread. The only difference from the +PthreadThread type is that it cleanups OpenSSL error queue upon exiting +the thread. Ideally, OpenSSL APIs should only be called from PosixSSLThread. -3. How to use SSL APIs +## How to use SSL APIs - // This is for demo. In real code, typically only one TSSLSocketFactory - // instance is needed. - shared_ptr getSSLSocketFactory() { - shared_ptr factory(new TSSLSocketFactory()); - // client: load trusted certificates - factory->loadTrustedCertificates("my-trusted-ca-certificates.pem"); - // client: optionally set your own access manager, otherwise, - // the default client access manager will be loaded. +This is for demo. In real code, typically only one TSSLSocketFactory +instance is needed. - factory->loadCertificate("my-certificate-signed-by-ca.pem"); - factory->loadPrivateKey("my-private-key.pem"); - // server: optionally setup access manager - // shared_ptr accessManager(new MyAccessManager); - // factory->access(accessManager); - ... - } + shared_ptr getSSLSocketFactory() { + shared_ptr factory(new TSSLSocketFactory()); + // client: load trusted certificates + factory->loadTrustedCertificates("my-trusted-ca-certificates.pem"); + // client: optionally set your own access manager, otherwise, + // the default client access manager will be loaded. + factory->loadCertificate("my-certificate-signed-by-ca.pem"); + factory->loadPrivateKey("my-private-key.pem"); + // server: optionally setup access manager + // shared_ptr accessManager(new MyAccessManager); + // factory->access(accessManager); + ... + } - // client code sample - shared_ptr factory = getSSLSocketFactory(); - shared_ptr socket = factory.createSocket(host, port); - shared_ptr transport(new TBufferedTransport(socket)); - ... +client code sample - // server code sample - shared_ptr factory = getSSLSocketFactory(); - shared_ptr socket(new TSSLServerSocket(port, factory)); - shared_ptr transportFactory(new TBufferedTransportFactory)); - ... + shared_ptr factory = getSSLSocketFactory(); + shared_ptr socket = factory.createSocket(host, port); + shared_ptr transport(new TBufferedTransport(socket)); + ... -4. AccessManager - AccessManager defines a callback interface. It has three callback methods: +server code sample - (a) Decision verify(const sockaddr_storage& sa); - (b) Decision verify(const string& host, const char* name, int size); - (c) Decision verify(const sockaddr_storage& sa, const char* data, int size); + shared_ptr factory = getSSLSocketFactory(); + shared_ptr socket(new TSSLServerSocket(port, factory)); + shared_ptr transportFactory(new TBufferedTransportFactory)); + ... - After SSL handshake completes, additional checks are conducted. Application - is given the chance to decide whether or not to continue the conversation - with the remote. Application is queried through the above three "verify" - method. They are called at different points of the verification process. +## AccessManager - Decisions can be one of ALLOW, DENY, and SKIP. ALLOW and DENY means the - conversation should be continued or disconnected, respectively. ALLOW and - DENY decision stops the verification process. SKIP means there's no decision - based on the given input, continue the verification process. +AccessManager defines a callback interface. It has three callback methods: - First, (a) is called with the remote IP. It is called once at the beginning. - "sa" is the IP address of the remote peer. +(a) Decision verify(const sockaddr_storage& sa); - Then, the certificate of remote peer is loaded. SubjectAltName extensions - are extracted and sent to application for verification. When a DNS - subjectAltName field is extracted, (b) is called. When an IP subjectAltName - field is extracted, (c) is called. +(b) Decision verify(const string& host, const char* name, int size); - The "host" in (b) is the value from TSocket::getHost() if this is a client - side socket, or TSocket::getPeerHost() if this is a server side socket. The - reason is client side socket initiates the connection. TSocket::getHost() - is the remote host name. On server side, the remote host name is unknown - unless it's retrieved through TSocket::getPeerHost(). Either way, "host" - should be the remote host name. Keep in mind, if TSocket::getPeerHost() - failed, it would return the remote host name in numeric format. +(c) Decision verify(const sockaddr_storage& sa, const char* data, int size); - If all subjectAltName extensions were "skipped", the common name field would - be checked. It is sent to application through (c), where "sa" is the remote - IP address. "data" is the IP address extracted from subjectAltName IP - extension, and "size" is the length of the extension data. +After SSL handshake completes, additional checks are conducted. Application +is given the chance to decide whether or not to continue the conversation +with the remote. Application is queried through the above three "verify" +method. They are called at different points of the verification process. - If any of the above "verify" methods returned a decision ALLOW or DENY, the - verification process would be stopped. +Decisions can be one of ALLOW, DENY, and SKIP. ALLOW and DENY means the +conversation should be continued or disconnected, respectively. ALLOW and +DENY decision stops the verification process. SKIP means there's no decision +based on the given input, continue the verification process. - If any of the above "verify" methods returned SKIP, that decision would be - ignored and the verification process would move on till the last item is - examined. At that point, if there's still no decision, the connection is - terminated. +First, (a) is called with the remote IP. It is called once at the beginning. +"sa" is the IP address of the remote peer. - Thread safety, an access manager should not store state information if it's - to be used by many SSL sockets. +Then, the certificate of remote peer is loaded. SubjectAltName extensions +are extracted and sent to application for verification. When a DNS +subjectAltName field is extracted, (b) is called. When an IP subjectAltName +field is extracted, (c) is called. -5. SIGPIPE signal +The "host" in (b) is the value from TSocket::getHost() if this is a client +side socket, or TSocket::getPeerHost() if this is a server side socket. The +reason is client side socket initiates the connection. TSocket::getHost() +is the remote host name. On server side, the remote host name is unknown +unless it's retrieved through TSocket::getPeerHost(). Either way, "host" +should be the remote host name. Keep in mind, if TSocket::getPeerHost() +failed, it would return the remote host name in numeric format. - Applications running OpenSSL over network connections may crash if SIGPIPE - is not ignored. This happens when they receive a connection reset by remote - peer exception, which somehow triggers a SIGPIPE signal. If not handled, - this signal would kill the application. +If all subjectAltName extensions were "skipped", the common name field would +be checked. It is sent to application through (c), where "sa" is the remote +IP address. "data" is the IP address extracted from subjectAltName IP +extension, and "size" is the length of the extension data. -6. How to run test client/server in SSL mode +If any of the above "verify" methods returned a decision ALLOW or DENY, the +verification process would be stopped. - The server and client expects the followings from the directory /test/ +If any of the above "verify" methods returned SKIP, that decision would be +ignored and the verification process would move on till the last item is +examined. At that point, if there's still no decision, the connection is +terminated. - - keys/server.crt - - keys/server.key - - keys/CA.pem +Thread safety, an access manager should not store state information if it's +to be used by many SSL sockets. - The file names are hard coded in the source code. You need to create these - certificates before you can run the test code in SSL mode. Make sure at least - one of the followings is included in "keys/server.crt", +## SIGPIPE signal - - subjectAltName, DNS localhost - - subjectAltName, IP 127.0.0.1 - - common name, localhost +Applications running OpenSSL over network connections may crash if SIGPIPE +is not ignored. This happens when they receive a connection reset by remote +peer exception, which somehow triggers a SIGPIPE signal. If not handled, +this signal would kill the application. - Run within /test/ folder, +## How to run test client/server in SSL mode - ./cpp/TestServer --ssl & - ./cpp/TestClient --ssl +The server and client expects the followings from the directory /test/ - If "-h " is used to run client, the above "localhost" in the above - server-certificate.pem has to be replaced with that host name. +- keys/server.crt +- keys/server.key +- keys/CA.pem -7. TSSLSocketFactory::randomize() +The file names are hard coded in the source code. You need to create these +certificates before you can run the test code in SSL mode. Make sure at least +one of the followings is included in "keys/server.crt", - The default implementation of OpenSSLSocketFactory::randomize() simply calls - OpenSSL's RAND_poll() when OpenSSL library is first initialized. +- subjectAltName, DNS localhost +- subjectAltName, IP 127.0.0.1 +- common name, localhost - The PRNG seed is key to the application security. This method should be - overridden if it's not strong enough for you. +Run within /test/ folder, + + ./cpp/TestServer --ssl & + ./cpp/TestClient --ssl + +If "-h " is used to run client, the above "localhost" in the above +keys/server.crt has to be replaced with that host name. + +## TSSLSocketFactory::randomize() + +The default implementation of OpenSSLSocketFactory::randomize() simply calls +OpenSSL's RAND_poll() when OpenSSL library is first initialized. + +The PRNG seed is key to the application security. This method should be +overridden if it's not strong enough for you.