1

I am supposed to write a program in C on Linux using sockets where the clients connect to the server, provide login credentials, the server verifies these credentials against a file, and then returns a different message depending on the valid/invalid status.

So far my server code is:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <curses.h>

void error(char *msg)
{
    perror(msg);
    exit(1);
}

void sendResponse(int newsockfd, int n)
{
    n = write(newsockfd, "Welcome to CPSC445-Comp Networking class\nYou are invited to use Fortnight", 73);
    if (n < 0)
    {
        error("ERROR writing to socket");
    }
}

void sendResponse1(int newsockfd, int n)
{
    n = write(newsockfd, "Only for ESU CPSC students taking CPSC445\nYou are not yet invited", 66);
    if (n < 0)
    {
        error("ERROR writing to socket");
    }
}

int readPass(int newsockfd, int n, char buffer[], int i)
{
    int u = i;
    bzero(buffer, 256);
    n = read(newsockfd,buffer,255);
    if (n < 0)
    {
        error("ERROR reading from socket");

    }


    char newbuf[256];
    char user[8];
    char pass[8];
    FILE *f1;

    f1 = fopen("passwd.txt", "r");

    for (int i = 0; i<=u; i++)
    {   
        fgets(newbuf, 256, f1);
        sscanf(newbuf, "%[^:]_%[^:]", user, pass);;
    }
    if (strcmp(buffer, pass) == 0)
    {
        n = write(newsockfd, "1", 1);
        sendResponse(newsockfd, n);
        return 1;
    }
    else
    {
        n = write(newsockfd, "Invalid password, please try again\n", 33);
        return 0;
    }
    sendResponse1(newsockfd, n);
    return 0;
}

int readUser(int newsockfd, int n, char buffer[])
{
    bzero(buffer, 256);
    n = read(newsockfd,buffer,255);
    printf("%s", buffer);

    if (n < 0)
    {
        error("ERROR reading from socket");

    }

    char valid[1];  
    char newbuf[256];
    char user[8];
    FILE *f1;

    f1 = fopen("passwd.txt", "r");

    int i = 0;
    while (!feof(f1))
    {   
        fgets(newbuf, 256, f1);
        sscanf(newbuf, "%[^:]", user);
        if (strcmp(buffer, user) == 0)
        {
            n = write(newsockfd, "1", 1);
            readPass(newsockfd, n, buffer, i);
            return 1;
        }
        else
        {
            i++;
        }
    }
    n = write(newsockfd, "Invalid username, please try again\n", 34);
    return 0;    
}



int main(int argc, char *argv[])
{
    pid_t cli2, cli3;
    int sockfd, newsockfd, portno, clilen;
    int cli_num = 0;
    int clients[3];
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    if (argc < 2) 
    {
        fprintf(stderr, "ERROR, no port provided\n");
        exit(1);
    }
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        error("ERROR opening socket");
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(portno);
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    {
        error("ERROR on binding");
    }
    listen(sockfd, 5);
    clilen = sizeof(cli_addr);

    //cli2 = fork();
    //cli3 = fork();
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

    if (newsockfd < 0) 
    {
        error("ERROR on accept");
    }

    readUser(newsockfd, n, buffer);
    return 0;
}

And my client code is:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ncurses.h>

void error(char *msg)
{
    perror(msg);
    exit(0);
}

void sendUser(int sockfd, int n, char buffer[], WINDOW *login)
{
    bzero(buffer, 256);
    getstr(buffer);
    n = write(sockfd, buffer, strlen(buffer));
    if (n = 0)
    {
        error("ERROR writing to socket");
    }
}

