diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e613fcf --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +all: passgen + +WARNINGS = -Wall +DEBUG = -ggdb -fno-omit-frame-pointer +OPTIMIZE = -O2 + +passgen: Makefile passgen.c + $(CC) -o $@ $(WARNINGS) $(DEBUG) $(OPTIMIZE) passgen.c + +clean: + rm -f passgen + +install: + echo "Installing is not supported" + +run: + ./passgen diff --git a/README.md b/README.md index 13b9b26..5e6ee7d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,101 @@ # passgen -A simple and efficient command line password generator written in C + +## Table of Contents + +- [Introduction](#introduction) +- [Building](#building) +- [Usage](#usage) +- [Options](#options) +- [Examples](#examples) + +## Introduction + +**passgen** is a password generation tool that allows you to create secure and +customizable passwords. It generates passwords based on user-specified +criteria, including password length and character types (lowercase letters, +uppercase letters, digits, and special characters). You can also use +**passgen** without any options to generate a random password with default +settings. + +## Building + +This tool is provided as source code and can be built using `make`. By just +typing make in the terminal within the code's directory: + +```bash +make +``` + +You should now have an executable named `passgen`. You can copy it to a location +in your PATH for easy access. + +## Usage + +To use passgen, open your terminal and execute the program with the desired +options. + +```bash +passgen [OPTIONS] +``` + +## Options + +**passgen** provides the following command-line options: + +- `-L`, `--length`: + - Specify the length of the generated password. Default is 24 characters. + - Valid range: 5 to 4096 characters. + +- `-l`, `--lower-case`: + - Enable lowercase letters in the password. + +- `-u`, `--upper-case`: + - Enable uppercase letters in the password. + +- `-d`, `--digits`: + - Enable digits in the password. + +- `-s`, `--special`: + - Enable special characters in the password. + +- `-h`, `--help`: + - Display the help message and exit. + +- `-v`, `--version`: + - Display the program version and exit. + +## Examples + +1. Generate a default password: + +```bash +passgen +``` + +This will generate a 24-character password with a mix of lowercase letters, +uppercase letters, digits, and special characters. + +2. Generate a password with specific options: + +```bash +passgen -L 12 -lud +``` + +This will generate a 12-character password with only lowercase letters, +uppercase letters, digits, and no special characters. + +3. Display help message: + +```bash +passgen -h +``` + +This will display the usage and available options. + +4. Display version: + +```bash +passgen -v +``` + +This will display the version of Passgen. diff --git a/passgen.c b/passgen.c new file mode 100644 index 0000000..f91b75e --- /dev/null +++ b/passgen.c @@ -0,0 +1,189 @@ +/* + * passgen.c + * + * Copyright 2024 Clay Gomera + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include +#include +#include +#include +#include +#include + +#define VERSION 0.1 +#define NAME "passgen" + +// Function prototypes +char* generatePassword(unsigned int length, bool wantsUpCase, bool wantsLowCase, bool wantsDigits, bool wantsSpecials); +void displayHelp(); +void displayVersion(); + +int main(int argc, char **argv) { + int option; + unsigned int length = 24; + bool wantsUpCase = false, + wantsLowCase = false, + wantsDigits = false, + wantsSpecials = false; + + // Generate a random password if no arguments are given + if (argc == 1) { + char* password = generatePassword(length, true, true, true, true); + printf("Password: %s\n", password); + return 0; + } + + // Options + static const char* short_options = "L:ludshv"; + static struct option long_options[] = { + {"length", required_argument, 0, 'L'}, + {"lower-case", no_argument, 0, 'l'}, + {"upper-case", no_argument, 0, 'u'}, + {"digits", no_argument, 0, 'd'}, + {"special", no_argument, 0, 's'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'}, + {NULL, 0, NULL, 0} + }; + + while ((option = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { + switch (option) { + case 'L': + if ((length = atoi(optarg)) != 0) { + if (length > 4096 || length < 5) { + fprintf(stderr, "Error: The password length can't be greater than 4096 or less than 5 characters.\n\n"); + displayHelp(); + return 1; + } + } + else { + fprintf(stderr, "Invalid value provided. Please provide a valid numeric value for the length.\n\n"); + displayHelp(); + return 1; + } + break; + case 'l': + wantsLowCase = true; + break; + case 'u': + wantsUpCase = true; + break; + case 'd': + wantsDigits = true; + break; + case 's': + wantsSpecials = true; + break; + case 'h': + displayHelp(); + return 0; + case 'v': + displayVersion(); + return 0; + case '?': + fprintf(stderr, "Use '-h, --help' for help.\n"); + return 1; + } + } + + if (!wantsLowCase && !wantsUpCase && !wantsDigits && !wantsSpecials) { + char* password = generatePassword(length, true, true, true, true); + printf("Password: %s\n", password); + return 0; + } + + char* password = generatePassword(length, wantsUpCase, wantsLowCase, wantsDigits, wantsSpecials); + printf("Password: %s\n", password); + + return 0; +} + +char* generatePassword(unsigned int length, bool wantsUpCase, bool wantsLowCase, bool wantsDigits, bool wantsSpecials) { + const char* uppercase_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char* lowercase_letters = "abcdefghijklmnopqrstuvwxyz"; + const char* digits = "0123456789"; + const char* special_chars = "!@#$%^&*()_=[{]}\\|;:'\",<.>?`~+-/*"; + + // Seed the random number generator with processor time + srand((unsigned int)clock()); + + // Calculate the total number of characters based on user preferences + unsigned int total_chars = 0; + if (wantsUpCase) total_chars += strlen(uppercase_letters); + if (wantsLowCase) total_chars += strlen(lowercase_letters); + if (wantsDigits) total_chars += strlen(digits); + if (wantsSpecials) total_chars += strlen(special_chars); + + char* password = (char*)malloc((length + 1) * sizeof(char)); // +1 for null-terminator + if (password == NULL) { + fprintf(stderr, "Memory allocation error.\n"); + exit(1); + } + + for (unsigned int i = 0; i < length; i++) { + int random_index = rand() % total_chars; + + if (wantsUpCase) { + if (random_index < strlen(uppercase_letters)) { + password[i] = uppercase_letters[random_index]; + continue; + } + random_index -= strlen(uppercase_letters); + } + if (wantsLowCase) { + if (random_index < strlen(lowercase_letters)) { + password[i] = lowercase_letters[random_index]; + continue; + } + random_index -= strlen(lowercase_letters); + } + if (wantsDigits) { + if (random_index < strlen(digits)) { + password[i] = digits[random_index]; + continue; + } + random_index -= strlen(digits); + } + if (wantsSpecials) { + password[i] = special_chars[random_index]; + } + } + + password[length] = '\0'; // Null-terminate the string + return password; +} + +// Function to display the help message +void displayHelp() { + printf("Usage: %s [OPTIONS]\n", NAME); + printf("Generate passwords with ease.\n\n"); + printf("Options:\n"); + printf("\t-L, --length Specify the length of the password.\n"); + printf("\t-l, --lower-case Enable lowercase for the password.\n"); + printf("\t-u, --upper-case Enable uppercase for the password.\n"); + printf("\t-d, --digits Enable digits for the password.\n"); + printf("\t-s, --special Enable special characters for the password.\n"); + printf("\t-h, --help Display this help message and exit.\n"); + printf("\t-v, --version Display version and exit.\n"); +} + +// Function to display the version information +void displayVersion() { + printf("%s v%.1f\n", NAME, VERSION); +}