step 1 complete :DDD
This commit is contained in:
parent
6f97cf1f39
commit
c1c885e1de
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
lab1/login_linux
|
||||
|
||||
lab1/mylogin
|
10
lab1/Makefile
Executable file
10
lab1/Makefile
Executable file
@ -0,0 +1,10 @@
|
||||
all: login_linux
|
||||
|
||||
mylogin: mylogin.c pwent.h pwent.c
|
||||
gcc -g -Wall pwent.c mylogin.c -lcrypt -o mylogin
|
||||
|
||||
login_linux: login_linux.c pwent.h pwent.c
|
||||
gcc -g -Wall pwent.c login_linux.c -lcrypt -o login_linux
|
||||
|
||||
clean:
|
||||
rm -f *.o mylogin login_linux
|
95
lab1/login_linux.c
Executable file
95
lab1/login_linux.c
Executable file
@ -0,0 +1,95 @@
|
||||
/* $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 */
|
||||
|
||||
#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 <shadow.h>
|
||||
#include "pwent.h" /* Step 2 */
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define LENGTH 16
|
||||
|
||||
void sighandler() {
|
||||
|
||||
/* add signalhandling routines here */
|
||||
/* see 'man 2 signal' */
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
struct passwd *passwddata; /* this has to be redefined in step 2 */
|
||||
/* see pwent.h */
|
||||
struct spwd *shadowpasswddata; /* this has to be redefined in step 2 */
|
||||
/* see pwent.h */
|
||||
|
||||
char important1[LENGTH] = "**IMPORTANT 1**";
|
||||
|
||||
char user[LENGTH];
|
||||
|
||||
char important2[LENGTH] = "**IMPORTANT 2**";
|
||||
|
||||
//char *c_pass; //you might want to use this variable later...
|
||||
char prompt[] = "password: ";
|
||||
char *user_pass;
|
||||
|
||||
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);
|
||||
|
||||
printf("login: ");
|
||||
fflush(NULL); /* Flush all output buffers */
|
||||
__fpurge(stdin); /* Purge any data in stdin buffer */
|
||||
|
||||
if (gets(user) == NULL) /* gets() is vulnerable to buffer */
|
||||
exit(0); /* overflow attacks. */
|
||||
|
||||
/* 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);
|
||||
|
||||
user_pass = getpass(prompt); //enter password using deprecated function :/
|
||||
//passwddata = getpwnam(user); //get user info from /etc/passwd /* Step 1 */
|
||||
|
||||
if (passwddata != NULL) {
|
||||
/* You have to encrypt user_pass for this to work */
|
||||
/* Don't forget to include the salt */
|
||||
shadowpasswddata = getspnam(user); //get encrypted password from /etc/shadow
|
||||
//printf("password in shadow file: %s \n", shadowpasswddata->sp_pwdp);
|
||||
|
||||
char *user_pass_encrypted = crypt(user_pass, shadowpasswddata->sp_pwdp);
|
||||
//printf("encryption of typed pass: %s \n", user_pass_encrypted);
|
||||
// schulze:
|
||||
// $6
|
||||
// $Dvon03J3/yxkUTWF$
|
||||
// JiIGRAV22.iMUOMPW9MJidTt.aPsKOYK4Bx.Av5EMcVmifp1SkhRELWHLKPWCGmv3nhcFk7tgi7/9.YCO/C
|
||||
//schulze:$6$Dvon03J3/yxkUTWF$JiIGRAV22.iMUOMPW9MJidTt.aPsKOYK4Bx.Av5EMcVmifp1SkhRELWHLKPWCGmv3nhcFk7tgi7/9.YCO/CnS/:18577:0:99999:7:::
|
||||
|
||||
if (!strcmp(user_pass_encrypted, shadowpasswddata->sp_pwdp)) {
|
||||
|
||||
printf(" You're in !\n");
|
||||
|
||||
/* check UID, see setuid(2) */
|
||||
/* start a shell, use execve(2) */
|
||||
|
||||
}
|
||||
}
|
||||
printf("Login Incorrect \n");
|
||||
}
|
||||
return 0;
|
||||
}
|
67
lab1/makepass.c
Executable file
67
lab1/makepass.c
Executable file
@ -0,0 +1,67 @@
|
||||
/* $Header: https://svn.ita.chalmers.se/repos/security/edu/course/computer_security/trunk/lab/login_linux/makepass.c 584 2013-01-19 10:30:22Z pk@CHALMERS.SE $ */
|
||||
|
||||
/* makepass.c - Make a UNIX password */
|
||||
/* compile with: gcc -o makepass makepass.c -lcrypt */
|
||||
/* usage: "makepass 'salt'" */
|
||||
|
||||
#include <crypt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int is_salt(char *salt) {
|
||||
char salts[] =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
|
||||
|
||||
return strlen(salt) == 2 && strchr(salts, salt[0]) != 0
|
||||
&& strchr(salts, salt[1]) != 0 && salt[0] != '\0' && salt[1] != '\0';
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *clear;
|
||||
char clear1[9];
|
||||
char *clear2;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s salt\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!is_salt(argv[1])) {
|
||||
fprintf(stderr, "(%s) is illegal salt!\n", argv[1]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
clear = getpass("Password: ");
|
||||
if (clear == NULL) {
|
||||
bzero(clear, 8);
|
||||
fprintf(stderr, "Not a tty!");
|
||||
return 3;
|
||||
}
|
||||
|
||||
strncpy(clear1, clear, 8);
|
||||
bzero(clear, 8);
|
||||
|
||||
clear2 = getpass("Re-enter password: ");
|
||||
if (clear2 == NULL) {
|
||||
bzero(clear2, 8);
|
||||
fprintf(stderr, "Not a tty!");
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (strcmp(clear1, clear2) != 0) {
|
||||
fprintf(stderr, "Sorry, passwords don't match.\n");
|
||||
bzero(clear1, 8);
|
||||
bzero(clear2, 8);
|
||||
return 4;
|
||||
}
|
||||
|
||||
printf("Encrypted password: \"%s\"\n", crypt(clear1, argv[1]));
|
||||
bzero(clear1, 8);
|
||||
bzero(clear2, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
108
lab1/pwent.c
Executable file
108
lab1/pwent.c
Executable file
@ -0,0 +1,108 @@
|
||||
/* $Header: https://svn.ita.chalmers.se/repos/security/edu/course/computer_security/trunk/lab/login_linux/pwent.c 584 2013-01-19 10:30:22Z pk@CHALMERS.SE $ */
|
||||
|
||||
/*
|
||||
A simple library for password databases. Tobias Gedell 2007
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pwent.h"
|
||||
|
||||
#define LINE_BUFFER_LENGTH 1000
|
||||
|
||||
/*
|
||||
Return pointer to password entry for specified user.
|
||||
|
||||
Upon error, or if the user couldn't be found, NULL is returned.
|
||||
|
||||
Note: The returned pointer points to static data.
|
||||
*/
|
||||
mypwent *mygetpwnam(char *name) {
|
||||
FILE *file;
|
||||
char buffer[LINE_BUFFER_LENGTH];
|
||||
|
||||
static char pwname[LINE_BUFFER_LENGTH], passwd[LINE_BUFFER_LENGTH],
|
||||
passwd_salt[LINE_BUFFER_LENGTH];
|
||||
static mypwent ent = { pwname, 0, passwd, passwd_salt, 0, 0 };
|
||||
|
||||
/* Open file, return NULL if it failed. */
|
||||
if ((file = fopen(MYPWENT_FILENAME, "rb")) == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Read each line, looking for the right entry. */
|
||||
while (fgets(buffer, sizeof(buffer), file) != NULL) {
|
||||
if (sscanf(buffer, "%[^:]:%d:%[^:]:%[^:]:%d:%d", ent.pwname, &ent.uid,
|
||||
ent.passwd, ent.passwd_salt, &ent.pwfailed, &ent.pwage) != 6)
|
||||
break;
|
||||
|
||||
if (strcmp(pwname, name) == 0) {
|
||||
fclose(file);
|
||||
return &ent;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
Update password entry for user.
|
||||
|
||||
Upon error, or if the user couldn't be found, -1 is returned,
|
||||
otherwise 0.
|
||||
*/
|
||||
int mysetpwent(char *name, mypwent *pw) {
|
||||
FILE *file;
|
||||
FILE *newfile;
|
||||
char buffer[LINE_BUFFER_LENGTH];
|
||||
char pwname[LINE_BUFFER_LENGTH];
|
||||
|
||||
int status = -1;
|
||||
|
||||
if ((file = fopen(MYPWENT_FILENAME, "rb")) == NULL)
|
||||
return -1;
|
||||
if ((newfile = fopen(MYPWENT_TMP_FILENAME, "wb")) == NULL) {
|
||||
fclose(file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read each line, looking for the right entry. */
|
||||
while (fgets(buffer, sizeof(buffer), file) != NULL) {
|
||||
if (sscanf(buffer, "%[^:]", pwname) != 1) {
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* See if we found the entry to be updated. */
|
||||
if (strcmp(pwname, name) == 0) {
|
||||
if (snprintf(buffer, sizeof(buffer), "%s:%d:%s:%s:%d:%d\n",
|
||||
pw->pwname, pw->uid, pw->passwd, pw->passwd_salt,
|
||||
pw->pwfailed, pw->pwage) >= sizeof(buffer)) {
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if (fputs(buffer, newfile) < 0) {
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(newfile);
|
||||
fclose(file);
|
||||
|
||||
/* Swap files if user successfully updated. */
|
||||
if (status == 0) {
|
||||
if (rename(MYPWENT_TMP_FILENAME, MYPWENT_FILENAME) != 0)
|
||||
status = -1;
|
||||
} else
|
||||
unlink(MYPWENT_TMP_FILENAME);
|
||||
|
||||
return status;
|
||||
}
|
50
lab1/pwent.h
Executable file
50
lab1/pwent.h
Executable file
@ -0,0 +1,50 @@
|
||||
/* $Header: https://svn.ita.chalmers.se/repos/security/edu/course/computer_security/trunk/lab/login_linux/pwent.h 586 2013-01-19 10:32:53Z pk@CHALMERS.SE $ */
|
||||
|
||||
/* pwent.h - Password entry header file */
|
||||
|
||||
/* These routines write and read records from a password database,
|
||||
named "passdb" in the current directory.
|
||||
|
||||
The 'mygetpwnam' routine takes as argument a username, and returns
|
||||
NULL on failure to find it in the database, or a pointer to static
|
||||
storage if found. This storage will be overwritten on the next
|
||||
call.
|
||||
|
||||
The 'mysetpwent' routine takes a name, and a struct 'mypwent', and
|
||||
replaces the data pertaining to 'name' in the database with the
|
||||
supplied struct. It returns 0 on success, -1 on failure to replace
|
||||
the record.
|
||||
|
||||
The database has free form records, the length of which must not
|
||||
exceed 79 characters, the fields are separated by ':', much like
|
||||
the passwd database. The fields are:
|
||||
name:uid:passwd:salt:no_of_failed_attempts:password_age respectively.
|
||||
|
||||
Note the separate 'salt' field, to simplify some of non-obligatory
|
||||
assignments, it is of course entirely possible, not to use this
|
||||
field, but instead to include the salt in the password field, in
|
||||
similarity with the passwd database. */
|
||||
|
||||
/* Usage: copy the files to your own working directory, and
|
||||
use; #include "pwent.h" to include it. */
|
||||
|
||||
#ifndef PWENT_H
|
||||
#define PWENT_H
|
||||
|
||||
/* Names of password files. */
|
||||
#define MYPWENT_FILENAME "passdb"
|
||||
#define MYPWENT_TMP_FILENAME "passdb.tmp"
|
||||
|
||||
typedef struct {
|
||||
char *pwname; /* Username */
|
||||
int uid; /* User id */
|
||||
char *passwd; /* Password */
|
||||
char *passwd_salt; /* Make dictionary attack harder */
|
||||
int pwfailed; /* No. of failed attempts */
|
||||
int pwage; /* Age of password in no of logins */
|
||||
} mypwent;
|
||||
|
||||
mypwent *mygetpwnam(char *name); /* Find entry matching username */
|
||||
int mysetpwent(char *name, mypwent *pw); /* Set entry based on uid */
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user