void sendPass(int sockfd, int n, char buffer[], WINDOW *login)
{
    bzero(buffer, 256);
    noecho();
    cbreak();

    int i = 0;
    while(1)
    {
        int temp = getch();
        if (temp == 10)
        {
            break;  
        }
        else
        {
            buffer[i] = temp;
            addch('*');
            i++;
        }
    }
    n = write(sockfd, buffer, strlen(buffer));
    if (n = 0)
    {
        error("ERROR writing to socket");
    }
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    char buffer[256];
    if (argc < 3) 
    {
        fprintf(stderr, "usage %s hostname post\n", argv[0]);
        exit(0);
    }
    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        error("ERROR opening socket");
    }
    server = gethostbyname(argv[1]);
    if (server == NULL)
    {
        fprintf(stderr, "ERROR, no such host\n");
        exit(0);
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
    serv_addr.sin_port = htons(portno);
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    {
        error("ERROR connecting");
    }

    char valid[1];
    WINDOW *login = initscr();

    int tries = 3;
    for (int i = 0; i<3; i++)
    {
        waddstr(login, "\nWelcome to Computer Science Department\n\n");
        waddstr(login, "Login: ");
        sendUser(sockfd, n, buffer, login);
        n = read(sockfd, valid, 1);

        if (strcmp(valid, "1") == 0)
        {
            valid[0] = 0;
            waddstr(login, "Password: ");
            sendPass(sockfd, n, buffer, login);
            n = read(sockfd, valid, 1);

            if (strcmp(valid,"1") == 0)
            {
                endwin();
                bzero(buffer, 256);
                n = read(sockfd, buffer, 255);
                if (n = 0)
                {
                    error("ERROR reading from socket");
                }
                printf("%s\n", buffer);
                break;
            }
            else
            {
                endwin();
                tries--;
                bzero(buffer, 256);
                n = read(sockfd, buffer, 255);
                if (n = 0)
                {
                    error("ERROR reading from socket");
                }
                printf("%s\n", buffer);
            }
        }
        else
        {
            endwin();
            tries--;
            bzero(buffer, 256);
            n = read(sockfd, buffer, 255);
            if (n = 0)
            {
                error("ERROR reading from socket");
            }
            printf("%s\n", buffer);
        }
    }
    if (strcmp(valid, "1") == 0)
    {
        return 0;
    }
    else
    {
        bzero(buffer, 256);
        n = read(sockfd, buffer, 255);
        if (n = 0)
        {
            error("ERROR reading from socket");
        }
        printf("%s\n", buffer);
    }
}

My question is: After the username is typed in, and the enter key is presses, nothing happens on either the client or server side(s). Why?

  • 1
    You are using very old code. A bulk of the socket setup has now been replaced by the `getaddrinfo()` function. See [Beej's Guide to Network Programming](https://beej.us/guide/bgnet/) -- a very good and very up to date guide with basic client/server examples. You will also want to look at [**Why is while ( !feof (file) ) always wrong?**](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong) – David C. Rankin Feb 09 '20 at 07:37

1 Answers1

0

Before calling endwin() in the client code check response from server, i.e. is the password valid or not. If not valid give possibility to re-enter two times or something and then post 'Access denied' message. You can implement the triple input of a password by using a loop in combination with manipulating the ncurses window, see following pseudo-code :

//bool pw_valid=false; https://stackoverflow.com/questions/1921539/using-boolean-values-in-c
int pw_valid=0; // 0 is false and 1 is true

for(int i=0; i<3; i++)
  {
     manipulate curses screen to (re-)enter password; check if password is valid  (ask server, create new response on the server that verifies valid or invalid password check...) and set pw_valid accordingly;
     if(pw_valid==1){printw("Password is valid!\n"); break;}

  }

if(pw_valid==0) printw("Access denied!\n");
endwin();    //https://linux.die.net/man/3/endwin

Critical is the break; instruction with that you can leave the loop without having to enter the password three times.

Also see http://www.cs.ukzn.ac.za/~hughm/os/notes/ncurses.html and http://www.cplusplus.com/articles/E6vU7k9E/#CURSES for curses commands and curses C++ examples

ralf htp
  • 9,149
  • 4
  • 22
  • 34
  • I tried to implement something like this, though I modified it and have edited the question to show the changes. But now after the username is typed in, and the enter key is presses, nothing happens on either the client or server side(s) – XxSwiftflamexX Feb 10 '20 at 05:12
  • See David Rankin's comment. Then you have to debug this i.e. is the communication between client and server working and what exactly are the sending and receiving (i.e. use simple printf debugging) and then check the curses part because curses is a deeper field than appears on first look – ralf htp Feb 10 '20 at 05:39
  • I'm using the old code instead of getaddrinfo() because that part of the code was given, and it was just supposed to be modified and extended. While (!eof()) works functionally, though I realize it might still be bad practice to use it, it does work. Also I tried putting prinft statements after the first n = write () on the client and n = read() on the server, and neither were reached or printed. I guess I'll have to try other printed statements or more advanced debugging with gbd or something else – XxSwiftflamexX Feb 10 '20 at 05:45
  • In a curss window use `printw()` or print to a log file – ralf htp Feb 10 '20 at 06:27