Without secure server applications, secure client applications are not required. With OpenSSL, we can create secure server applications. This is not the case even though the document makes it look complicated. In this article, we will learn how to use the concepts learned in part 1 of this three-part series to build secure server applications.
The first two sections of this series discuss how to use OpenSSL to create client applications. Part 1 discusses the use of OpenSSL to create basic security clients, and Part 2 discusses the issues related to digital certificates in depth. After reading this article and sending me a lot of e-mail and positive feedback, I am very clear that the next theoretical introduction should be about servers.
The server provides network and Internet access to resources such as files and devices. Sometimes we have to provide these services through a secure channel. OpenSSL allows us to write services using secure channels and open channels.
Using OpenSSL to create basic server applications is essentiallyAlmostIt is equivalent to creating a basic client application. There are few differences between the two. Obviously, one of the differences is that the server will be set to receive connections, rather than establishing external connections. And, as we can see from the discussion of digital certificates in part 1 of this series, the server must also provide security certificates during the handshake process.
Wait
The server is basically a connection that stays there waiting to arrive. After all, this is why the server exists. The Web server waits for the browser request page, the FTP server waits for the client request file, and the Chat Server waits for the connection from the chat client. Therefore, the server has to wait.
There is little difference between client and server communication. The only difference is that for handshakes, the server is like the opposite of a coin. Everything else is the same.
This allows us to use OpenSSL to write secure server applications. Let's assume that you have learned how to use OpenSSL to write client applications. (If you do not know any more, refer to "API overview" in section 1st of this series to learn how to set up the OpenSSL library .)
Two forms of identity
|
SSL Context To set the SSL context used in this article, use the following code. This function returns NULL when an error occurs: SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
|
|
It can also be said to be two parts of the logo.
The server is responsible for providing the security certificate used during the handshake. The complete server certificate consists of the public key and private key. The Public Key is sent to the client, while the private key is confidential.
Just as a trusted certificate must be provided to the database used by the client application, the server key must also be provided to the database used by the server application. Several functions provide this function:
List 1. Functions for loading server certificates
SSL_CTX_use_certificate(SSL_CTX *, X509 *)SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d);SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); |
This functionASN1
The variant can load the ASN1-encoded digital certificate at the specified memory location to the SSL environment. This function loads an X.509 certificate provided in the given memory structure. The last function_file
Will load a PEM-encoded digital certificate from the file. This functiontype
The parameter allows us to load the certificate using DER encoding.
To load the private key, use one of the following functions:
Listing 2. functions used to load the Private Key
SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, unsigned char *d, long len);SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len);SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); |
Required interaction
Private keys are most suitable for encrypted storage. However, the problem is that the function that loads the certificate does not request the password to use the encrypted certificate. On the contrary, OpenSSL provides a callback mechanism for obtaining passwords.
The callback format is as follows:
Listing 3. Callback format
int password_callback(char *buf, int size, int rwflag, void *userdata); |
For the purpose of this Article, the last parameteruserdata
Yes. The buffer zone is called before calling this function, so we cannot control the size of this buffer zone.
|
Server Private Key Note: For server certificates, the private key should not be encrypted and saved. Otherwise, the Administrator may be asked too frequently to enter the password. |
|
Parametersrwflag
Is the read/write mark. The purpose of using it is to allow us to program and determine that this password is being used to encrypt information (rwflag
= 1) or decrypt the information (rwflag
= 0 ). If you are using a callback function to request the password used for data encryption, it is best to request the password twice in a certain way, so that you can receive user input once more.
When the certificate is loaded, the password is requested only once, so that it can be decrypted and saved to the memory. How to obtain a password from a user depends on your implementation.
Once the password callback function is created, you can use the following method:SSL_CTX_set_default_passwd_cb
Install it in the SSL environment:
Listing 4. Installing the callback function
/* ctx is a pointer to a previously created SSL context, and cb is the pointer * to the callback function you created. */SSL_CTX_set_default_passwd_cb(ctx, cb); |
Engine launch
Now the user is prompted that the callback function for entering the password has been created, and then we can use the function for actually importing the certificate. Certificates can be imported from existing memory structures or files.
To better meet the common requirements for processing digital certificates, such as in the Apache HTTP Server project, I will show you how to load certificates from files. If we have read Part 1 of this series of articles, the way to load certificates is very similar to the way to load trust storage described in the previous article.
We will start with the public certificate, which will be sent to the client.
Listing 5. Load a public certificate
/** * ctx is the SSL context created earlier */if(SSL_CTX_use_certificate_file(ctx, "/path/to/certificate.pem", SSL_FILETYPE_PEM) < 1){ /* Handle failed load here */} |
After the public certificate is loaded, the private certificate must be loaded. This is required during the handshake because the client is sending the information to the server that encrypts the public key. The data can only be decrypted using the private key. Similarly, to maintain consistency, we will also load the key from the file.
Listing 6. loading the Private Key
if(SSL_CTX_use_PrivateKey_file(ctx, "/path/to/private.key", SSL_FILETYPE_PEM) < 1){ /* Handle failed load here */} |
Complete settings
After setting the environment (see the SSL environment above) and loading the key, you should create a bio object to complete the settings. We can recall how the OpenSSL BIO library is used in section 1st to establish SSL and non-SSL communication. To be consistent with this article, we will also implement the same functions in this article.
Listing 7. Bio pointer
3 Bio objects? Why do we need to use three bio objects? This has a purpose. Please believe me. (Remember, the goal of trust and security is the same .)
First pointerbio
Is the main bio object, which can be created from the SSL environment. Second objectabio
It is the bio used to accept connections and is used to receive incoming connections. The third bioout
Is the object that the server sends to the client.
Listing 8. Setting main bio objects
bio = BIO_new_ssl(ctx, 0);if(bio == NULL){ /* Handle failure here */}/* Here, ssl is an SSL* (see Part 1) */BIO_get_ssl(bio, &ssl);SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); |
The bio object settings are slightly different from the bio settings used for client connection. We can recall that in part 1, client connection is usedBIO_new_ssl_connect
Created.
Here, the setting is to useBIO_new_ssl
Add two parameters: a pointer to the ssl_ctx object and a tag. This tag tells OpenSSL which bio object to create: 0 for the server, 1 for the client. As this code tries to establish a client connection, this flag should be set to 0.
Listing 9. Set bio receiving
abio = BIO_new_accept("4422");BIO_set_accept_bios(abio, bio); |
WhereBIO_do_connect
Create bio for client connection,BIO_new_accept
Create bio for the server connection. It only needs one parameter, that is, the listening port, which is encoded in the string.
Since this assumption is listening for secure connections, we need to link a security bio to this receiving bio. This is the second function call.BIO_set_accept_bios
Used. She connected the previously created SSL bio to the receiving bio.
This function call does not need to release SSL bio. After receiving Bio is destroyed, it is automatically released.
Sit down and wait.
The server is like a fisherman; it just needs to sit there and wait for the client to hook up. The server is waiting for the game. You only need to wait for the client connection to arrive.
If you have had experience programming using Winsock or BSD socket, you may haveaccept
Function usage experience. The corresponding part of OpenSSL isBIO_do_accept
But we do not call it only once.accept
Then wait, but before waiting, you must callBIO_do_accept
Twice.
Listing 10. Tell the server to "sit down"
/* First call to set up for accepting incoming connections... */if(BIO_do_accept(abio) <= 0){ /* Handle fail here */}/* Second call to actually wait */if(BIO_do_accept(abio) <= 0){ /* Handle fail here */}/* Any other call will cause it to wait automatically */ |
First callBIO_do_accept
Bio is set to receive the connection. The second call needs to actually sit down and wait. It is allowed to wait at any time thereafter.
Response to connection
BIO_do_accept
Will return when the connection is received1
. However, we cannot communicate only by receiving bio. Instead, OpenSSL creates another bio, which must be usedBIO_pop
To receive bio.
Listing 11. Pop-up connection for communication
out = BIO_pop(abio);if(BIO_do_handshake(out) <= 0){ /* Handle fail here */} |
After the pop-up connection arrives to receive bio, the handshake needs to useBIO_do_handshake
. If the settings in the previous sections are successful, the handshake here should also be successful.
The server will actually communicate with the client through various read/write functions of the Bio database. We have discussed these issues in part 1, so we can find more in this article.
Provide excellent services
In general, once you understand how this works, it is no longer difficult to use OpenSSL to create secure server applications. From now on, we can expand the provided sample code to create a full version of the SSL server application to meet our requirements. However, please note in advance that the sample code provided here and the download section is simplified as much as possible and should only be applicable to the purpose of the experiment. Before creating a complete SSL server application, make sure to read and study the latest security recommendations.
Download
Description |
Name |
Size |
Download Method |
Sample Code in this article |
Openssl3.tar.gz |
4 kb |
HTTP |
|
|
Information about the Download Method |
|
References