password authentication in Client server model in C - c

I am trying to authenticate client using a password and if the client enters different password he should be again asked to re-enter the password
Following is my server code:
while (1) {
printf("Expecting the pass\n");
ret = recv(sock, pass, sizeof(pass), 0);
if (ret == -1) {
perror("Error receiving message");
exit(1);
} else {
pass[strlen(pass) - 1] = '\0';
printf("Password received %s of length %d\n", pass, strlen(pass));
}
printf("Received\n");
if (strcmp("Abhishek", pass) == 0) {
printf("Password entered is correct\n");
snprintf(buffer, sizeof(buffer), "CORRECT");
break;
} else {
printf("Incorrect Password %s\n", pass);
snprintf(buffer, sizeof(buffer), "I");
}
printf("SENDING : %s\n",buffer);
ret = send(sock, buffer, strlen(buffer), 0);
if (ret == -1) {
perror("Error sending message");
exit(1);
}
}
And client side code is :
while (1) {
printf("Enter the password :");
fgets(buf, sizeof(buf), stdin);
buf[ret] = '\0';
ret = send(sockid, buf, strlen(buf), 0);
if (ret == -1) {
perror("Error sending message");
exit(1);
} else {
printf("Password sent\n");
}
memset(&buf[0], 0, sizeof(buf));
ret = recv(sockid, buf, sizeof(buf), 0);
printf("RECEIVED %s\n", buf);
if (ret == -1) {
perror("Error receiving message");
exit(1);
}
if (buf[0] != 'I') {
break;
}
}
When I execute them in different windows, I can see at server side:
Asking for password authentication
Expecting the pass
At client side:
Start the Admin Dialogue
Enter the password :
Now when I enter password in client window, it says:
Password sent
but Server is still at
Expecting the pass
Can somebody help me with that I am new to this concept

You did not provide a complete function: definitions for the arrays and various variables are missing. Are pass and buf indeed defined an arrays?
You are not sending the '\0' terminators. The message recv'd on the client side is not null terminated. strlen(pass) invokes undefined behavior. Unlikely to be the cause of your problem, but a significant bug nonetheless.
You need some kind of protocol to determine in the server and in the client when a complete message has been received. You should either use '\n' as an end of message indicator or possibly a '\0'.
Here is how you would force null termination on the server side:
printf("Expecting the pass\n");
ret = recv(sock, pass, sizeof(pass) - 1, 0);
if (ret == -1) {
perror("Error receiving message");
exit(1);
} else {
pass[ret] = '\0';
if (ret > 0 && pass[ret - 1] == '\n')
pass[--ret] = '\0';
printf("Password received %s of length %d\n", pass, ret);
}
But this is not sufficient to ensure that the full message has been received by the server, you really should recv until you get a linefeed, or some sort of protocol indicating a complete message.
On the client side, buf[ret] = '\0'; seems useless and potentially risky.

Related

Authentication and parsing problem web server

