2022-01-29 10:32:11 +01:00
|
|
|
/* $Header: https://svn.ita.chalmers.se/repos/security/edu/course/computer_security/trunk/lab/login_linux/login_linux.c 585 2013-01-19 10:31:04Z pk@CHALMERS.SE $ */
|
|
|
|
|
|
|
|
/* gcc -std=gnu99 -Wall -g -o mylogin login_linux.c -lcrypt */
|
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
/* Note, makepass.c is first used to create hashed password
|
|
|
|
then, info is manually saved in file passdb */
|
|
|
|
|
|
|
|
|
2022-01-29 10:32:11 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdio_ext.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <crypt.h>
|
|
|
|
#include "pwent.h" /* Step 2 */
|
2022-01-31 16:38:30 +01:00
|
|
|
#include <termios.h>
|
|
|
|
#include <stdbool.h>
|
2022-01-29 10:32:11 +01:00
|
|
|
|
|
|
|
#define TRUE 1
|
|
|
|
#define FALSE 0
|
|
|
|
#define LENGTH 16
|
|
|
|
|
|
|
|
void sighandler() {
|
2022-01-29 15:26:19 +01:00
|
|
|
signal(SIGINT, SIG_IGN); /* This will catch ctrl+c and ignore it*/
|
2022-02-03 18:35:28 +01:00
|
|
|
signal(SIGTSTP, SIG_IGN); /* This will catch ctrl+z and ignore it*/
|
2022-01-29 10:32:11 +01:00
|
|
|
}
|
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
|
2022-01-29 10:32:11 +01:00
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
2022-02-03 18:36:54 +01:00
|
|
|
mypwent *passwddata;
|
2022-01-29 10:32:11 +01:00
|
|
|
|
|
|
|
char important1[LENGTH] = "**IMPORTANT 1**";
|
|
|
|
|
|
|
|
char user[LENGTH];
|
|
|
|
|
|
|
|
char important2[LENGTH] = "**IMPORTANT 2**";
|
|
|
|
|
2022-02-03 18:36:54 +01:00
|
|
|
char user_pass[LENGTH];
|
2022-01-29 10:32:11 +01:00
|
|
|
|
|
|
|
sighandler();
|
|
|
|
|
|
|
|
while (TRUE) {
|
|
|
|
/* check what important variable contains - do not remove, part of buffer overflow test */
|
|
|
|
printf("Value of variable 'important1' before input of login name: %s\n",
|
|
|
|
important1);
|
|
|
|
printf("Value of variable 'important2' before input of login name: %s\n",
|
|
|
|
important2);
|
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-01-29 10:32:11 +01:00
|
|
|
printf("login: ");
|
|
|
|
fflush(NULL); /* Flush all output buffers */
|
|
|
|
__fpurge(stdin); /* Purge any data in stdin buffer */
|
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
bool okusername = true;
|
|
|
|
/* using fgets instead of gets to avoid buffer overflow attacks*/
|
2022-01-29 15:26:19 +01:00
|
|
|
if (fgets(user,sizeof(user),stdin) == NULL ) {
|
2022-01-31 16:38:30 +01:00
|
|
|
clearerr(stdin);
|
|
|
|
okusername = false;
|
2022-01-29 15:26:19 +01:00
|
|
|
}
|
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
if (strlen(user) == sizeof(user)-1 || strlen(user) == 1){
|
|
|
|
// too long username or no username was entered
|
|
|
|
okusername = false;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
// replacing \n with \0
|
|
|
|
user[strcspn(user,"\n")] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-01-29 10:32:11 +01:00
|
|
|
/* check to see if important variable is intact after input of login name - do not remove */
|
|
|
|
printf("Value of variable 'important 1' after input of login name: %*.*s\n",
|
|
|
|
LENGTH - 1, LENGTH - 1, important1);
|
|
|
|
printf("Value of variable 'important 2' after input of login name: %*.*s\n",
|
|
|
|
LENGTH - 1, LENGTH - 1, important2);
|
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-01-31 19:02:53 +01:00
|
|
|
// using termios instead of the outdated getpass for a more secure program
|
2022-01-31 16:38:30 +01:00
|
|
|
// user_pass = getpass(prompt);
|
|
|
|
|
|
|
|
struct termios old_term_flags, new_term_flags;
|
|
|
|
|
|
|
|
/* Turn echoing off so password will not be shown in terminal */
|
|
|
|
if (tcgetattr(fileno(stdin), &old_term_flags) != 0){
|
|
|
|
perror("Error");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
new_term_flags = old_term_flags;
|
|
|
|
new_term_flags.c_lflag &= ~ECHO;
|
|
|
|
if (tcsetattr(fileno(stdin), TCSAFLUSH, &new_term_flags) != 0) {
|
|
|
|
perror("Error");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool okpassword = true;
|
|
|
|
printf("password: ");
|
|
|
|
if (fgets(user_pass,sizeof(user_pass),stdin) == NULL ) {
|
|
|
|
clearerr(stdin);
|
|
|
|
okpassword = false;
|
|
|
|
}
|
|
|
|
if (strlen(user_pass) == sizeof(user_pass)-1 || strlen(user_pass) == 1){
|
|
|
|
okpassword = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Restore terminal */
|
|
|
|
if (tcsetattr(fileno(stdin), TCSAFLUSH, &old_term_flags) != 0) {
|
2022-01-31 19:28:45 +01:00
|
|
|
perror("Error");
|
|
|
|
exit(EXIT_FAILURE);
|
2022-01-31 16:38:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!okpassword || !okusername){
|
|
|
|
printf("\nLogin Incorrect \n \n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
user_pass[strcspn(user_pass, "\n")] = '\0'; // replacing \n with \0
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-01-31 19:28:45 +01:00
|
|
|
// get user info from passdb
|
2022-01-31 16:38:30 +01:00
|
|
|
passwddata = mygetpwnam(user);
|
|
|
|
|
2022-01-29 10:32:11 +01:00
|
|
|
if (passwddata != NULL) {
|
2022-01-31 16:38:30 +01:00
|
|
|
|
|
|
|
if (passwddata->pwfailed >= 10) {
|
|
|
|
printf("\nToo many failed login attempts. Your account has been locked.\nContact and Admin to unlock your account.\n");
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-29 15:26:19 +01:00
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
/* Encryp user_pass with salt included */
|
2022-01-29 15:26:19 +01:00
|
|
|
char *user_pass_encrypted = crypt(user_pass, passwddata->passwd_salt);
|
2022-01-31 16:38:30 +01:00
|
|
|
if (user_pass_encrypted == NULL) {
|
2022-01-29 15:26:19 +01:00
|
|
|
perror("Error");exit(EXIT_FAILURE);
|
|
|
|
}
|
2022-01-29 10:32:11 +01:00
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
if (!strcmp(user_pass_encrypted, passwddata->passwd)) {
|
|
|
|
// successfull login
|
2022-01-31 19:02:53 +01:00
|
|
|
printf("\n%d failed attemts to login \n",passwddata->pwfailed);
|
2022-01-29 15:26:19 +01:00
|
|
|
passwddata->pwfailed = 0;
|
|
|
|
passwddata->pwage = passwddata->pwage + 1;
|
2022-01-31 16:38:30 +01:00
|
|
|
|
|
|
|
if (mysetpwent(user, passwddata) < 0) {
|
2022-01-29 16:07:55 +01:00
|
|
|
perror("Error");exit(EXIT_FAILURE);
|
|
|
|
}
|
2022-01-31 19:02:53 +01:00
|
|
|
if (passwddata->pwage > 10) {
|
|
|
|
printf("You need to change your password !\n");
|
2022-01-29 15:26:19 +01:00
|
|
|
}
|
|
|
|
|
2022-01-31 16:38:30 +01:00
|
|
|
|
|
|
|
|
2022-01-29 10:32:11 +01:00
|
|
|
/* check UID, see setuid(2) */
|
2022-02-03 18:39:30 +01:00
|
|
|
if (setuid(passwddata->uid) < 0) { //replace this with the ID of the user running the program if you don't have sudo rights
|
2022-01-31 19:28:45 +01:00
|
|
|
perror("Error");
|
|
|
|
exit(EXIT_FAILURE);
|
2022-01-29 16:07:55 +01:00
|
|
|
}
|
2022-01-29 10:32:11 +01:00
|
|
|
/* start a shell, use execve(2) */
|
2022-01-31 16:38:30 +01:00
|
|
|
if (execve("/bin/bash",NULL,NULL) < 0) {
|
2022-01-31 19:28:45 +01:00
|
|
|
perror("Error");
|
|
|
|
exit(EXIT_FAILURE);
|
2022-01-29 15:52:22 +01:00
|
|
|
}
|
2022-01-31 19:02:53 +01:00
|
|
|
printf("\nWelcome to this system !\n");
|
2022-01-31 16:38:30 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// user name exists but password does not match
|
2022-01-29 15:26:19 +01:00
|
|
|
passwddata->pwfailed = passwddata->pwfailed + 1;
|
2022-01-31 16:38:30 +01:00
|
|
|
if (mysetpwent(user, passwddata) < 0) {
|
2022-01-31 19:28:45 +01:00
|
|
|
perror("Error");
|
|
|
|
exit(EXIT_FAILURE);
|
2022-01-29 16:07:55 +01:00
|
|
|
}
|
2022-01-29 10:32:11 +01:00
|
|
|
}
|
|
|
|
}
|
2022-01-31 16:38:30 +01:00
|
|
|
printf("\nLogin Incorrect \n \n");
|
2022-01-29 10:32:11 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|