An Introduction to OpenSSL Programming, Part II of II
Automatic rehandshake support is built into SSL_read(), so the client doesn't have to do anything explicit to enable rehandshake. However, this doesn't necessarily mean that arbitrary clients will work. In particular, the client must be prepared to handle the SSL_ERROR_WANT_READ return value from SSL_read(). Ordinarily, if the client is using blocking I/O--as we are in wclient2--SSL_read() would never return this error. However, it's required if rehandshaking occurs.
To see why this is, imagine that your client uses select() to determine when there is data available from the server. When select() returns, you call SSL_read(). If the server is requesting rehandshake, however, the data will be a HelloRequest message. SSL_read() consumes the message and performs the handshake. There's no guarantee that there will be any more data available on the socket, so SSL_read() needs to return without any data--hence the SSL_ERROR_WANT_READ return value.
Our original wclient program, despite functioning properly in every other respect, broke utterly when dealing with rehandshake, thereby proving once again that if you haven't tested some feature, it almost certainly doesn't work. The fix in wclient2 is to change the read loop that is shown in Listing 5.
Listing 5. New Client Read Loop with Rehandshake Support
48 /* Now read the server's response, assuming
49 that it's terminated by a close */
50 while(1){
51 r=SSL_read(ssl,buf,BUFSIZZ);
52 switch(SSL_get_error(ssl,r)){
53 case SSL_ERROR_NONE:
54 len=r;
55 break;
56 case SSL_ERROR_WANT_READ:
57 continue;
58 case SSL_ERROR_ZERO_RETURN:
59 goto shutdown;
60 case SSL_ERROR_SYSCALL:
61 fprintf(stderr,
62 "SSL Error: Premature close\n");
63 goto done;
64 default:
65 berr_exit("SSL read problem");
66 }
67
68 fwrite(buf,1,len,stdout);
69 }
Since this is an HTTP client and it's already written the request, there's no need to wonder if there is data coming from the server. The next traffic on the wire will always be the server's response. Thus, we don't need to select() on the socket. If we get SSL_ERROR_WANT_READ, we just go back to the top of the loop and call SSL_read() again.
When using client authentication it's important to understand what it does and doesn't provide. So far, all the server knows is that the client possessed the private key corresponding to some valid certificate. In some cases this might be enough, but in most cases the server wants to know who the client is in order to make authorization decisions.
Checking the client's certificate is roughly similar to the check_cert() function we used to check the server's identity. The server would extract the client's name from the certificate and check it against some access control list. If the name is on the list, the client will be accorded the appropriate privileges. Otherwise, access will be denied.
SSL offers a multiplicity of cryptographic algorithms. Since they are not equally strong and fast, users often want to choose one algorithm over another. By default, OpenSSL supports a broad variety of ciphers; however, it provides an API for restricting the cipher that it will negotiate. We expose this functionality in wclient2 and wserver2 with the -a flag.
To use the -a flag, the user provides a colon-separated list of ciphers, as in -a RC4-SHA:DEC-CBC3-SHA:DES-CBC- SHA. This string is then passed to OpenSSL via the SSL_CTX_set_cipher_list() function, as shown in Listing 6.
Listing 6. Setting the Cipher List
126 /* Set our cipher list */
127 if(ciphers){
128 SSL_CTX_set_cipher_list(ctx,ciphers);
129 }
You can get a list of all the algorithms that OpenSSL supports using the openssl command. Try openssl ciphers. Also, you might want to try using the -a flag with both client and server. Verify for yourself that if you use the same cipher (or have the same one on both lists) things work and, otherwise, the connection fails.
Our wclient program is just about the most trivial client program possible because the I/O semantics are so simple. The client always writes everything it has to write, and then reads everything that the server has to read. Reads and writes are never interlaced, and the client just stops and waits for data from the server. This works fine for simple applications, but there are many situations in which it's unacceptable. One such application is a remote login client.
A remote login client such as Telnet or ssh needs to process at least two sources of input: the keyboard and the network. Input from the keyboard and the server can appear asynchronously. That is to say they can appear in any order. This means that the read/write type I/O discipline that we had in wclient is fundamentally inadequate.
It's easy to see this. Consider an I/O discipline analogous to the one we used in wclient, represented by the pseudo-code in Listing 7.
Listing 7. A Broken Client I/O Discipline
1 while(1){
2 read(keyboard,buffer);
3 write(server,buffer);
4 read(server,buffer);
5 write(screen,buffer);
6 }
Consider the case in which you're remotely logged into some machine and request a directory listing. Your request is a single line (ls on UNIX boxes) but the response is a large number of lines. In general, these lines will be written in more than one write. Thus, it may very well take more than one read in order to read them from the server. However, if we use the I/O discipline in Listing 7, we'll run into a problem.
We read the command from the user and the first chunk of the server's response, but after that we get deadlocked. The client is waiting in line 2 for the user to type something, but the user is waiting for the rest of the directory listing. We're deadlocked. In order to break the deadlock, we need some way to know when either the keyboard or the network is ready to read. We can then service that source of input and keep from deadlocking. Conveniently, Linux provides us with a call that does exactly that-- select(2). select() is the standard tool for doing multiplexed I/O. It lets you determine whether any of a set of sockets is ready to read or write. If you're not familiar with it already, read the man page or consult Richard Stevens's fine book Advanced Programming in the UNIX Environment (Addison-Wesley 1992).
Unfortunately, although select() is a common UNIX idiom, its use with OpenSSL is far from clean and requires understanding of some subtleties of SSL. In order to demonstrate them, we present a new program, sclient. sclient is a simple model of an SSLized remote access client. It connects to the server and then transfers anything typed at the keyboard to the server, and anything sent from the server to the screen.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.
Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.
Sponsored by ActiveState
| Speed Up Your Web Site with Varnish | Jun 19, 2013 |
| Non-Linux FOSS: libnotify, OS X Style | Jun 18, 2013 |
| Containers—Not Virtual Machines—Are the Future Cloud | Jun 17, 2013 |
| Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer | Jun 12, 2013 |
| Weechat, Irssi's Little Brother | Jun 11, 2013 |
| One Tail Just Isn't Enough | Jun 07, 2013 |
- Containers—Not Virtual Machines—Are the Future Cloud
- Non-Linux FOSS: libnotify, OS X Style
- Linux Systems Administrator
- Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer
- Validate an E-Mail Address with PHP, the Right Way
- Technical Support Rep
- Senior Perl Developer
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- Introduction to MapReduce with Hadoop on Linux
- Cari Uang
1 hour 49 min ago - user namespaces
4 hours 43 min ago - yea
5 hours 8 min ago - One advantage with VMs
7 hours 37 min ago - about info
8 hours 10 min ago - info
8 hours 11 min ago - info
8 hours 12 min ago - info
8 hours 14 min ago - info
8 hours 15 min ago - abut info
8 hours 17 min ago
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?



Comments
Block socket with SSL_MODE_AUTO_RETRY
If I use block socket with SSL_MODE_AUTO_RETRY
The flag SSL_MODE_AUTO_RETRY will cause read/write operations to only return after the handshake and successful completion.
Do I have to handle the retrying in SSL_Read and SSL_Write? Isn't it easier to do this way? I know it hurts throughput a little, but is it a big deal?