I am currently working on a piece of code that redirects me to a website that asks for authentification first (username and password). If the correct username and password is inputted, it should be parsed so that it can be compared to the string token.
To show it visually:
Token: MjAxOC0xMzc0OTpwYXNzd29yZA==, tokensize : 28
Authorization: Basic MjAxOC0xMzc0OToyMDE4LTEzNzQ5
What I need to do is parse MjAxOC0xMzc0OToyMDE4LTEzNzQ5 from Authorization: Basic and then compare it to the token value. If they match, the loop ends and the user can enter the website. If they don't, the user needs to keep inputting the username and password. However, my code does not seem to be working.
while(1){
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
//accept connection
//send 401 message(more information about 401 message and authentificate user
if(newsockfd == -1){
perror("accept error");
exit(1);
}
char buffer[9000];
int tracker = 1;
int bytes;
bytes = 0;
//receive the socket
bytes = recv(newsockfd, buffer, 1500, 0);
//send the 401 unauthorized message
char message[] = "HTTP/1.1 401 Unauthorized\r\nWWW-authenticate: Basic realm='localhost'\r\nContent-Type: text/html;\r\n\r\n";
//get the length of the message
int length = strlen(message);
//while the message exists, send it to the client
while(length > 0){
printf("send bytes : %d\n", bytes);
bytes = send(newsockfd, message, length, 0);
if(bytes==-1){
continue;
}
length -= bytes;
}
//get the size of the token
int tokensize = strlen(token);
printf("Token: %s, tokensize : %d\n", token, tokensize);
// this is where the parsing happens
char* parse;
bytes = 0;
bytes = recv(newsockfd, buffer, 1500, 0);
if(bytes == -1){
printf("error receiving message");
exit(1);
}
parse = strtok(buffer, "\r\n");
while(parse != 0){
parse = strtok(NULL, "\r\n");
if(parse != NULL && strncmp(parse, "Authorization", strlen("Authorization")) == 0){
printf("%s\n", parse);
char* str;
str = strtok(parse, " ");
printf("%s", str);
//this is where it's compared to the string token
while(str){
str = strtok(NULL, " ");
printf("%s", str);
if(str == NULL)
break;
else if (strcmp(str, "Basic") == 0){
continue;
}
if(strcmp(str, token) == 0){
break;
}
}
}
}

Server only sending one message to client

My Server is only able to send one message to the client (HELLO), the client then sends a WORD message and after the server had received the WORD message it's supposed to send a word.
For some reason the server only sends the HELLO message and upon receiving the WORD message it never sends the next message (in this case it's GREEK). I've tried so many different things but it just doesn't seem to work.
Server code (only the relevant parts) ALL CODE IS IN C
while (1) {
if ((newsockfd = accept(sockfd, (struct sockaddr *)&dest, &destlen)) == -1) {
perror("Accept call failed");
exit(-1);
}
if ((childpid = fork()) == 0) {
//close(sockfd);
talk_to_client(newsockfd);
//close(newsockfd);
}
else if (childpid > 0) {
//close(newsockfd);
}
}
}
talk_to_client()
void talk_to_client(int sockfd) {
char message[1024] = "HELLO";
char message2[1024] = "GREEK";
char recieved[1024];
ssize_t n;
//cannot send more than one!!!!!!!!! WHY NOT
write(sockfd, message, sizeof(message));
while (1) {
recv(sockfd, recieved, sizeof(recieved), 0);
if (recieved == "WORD") {
//send initial word
printf("SENDING WORD");
write(sockfd, message2, sizeof(message2));
}
if (recieved == "QUIT") {
//close connection
close(sockfd);
}
}
return;
}
Client code (only relevant parts)
char srv[512];
char cli[512] = "WORD";
// Connects socket to server
rv = connect(sockfd, (struct sockaddr *) servaddr, sizeof(struct sockaddr));
if (rv == -1){
perror("Error connecting to the server");
exit(-1);
}
if(recv(sockfd, srv, sizeof(srv), 0) == -1) {
perror("Client receiving error");
}
printf("Client received: %s\n", srv);
if(send(sockfd, cli, sizeof(cli), 0) == -1){
perror("Error sending message to the server");
exit(-1);
}
printf("Client sending: %s\n", cli);
if(recv(sockfd, srv, sizeof(srv), 0) == -1) {
perror("Client receiving error");
}
printf("Client received: %s\n", srv);
close(sockfd);
I tried many different ways to write to client (write, send, etc..) and I know for a fact it has nothing to do with my connect, bind, socket, listen or accept calls but this is the output I keep getting,
Client received: HELLO
Client sending: WORD
Client received:
char cli[512] = "WORD";
...
if(send(sockfd, cli, sizeof(cli), 0) == -1){
sizeof(cli) is 512 based on the definition of cli. So it will send 512 bytes. strlen(cli)+1 would be more correct, i.e. send the string and the \0 at the end of the string.
recv(sockfd, recieved, sizeof(recieved), 0);
This will thus likely receive these 512 bytes in the server, i.e. WORD\0 followed by many bytes junk. Note that I said "likely" since TCP is not a message based protocol but a byte stream and a single send does not need to match a single recv.
if (recieved == "WORD") {
This does not do a string comparison but compares pointer values. strcmp would be more correct here.

Second recv() hangs

My client sends two c-strings to the server, only one is received the second recv() just hangs and I have to CTRL-C out of my program.
How can I get both messages to receive?
Here is the area I am having trouble with.
//SERVER CODE
// Retrieve plaintext from the client while connected.
while ((n = recv(client_socket, buffer_a, sizeof(buffer_a), 0)) > 0) {
buffer_a[n] = '\0';
// Retrieve the key from the client.
// PROBLEM HERE - THIS WILL DO NOTHING AND PROGRAM HANGS
if (recv(client_socket, buffer_b, sizeof(buffer_b)-1, 0) == -1) {
perror("recv key error");
}
}
//CLIENT CODE
while ((n = read(fileno(plain_text), buffer_a, sizeof(buffer_a)-1))
0)
/*Read contents of file*/
{
// Format the buffer as a c-string.
buffer_a[n] = '\0';
// Get the key.
if (read(fileno(key), buffer_b, sizeof(n)-1) == -1) {
perror("read key file error");
exit(1);
}
buffer_b[n] = '\0';
// Send plaintext to the server.
if (send(client_fd, buffer_a, n, 0) == -1) {
perror("send plaintext error");
exit(1);
}
// Send key to the server.
if (send(client_fd, buffer_b, n, 0) == -1)
{
perror("send key error");
exit(1);
}
}

C: Pass socket connection via execl

I am attempting to create a basic server that supports multiple clients. I want the main server to connect to two clients, and then fork off and pass the file descriptors for the clients to another program via a call to execl. Both of the clients connect to the server and are able to communicate with it (tested via asking the clients for user names or handles), but when I attempt to pass the clients to the second program (which is meant to be a personal server between the clients to host a board game match) no output is shown on the client's end when the second program attempts to contact them, I am positive it is the way I am attempting to pass the connection information. Any help with passing the connections correctly is appreciated.
Here is the code for the main server after it accepts two connections:
Main Server: Note. Added additional error checking as recommended.
if(fork() == 0){
close(listener);
int nBytes;
char* playerOne[20];
char* playerTwo[20];
//Creates strings to hold file descriptor information for execl
char connAscii[sizeof(int)];
char connAscii2[sizeof(int)];
snprintf(connAscii,sizeof(conn), "%d", conn);
snprintf(connAscii2,sizeof(conn2), "%d", conn2);
fprintf(stderr, "Int conn: %d, asciiConn: %s, backToInt: %d", conn, connAscii, atoi(connAscii));
char *argf[2];
argf[0] = connAscii;
argf[1] = connAscii2;
//Send Handle Request to Connection 1
nBytes = send(conn, handleRequest, sizeof(handleRequest),0);
if(nBytes == -1){
perror("send");
exit(1);
}
//Receive Handle from Connection 1
nBytes = recv(conn, playerOne, 20, 0);
if(nBytes == -1){
perror("recv");
exit(1);
}
//Send Handle Request to Connection 2
nBytes = send(conn2, handleRequest, sizeof(handleRequest),0);
if(nBytes == -1){
perror("send");
exit(1);
}
//Receive Handle from Connection 2
nBytes = recv(conn2, playerTwo, 20, 0);
if(nBytes == -1){
perror("recv");
exit(1);
}
//Send Handle for Connection 2 to Connection 1
nBytes = send(conn, playerTwo, sizeof(playerTwo),0);
if(nBytes == -1){
perror("send");
exit(1);
}
//Send Handle for Connection 1 to Connection 2
nBytes = send(conn2, playerOne, sizeof(playerOne),0);
if(nBytes == -1){
perror("send");
exit(1);
}
//Passes file descriptors to nimMatch
execl("nimMatch", "nimMatch", argf, (char *)0);
}
The personal server(different .c file than main server): Note. Added debuging statements
char greet[] = {"Hello players, please wait for match setup."};
int main(int argc, char *argv[]) {
int conn1 = atoi(argv[1]);
int conn2 = atoi(argv[2]);
int sent;
fprintf(stderr, "Attempting connection\n");
sent = send(conn1, greet,sizeof(greet),0);
if(sent == -1){
perror("send");
exit(1);
}
return 0;
}
And the client code after it has been connected and matched with an opponent:
printf("Your opponent is: %s\n\n Connecting to match server...", otherHandle);
memset(&buf[0],0,sizeof(buf));
if ((numbytes = recv(sockfd, buf, 99, 0)) == -1) { //should come from personal server
perror("recv");
exit(1);
}
printf("From match server: %s\n", buf);
If more code is needed let me know, I know that the clients successfully connect to the server and I get no errors when compiling or running.
The suggested answer from EJP ensures the private server receives the correct input, but the client does not appear to be storing the string from the private server. The adjusted client code below states that the client is receiving 64 bytes but the buf is empty.
printf("You're opponent is: %s\n\n Connecting to match server...", otherHandle);
memset(&buf[0],0,sizeof(buf));
numbytes = recv(sockfd, buf, 99, 0);
if (numbytes == -1) {
perror("recv");
exit(1);
}
if(strlen(buf) < 1)
fprintf(stderr, "No buffer input, found %d bytes\n", numbytes);
printf("From match server: %s\n", buf);
You're passing the arguments to execl() incorrectly. It doesn't take an argument array, it takes a varargs list of arguments. It should be
execl(path, connAscii, connAscii2, (char*)0);

Client prints Half Data Before Connection is Closed By Server on Socket

I have this scenario. I'm trying to use socket in C to send and receive data. Client sends some string, server manipulates it, sends it back to the client. Everything is fine but one small issue is: The client receives only the first line from server, displays it and then halts till the connection is closed by server after a time out. Although the bytes sent by server = the bytes received by client. As soon as the connection is closed, the rest of the string is displayed by the client.
I would like to know your thoughts and possible issues. Please let me know if you ahve any questions.
Protocol used: TCP
Here is the code for the server:
for (;;)
{
n=recv(s, buf, RBUFLEN-1, 0);
if (n < 0)
{
printf("Read error\n");
closesocket(s);
printf("Socket %d closed\n", s);
break;
}
else if (n==0)
{
printf("Connection closed by party on socket %d\n",s);
closesocket(s);
break;
}
else
{
printf("Received line from socket %03d : \n",s);
printf("N bytes received: %d \n",n);
// DoSomeOperationsOnTheData()
if(send(s, buffer, n, 0) != n)
printf("Write error while replying\n");
else
{
printf("Reply sent: %d bytes\n",n);
}
}
Code for client:
do
{
memset(buffer,0x0,BUFFER_SIZE); // init line
rc = read(sd, buffer, BUFFER_SIZE);
printf("\nReceived bytes: %d", rc);
if( rc > 0)
{
printf("%s",buffer);
size +=rc;
}
}while(rc>0);
printf("\n Total recieved response bytes: %d\n",size);
close(sd);
This
do
{
memset(buffer, 0, BUFFER_SIZE); // init line
rc = read(sd, buffer, BUFFER_SIZE);
printf("\nReceived bytes: %d", rc);
if( rc > 0)
{
printf("%s",buffer);
size +=rc;
}
}while(rc>0);
should be:
memset(buffer,0x0,BUFFER_SIZE); // init line
size_t size = 0;
size_t toread = BUFFER_SIZE;
do
{
ssize_t rc = read(sd, buffer+size, toread);
if (rc > 0)
{
printf("\nReceived bytes:%zd", rc);
printf("%s", buffer);
size += rc;
toread -= rc;
}
else if (rc == 0)
{
printf("The server hung up.\");
break;
}
else
{
perror("read() failed");
break;
}
} while (toread);
if (toread < BUFFERSIZE)
{
printf("Warning: Read less bytes (%zu) then expected (%d).\n", toread, BUFFERSIZE);
}
try flush data after sent.
it needs if you use socket with fdopen
FILE *fdsock = fdopen(sock, "a+");
...
fwrite(fdsock, 1, 1 "A");
fflush(fdsock);
...
fclose(fdsock);
and to finish socket, close with shutdown(sock, SD_SEND);
UPDATE
Take memset out of loop

Resources