OpenSSL DTLS connection never establishes - c

I'm sorry for such a big block of code, but I'm so lost as to what is happening, I have no idea where the problem might be...
I am trying to get a VERY minimal dtls server going and I can't get the client and server to finish handshaking.
Here is my code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/opensslv.h>
int generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
{
cookie = "cookie";
cookie_len = 5;
return 1;
}
int verify_cookie(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len)
{
return 1;
}
int dtls_verify_callback (int ok, X509_STORE_CTX *ctx) {
/* This function should ask the user
* if he trusts the received certificate.
* Here we always trust.
*/
return 1;
}
int main() {
char buff[FILENAME_MAX];
getcwd(buff, FILENAME_MAX);
union {
struct sockaddr_storage ss;
struct sockaddr_in s4;
struct sockaddr_in6 s6;
} client_addr;
struct sockaddr_in server_addr;
const int on = 1, off = 0;
memset(&server_addr, 0, sizeof(server_addr));
memset(&client_addr, 0, sizeof(client_addr));
int res;
SSL *ssl;
BIO *bio;
int sock;
struct timeval timeout;
SSL_CTX *ctx = SSL_CTX_new(DTLS_server_method());
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
if(!SSL_CTX_use_certificate_file(ctx, "/home/matthew/CLionProjects/OpenSSL.Test/cmake-build-debug/certs/cert.crt", SSL_FILETYPE_PEM))
{
perror("cert");
exit(EXIT_FAILURE);
}
if(!SSL_CTX_use_PrivateKey_file(ctx, "/home/matthew/CLionProjects/OpenSSL.Test/cmake-build-debug/certs/key.key", SSL_FILETYPE_PEM))
{
perror("key");
exit(EXIT_FAILURE);
}
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback);
SSL_CTX_set_read_ahead(ctx, 1);
SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie);
SSL_CTX_set_cookie_verify_cb(ctx, &verify_cookie);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(1114);
if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(EXIT_FAILURE);
}
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, (socklen_t) sizeof(on)) < 0)
{
perror("set reuse address");
exit(EXIT_FAILURE);
}
if(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*) &on, (socklen_t) sizeof(on)) < 0)
{
perror("set reuse port");
exit(EXIT_FAILURE);
}
if(bind(sock, (const struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)
{
perror("bind");
exit(EXIT_FAILURE);
}
memset(&client_addr, 0, sizeof(struct sockaddr_storage));
/* Create BIO */
bio = BIO_new_dgram(sock, BIO_NOCLOSE);
/* Set and activate timeouts */
timeout.tv_sec = 5;
timeout.tv_usec = 0;
BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
ssl = SSL_new(ctx);
SSL_set_bio(ssl, bio, bio);
SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
if(!SSL_set_fd(ssl, sock))
{
perror("set fd");
exit(EXIT_FAILURE);
}
res = 0;
while(res <= 0)
{
res = DTLSv1_listen(ssl, (BIO_ADDR *) &client_addr);
if(res < 0)
{
perror("dtls listen"); <--- "Destination address required"
exit(EXIT_FAILURE);
}
}
SSL_accept(ssl);
printf("Hello, World!\n");
return 0;
}
I've added error checks in every nook and cranny I can think of...
What happens is, it loops over DTLSv1_accept() fine until a connection is attempted. As soon as the client tries to connect (sends the Client Hello), DTLSv1_accept() return -1. A call to SSL_get_error gives me 5, which is an SSL_ERROR_SYSCALL.
So I do perror and get Destination address required...
AFAIK the whole point of DTLSv1_listen is to listen for any incoming Client Hellos and populate the BIO_ADDR with the client's address once the handshake is finished...
I am using this to test the server:
openssl s_client -dtls -connect 127.0.0.1:1114
I've spent many hours on this. I am about to give up on OpenSSL and try libressl...
Any help is greatly appreciated.
P.S. the code is complete, in that it should compile and run if you want to try it out.
Thanks!

There are two significant problems in your code sample.
First your code to generate a cookie is not correct. You are supposed to create the
cookie and store it in the location pointed to by cookie, and then fill in the length of the cookie in *cookie_len. So the code should like this:
int generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
{
memcpy(cookie, "cookie", 6);
*cookie_len = 6;
return 1;
}
However, the most important error comes later when setting up the SSL object for use. OpenSSL has the concept of a BIO for abstracting the underlying transport layer. In order to do DTLS over UDP you need to use a "dgram" BIO. You do this bit correctly:
/* Create BIO */
bio = BIO_new_dgram(sock, BIO_NOCLOSE);
/* Set and activate timeouts */
timeout.tv_sec = 5;
timeout.tv_usec = 0;
BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
ssl = SSL_new(ctx);
SSL_set_bio(ssl, bio, bio);
So at this point the SSL object is correctly setup for the DTLSv1_listen() call. However you then do this:
if(!SSL_set_fd(ssl, sock))
{
perror("set fd");
exit(EXIT_FAILURE);
}
The SSL_set_fd function is an alternative to the SSL_set_bio function. What it does is take the supplied fd, wraps it in a "socket" BIO and then calls SSL_set_bio() with the result. A socket BIO is primarily useful for standard TLS and can't be used for DTLS. So the effect of the above code is to throw away the dgram BIO that you previously set up.
In my tests, if I made the generate_cookie change I suggested above, and removed the SSL_set_fd line, it all started to work as expected.

Related

Unable to show all UPnP devices within the local network C++

I am new to UPnP development and trying to discover all UPnP device within the local network, and I followed an example from the online resource, but my code will only keep looping at the first response. How could I get another response other than the first one, could I get some hints for this?
Example :
First Response from 192.168.xxx.123, and it will keeps printing the following result:
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=1790
DATE: Thu, 01 Jan 2015 10:43:15 GMT
ST: uuid:4d696xxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
USN: uuid:4d696xxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
EXT:
SERVER: Linux 2.6 DLNADOC/1.50 UPnP/1.0 ReadyDLNA/1.0.26
LOCATION: http://192.168.xxx.123:xxxx/rootDesc.xml
Content-Length: 0
I checked in Wireshark, and I can see the other device [IP: 192.168.xxx.99] has given me a response, but I am not able to receive it in my code.
I also read a question on SO and used select in my code, but still cannot get it working.
Receiving response(s) from N number of clients in reply to a broadcast request over UDP
The code:
#include <QCoreApplication>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#define RESPONSE_BUFFER_LEN 1024
#define SSDP_MULTICAST "239.255.255.250"
#define SSDP_PORT 1900
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int sock;
size_t ret;
unsigned int socklen;
struct sockaddr_in sockname;
struct sockaddr clientsock;
struct hostent *hostname;
char data[] =
"M-SEARCH * HTTP/1.1\r\n"
"HOST: 239.255.255.250:1900\r\n"
"MAN: \"ssdp:discover\"\r\n"
"ST: ssdp:all\r\n"
"MX: 120\r\n"
"\r\n";
char buffer[RESPONSE_BUFFER_LEN];
unsigned int len = RESPONSE_BUFFER_LEN;
fd_set fds;
struct timeval timeout;
hostname = gethostbyname(SSDP_MULTICAST);
hostname->h_addrtype = AF_INET;
if((sock = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("err: socket() failed");
return -1;
}
memset((char *)&sockname, 0, sizeof(struct sockaddr_in));
sockname.sin_family = AF_INET;
sockname.sin_port = htons(SSDP_PORT);
sockname.sin_addr.s_addr = *((unsigned long *)(hostname->h_addr_list[0]));
ret = sendto(sock, data, strlen(data), 0, (struct sockaddr *)&sockname,
sizeof(struct sockaddr_in));
if(ret != strlen(data))
{
printf("err:sendto");
return -1;
}
/* Get response */
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 5;
timeout.tv_usec = 5;
while(select(sock + 1, &fds, NULL, NULL, &timeout) > 0)
{
if(FD_ISSET(sock, &fds))
{
socklen = sizeof(clientsock);
if((len = recvfrom(sock, buffer, len, MSG_PEEK, &clientsock, &socklen)) == (size_t)-1)
{
printf("err: recvfrom");
return -1;
}
buffer[len] = '\0';
/* Check the HTTP response code */
if(strncmp(buffer, "HTTP/1.1 200 OK", 12) != 0)
{
printf("err: ssdp parsing ");
return -1;
}
printf(buffer);
}
else
{
printf("err: no ssdp answer");
}
}
//close(sock);
return a.exec();
}
You are using MSG_PEEK, which means to read the first message in the socket's receive buffer, but not remove it from the buffer.
Therefore every time you call recvfrom you get the first received message.
Change MSG_PEEK to 0 and then each call will read the first message that hasn't been read yet. (So the second call will read the second message, and so on)

global table of clients C : Chatroom

I created a client/server chatroom in C. I need to put in a global table of all clients connected so that I can send every message the server receives to all the clients connected. I can't figure out how to do this. I assume I have to create a struct of some sort and add every specific socket descriptor for each thread I spawn. Then I have to send my message to every specific SD in that struct.
I don't know how to code this and wanted to see if anyone could show me some example code of what I have to write after every connection is made and what I have to write to then send my messages to every thread. My server code is below if needed.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <errno.h>
#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>
void *
client_session_thread(void * arg)
{
int SD;
char request[2048];
char message[2048] = "server receives input: ";
int chatfile;
char msgr[50000];
SD = *(int *)arg;
free (arg);
pthread_detach(pthread_self());
chatfile = open("chathistory.txt", O_RDWR|O_CREAT|O_EXCL,0666);
close(chatfile);
chatfile = open("chathistory.txt", O_RDWR | O_APPEND);
read(chatfile,msgr,sizeof(msgr));
write(SD, msgr, strlen(msgr));
while (read(SD, request, sizeof(request)))
{
strcat(message, request);
strcat(message,"\n");
fprintf(stdout, message);
write(SD,request,strlen(request));
write(chatfile,request,strlen(request));
strcpy(request,"");
strcpy(message, "server receives input: ");
bzero(request, sizeof(request));
bzero(message,sizeof(message));
}
close(SD);
close(chatfile);
return 0;
}
int main(int argc, char *argv[])
{
//create a socket. SD is my socket.
struct addrinfo addrinfo;
struct addrinfo * result;
char message[256];
int SD;
int FD;
pthread_t ignore;
int * FDpntr;
int on = 1;
addrinfo.ai_flags = 0;
addrinfo.ai_family = AF_INET; // IPv4 only
addrinfo.ai_socktype = SOCK_STREAM; // Want TCP/IP
addrinfo.ai_protocol = 0; // Any protocol
addrinfo.ai_addrlen = 0;
addrinfo.ai_addr = NULL;
addrinfo.ai_canonname = NULL;
addrinfo.ai_next = NULL;
if (getaddrinfo("clamshell.rutgers.edu", "5700", &addrinfo, &result) !=0)
{
printf("\x1b[1;31mProblem with getaddrinfo\x1b[0m\n");
}
//Create socket
SD = socket(AF_INET, SOCK_STREAM, 0);
if (SD == -1)
{
printf("\x1b[1;31mProblem creating socket\x1b[0m\n");
}
//Bind the socket to our specified IP and port
if (setsockopt(SD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) ==-1)
{
printf("\x1b[1;31mProblem with sockopt\x1b[0m\n");
freeaddrinfo(result);
return -1;
}
if (bind(SD, result->ai_addr, result->ai_addrlen) != 0)
{
printf("\x1b[1;31mProblem binding socket\x1b[0m\n");
}
//first we bind our socket and then recast our address just like in client
//Listen function listens for connections
if (listen(SD, 20) == -1)
{
printf("\x1b[1;31mProblem with listen\x1b[0m\n");
close(SD);
return 0;
}
else
{
//Accept function for accepting incoming connection
//sos = sizeof(struct sockaddr_in);
//while (FD = accept(SD, (struct sockaddr *)&client, (socklen_t*)&sos))
while ((FD = accept(SD,0,0)) != -1)
{
FDpntr = (int *)malloc(sizeof(int));
*FDpntr = FD;
if (pthread_create(&ignore, NULL, client_session_thread, FDpntr) != 0)
{
printf("\x1b[1;31mProblem creating thread\x1b[0m\n");
}
else
{
continue;
}
}
close(SD);
return 0;
}
}
suggest implement a separate file.
That file would have entry points:
initializeClientTable()
destroyClientTable()
addClient()
deleteClient(),
getClient()
The getClient() function would return a client.
it would have a parameter that (probably an enum value) that indicates to get the first client or get the next client from the ClientTable
When at the end of the ClientTable, return an indication of such event.
The ClientTable could easily be implemented as a linked list.

compressing multicast packets with zlib library

I am listening packets from a multicast ip port and trying to compress that packet using zlib library, ( want to know the compression ratio from zlib in the live packets, as this is the requirement from our client). I have implemented zlib compression code as below, but length of outputDataBuffer is not printing correct, I dont know what I am missing.
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <zlib.h>
using namespace std;
struct sockaddr_in localSock;
struct ip_mreq group;
int maxpacketsize = 1500;
void connectSocket(int &sd,char *multicastIP,int multicastPort,char *interfaceIP);
void listenSocket(int &sd,const short &structureSize,const short &compressionType);
void compressZlib(char *inputDataBuffer,int inputDataLength,z_stream &defstream)
int main(int argc, char *argv[])
{
int sd = 0;
char multicastIP[16]="230.0.0.50";
char interfaceIP[16]="192.168.225.132";
int multicastPort = 13551;
short structureSize = 0;
connectSocket(sd,multicastIP,multicastPort,interfaceIP);
listenSocket(sd,structureSize);
return 0;
}
void connectSocket(int &sd,char *multicastIP,int multicastPort,char *interfaceIP)
{
int reuse = 1;
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
printf("Opening datagram socket....OK.\n");
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
close(sd);
exit(1);
}
printf("Setting SO_REUSEADDR...OK.\n");
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(multicastPort);
localSock.sin_addr.s_addr = INADDR_ANY;
if(bind(sd, (struct sockaddr*)&localSock, sizeof(localSock)))
{
perror("Binding datagram socket error");
close(sd);
exit(1);
}
printf("Binding datagram socket...OK.\n");
group.imr_multiaddr.s_addr = inet_addr(multicastIP);
group.imr_interface.s_addr = inet_addr(interfaceIP);
if(setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
perror("Adding multicast group error");
close(sd);
exit(1);
}
printf("Adding multicast group...OK.\n");
}
void compressZlib(char *inputDataBuffer,int inputDataLength,z_stream &defstream)
{
char *outputDataBuffer = new char[inputDataLength];
memset(outputDataBuffer,0,inputDataLength);
defstream.avail_in = (uInt)strlen(inputDataBuffer)+1;
defstream.next_in = (Bytef *)inputDataBuffer;
defstream.avail_out = (uInt)sizeof(outputDataBuffer);
defstream.next_out = (Bytef *)outputDataBuffer;
if(deflate(&defstream, Z_FINISH) != Z_OK )
{
cout<<"Error"<<endl;
}
//printf("%lu %lu\n", inputDataLength,defstream.total_in);
printf("%lu %lu\n", inputDataLength,strlen(outputDataBuffer));
}
void listenSocket(int &sd,const short &structureSize)
{
char databuf[5000] = "";
int receivedBytes = 0;
z_stream defstream;
defstream.zalloc = Z_NULL ;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
deflateInit(&defstream, Z_FULL_FLUSH);
while(1)
{
int socklen = sizeof(struct sockaddr_in);
struct sockaddr_in saddr;
receivedBytes = recvfrom(sd, databuf, maxpacketsize, 0, (struct sockaddr *)&saddr, (socklen_t*)&socklen);
if(receivedBytes < 0)
{
perror("Reading datagram message error");
close(sd);
exit(1);
}
compressZlib(databuf,receivedBytes,defstream);
//compressZlib(databuf1,strlen(databuf1));
//compressZlib();
//cout<<receivedBytes<<endl;
}
deflateEnd(&defstream);
}
I also used compress2() function which is as below:
compress2((unsigned char*)outputBuffer,&outputDataLength,(const unsigned char*)inputBuffer,(unsigned long)inputBufferLength,Z_DEFAULT_COMPRESSION);
but this is also not working, outputDataLength is 0 all the time.
Calling deflate() with Z_FINISH means that you are or have already fed deflate the last of the input data. deflate will then terminate the stream. Once it has been provided enough output space to write the last of the compressed data, which may very well be on the first such call, deflate() will return Z_STREAM_END, not Z_OK. Then the deflate() engine is done and can't be used again unless you do a deflateEnd() followed by a deflateInit(), or equivalently and faster, a deflateReset().
It would seem that what you are missing are the rewards that come from having read the documentation.

