Skip to content

Add support for hostname validation feature. #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ libnopoll_la_SOURCES = \
nopoll_io.c \
nopoll_msg.c \
nopoll_win32.c \
nopoll_conn_opts.c
nopoll_conn_opts.c \
nopoll_hostname_validation.c \
nopoll_hostname_compare.c \
nopoll_hostcheck.c

libnopollinclude_HEADERS = \
nopoll.h \
Expand All @@ -39,7 +42,10 @@ libnopollinclude_HEADERS = \
nopoll_io.h \
nopoll_msg.h \
nopoll_win32.h \
nopoll_conn_opts.h
nopoll_conn_opts.h \
nopoll_hostname_validation.h \
nopoll_hostname_compare.h \
nopoll_hostcheck.h

libnopoll_la_LDFLAGS = -no-undefined -export-symbols-regex '^(nopoll|__nopoll|_nopoll).*'

Expand Down
1 change: 1 addition & 0 deletions src/nopoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ BEGIN_C_DECLS
#include <nopoll_listener.h>
#include <nopoll_io.h>
#include <nopoll_loop.h>
#include <nopoll_hostname_validation.h>

/**
* \addtogroup nopoll_module
Expand Down
24 changes: 23 additions & 1 deletion src/nopoll_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

#include <nopoll_conn.h>
#include <nopoll_private.h>

#include <nopoll_hostname_validation.h>
#if defined(NOPOLL_OS_UNIX)
# include <netinet/tcp.h>
#endif
Expand Down Expand Up @@ -1020,6 +1020,28 @@ noPollConn * __nopoll_conn_new_common (noPollCtx * ctx,

return conn;
}

/* Check for opts to verify hostname validation during conn handshake */
if (options == NULL || options->host_verify)
{
noPollHostValidationStatus status = ERROR;
/* hostname should be validated without http/https, so pass conn->host_name */
status = nopoll_validate_hostname(server_cert, conn->host_name);
if( status == MATCH_FOUND )
{
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Hostname validation SUCCESS, done as part of client \n");
}
else
{
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL,"Hostname validation FAILED with errno %d \n",status);
/* release connection options */
nopoll_free (content);
nopoll_conn_shutdown (conn);
__nopoll_conn_opts_release_if_needed (options);
X509_free (server_cert);
return NULL;
}
}
X509_free (server_cert);

/* call to check post ssl checks after SSL finalization */
Expand Down
20 changes: 20 additions & 0 deletions src/nopoll_conn_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ noPollConnOpts * nopoll_conn_opts_new (void)

/* by default, disable ssl peer verification */
result->disable_ssl_verify = nopoll_true;
/* by default, enable hostname validation */
result->host_verify = nopoll_true;

return result;
}
Expand Down Expand Up @@ -176,6 +178,24 @@ void nopoll_conn_opts_ssl_peer_verify (noPollConnOpts * opts, nopoll_bool verify
return;
}

/**
* @brief Allows to enable hostname validation
*
* @param opts The connection option to configure.
*
* @param hostVerify nopoll_true to enable hostname validation
* otherwise, nopoll_false should be used. By default hostname validation
* is enabled.
*/

void nopoll_conn_opts_ssl_host_verify (noPollConnOpts * opts, nopoll_bool hostVerify)
{
if (opts == NULL)
return;
opts->host_verify = hostVerify;
return;
}

/**
* @brief Allows to set Cookie header content to be sent during the
* connection handshake. If configured and the remote side server is a
Expand Down
2 changes: 2 additions & 0 deletions src/nopoll_conn_opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ void nopoll_conn_opts_set_interface (noPollConnOpts * opts, const char * _int
void nopoll_conn_opts_set_extra_headers (noPollConnOpts * opts, const char * extra_headers);

void nopoll_conn_opts_free (noPollConnOpts * opts);
/* hostname validation */
void nopoll_conn_opts_ssl_host_verify (noPollConnOpts * opts, nopoll_bool verify);

/** internal API **/
void __nopoll_conn_opts_release_if_needed (noPollConnOpts * options);
Expand Down
45 changes: 45 additions & 0 deletions src/nopoll_hostcheck.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <nopoll_hostname_validation.h>

static noPollHostMatchStatus nopoll_hostcheck(char *pattern, char *hostname);

static noPollHostMatchStatus nopoll_hostcheck(char *pattern, char *hostname){
char *pattern_wildcard = NULL;

size_t p_length = strlen(pattern);
size_t h_length = strlen(hostname);
/* pattern or hostname should not end with "." */
if( pattern[p_length-1] == '.' || hostname[h_length-1] == '.')
{
return MATCH_FAIL;
}

pattern_wildcard = strchr(pattern, '*');

if (pattern_wildcard == NULL) {
return nopoll_hostname_compare_without_wildcard(pattern,hostname) ? MATCH_SUCCESS : MATCH_FAIL;
}
if (nopoll_hostname_validate_inet(AF_INET, hostname) > 0) {
return MATCH_FAIL;
}
else if(nopoll_hostname_validate_inet(AF_INET6, hostname) > 0)
return MATCH_FAIL;
return nopoll_hostname_compare_with_wildcard(pattern,hostname) ? MATCH_SUCCESS : MATCH_FAIL;
}

noPollHostMatchStatus nopoll_match_hostname(const char *pattern, const char *hostname)
{
char *match_pattern;
char *host;
int result = MATCH_FAIL;
match_pattern = nopoll_strdup(pattern);
host = nopoll_strdup(hostname);

if(match_pattern && host) {
result = nopoll_hostcheck(match_pattern,host);
nopoll_free(host);
nopoll_free(match_pattern);
return result;
}
return result;
}

11 changes: 11 additions & 0 deletions src/nopoll_hostcheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef __NOPOLL_HOSTCHECK_H__
#define __NOPOLL_HOSTCHECK_H__

typedef enum {
MATCH_FAIL = 0,
MATCH_SUCCESS,
} noPollHostMatchStatus;
noPollHostMatchStatus nopoll_match_hostname(const char *pattern,const char *hostname);

#endif /* __NOPOLL_HOSTCHECK_H__ */

Loading