connected client needs to provide a username which will be communicated to rejected clients

This commit is contained in:
Igor Socec 2014-04-03 02:04:13 +02:00
parent 55367f5fee
commit 75b30f3aa6
5 changed files with 63 additions and 17 deletions

View file

@ -82,3 +82,46 @@ int client_write(struct client_t *client, char *databuf, int datalen) {
return len;
}
/* Waits for client to provide a username. Blocks until a username is entered. */
int client_ask_username(struct client_t *client) {
int i;
char databuf[DATABUF_LEN];
fd_set read_fds;
/* send username request to client */
snprintf(databuf, DATABUF_LEN,
"\nPlease provide a username to identify yourself to other users (max %d characters):\n", USERNAME_LEN);
client_write(client, databuf, strlen(databuf));
/* wait for client input */
client->username[0] = '\0';
while (client->username[0] == '\0') {
/* send prompt character to client */
snprintf(databuf, DATABUF_LEN, "> ");
client_write(client, databuf, strlen(databuf));
/* setup select() parameters */
FD_ZERO(&read_fds);
FD_SET(client->socket, &read_fds);
select((client->socket)+1, &read_fds, NULL, NULL, NULL);
if (FD_ISSET(client->socket, &read_fds)) {
client_read(client);
/* handle client input */
for (i = 0; i < USERNAME_LEN; i++) {
if (client->data[i] == '\r') {
break;
}
client->username[i] = client->data[i];
}
client->username[i+1] = '\0';
}
}
/* send welcome message to client */
snprintf(databuf, DATABUF_LEN,
"\nWelcome %s!\n\n", client->username);
client_write(client, databuf, strlen(databuf));
return 0;
}

View file

@ -1,12 +0,0 @@
- support multiple client connections at the same time
- first client has control
- additional clients can see the traffic
- read-only: requests from controlling client and responses from tty device
- need to avoid unintentional lock up if controlling client stays connected but user goes away and forgets about it
- additional clients should be able to force disconnecting controlling client
- first additional client that forces this becomes controlling client
- require username when connecting to the server
- allows tracking users
- makes the feature above (forcing disconnect) easier to use
- username can be connected to a person easier than an IP address

View file

@ -210,12 +210,14 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "[%s] problem accepting client\n", NAME);
continue;
}
/* ask client to provide a username before going to "character" mode */
client_ask_username(&client);
/* put client in "character" mode */
telnet_set_character_mode(&client);
}
/* reject connection request if a client is already connected */
else {
server_reject(&server);
server_reject(&server, &client);
}
}
/* check client status if connected */

View file

@ -17,6 +17,7 @@
#define TIMESTAMP_FORMAT "%d.%m.%Y. %H:%M:%S"
#define TIMESTAMP_LEN 20+1 /* calculated following timestamp format */
#define CONFILE "moxanix.cfg"
#define USERNAME_LEN 32
/* Structures used for communication parameters. */
struct server_t {
@ -30,6 +31,7 @@ struct client_t {
struct sockaddr_in address; /* client address information */
char ip_string[INET_ADDRSTRLEN]; /* client IP address as a string */
time_t last_active; /* time of client's last activity in seconds from Epoch */
char username[USERNAME_LEN]; /* username for human identification */
char data[DATABUF_LEN]; /* buffer for data received from client */
};
@ -94,7 +96,7 @@ int server_accept(struct server_t *server, struct client_t *accepted_client);
* Returns:
* 0 always, errors with rejected client are ignored
*/
int server_reject(struct server_t *server);
int server_reject(struct server_t *server, struct client_t *client);
/* Functions handling communication with clients. */
@ -127,6 +129,15 @@ int client_read(struct client_t *client);
*/
int client_write(struct client_t *client, char *databuf, int datalen);
/**
* Waits for client to provide a username.
* Blocks until a username is entered.
*
* Returns:
* 0 always
*/
int client_ask_username(struct client_t *client);
/* Functions handling details related to telnet protocol. */

View file

@ -104,7 +104,7 @@ int server_accept(struct server_t *server, struct client_t *accepted_client) {
}
/* Rejects incoming client connection. Errors with rejected client are ignored. */
int server_reject(struct server_t *server) {
int server_reject(struct server_t *server, struct client_t *client) {
int namelen;
struct client_t rclient;
@ -114,8 +114,10 @@ int server_reject(struct server_t *server) {
/* accept connection request */
namelen = sizeof(rclient.address);
rclient.socket = accept(server->socket, (struct sockaddr *) &rclient.address, (socklen_t *) &namelen);
/* send reject message */
sprintf(reject_msg, "[%s] port %u is already being used\n", __func__, server->port);
/* send reject message to client */
time2string(client->last_active, timestamp);
sprintf(reject_msg, "\nPort %u is already being used:\ncurrent user: %s\nlast activity: @ %s\n\n",
server->port, client->username, timestamp);
send(rclient.socket, reject_msg, strlen(reject_msg), 0);
/* close connection */
close(rclient.socket);