I'm programming TLS server using OpenSSL 1.0.0 library, as such I'm using BIO* objects, not SSL* objects (I'm using IBM documentation: part 1, part 2 and part 3).
To get a socket to remote client I run following code:
BIO *new_client;
while(1)
{
if (BIO_do_accept(socket) <= 0)
{ handle error }
new_client = BIO_pop(socket);
BIO_do_handshake(new_client);
// fire a thread and do rest of communication
}
This works without problem, I can send data to client, client can respond. If I don't provide my custom CA cert file to client, client refuses connection because failure of verification of certificate, etc. In short, everything looks perfectly well.
Problem is, I can't get peer host address.
I can't find any OpenSSL specific API to do that. Then I tried to get the file descriptor of the socket and invoke getpeername() using following code:
// get peer address
int sock_fd;
if (BIO_get_fd(socket, &sock_fd) == -1)
{
fprintf(stderr, "Uninitialized socket passed to worker");
goto listen_cleanup;
}
printf("socket fd: %i\n", sock_fd);
struct sockaddr addr;
socklen_t addr_len;
// make enough space for ipv6 address and few extra chars
ctx->hostname = malloc(sizeof(char) * 80);
if (!ctx->hostname)
{
fprintf(stderr, "Out of memory\n");
goto internal_error;
}
// ignore failures, as any problem will be caught in TLS handshake
getpeername(sock_fd, &addr, &addr_len);
if (addr.sa_family == AF_INET)
inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr,
ctx->hostname, 40);
else if (addr.sa_family == AF_INET6)
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr,
ctx->hostname, 40);
else
{
fprintf(stderr, "Unknown socket type passed to worker(): %i\n",
addr.sa_family);
goto internal_error;
}
but both before and after BIO_do_handshake(), it fails while checking sa_family, I get Unknown socket type passed to worker(): 50576.
How to get peer address while using OpenSSL BIO objects that wrap TLS?