Is this the correct way to do error handling in OpenSSL?
And what is the difference between SSL_get_error and ERR_get_error?
The docs are quite vague in this regard.
int ssl_shutdown(SSL *ssl_connection)
{
int rv, err;
ERR_clear_error();
rv = SSL_shutdown(ssl_connection);
if (rv == 0)
SSL_shutdown(ssl_connection);
if (rv < 0)
{
err = SSL_get_error(ssl_connection, rv);
if (err == SSL_ERROR_SSL)
fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
fprintf(stderr, "%s\n", SSL_state_string(ssl_connection));
return 1;
}
SSL_free(ssl_connection);
return 0;
}
SSL_get_error:
SSL_get_error() returns a result code (suitable for the C "switch"
statement) for a preceding call to SSL_connect(), SSL_accept(),
SSL_do_handshake(), SSL_read(), SSL_peek(), or SSL_write() on ssl. The
value returned by that TLS/SSL I/O function must be passed to
SSL_get_error() in parameter ret.
ERR_get_error:
ERR_get_error() returns the earliest error code from the thread's
error queue and removes the entry. This function can be called
repeatedly until there are no more error codes to return.
So the latter is for more general use and those shouldn't be used together, because:
The current thread's error queue must be empty before the TLS/SSL I/O operation is attempted, or SSL_get_error() will not work reliably.
So you have to read all of the errors using ERR_get_error and handle them (or ignore them by removal as you did in your code sample with ERR_clear_error) and then perform the IO operation. Your approach seems to be correct, although I can't check all aspects of it by myself at the moment.
Refer to this answer and this post for more information.
EDIT: according to this tutorial, BIO_ routines may generate an error and affect error queue:
The third field is the name of the package that generated the error,
such as "BIO routines" or "bignum routines".
And what is the difference between SSL_get_error and ERR_get_error?
There are two logical parts to OpenSSL. First is the SSL library, libssl.a (and libssl.so), and it includes the communication related stuff. Second is the cryptography library, libcrypto.a (and libcrypto.so), and it includes big numbers, configuration, input/output, etc.
libssl.a depends upon libcrypto.a, and its why the link command is ordered as -lssl -lcrypto.
You use SSL_get_error to retrieve most errors from the SSL portion library, and you use ERR_get_error to retrieve errors not in the SSL portion of the library.
Is this the correct way to do error handling in OpenSSL?
The code you showed is closer to "how do you shutdown a SSL socket". Ultimately, the gyrations control two cases. First is a half open connection, when the client shutdowns without sending the close notify message. The second is your program's behavior when sending the close notify message.
Its hard to answer "is it correct" because we don't know the behavior you want. If you don't care if the close notify is sent, then I believe you only need to call SSL_shutdown once, regardless of what the client does.
Related
I am reading An Introduction to OpenSSL Programming and here's code from Figure 6
while(1){
r=SSL_read(ssl,buf,BUFSIZZ);
switch(SSL_get_error(ssl,r)){
case SSL_ERROR_NONE:
len=r;
break;
case SSL_ERROR_ZERO_RETURN:
goto shutdown;
case SSL_ERROR_SYSCALL:
fprintf(stderr,
"SSL Error: Premature close0");
goto done;
default:
berr_exit("SSL read problem");
}
fwrite(buf,1,len,stdout);
}
And underneath, in the Error Handling sections, it says:
Error Handling
If the return value was something negative then some
kind of error occurred. There are two kinds of errors we’re concerned
with: ordinary errors and "premature closes". We use the
SSL_get_error() call to determine which kind of error we have. Error
handling in our client is pretty primitive so with most errors we
simply call berr_exit() to print an error message and exit. Premature
closes have to be handled specially.
What is premature close? (I didn't find anything related on SO) Why here it's saying it need to be handled specially?
At the risk of oversimplifying:
At the TCP/IP level, a TCP connection may be "closed gracefully" (both sides send a FIN to close their respective connections), or "terminated abruptly" (one side or another gets a RST). You can read more in RFC 783.
SSL introduces additional protocols on top of TCP/IP.
Older versions of SSL were vulnerable to "truncation attacks":
https://www.cs.cmu.edu/~srini/15-441/F02/Projects/lab01/reference/part1.pdf
TCP uses a FIN segment to indicate that the sender has sent all of its
data. SSL version 2 simply allowed either side to send a TCP FIN to
terminate the SSL connection. This allowed for a "truncation attack":
the attacker could make it appear that a message was shorter than it
was simply by forging a TCP FIN. Unless the victim had some other way
of knowing what message length to expect it would simply believe that
it had received a shorter message.
SSLv3 introduced a "close_notify alert" to mitigate this potential security problem:
The close_notify is an SSL message (and therefore secured) but
is not part of the data stream itself and so is not seen by the
application. No data may be transmitted after the close_notify is
sent.
Thus, when SSL_read() returns 0 to indicate that the socket has
been closed, this really means that the close_notify has been
received. If the client receives FIN before receiving
a close_notify, SSL_read() will return with an error. This is called a
"premature close".
"Unfortunately", the article continues, "sending premature closes is a rather common error, particularly common with clients". They should be handled "differently" from other errors. Or perhaps sometimes even best ignored.
Here's another good link: https://stackoverflow.com/a/28056464/421195
I've created a publisher-subscriber communication scheme with ZeroMQ and I noticed one small issue with my server and client programs.
I know there is no try catch in C (according to my brief research) however having the next two while(1) without an exception catching seems dangerous to me.
Taking into account the following code snippets, what would be the most correct way to handle an exception (inside the while)? With the structure I have right now (as you can see below), the zmq_close and zmq_ctx_destroy will never execute, but I want them to, in case of a program error/exception (whichever the origin).
Note: In this architecture I have one client listening to multiple publishers, thus the for cycles in the Client code.
Server
(...inside main)
while (1) {
char update[20];
sprintf(update, "%s", "new_update");
s_send(publisher, update);
sleep(1);
}
zmq_close(publisher);
zmq_ctx_destroy(context);
return 0;
Client
(...inside main)
while(1){
for (c = 1; c < server_num; c = c + 1){
char *msg = s_recv(subscribers[c]);
if (msg) {
printf("%s\n",msg);
free(msg);
}
sleep(1);
}
}
for (c = 0; c < server_num; c = c + 1)
zmq_close(subscribers[c]);
zmq_ctx_destroy(context);
return 0;
In case one has never worked with ZeroMQ,
or have never met the concept of the art of Zen-of-Zero,
one may here enjoy to first look at "ZeroMQ Principles in less than Five Seconds" before diving into further details
Being the tag error-handling present ... :
Q : what would be the most correct way to handle an exception (inside the while)?
The best strategy is an error-prevention rather than any kind of "reactive" ( ex-post Exception ) handling.
Always assume the things may and will turn wreck havoc and let them fail cheaply. The cheaper the costs of failings are, the better and sooner the system may turn back into its own, intended behaviour.
This said, in modern low-latency distributed-systems, the more in real-time-systems an exception is extremely expensive, disruptive element of the designed code-execution flow.
For these reasons, and for allowing sustained levels of the utmost performance too,
ZeroMQ has since ever a very different approach :
0)
better use zmq_poll() as a cheapest ever detection of a presence ( or not presence ) of any read-able message ( already delivered and being ready so as to be received ), before ever, if at all, calling an API function of a zmq_recv(), to fetch such data into your application-level code's hands, from inside the Context()-instance internal storage.
1)
depending on your language binding (wrapper), best enjoy the non-blocking forms of the .poll(), .send() and .recv() methods. The native API is the most straightforward in always going in this mode with retCode = zmq_recv( ..., ZMQ_NOBLOCK );
2)
Always analyse the retCode - be it in a silent or explanatory assert( retCode == 0 && zmq_errno() ) or otherwise.
3)
Best review and fine-tune all configuration attributes of the instantiated tools available from ZeroMQ framework and harness all their hidden strengths to best match your application domain's needs. Many native API-settings may help mitigate, if not principally avoid, lots of colliding requirements right inside the Context()-engine instance, so do not hesitate to learn all details of possible settings and use them to the best of their help for your code.
Without doing all of this above, your code is not making the best of the Zen-of-Zero
Q : With the structure I have right now (...), the zmq_close and zmq_ctx_destroy will never execute, but I want them to, in case of a program error/exception (whichever the origin).
it is fair enough to set an explicit flag:
bool DoNotExitSoFar = True;
while ( DoNotExitSoFar ){
// Do whatever you need
// Record return-codes, always
retCode = zmq_...(...);
// Test/Set the explicit flag upon a context of retCode and zmq_errno()
if ( retCode == EPROTONOTSUPPORTED ){
// take all due measures needed
...
// FINALLY: Set
DoNotExitSoFar = False;
}
}
// --------------------------------------------- GRACEFUL TERMINATION .close()
if ( ENOTSOCK == zmq_close(...) ) { ...; }
...
// --------------------------------------------- GRACEFUL TERMINATION .term()
retCode = zmq_ctx_term(...);
if ( EINTR == retCode ){ ...; }
if ( EFAULT == retCode ){ ...; }
...
Using other tooling, like int atexit(void (*func)(void)); may serve as the last resort for a ALAP calling zmq_close() or zmq_ctx_term()
You are correct, C has no concept of try/catch, but that shouldn't be an issue. It just means you need to handle exceptions in the s_send() and s_recv() routines (so, for example, if something unexpected happens (like malloc() returning NULL), you have to deal with it and continue processing or return).
I would also suggest you look at the poll() or select() system calls for your client instead of doing a looping poll. It's much more elegant to only service the file descriptors that have data waiting to be read.
The idiomatic way in C to check for error is to look the return value and then check errno if it's negative.
// ... Your previous code
int ret = zmq_ctx_destroy(context);
if(ret < 0) {
// Process your error here
printf("My error message is : %s\n", strerror(errno));
}
You may need to add #include <errno.h> and <string.h> if it's not already in your program.
You can also read strerror documentation.
Now to adress this part of the question :
Taking into account the following code snippets, what would be the most correct way to handle an exception (inside the while)? With the structure I have right now (as you can see below), the zmq_close and zmq_ctx_destroy will never execute, but I want them to, in case of a program error/exception (whichever the origin).
All zmq_* functions will return an error and set errno. Check every function and break when an error occur. In that scenario, polling on non-blocking function is best to break out of your whileloop when an error occurs.
On Linux, you can also set a signal handler and execute a clean up routine when a singal is raised (for example, it is very common to catch SIGINT to properly exit a program on UNIX on ctrl+C in the console). See this answer
Hi guys i have a problem that i can not find an answer for, so i thought i'd ask you guys :p
so i'm trying to make an HTTP server in C and i'm using "errno.h" for error handling but i don't know which error codes i should test for, to be more specific i want to check for errors returned by the functions: socket(), bind(), accept() etc.. so that i act accordingly to each error and not in the same manner for every error.
do i check every single possible error code every time i make a system/library call or i don't use errno at all???
You check for the error codes that means something specific to you on the call you are making, then genrically error on the rest.
doFoo()
if(errno == EMISSING)
return FooNotFound;
if(errno == EAGAIN)
retryFoo();
else
perror....
For example, if it failed to invoke msgsnd/msgrcv:
How to handle the errno – what is the best way?
What principle is applying to business product?
Shall I have to cover all of them?
What kinds of error must be handled? Do I have to write a signal handler for EINTR or something like this?
Here's my straw-man code:
RetVal = msgrcv(... );
if( RetVal == -1 )
{
switch (errno)
{
case E2BIG:
...
case EAGAIN:
...
case EFAULT:
...
case EIDRM:
...
case EINTR:
...
case EINVAL:
...
case ENOMEM:
...
default:
...
}
This depends on the coding standards you want to apply, and how you might reasonably respond to the failures.
You should always check errors, but you might commonly only handle one or two of them such as EINTR. I would at least try to print some kind of diagnostic last-gasp message before violently exiting in the case of unexpected errors.
The more critical the software, the more carefuly-designed it needs to be, and more comprehensive error handling is part of that.
Since your tags are "C" and "Linux" I assume you're using GCC, in which case have a look at the handy %m in printf.
Obviously this too simple for some cases, but until your program is finished something like this is a good stub to have.
if(RetVal == -1) {
perror("message receive");
exit(1);
}
Typically, one only looks at the exact error if a specific recovery is called for in that case. Until you have some code that you need to make conditional on exactly the type of error, you should simply decide between...
Silently ignore the error
Warn, and then continue
Complain, and then exit
See also...
the nonstandard-but-useful err(3).
setjmp, longjmp, sigsetjmp, et al
It depends on your code and what you can do (similar to exception) and what error you have received. For example EAGAIN is not a strictly an error (it denotes that you tried non-blocking operation and it would block).
If it is a quick program you may do nothing (say - you just playing with API). If it has GUI it might display a message (say "disk is full" or "cannot connect to network") etc.
If the question had an ultimate answer there would be no need for errno - system call could do it as well.
The basic Linux system calls almost universally return -1 on error, and 0 or positive value on success. Also, the errno is set to one of the predefined values. So, checking failure of system calls is pretty easy and should be done consistently. Checking the errno for what type of error occurs should be done for the errors you can handle in your program itself. For other errors, it is best to inform the user that he made an error and notify him with the error. The strerror() in the string.h takes erroro as the parameter and returns a pointer to string describing the error.
#include<string.h>
char* strerror(int errno);
After telling the error, it is on the severity of the error whether to continut running the program or exit the program by
exit(1);
I am using the library Function ConnectToTCPServer. This function times out when the host is not reachable. In that case the application crashes with the following error:
"NON-FATAL RUN-TIME ERROR: "MyClient.c", line 93, col 15, thread id 0x000017F0: Library function error (return value == -11 [0xfffffff5]). Timeout error"
The Errorcode 11 is a Timeout error, so this could happen quite often in my application - however the application crashes - i would like to catch this error rather than having my application crash.
How can i catch this runtime error in Ansi C90?
EDIT:
Here is a Codesnippet of the current use:
ConnectToTCPServer(&srvHandle, srvPort, srvName, HPMClientCb, answer, timeout);
with
int HPMClientCb(UINT handle, int xType, int errCode, void *transData){
printf("This was never printed\n");
return errCode;
}
The Callbackfunction is never called. My Server is not running, so ConnectToTCPServer will timeout. I would suspect that the callback is called - but it never is called.
EDIT 2: The Callback function is actually not called, the Returnvalue of ConnectToTCPServer contains the same error information. I think it might be a bug that ConnectToTCPServer throws this error. I just need to catch it and bin it in C90. Any Ideas?
EDIT 3: I tested the Callbackfunction, on the rare occaision that my server is online the callback function is actually called - this does not help though because the callback is not called when an error occurs.
Looking in NI documentation, I see this:
"Library error breakpoints -- You can set an option to break program execution whenever a LabWindows/CVI library function returns an error during run time. "
I would speculate they have a debug option to cause the program to stop on run-time errors, which you need to disable in configuration, in compile time or in run-time.
My first guess would have been configuration value or compilation flag, but this is the only option I found, which is a run-time option:
// If debugging is enabled, this function directs LabWindows/CVI not
// to display a run-time error dialog box when a National Instruments
// library function reports an error.
DisableBreakOnLibraryErrors();
Say if it helped.
Theres no such thing as a general case of "catching" an error (or an 'exception') in standard C. Thats up to your library to decide what to do with it. Likely its logging its state and then simply calling abort(). In Unix, that signals SIGABRT which can be handled and not just exit()ed. Or their library may just be logging and then calling exit().
You could run your application under a utility like strace to see what system calls are being performed and what signals are being asserted.
I'd work with your vendor if you can't make any headway otherwise.
From the documentation, it seems you should get a call to your clientCallbackFunction when an error occurs. If you don't, you should edit your question to clarify that.
I'm not sure I understand you.
I looked at the documentation for the library function ConnectToTCPServer(). It returns an int; 0 means success, negative numbers are the error codes.
EDIT: Here is a Codesnippet of the
current use:
ConnectToTCPServer(&srvHandle, srvPort, srvName, HPMClientCb, answer, timeout);
If that's really the current use, you don't seem to be trying to tell whether ConnectToTCPServer() succeeds. To do that, you'd need
int err_code;
...
err_code = ConnectToTCPServer(&srvHandle, srvPort, srvName, HPMClientCb, answer, timeout);
and then test err_code.
The documentation for ConnectToTCPServer()implies that your callback function won't be called unless there's a message from a TCP server. No server, no message. In that case,
ConnectToTCPServer() should return a negative number.
You should check the return value of ConnectToTCPServer().
Finding a negative number there, you should do something sensible.
Did I understand the documentation correctly?
Normally, you should be able to simply check the return value. The fact that your application exits implies that something is already catching the error and asserting (or something similar). Without seeing any context (i.e. code demonstrating how you're using this function), it's difficult to be any more precise.
The documentation states that ConnectToTCPServer will return the error code. The callback is only called if the connection is established, disconnected or when there is data ready to be read.
The message you get states that the error is NON-FATAL, hence it shouldn't abort. If you're sure the code doesn't abort later it seems indeed like a bug in the library.
I'm not familiar with CVI, but there might be a (compile-/runtime-) option to abort even on non-fatal errors (for debugging purposes). If you can reproduce this in a minimal example you should report it to NI.