Socket Programming: Bad address Error in read() when used in loop - c

I was trying to implement FTP Server as a part of an assignment and I wrote the following code to implement GET Command, which essentially reads file1 from server and stores it in file2.
int getCommandImpl(int clientSocket, char *file1, char *file2){
char *messageContent;
char buffer[256], userCommand[256], *tempString ;
int messageHead, endOfTransfer =0;
int messageLength;
sprintf(userCommand, "GET %s", file1);
messageLength = write(clientSocket,userCommand,strlen(userCommand));
if(messageLength <0){
perror("Error sending data to server in RETR");
return 0;
}
FILE *fp;
fp = fopen(file2, "w");
if(fp==NULL){
printf("%s Can not be created\n", file2);
return 0;
}
printf("Writing to file %s\n", file2);
while(!endOfTransfer){
messageLength = read(clientSocket, buffer, strlen(buffer)-1);
if(messageLength == -1){
perror("GET: Error in read() ");
break;
}
//puts(buffer);
printf("Buffer is %s with len %d\n", buffer, strlen(buffer));
tempString = strdup(buffer);
messageHead = atoi(strtok(tempString, " "));
messageContent = strtok(NULL, " ");
if(messageHead == 0 && strlen(messageContent)==0){ //End of file transfer
endOfTransfer = 1;
break;
}
fwrite(messageContent, sizeof(char), sizeof(messageContent), fp);
memset(buffer,0,sizeof(buffer));
printf("Buffer is %s with len %d\n", buffer, strlen(buffer));
}
fclose(fp);
return 1;
}
While running it, I am always getting the error "GET: Error in read() : Bad address". If I remove the statement
memset(buffer,0,sizeof(buffer));
I am getting a segmentation fault. I am assuming that the error has something to do with the string buffer being empty from the second iteration.
Any help to solve this will be highly appreciated.

Related

Server/client program doesn't work when I add a function in C

I'm making a program that copies a file from client to server. I have to send the length of the file to the server before copying. Both of the programs work fine, until I add int sizeFile = getSizeFile(originalFile); in the client part of my program. All of a sudden (after I add the function) the while() loop in my server gets stuck on recv(). And the while() in my client just loops once and then breaks.
Why does my program work fine until I add the getSizeFile() function and how can I solve it?
function:
int getSizeFile(FILE* file)
{
// get file size
FILE *f = file;
fseek(f, 0L, SEEK_END);
int sizeFile = ftell(f);
return sizeFile;
}
server:
char ch[70];
printf("where do you want to save it(full path + name): ");
scanf_s("%s", ch, 70);
char c[70];
printf("which file you want to copy(full path + name): ");
scanf_s("%s", c, 70);
r = send(s, c, 70, 0); // B
if (r == SOCKET_ERROR)
{
printf("2 error: %d\n", WSAGetLastError);
}
FILE* copyFile;
fopen_s(&copyFile, ch, "wb");
if (copyFile == NULL)
{
printf("Error opening file\n");
}
char buf[BUFSIZE];
size_t size = BUFSIZE;
int counter = 0;
while (1)
{
int res = recv(s, buf, BUFSIZE, 0);
if (res == SOCKET_ERROR)
{
printf("3 error %d\n", WSAGetLastError);
break;
}
size = fwrite(buf, 1, res, copyFile);
printf("size: %d\n", size);
printf("res: %d\n", res);
counter++;
printf("counter: %d\n", counter);
}
fclose(copyFile);
client:
char c[70];
res = recv(ClientSocket, c, 70, 0); // B
if (res == SOCKET_ERROR)
{
printf("Server disconeccted\n");
break;
}
FILE* originalFile;
fopen_s(&originalFile, c, "rb");
if (originalFile == NULL)
{
printf("Error opening file\n");
}
char buf[BUFSIZE];
size_t size = BUFSIZE;
int counter = 0;
int sizeFile = getSizeFile(originalFile); // <-- this one
while (size == BUFSIZE)
{
size = fread(buf, 1, BUFSIZE, originalFile);
int r = send(ClientSocket, buf, size, 0);
if (r == SOCKET_ERROR)
{
printf("1 error: %d\n", WSAGetLastError);
break;
}
printf("size: %d\n", size);
printf("r: %d\n", r);
counter++;
printf("counter: %d\n", counter);
}
fclose(originalFile);
Would make this a comment since it just riffs off what Alex F said, but not enough reputation. In any case, if you add rewind(f); after int sizeFile = ftell(f); in getSizeFile(FILE* file), that should solve the issue of not being able to read the file properly.

Program stuck writing contents to the file in C

