From 8957cbc53f721786e4b4db674597f79e838186d0 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Mon, 4 Nov 2019 17:27:13 -0500 Subject: Hash client passwords with crypt --- Makefile | 2 +- bounce.c | 14 +++++++++++++- bounce.h | 4 +--- client.c | 19 ++++++++++++------- pounce.1 | 14 +++++++++++++- state.c | 2 +- 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index a41d96d..19ccc0d 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ LIBRESSL_PREFIX = /usr/local CFLAGS += -std=c11 -Wall -Wextra -Wpedantic CFLAGS += -I${LIBRESSL_PREFIX}/include LDFLAGS += -L${LIBRESSL_PREFIX}/lib -LDLIBS = -ltls +LDLIBS = -lcrypt -ltls BINS = calico pounce MANS = ${BINS:=.1} diff --git a/bounce.c b/bounce.c index 537f539..889ed5b 100644 --- a/bounce.c +++ b/bounce.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,16 @@ #define SIGINFO SIGUSR2 #endif +static void hashPass(void) { + char *pass = getpass("Password: "); + byte rand[12]; + ssize_t len = getrandom(rand, sizeof(rand), 0); + if (len < 0) err(EX_OSERR, "getrandom"); + char salt[3 + BASE64_SIZE(sizeof(rand))] = "$6$"; + base64(&salt[3], rand, sizeof(rand)); + printf("%s\n", crypt(pass, salt)); +} + static FILE *saveFile; static void saveExit(void) { @@ -190,7 +201,7 @@ int main(int argc, char *argv[]) { const char *away = "pounced :3"; const char *quit = "connection reset by purr"; - const char *Opts = "!A:C:H:K:NP:Q:U:W:a:f:h:j:n:p:r:s:u:vw:"; + const char *Opts = "!A:C:H:K:NP:Q:U:W:a:f:h:j:n:p:r:s:u:vw:x"; const struct option LongOpts[] = { { "insecure", no_argument, NULL, '!' }, { "away", required_argument, NULL, 'A' }, @@ -244,6 +255,7 @@ int main(int argc, char *argv[]) { break; case 'u': user = optarg; break; case 'v': verbose = true; break; case 'w': pass = optarg; + break; case 'x': hashPass(); return EX_OK; break; default: return EX_USAGE; } } diff --git a/bounce.h b/bounce.h index b8c2298..434a1f8 100644 --- a/bounce.h +++ b/bounce.h @@ -116,9 +116,7 @@ static const char Base64[64] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" }; -static inline size_t base64Size(size_t len) { - return 1 + (len + 2) / 3 * 4; -} +#define BASE64_SIZE(len) (1 + ((len) + 2) / 3 * 4) static inline void base64(char *dst, const byte *src, size_t len) { size_t i = 0; diff --git a/client.c b/client.c index c951590..35faa4b 100644 --- a/client.c +++ b/client.c @@ -25,6 +25,7 @@ #include #include #include +#include enum Need { NeedNick = 1 << 0, @@ -96,7 +97,7 @@ static void passRequired(struct Client *client) { client->error = true; } -static void sync(struct Client *client) { +static void maybeSync(struct Client *client) { if (client->need == NeedPass) passRequired(client); if (!client->need) stateSync(client); } @@ -106,7 +107,7 @@ typedef void Handler(struct Client *client, struct Message *msg); static void handleNick(struct Client *client, struct Message *msg) { (void)msg; client->need &= ~NeedNick; - sync(client); + maybeSync(client); } static void handleUser(struct Client *client, struct Message *msg) { @@ -119,17 +120,21 @@ static void handleUser(struct Client *client, struct Message *msg) { } else { client->need &= ~NeedUser; client->consumer = ringConsumer(msg->params[0]); - sync(client); + maybeSync(client); } } static void handlePass(struct Client *client, struct Message *msg) { if (!clientPass) return; - if (!msg->params[0] || strcmp(msg->params[0], clientPass)) { + if (!msg->params[0]) { passRequired(client); - } else { + return; + } + if (!strcmp(crypt(msg->params[0], clientPass), clientPass)) { client->need &= ~NeedPass; - sync(client); + maybeSync(client); + } else { + passRequired(client); } } @@ -139,7 +144,7 @@ static void handleCap(struct Client *client, struct Message *msg) { if (!strcmp(msg->params[0], "END")) { if (!client->need) return; client->need &= ~NeedCapEnd; - sync(client); + maybeSync(client); } else if (!strcmp(msg->params[0], "LS")) { if (client->need) client->need |= NeedCapEnd; diff --git a/pounce.1 b/pounce.1 index cbb5eaa..a18cb98 100644 --- a/pounce.1 +++ b/pounce.1 @@ -1,4 +1,4 @@ -.Dd November 3, 2019 +.Dd November 4, 2019 .Dt POUNCE 1 .Os . @@ -28,6 +28,7 @@ .Op Fl u Ar user .Op Fl w Ar pass .Op Ar config ... +.Nm Fl x . .Sh DESCRIPTION The @@ -124,6 +125,11 @@ and Require the server password .Ar pass for clients to connect. +The +.Ar pass +string must be hashed using the +.Fl x +flag. . .It Fl a Ar user : Ns Ar pass , Cm sasl = Ar user : Ns Ar pass Authenticate as @@ -187,6 +193,12 @@ and blue to clients. .It Fl w Ar pass , Cm pass = Ar pass Log in with the server password .Ar pass . +. +.It Fl x +Prompt for a password +and output a hash +for use with +.Fl W . .El . .Pp diff --git a/state.c b/state.c index 421c23f..a0336dc 100644 --- a/state.c +++ b/state.c @@ -49,7 +49,7 @@ void stateLogin( for (size_t i = 0; auth[i]; ++i) { plain[1 + i] = (auth[i] == ':' ? 0 : auth[i]); } - plainBase64 = malloc(base64Size(sizeof(plain))); + plainBase64 = malloc(BASE64_SIZE(sizeof(plain))); if (!plainBase64) err(EX_OSERR, "malloc"); base64(plainBase64, plain, sizeof(plain)); serverFormat("CAP REQ :sasl\r\n"); -- cgit 1.4.1