send() socket operation on non-socket

While trying to implement a server and client, I noticed that the client was writing to stdout instead
of through the network. I figured out that the file descriptor being returned by connect() is always zero, which explains why it was writing to stdout. But I can not figure out why connect() always returns zero instead of a valid socket. All the articles on the web I found with the same problem were due to precedence issues with wrapping if() around the connect() call. But I haven't done that, any help would be appreciated.
server code
int setUpServer(struct fuzzerObj *ptr, int *firstClient)
{
/* Declarations */
int hostSocket, yes = 1, rtrn, clientfd;
union
{
struct sockaddr_in in;
}address;
/* Create Socket */
hostSocket = socket(AF_INET, SOCK_STREAM, 0);
if(hostSocket < 0)
{
errorHandler("Could not create socket\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
/* Reuse Address */
rtrn = setsockopt(hostSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
if(rtrn < 0)
{
errorHandler("Couldn't Reuse Address\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
/* Set Up Struct */
address.in.sin_len = sizeof(address.in);
address.in.sin_family = AF_INET;
address.in.sin_port = htons(BBPORT_NUMBER);
address.in.sin_addr.s_addr = htonl(INADDR_ANY);
memset(address.in.sin_zero, 0, sizeof(address.in.sin_zero));
/* Bind Address to Socket */
rtrn = bind(hostSocket, (struct sockaddr*) &address, address.in.sin_len);
if(rtrn < 0)
{
errorHandler("Can't Bind Address to Socket\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
/* listen */
rtrn = listen(hostSocket, ptr->numberOfClients);
if(rtrn < 0)
{
errorHandler("Can't Listen\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
while(1)
{
rtrn = acceptClient(hostSocket, &clientfd);
if(rtrn < 0)
{
printf("Can't Accept Client\n");
return -1;
}
break;
}
*firstClient = clientfd;
return 0;
}
client code
#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#define BLACKBOX_PORT 9696
int main(int argc, char *argv[])
{
/* Check To See If an argument was passed */
if(argc < 2)
{
printf("No enough Arguments\n");
return -1;
}
/* Declaration's */
const char *ip = argv[1];
int sockfd, fd, rtrn;
char *outBuf;
struct sockaddr_in servaddr;
/* Get Socket to Connect to Fuzz Server */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("Can't Create Socket");
return -1;
}
/* Fill Out Struct */
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(BLACKBOX_PORT);
inet_pton(AF_INET, ip, &servaddr.sin_addr);
/* Attempt Connection */
fd = connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
if(fd < 0)
{
perror("Can not connect to BlackBox Fuzz server");
return -1;
}
/* Allocate Space in Memory for Outgoing Connection */
rtrn = asprintf(&outBuf, "Mac OSX 10.9\n");
if(rtrn < 0)
{
perror("Copy Error");
return -1;
}
/* Send Data to Fuzzer via Socket */
rtrn = send(fd, outBuf, strlen(outBuf), 0);
if(rtrn < 0)
{
perror("Can't write Data to BlackBox Server");
return -1;
}
free(outBuf);
return 0;
}
Upon successfully calling connect(), the sockfd is connected. The 0 return value indicates that the call is successful. If the value was not 0, it would have indicated an error, and that the connection attempt has failed or is not yet completed (if the connect is non-blocking).
After determining that connect() has succeeded, call send() on the sockfd, not on the return value of the connect() call.
rtrn = send(sockfd, outBuf, strlen(outBuf), 0);

Connection refused implementing a tcp server

I'm trying to make a server and client. But when I try to connect the client to the server, I get connection refused. The other answers on stack overflow said to make sure you have listen() and accept(), which I do, and to check the firewalls. So I turned off all the firewalls just to make sure.
I still get connection refused, so I tried ./telnet 10.1.10.13 9696, and got:
Trying 10.1.10.13...
telnet: connect to address 10.1.10.13: Connection refused
telnet: Unable to connect to remote host
Here's the code for the server
int setUpServer(struct fuzzerObj *ptr)
{
/* Declarations */
int hostSocket, yes = 1, rtrn;
union
{
struct sockaddr_in in;
}address;
/* Create Socket */
hostSocket = socket(AF_INET, SOCK_STREAM, 0);
if(hostSocket < 0)
{
errorHandler("Could not create socket\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
/* Reuse Address */
rtrn = setsockopt(hostSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
if(rtrn < 0)
{
errorHandler("Couldn't Reuse Address\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
errno = 0;
/* Set Up Struct */
address.in.sin_len = sizeof(address.in);
address.in.sin_family = AF_INET;
address.in.sin_port = BBPORT_NUMBER;
address.in.sin_addr.s_addr = htonl(INADDR_ANY);
memset(address.in.sin_zero, 0, sizeof(address.in.sin_zero));
/* Bind Address to Socket */
rtrn = bind(hostSocket, (struct sockaddr*) &address, address.in.sin_len);
if(rtrn < 0)
{
errorHandler("Can't Bind Address to Socket\n", FUNCTION_ID_SET_UP_SERVER);
perror("");
return -1;
}
/* listen */
rtrn = listen(hostSocket, ptr->numberOfClients);
if(rtrn < 0)
{
errorHandler("Can't Listen\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
while(1) acceptClient(hostSocket);
return 0;
}
int acceptClient(int fd)
{
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
int clientFd = accept(fd, (struct sockaddr *) &addr, &addr_len);
if(clientFd < 0)
{
printf("Can't Accept Client\n");
return -1;
}
return clientFd;
}
and the code for the client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#define BLACKBOX_PORT 9696
int main(int argc, char *argv[])
{
/* Check To See If an argument was passed */
if(argc < 2)
{
printf("No enough Arguments\n");
return -1;
}
/* Declaration's */
const char *ip = argv[1];
int sockfd, fd, rtrn;
char *inBuf;
struct sockaddr_in servaddr,cliaddr;
socklen_t len = sizeof(cliaddr);
/* Get Socket to Connect to Fuzz Server */
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("Can't Create Socket");
return -1;
}
/* Fill Out Struct */
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(BLACKBOX_PORT);
inet_pton(AF_INET, ip, &servaddr.sin_addr);
/* Attempt Connection */
fd = connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
if(fd < 0)
{
perror("Can not connect to BlackBox Fuzz server");
return -1;
}
/* Allocate Space in Memory for Incoming Connection */
inBuf = (char *) malloc(1025);
if(inBuf == NULL)
{
perror("Mem Error");
return -1;
}
/* Read From Socket */
rtrn = read(fd, inBuf, 1024);
if(rtrn < 0)
{
perror("Can't Read Data From BlackBox Server");
return -1;
}
printf("Received Data: %s\n", inBuf);
free(inBuf);
return 0;
}
Output from client:
./client 10.1.10.13
Can not connect to BlackBox Fuzz server
Connection refused
Any help would be appreciated, thanks.
Assuming that you're running this code on a little-endian machine, you need to use htons() when assigning the port number on the server side too.
(On big-endian machines htons() is a "no-op", but you should always use it to ensure portability)

Resources