I'm sending a file from the client to the server.
Client sends filename
Server receives filename
Client sends file size
Server receives file size
Client sends file contents
Server receives file contents
When I print out the file size that I sent, it is the exact number of bytes as the file I wish to send so that's fine. The issue is that the server (receives) doesn't seem to exit the while loop when writing to the new file. I know this because the final print statement printf("The server has received the requested document\n"); is never reached and it just hangs. What could be causing this?
Client snippet (sends):
else if(strcmp(shortCommand, "put") == 0){
char *tmp = buf + 4;
char filename[MAX_BLOCK_SIZE];
size_t size, bytes_read, bytes_written;
int x;
strcpy(filename, "filename ");
strcat(filename, tmp);
FILE *fp;
printf("File name: %s\n", tmp);
fp = fopen(tmp, "rb");
if(fp == NULL){
printf("ERROR: Requested file does not exist.\n");
}
else{
printf("Client sending filename...\n");
if ((x = write(sd, buf, sizeof(buf))) < 0){ //sending the file name to the client first
printf("Error sending client's filename.\n");
}
printf("Client sending file...\n");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
printf("Sending file size\n");
if((write(sd, &size, sizeof(size))) < 0){ //sending filesize
printf("error sending file size\n");
}
printf("Sending file\n");
while((bytes_read = fread(buf, 1, sizeof(buf), fp)) > 0){ //sending file contents
if ((bytes_written = write(sd, buf, bytes_read)) < 0){
printf("Error sending client file.\n");
}
}
printf("bytes written: %ld\n", bytes_written);
fclose(fp);
}
}
Server snippet (receives):
if(strcmp(shortCommand, "put") == 0){
char *tmp = buf + 4;
char filename2[MAX_BLOCK_SIZE];
size_t filesize;
size_t total_bytes_read = 0;
ssize_t bytes_read = 0;
size_t error;
FILE *fp;
strcpy(filename2, tmp);
printf("Server receiving file name...\n"); //filename is received on the first read before this IF
fp = fopen(filename2, "wb");
if(fp == NULL){
printf("File could not be opened.\n");
exit(1);
}
printf("Server receiving file size...\n");
if((error = read(sd, &filesize, sizeof(filesize))) < 0){ //receiving file size
perror("Error reading filesize\n");
exit(1);
}
printf("Filesize is: %ld \n", filesize);
while(total_bytes_read < filesize){
while((bytes_read = read(sd, buf, sizeof(buf))) > 0){ //receving file contents and writing to file
fwrite(buf, 1, bytes_read, fp);
total_bytes_read += bytes_read;
if(ferror(fp)){
perror("error");
fclose(fp);
}
}
}
printf("The server has received the requested document.\n");
fflush(stdout);
fclose(fp);
}
After I exit the program by force, I can actually see that the file has been copied. Just doesn't exit that while loop to let me go back to the client.
Time for some basic debugging. I'd suggest changing your read loop to something like this:
while (total_bytes_read < filesize) {
printf("DEBUG A: total=%zu, size=%zu\n", total_bytes_read, filesize);
while ((bytes_read = read(sd, buf, sizeof(buf))) > 0) {
printf("DEBUG B: read=%zd\n", bytes_read);
fwrite(buf, 1, bytes_read, fp);
total_bytes_read += bytes_read;
printf("DEBUG C: total=%zu\n", total_bytes_read);
if (ferror(fp))
printf("DEBUG D\n");
perror("error");
fclose(fp);
}
printf("DEBUG E\n");
}
printf("DEBUG F\n");
}
printf("DEBUG G\n");
Then run it, piping the output through less or some other pager, it should then hopefully become clearer what's actually happening.
Feel free to post the output of this modified code (in a comment, or in the actual question), we'll no doubt be able to help with the analysis.

C Web Server Segmentation Fault

