diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 144 |
1 files changed, 127 insertions, 17 deletions
@@ -1,29 +1,125 @@ // TODO: Secret stored in memory must be encrypted with a key derived from the // user password or consider making password manager stateless (no passwords // stored locally) -// TODO: Replace CBC with GCM or CCM to prevent padding attacks -// TODO: Have ascii art of a cerberus on start menu/page #include "main.h" struct Password passwords[MAX_PASSWORDS]; int numPasswords = 0; +FILE *log_file; + +void log_message(const char *message) { + if (log_file == NULL) { + printf("Error: Log file not available.\n"); + return; + } + + time_t current_time; + struct tm *time_info; + char time_string[80]; + + time(¤t_time); + time_info = localtime(¤t_time); + + strftime(time_string, sizeof(time_string), "[%Y-%m-%d %H:%M:%S] ", time_info); + fprintf(log_file, "%s %s\n", time_string, + message); // Print timestamp and message +} + +void initialize_log() { + log_file = fopen("cerberus.log", "a"); + if (log_file == NULL) { + printf("Error: Could not open log file.\n"); + } else { + log_message("=== cerberus log ==="); // Initial log message + } +} + +void close_log() { + if (log_file != NULL) { + fclose(log_file); + } +} + +void error_exit(const char *error_message) { + log_message(error_message); + if (log_file != NULL) { + fclose(log_file); + } + exit(1); +} + +void clear_input_buffer() { + int c; + while ((c = getchar()) != '\n' && c != EOF) + ; +} + +void check_password_policy(const char *password) { + int length = strlen(password); + if (length < 8) { + error_exit("Password must be at least 8 characters long."); + } + + bool has_upper = false, has_lower = false, has_digit = false, + has_special = false; + for (int i = 0; i < length; i++) { + if (isupper(password[i])) { + has_upper = true; + } else if (islower(password[i])) { + has_lower = true; + } else if (isdigit(password[i])) { + has_digit = true; + } else { + has_special = true; + } + } + + if (!has_upper || !has_lower || !has_digit || !has_special) { + error_exit("Password must contain at least one uppercase letter, one " + "lowercase letter, one digit, and one special character."); + } +} + void generate_password(char *password, int length) { - // Define the character set for the password + if (length < 8 || length > MAX_PASSWORD_LENGTH - 1) { + printf("Invalid password length. Please enter a length between 8 and %d.\n", + MAX_PASSWORD_LENGTH - 1); + return; + } + char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456" - "789!@#$%^&*-_=+{}[]|;:',.<>/?"; + "789!@#$%^&*()-_=+[]{}|;:',.<>?"; int charset_size = strlen(charset); - // Seed the random number generator srand(time(NULL)); - for (int i = 0; i < length; i++) { - int index = rand() % charset_size; - password[i] = charset[index]; + // Initialize flags to check if each required character type is included + bool has_upper = false, has_lower = false, has_digit = false, + has_special = false; + + // Create password with at least one character from each required type + password[0] = charset[rand() % 26]; // at least one uppercase letter + password[1] = charset[26 + rand() % 26]; // at least one lowercase letter + password[2] = charset[52 + rand() % 10]; // at least one digit + password[3] = charset[62 + rand() % 14]; // at least one special character + + // Fill the rest of the password randomly from the character set + for (int i = 4; i < length; i++) { + password[i] = charset[rand() % charset_size]; } password[length] = '\0'; + + // Shuffle the password characters + for (int i = 0; i < length; i++) { + int j = rand() % length; + char temp = password[i]; + password[i] = password[j]; + password[j] = temp; + } + printf("Generated Password: %s\n", password); } @@ -221,6 +317,8 @@ void print_ascii_art(const char *filename) { } int main() { + initialize_log(); + const char *dir = "tmp"; // Directory to store password files mkdir(dir, 0700); // Create directory if it doesn't exist @@ -266,25 +364,33 @@ int main() { printf("3. Exit\n"); printf("Enter your choice: "); scanf("%d", &choice); + clear_input_buffer(); // Clear input buffer after scanf switch (choice) { case 1: { - if (numPasswords >= MAX_PASSWORDS) { - printf("Maximum number of passwords reached.\n"); - break; - } struct Password password; int length; - printf("Enter password length: "); - scanf("%d", &length); + do { + printf("Enter password length: "); + scanf("%d", &length); + clear_input_buffer(); + if (length < 8 || length > MAX_PASSWORD_LENGTH - 1) { + printf("Invalid password length. Please enter a length between 8 and " + "%d.\n", + MAX_PASSWORD_LENGTH - 1); + } + } while (length < 8 || length > MAX_PASSWORD_LENGTH - 1); generate_password(password.password, length); printf("Enter website: "); - scanf("%s", password.website); + fgets(password.website, sizeof(password.website), stdin); + password.website[strcspn(password.website, "\n")] = + 0; // Remove newline character printf("Enter username: "); - scanf("%s", password.username); + fgets(password.username, sizeof(password.username), stdin); + password.username[strcspn(password.username, "\n")] = + 0; // Remove newline character save_password(&password, password.website, dir, user_password); printf("Password information saved to %s\n", password.website); - passwords[numPasswords++] = password; break; } case 2: { @@ -292,6 +398,7 @@ int main() { printf("Enter the number of the password to copy (0 to cancel): "); int selection; scanf("%d", &selection); + clear_input_buffer(); if (selection > 0 && selection <= numPasswords) { struct Password selected_password = passwords[selection - 1]; printf("Selected Password:\n"); @@ -302,6 +409,7 @@ int main() { "cancel): "); int copy_choice; scanf("%d", ©_choice); + clear_input_buffer(); switch (copy_choice) { case 1: copy_to_clipboard(selected_password.password); @@ -319,11 +427,13 @@ int main() { } case 3: printf("Exiting program...\n"); + close_log(); return 0; default: printf("Invalid choice. Please enter 1, 2, or 3.\n"); } } + close_log(); return 0; } |
