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.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- RSS Feeds
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Drupal Is a Framework: Why Everyone Needs to Understand This
- Home, My Backup Data Center
- A Topic for Discussion - Open Source Feature-Richness?
- Dart: a New Web Programming Experience
- Developer Poll
- May 2013 Issue of Linux Journal: Raspberry Pi
- Trying to Tame the Tablet
- great post
7 min 25 sec ago - Google Docs
29 min 56 sec ago - Reply to comment | Linux Journal
5 hours 18 min ago - Reply to comment | Linux Journal
6 hours 5 min ago - Web Hosting IQ
7 hours 39 min ago - Thanks for taking the time to
9 hours 15 min ago - Linux is good
11 hours 13 min ago - Reply to comment | Linux Journal
11 hours 30 min ago - Web Hosting IQ
12 hours 38 sec ago - Web Hosting IQ
12 hours 1 min ago
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.



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?