I am having some trouble understanding why I am getting a segmentation fault in my homemade web server. I am trying to correctly label the content type for .html and .txt documents. I can open an .html file in my web browser just fine when my server is running. However, my server is closing on a segmentation fault when I try to open a .txt document. The code below is where I am getting the issue.
void* thread_runner(void* sockfd)
{
char buffer[256];
int n;
int sock = *(int*)sockfd;
bzero(buffer,256);
char filename[256];
bzero(filename,256);
n = read(sock,filename,255);
if (n < 0) error("ERROR reading from socket");
FILE *fp;
char file[4096];
char* word = strtok(filename, " ");
word = strtok(NULL, " ");
word++;
printf("filename = \"%s\"\n", word);
fp = fopen(word, "r");
if (fp == NULL) {
printf("file pointer is NULL\n");
return 0;
}
char string[4096];
char* extension;
bzero(string, 4096);
bzero(file, 4096);
char* word2;
word2 = strtok(word, ".");
while ((word2 = strtok(NULL, ".")) != NULL)
{
extension = word2;
}
printf("File Extension: %s\n", extension);
if (strncmp(extension, "html", 4096) == 0) {
printf("HTML FILE FOUND\n");
strcat(string, "HTTP/1.1 200 OK\nContent-Type: text/html\nContent-Length: 4096 \nConnection: keep-alive\n\n");
}
else if (strncmp(extension, "txt", 4096) == 0) {
printf("TXT FILE FOUND\n");
strcat(string, "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 4096\nConnection: keep-alive\n\n");
}
the error occurs in this loop.
I have used bzero on 'string'.
while (fgets(file, 4096, fp))
{
strcat(string, file);
}
//printf("Sending text:%s", string);
printf("The requested file was: %s.%s\n",word,extension);
n = write(sock,string,4096);
printf("file contents are %s\n", string);
fclose(fp);
if (n < 0) error("ERROR writing to socket");
if (n == 0)
{
close(sock);
}
You're writing past the end of string. string only has 4096 characters in it, but your loop tries to read the entire file into it when it keeps calling strcat() in a loop.
Instead of concatenating the entire file into a variable and then writing it all, use fread() to read the file in chunks and immediately write them to the socket. There's no need to read line by line.
size_t in;
while ((in = fread(file, 1, sizeof file, fp) > 0) {
int n = write(sock, file, in);
if (n < in) {
error("ERROR writing to socket");
}
}
close(sock);
fclose(fp);

C: Can not decrypt message Openssl

I'm new with cryptography, so I decided to create simple program that would open a file encrypt data, put it in etest.txt, then open this file decrypt it and put it indetest.txt. I know it sounds really weired but its for educational purposes. so here is my code.
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>
int main(void) {
size_t pri_len; // Length of private key
size_t pub_len; // Length of public key
char *pri_key; // Private key
char *pub_key; // Public key
char *msg = malloc(256); // Message to encrypt
char *encrypt = NULL; // Encrypted message
char *decrypt = NULL; // Decrypted message
char *err; // Buffer for any error messages
// Generate key pair
RSA *keypair = RSA_generate_key(2048, 3, NULL, NULL);
FILE *in = fopen("test.txt", "rb");
FILE *out = fopen("etest.txt", "wb");
if(in == NULL)
{
printf("in Error is %d (%s).\n", errno, strerror(errno));
}
if(out == NULL)
{
printf("out Error is %d (%s).\n", errno, strerror(errno));
}
encrypt = malloc(RSA_size(keypair));
for(;;)
{
//213 because of padding
memset(msg, '\0', 256);
memset(encrypt, '\0', 256);
fread(msg, 213, 1, in);
if((RSA_public_encrypt(strlen(msg), (unsigned char*)msg, (unsigned char*)encrypt,
keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
}
if(fwrite(encrypt, 256, 1, out) != 1)
{
printf("fwrite Error is %d (%s).\n", errno, strerror(errno));
}
if(feof(in))
{
break;
}
}
fclose(in);
fclose(out);
in = fopen("etest.txt", "rb");
out = fopen("dtest.txt", "wb");
if(in == NULL)
{
printf("in Error is %d (%s).\n", errno, strerror(errno));
}
if(out == NULL)
{
printf("out Error is %d (%s).\n", errno, strerror(errno));
}
decrypt = malloc(RSA_size(keypair));
for(;;)
{
//I use malloc because if i didnt it would from file and if it filled the msg and if this function would execute second time it would not overwrite the whole buffer and would cause problem
memset(decrypt, '\0', 256);
memset(msg, '\0', 256);
fread(msg, 256, 1, in);
if(RSA_private_decrypt(256, (unsigned char*)msg, (unsigned char*)decrypt,
keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error decrypting message: %s\n", err);
}
fwrite(decrypt, 256, 1, out);
if(feof(in))
{
break;
}
}
fclose(in);
fclose(out);
RSA_free(keypair);
return 0;
}
When I run code it gives me back error saying:Error decrypting message: error:0407A079:rsa routines:RSA_padding_check_PKCS1_OAEP:oaep decoding error but if i delete this codememset(msg, '\0', 256); it shows that everything works fine but it causes problems because msg buffer is overwritten with first few bytes that second fread() function overwrote.
Sorry if my questions sound silly. Hope you can help. thanks.
Your are using fwrite(decrypt, 256, 1, out); which is wrong.size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) Second parameter is the size in bytes of each element to be read And the third one is number of elements, each one with a size of size bytes.

Warning: assignment makes integer from pointer without a cast

I'm learning C almost one year and it's my first time that I got that warnings.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <string.h>
int socket_creation(FILE* fp){
int s;
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET){
printf("Error occurred while creating socket: %d\n", WSAGetLastError());
fprintf(fp, "Error occurred while creating socket: %d\n", WSAGetLastError());
}
else{
printf("Socket creation was successful.\n");
fprintf(fp, "Socket creation was successful.\n");
}
return s;
}
void connect_to_server(int s, struct sockaddr_in ClientService, FILE* fp){
int cResult;
cResult = connect(s, (struct sockaddr*) &ClientService, sizeof(ClientService));
if (cResult == SOCKET_ERROR){
printf("connection to the server has been failed: %d\n", WSAGetLastError());
fprintf(fp, "connection to the server has been failed: %d\n", WSAGetLastError());
cResult = closesocket(s);
if (cResult == SOCKET_ERROR){
printf("error occurred while trying to close socket. \n");
fprintf(fp, "error occurred while trying to close socket. \n");
}
WSACleanup();
}
else{
printf("Connection to serevr has been made successfully. \n");
fprintf(fp, "Connection to serevr has been made successfully. \n");
}
}
int send_to_serv(char buffer[], int s){
int sendto;
sendto = send(s, buffer, 1024, 0);
if (sendto == -1)
printf("\nError: couldn't send the Code.\n", buffer);
else printf("\nCode: <%s> SENT.\n", buffer);
return sendto;
}
int recv_from_serv(int s, int* numberLines, FILE *fp){
int recvfrom;
char buffer[1024] = "";
recvfrom = recv(s, buffer, 1024, 0);
if (recvfrom == -1)
printf("\nError: couldn't receive Code. !\n");
else printf("\nRespond: <%s>, RECEIVED. \n", buffer);
fprintf(fp, "\n");
fprintf(fp, buffer);
*numberLines = atoi(buffer + 3);
return recvfrom;
}
int main() {
WSADATA info;
int error, s;
int sResults, sendError, recvError,convert2;
char buffer[1024] = "";
char recvbuf[1024] = "";
int numberLines, i, temp, convert;
char converted_num[1024] = "";
struct sockaddr_in ClientService;
FILE *fp = fopen("stored_data.txt", "w");
char* lines_array;
error = WSAStartup(MAKEWORD(2, 0), &info);
if (error != 0){
printf("WSAstartup failed with error: %d\n", error);
exit(1);
}
for (i=0; i <=numberLines; i++) {
lines_array[i]=NULL;
}
s = socket_creation(fp);
ClientService.sin_family = AF_INET;
ClientService.sin_addr.s_addr = inet_addr("54.209.143.42");
ClientService.sin_port = htons(6714);
connect_to_server(s, ClientService, fp);
strcpy(buffer, "100");
sendError = send_to_serv(buffer, s);
recvError = recv_from_serv(s, &numberLines, fp);
strcpy(buffer, "400");
sendError = send_to_serv(buffer, s);
recvError = recv_from_serv(s, &numberLines, fp);
printf("\nNumber of Lines are: %d\n", numberLines);
lines_array = malloc(sizeof(char*)*numberLines);
temp = numberLines;
for (i = 0; i < temp; i++){
convert = 5000001 + i;
_itoa(convert, converted_num, 10);
sendError = send_to_serv(converted_num, s);
convert2=atoi(convert);
convert=convert%10000;
if(convert2==0) {
for(i=0; i<=1024; i++) {
buffer[i]=0;
}
lines_array= (convert);
recv_from_serv(s, &numberLines, fp);
}
else{
for(i=0; i<=1024; i++) {
buffer[i]=0;
}
}
}
close(fp);
//system("PkAUSE>nul");
system("PAUSE");
return 0;
}
This is that output that my compiler (MinGW) giving to me:
finalproject1.c: In function main': finalproject1.c:87: warning:
assignment makes integer from pointer without a cast
finalproject1.c:113: warning: passing arg 1 ofatoi' makes pointer
from integer without a cast finalproject1.c:119: warning: assignment
makes pointer from integer without a cast finalproject1.c:133:3:
warning: no newline at end of file
Please help me I don't know what to do and my guid told me to "Google it" when I asked him to help me.
The line that triggers the warning is:
lines_array[i]=NULL;
and this variable is declared like so:
char* lines_array;
so you're cramming a pointer (the NULL macro expands to a pointer-type value on your system) into a single char, which won't fit and is a very strange thing to be doing.
Probably you wanted an array of character pointers, i.e.
char **lines_array;
but then you must of course allocate the array once you know how many lines you're going to be dealing with.
First of all, i can see you are using an integer numberLines as a condition in your for loop without initializing it first:
int numberLines;
for (i=0; i <=numberLines; i++) {
lines_array[i]=NULL;
}
Simply if you want to initialize your array to null you can initialize it as:
char* lines_array = null;
Try this and let me know if the warnings still exist.

Resources