A small socket-programming lab showing how unsafe input handling becomes a memory-safety problem
18-03-2018
These are historical lab examples of a simple TCP service, shown in Windows and POSIX variants. Their value is as a code-reading exercise: follow bytes from recv() into a fixed-size buffer, then watch what happens when the code assumes the input is shorter, terminated, or safe to print.
Several examples contain distinct bugs. One copies as many as 2047 received bytes into a 1024-byte stack buffer; another can write past the end of its heap buffer when terminating a full read. The authentication example also passes input directly to printf, treating it as a format string. These are useful demonstrations, not implementation patterns to reuse.
The servers bind to all interfaces in some variants. Do not run them on a reachable network; use an isolated lab. The original code is retained below as an artifact, without implying that it is a complete or safe server.
#include<stdio.h>
#include<stdlib.h>
#include<winsock.h>#define IP_ADDRESS ""
#define PORT_NUMBER 31337
#define BUF_SIZE 2048
voidprocess(SOCKET);voidmain(intargc,char*argv[]){SOCKETsock;SOCKETnew_sock;structsockaddr_insa;WSADATAwsaData;if(WSAStartup(MAKEWORD(2,0),&wsaData)!=0){fprintf(stderr,"WSAStartup() failed");exit(1);}printf("Initializing the server...\n");memset(&sa,0,sizeof(structsockaddr_in));sa.sin_family=AF_INET;// bind to a specific address//sa.sin_addr.s_addr = inet_addr(IP_ADDRESS);// bind to all addressessa.sin_addr.s_addr=htonl(INADDR_ANY);sa.sin_port=htons(PORT_NUMBER);sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){printf("Could not create socket server...\n");exit(1);}if(bind(sock,(structsockaddr*)&sa,sizeof(structsockaddr_in))==SOCKET_ERROR){closesocket(sock);printf("Could not bind socket...\n");exit(1);}printf("Listening for connections...\n");listen(sock,10);while(1){new_sock=accept(sock,NULL,NULL);printf("Client connected\n");if(new_sock<0){printf("Error waiting for new connection!\n");exit(1);}process(new_sock);closesocket(new_sock);}}voidprocess(SOCKETsock){char*tmp;charbuf[1024];// whoops! should've used the defined BUF_SIZE hereinti;memset(&buf,0,sizeof(buf));tmp=malloc(BUF_SIZE);i=recv(sock,tmp,BUF_SIZE-1,0);tmp[i+1]='\x00';// this would be alright if buf and tmp were the same sizestrcpy(&buf,tmp);free(tmp);// print dataprintf("Got message:\n%s\n",buf);}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>#define IP_ADDRESS "127.0.0.1"
#define PORT_NUMBER 31337
#define BUF_SIZE 2048
voidprocess(int);intmain(intargc,char*argv[]){intsock;intnew_sock;intcli_len;structsockaddr_insa,ca;printf("Initializing the server...\n");memset(&sa,0,sizeof(structsockaddr_in));memset(&ca,0,sizeof(structsockaddr_in));sa.sin_family=AF_INET;// bind to a specific address//sa.sin_addr.s_addr = inet_addr(IP_ADDRESS);// bind to all addressessa.sin_addr.s_addr=INADDR_ANY;sa.sin_port=htons(PORT_NUMBER);sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){printf("Could not create socket server...\n");exit(1);}if(bind(sock,(structsockaddr*)&sa,sizeof(structsockaddr_in))<0){close(sock);printf("Could not bind socket...\n");exit(1);}printf("Listening for connections...\n");listen(sock,10);while(1){cli_len=sizeof(ca);new_sock=accept(sock,(structsockaddr*)&ca,&cli_len);printf("Client connected\n");if(new_sock<0){printf("Error waiting for new connection!\n");exit(1);}process(new_sock);close(new_sock);}return0;}voidprocess(intsock){char*tmp;charbuf[1024];// whoops! should've used the defined BUF_SIZE hereinti;memset(&buf,0,sizeof(buf));tmp=malloc(BUF_SIZE);i=recv(sock,tmp,BUF_SIZE-1,0);tmp[i+1]='\x00';// this would be alright if buf and tmp were the same sizestrcpy(&buf,tmp);// ergh... seg fault would be detected here on free by gcc//free(tmp);// print dataprintf("Got message:\n%s\n",buf);}
#include<stdio.h>
#include<stdlib.h>
#include<winsock.h>#define IP_ADDRESS ""
#define PORT_NUMBER 31337
#define PASSWORD "im_so_lonely\n"
#define BUF_SIZE 128
intauth(SOCKET);voidmain(intargc,char*argv[]){SOCKETsock;SOCKETnew_sock;structsockaddr_insa;WSADATAwsaData;if(WSAStartup(MAKEWORD(2,0),&wsaData)!=0){fprintf(stderr,"WSAStartup() failed");exit(1);}printf("Initializing the server...\n");memset(&sa,0,sizeof(structsockaddr_in));sa.sin_family=AF_INET;// bind to a specific address//sa.sin_addr.s_addr = inet_addr(IP_ADDRESS);// bind to all addressessa.sin_addr.s_addr=htonl(INADDR_ANY);sa.sin_port=htons(PORT_NUMBER);sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){printf("Could not create socket server...\n");exit(1);}if(bind(sock,(structsockaddr*)&sa,sizeof(structsockaddr_in))==SOCKET_ERROR){closesocket(sock);printf("Could not bind socket...\n");exit(1);}printf("Listening for connections...\n");listen(sock,10);while(1){new_sock=accept(sock,NULL,NULL);printf("Client connected\n");if(new_sock<0){printf("Error waiting for new connection!\n");exit(1);}if(auth(new_sock)){send(new_sock,"\n***Access granted***\n\n",23,0);printf("\n***Access granted***\n\n");}else{send(new_sock,"\n***Access denied***\n\n",22,0);printf("\n***Access denied***\n\n");}closesocket(new_sock);}}intauth(SOCKETsock){charbuf[BUF_SIZE];inti=0;intres;memset(&buf,0,sizeof(buf));// send promptsend(sock,"Enter Password: ",16,0);// read datai=recv(sock,buf,BUF_SIZE-1,0);buf[i]=0;if(strcmp(buf,PASSWORD)==0)res=1;elseres=0;// print dataprintf("Got password: ");printf(buf);returnres;}
#include<stdio.h>
#include<stdlib.h>
#include<winsock.h>#define IP_ADDRESS ""
#define PORT_NUMBER 31337
#define BUF_SIZE 1461
voidprocess(SOCKET);voidmain(intargc,char*argv[]){SOCKETsock;SOCKETnew_sock;structsockaddr_insa;WSADATAwsaData;if(WSAStartup(MAKEWORD(2,0),&wsaData)!=0){fprintf(stderr,"WSAStartup() failed");exit(1);}printf("Initializing the server...\n");memset(&sa,0,sizeof(structsockaddr_in));sa.sin_family=AF_INET;// bind to a specific address//sa.sin_addr.s_addr = inet_addr(IP_ADDRESS);// bind to all addressessa.sin_addr.s_addr=htonl(INADDR_ANY);sa.sin_port=htons(PORT_NUMBER);sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){printf("Could not create socket server...\n");exit(1);}if(bind(sock,(structsockaddr*)&sa,sizeof(structsockaddr_in))==SOCKET_ERROR){closesocket(sock);printf("Could not bind socket...\n");exit(1);}printf("Listening for connections...\n");listen(sock,10);while(1){new_sock=accept(sock,NULL,NULL);printf("Client connected\n");if(new_sock<0){printf("Error waiting for new connection!\n");exit(1);}process(new_sock);closesocket(new_sock);}}voidprocess(SOCKETsock){charbuf[BUF_SIZE];inti=0;memset(&buf,0,sizeof(buf));// read datai=recv(sock,buf,BUF_SIZE-1,0);buf[i]=0;// print dataprintf("Got message: ");printf(buf);printf("\n");}