aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lpass.c103
1 files changed, 87 insertions, 16 deletions
diff --git a/lpass.c b/lpass.c
index 2193359..44f88a2 100644
--- a/lpass.c
+++ b/lpass.c
@@ -1,13 +1,16 @@
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <getopt.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+
#define MAX_BUF 1024
#define ENTROPY_ITERATIONS 100000
#define ENTROPY_KEY_LENGTH 32
+#define DEFAULT_LENGTH 16
#define CHAR_SUBSET_LOWER "abcdefghijklmnopqrstuvwxyz"
#define CHAR_SUBSET_UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -19,6 +22,13 @@ const char *CHAR_SET = (CHAR_SUBSET_LOWER
CHAR_SUBSET_DIGITS
CHAR_SUBSET_SYMBOLS);
+enum CharSet {
+ CHAR_SET_LOWER = 1 << 0,
+ CHAR_SET_UPPER = 1 << 1,
+ CHAR_SET_DIGITS = 1 << 2,
+ CHAR_SET_SYMBOLS = 1 << 3,
+};
+
static BIGNUM *
calc_entropy(const char *site,
const char *login,
@@ -30,7 +40,7 @@ calc_entropy(const char *site,
memset(salt, 0, sizeof(salt));
int saltlen = snprintf(salt, MAX_BUF, "%s%s%lx", site, login, counter);
if (saltlen > MAX_BUF) {
- return 0;
+ return NULL;
}
unsigned char key[ENTROPY_KEY_LENGTH];
@@ -42,7 +52,7 @@ calc_entropy(const char *site,
ENTROPY_KEY_LENGTH,
key);
if (status == 0) {
- return 0;
+ return NULL;
}
/* NULL as last arg to allocate a new BIGNUM */
@@ -132,26 +142,87 @@ render_pass(BIGNUM *entropy, char *out, int length)
insert_str_pseudo_randomly(out, entropy, str_to_add);
}
+static void
+err(const char *msg)
+{
+ fprintf(stderr, "lpass: %s\n", msg);
+ exit(EXIT_FAILURE);
+}
+
+static void
+usage()
+{
+ fputs("usage: lpass SITE LOGIN [OPTIONS]\n", stderr);
+ fputs("\nlpass is a C implementation of LessPass, a stateless password manager.\n", stderr);
+ fputs("\nPositional arguments:\n", stderr);
+ fputs(" SITE The domain name or URL used in password generation.\n", stderr);
+ fputs(" LOGIN The username/login used in that domain or URL.\n", stderr);
+ fputs("\nOptions:\n", stderr);
+ fputs(" -L LENGTH, --length LENGTH\n", stderr);
+ fputs(" password length (default: 16)\n", stderr);
+ fputs(" --no-symbols no symbols in password\n", stderr);
+ fputs("\nThe environment variable LESSPASS_MASTER_PASSWORD must be set with the master\n", stderr);
+ fputs("password for producing the desired password.\n", stderr);
+}
+
int
main(int argc, char *argv[])
{
- if (argc != 5) {
- return 1;
+ const char *master_pass = getenv("LESSPASS_MASTER_PASSWORD");
+ if (master_pass == NULL) {
+ err("environment variable LESSPASS_MASTER_PASSWORD is not set");
}
- const char *master_pass = argv[1];
- int passlen = strlen(master_pass);
- const char *site = argv[2];
- const char *login = argv[3];
- int length = 0;
- if (sscanf(argv[4], "%d", &length) == 0) {
- return 1;
+ int c;
+ int length = DEFAULT_LENGTH;
+ uint8_t charsets = 0;
+ for (;;) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"length", required_argument, 0, 'L'},
+ {"no-symbols", no_argument, 0, 0 },
+ {0, 0, 0, 0 }
+ };
+
+ c = getopt_long(argc, argv, "L:", long_options, &option_index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 0:
+ if (option_index == 1) {
+ /* TODO: no-symbols */
+ }
+ break;
+ case 'L':
+ if (!optarg || sscanf(optarg, "%d", &length) == 0 || length < 1) {
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ break;
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /*
+ * We are still looking for 2 positional arguments, abort if they
+ * are not there.
+ */
+ if (optind > argc - 2) {
+ usage();
+ exit(EXIT_FAILURE);
}
+ const char *site = argv[optind++];
+ const char *login = argv[optind++];
+ int passlen = strlen(master_pass);
uint64_t counter = 1;
BIGNUM *entropy = calc_entropy(site, login, counter, master_pass, passlen);
if (entropy == NULL) {
- return 1;
+ err("Failed to calculate entropy");
}
char generated_pass[length + 1];
@@ -159,5 +230,5 @@ main(int argc, char *argv[])
render_pass(entropy, generated_pass, length);
printf("%s\n", generated_pass);
BN_free(entropy);
- return 0;
+ return EXIT_SUCCESS;
}