diff options
Diffstat (limited to '')
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 16 | ||||
-rw-r--r-- | config.mk | 4 | ||||
-rw-r--r-- | demo-login.c | 172 | ||||
-rw-r--r-- | demo-setup.c | 98 | ||||
-rw-r--r-- | libsecauth_format_spec.c | 2 | ||||
-rw-r--r-- | libsecauth_parse_spec.c | 11 | ||||
-rw-r--r-- | libsecauth_server_hash.c | 3 |
8 files changed, 300 insertions, 9 deletions
@@ -7,3 +7,6 @@ *.su *.dll *.dylib +/democonfig +/demo-setup +/demo-login @@ -25,11 +25,17 @@ OBJ =\ HDR =\ libsecauth.h +BIN =\ + demo-setup\ + demo-login + LOBJ = $(OBJ:.o=.lo) -all: libsecauth.a libsecauth.$(LIBEXT) +all: libsecauth.a libsecauth.$(LIBEXT) $(BIN) $(OBJ): $($@:.o=.c) $(HDR) +demo-setup.o: demo-setup.c $(HDR) +demo-login.o: demo-login.c $(HDR) libsecauth.a: $(OBJ) -rm -f -- $@ @@ -45,6 +51,12 @@ libsecauth.$(LIBEXT): $(LOBJ) .c.lo: $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(CPPFLAGS) +demo-setup: demo-setup.o libsecauth.a + $(CC) -o $@ demo-setup.o libsecauth.a $(LDFLAGS) + +demo-login: demo-login.o libsecauth.a + $(CC) -o $@ demo-login.o libsecauth.a $(LDFLAGS) + install: libsecauth.a libsecauth.$(LIBEXT) mkdir -p -- "$(DESTDIR)$(PREFIX)/lib" mkdir -p -- "$(DESTDIR)$(PREFIX)/include" @@ -62,7 +74,7 @@ uninstall: -rm -f -- "$(DESTDIR)$(PREFIX)/include/libsecauth.h" clean: - -rm -rf -- *.o *.a *.so *.lo *.su *.dll *.dylib + -rm -rf -- *.o *.a *.so *.lo *.su *.dll *.dylib democonfig $(BIN) .SUFFIXES: .SUFFIXES: .c .o .lo @@ -4,5 +4,5 @@ MANPREFIX = $(PREFIX)/share/man CC = cc CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -CFLAGS = -std=c99 -Wall -Os -LDFLAGS = -s +CFLAGS = -std=c99 -Wall -O2 +LDFLAGS = -s -lcrypt diff --git a/demo-login.c b/demo-login.c new file mode 100644 index 0000000..fd3c750 --- /dev/null +++ b/demo-login.c @@ -0,0 +1,172 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsecauth.h" +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define PEPPER "pepper" + + +static char * +server_lookup_hash(void) +{ + char *settings; + size_t size, len; + ssize_t r; + int fd; + + fd = open("democonfig", O_RDONLY); + if (fd < 0) { + perror("open"); + return NULL; + } + settings = NULL; + size = 0; + for (len = 0;; len += (size_t)r) { + if (len == size) { + settings = realloc(settings, size += 128); + if (!settings) { + perror("realloc"); + return NULL; + } + } + r = read(fd, &settings[len], size - len); + if (r <= 0) { + if (!r) + break; + perror("read"); + return NULL; + } + } + close(fd); + if (!len || settings[len - 1] != '\n') { + fprintf(stderr, "./democonfig is corrupt\n"); + return NULL; + } + settings[len - 1] = '\0'; + + return settings; +} + +int +main(int argc, char *argv[]) +{ + struct libsecauth_spec spec; + char *message, *settings, *expected; + size_t size, off; + int fd; + ssize_t w; + int r; + + if (argc != 2) { + fprintf(stderr, "usage: %s password", argv[0]); + return 1; + } + + /* -- SERVER -- */ + + settings = server_lookup_hash(); + if (!settings) + return 1; + if (libsecauth_parse_spec(&spec, settings)) { + perror("libsecauth_parse_spec"); + return 1; + } + spec.posthash = NULL; + spec.expected = NULL; + spec.client_rounds -= spec.client_rounds > 0; + spec.server_rounds = 0; + + size = libsecauth_format_spec(&spec, NULL, 0); + message = malloc(size); + if (!message) { + perror("malloc"); + return 1; + } + libsecauth_format_spec(&spec, message, size); + free(settings); + + /* -- CLIENT -- */ + + settings = message; + if (libsecauth_parse_spec(&spec, settings)) { + perror("libsecauth_parse_spec"); + return 1; + } + message = libsecauth_client_hash(&spec, argv[1]); + if (!message) { + perror("libsecauth_client_hash"); + return 1; + } + free(settings); + + /* -- SERVER -- */ + + settings = server_lookup_hash(); + if (!settings) + return 1; + if (libsecauth_parse_spec(&spec, settings)) { + perror("libsecauth_parse_spec"); + return 1; + } + spec.server_rounds += spec.client_rounds > 0; + spec.client_rounds -= spec.client_rounds > 0; + r = libsecauth_server_hash(&spec, message, PEPPER, NULL); + if (r < 0) { + perror("libsecauth_server_hash"); + return 1; + } else if (!r) { + free(settings); + free(message); + printf("Incorrect password\n"); + return 0; + } + printf("Login OK\n"); + + expected = NULL; + if (!spec.client_rounds) { + spec.xferhash = "$1$newsalt1$"; + spec.posthash = "$6$rounds=1000$newsalt2$"; + spec.expected = NULL; + spec.server_rounds = 100; + if (libsecauth_server_hash(&spec, message, PEPPER, &expected) < 0) { + perror("libsecauth_server_hash"); + return 1; + } + spec.client_rounds = spec.server_rounds; + spec.server_rounds = 0; + spec.expected = expected; + printf("password rehashed\n"); + } + free(message); + size = libsecauth_format_spec(&spec, NULL, 0); + message = malloc(size); + if (!message) { + perror("malloc"); + return 1; + } + libsecauth_format_spec(&spec, message, size); + free(settings); + free(expected); + + message[size - 1] = '\n'; + fd = open("democonfig", O_WRONLY | O_TRUNC, 0600); + if (fd < 0) { + perror("open"); + return 1; + } + for (off = 0; off < size; off += (size_t)w) { + w = write(fd, &message[off], size - off); + if (w <= 0) { + perror("write"); + return 1; + } + } + close(fd); + + free(message); + + return 0; +} diff --git a/demo-setup.c b/demo-setup.c new file mode 100644 index 0000000..fa18c05 --- /dev/null +++ b/demo-setup.c @@ -0,0 +1,98 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsecauth.h" +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define PEPPER "pepper" + + +int +main(int argc, char *argv[]) +{ + struct libsecauth_spec spec; + char *message, *hash; + size_t size, off; + ssize_t r; + int fd; + + if (argc != 2) { + fprintf(stderr, "usage: %s password", argv[0]); + return 1; + } + + /* -- SERVER -- */ + + memset(&spec, 0, sizeof(spec)); + spec.prehash = "$6$rounds=2000$salt1$"; + spec.xferhash = "$1$salt2$"; + spec.client_rounds = 100; + spec.server_rounds = 0; + + size = libsecauth_format_spec(&spec, NULL, 0); + message = malloc(size); + if (!message) { + perror("malloc"); + return 1; + } + libsecauth_format_spec(&spec, message, size); + + /* -- CLIENT -- */ + + memset(&spec, 0, sizeof(spec)); + if (libsecauth_parse_spec(&spec, message)) { + perror("libsecauth_parse_spec"); + return 1; + } + + hash = libsecauth_client_hash(&spec, argv[1]); + if (!hash) { + perror("libsecauth_client_hash"); + return 1; + } + free(message); + message = hash; + + /* -- SERVER -- */ + + memset(&spec, 0, sizeof(spec)); + spec.prehash = "$6$rounds=2000$salt1$"; + spec.xferhash = "$1$salt2$"; + spec.client_rounds = 100; + spec.server_rounds = 0; + spec.posthash = "$6$rounds=1000$salt3$"; + if (libsecauth_server_hash(&spec, message, PEPPER, &hash) < 0) { + perror("libsecauth_server_hash"); + return 1; + } + spec.expected = hash; + free(message); + size = libsecauth_format_spec(&spec, NULL, 0); + message = malloc(size); + if (!message) { + perror("malloc"); + return 1; + } + libsecauth_format_spec(&spec, message, size); + free(hash); + + message[size - 1] = '\n'; + fd = open("democonfig", O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) { + perror("open"); + return 1; + } + for (off = 0; off < size; off += (size_t)r) { + r = write(fd, &message[off], size - off); + if (r <= 0) { + perror("write"); + return 1; + } + } + close(fd); + free(message); + + return 0; +} diff --git a/libsecauth_format_spec.c b/libsecauth_format_spec.c index 83a08cf..09fa600 100644 --- a/libsecauth_format_spec.c +++ b/libsecauth_format_spec.c @@ -25,5 +25,5 @@ libsecauth_format_spec(struct libsecauth_spec *spec, char *buffer, size_t buffer client_rounds, server_rounds, spec->posthash ? "{$" : "", spec->posthash ? spec->posthash : "", spec->posthash ? "$}" : "", expected_with_dollars ? "{$" : "", spec->expected ? spec->expected : "" , expected_with_dollars ? "$}" : ""); - return i > 0 ? (size_t)i : 0; + return i > 0 ? (size_t)(i + 1) : 0; } diff --git a/libsecauth_parse_spec.c b/libsecauth_parse_spec.c index 2961268..e1b0e7d 100644 --- a/libsecauth_parse_spec.c +++ b/libsecauth_parse_spec.c @@ -14,6 +14,7 @@ get_subhash(char *s, char **endp) if (s[0] == '{' && s[1] == '$') { s = ret = &s[2]; + depth += 1; } else { ret = s; } @@ -24,12 +25,15 @@ get_subhash(char *s, char **endp) if (!depth) return NULL; if (!--depth) { + s[-1] = '\0'; *s++ = '\0'; *s++ = '\0'; + *endp = s; return ret; } } else if (s[0] == '$' && !depth) { *s++ = '\0'; + *endp = s; return ret; } } @@ -53,6 +57,7 @@ libsecauth_parse_spec(struct libsecauth_spec *spec, char *s) { const char *client_rounds, *server_rounds; size_t slen = strlen(s); + char *sorig = s; memset(spec, 0, sizeof(*spec)); @@ -65,20 +70,20 @@ libsecauth_parse_spec(struct libsecauth_spec *spec, char *s) client_rounds = get_subhash(s, &s); server_rounds = get_subhash(s, &s); spec->posthash = get_subhash(s, &s); - spec->expected = get_subhash(s, &s); + spec->expected = s; if (client_rounds && strtou32(client_rounds, &spec->client_rounds)) goto invalid; if (server_rounds && strtou32(server_rounds, &spec->server_rounds)) goto invalid; - if (*s) + if (strchr(s, '$')) goto invalid; return 0; invalid: - memset(s, 0, slen); + memset(sorig, 0, slen); errno = EINVAL; return -1; } diff --git a/libsecauth_server_hash.c b/libsecauth_server_hash.c index 6f0d4f0..80f9318 100644 --- a/libsecauth_server_hash.c +++ b/libsecauth_server_hash.c @@ -15,7 +15,8 @@ libsecauth_server_hash(const struct libsecauth_spec *spec, const char *inhash, c uint32_t rounds; size_t i = 0; - *resultp = NULL; + if (resultp) + *resultp = NULL; memset(hashbuf, 0, sizeof(hashbuf)); for (i = 0, rounds = spec->server_rounds; rounds--; i ^= 1) { |