diff options
author | Calvin Morrison <calvin@pobox.com> | 2025-09-03 21:15:36 -0400 |
---|---|---|
committer | Calvin Morrison <calvin@pobox.com> | 2025-09-03 21:15:36 -0400 |
commit | 49fa5aa2a127bdf8924d02bf77e5086b39c7a447 (patch) | |
tree | 61d86a7705dacc9fddccc29fa79d075d83ab8059 /server/_build/default/lib/bcrypt/c_src/bcrypt_port.c |
Diffstat (limited to 'server/_build/default/lib/bcrypt/c_src/bcrypt_port.c')
-rw-r--r-- | server/_build/default/lib/bcrypt/c_src/bcrypt_port.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/server/_build/default/lib/bcrypt/c_src/bcrypt_port.c b/server/_build/default/lib/bcrypt/c_src/bcrypt_port.c new file mode 100644 index 0000000..7cafb2b --- /dev/null +++ b/server/_build/default/lib/bcrypt/c_src/bcrypt_port.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2011 Hunter Morris <hunter.morris@smarkets.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "erl_blf.h" +#include "ei.h" + +#define dec_int16(s) ((((unsigned char*)(s))[0] << 8) | \ + (((unsigned char*)(s))[1])) + +#define BUFSIZE (1 << 16) +#define CMD_SALT 0 +#define CMD_HASHPW 1 + +#define DATASIZE 1024 + +extern int ts_bcrypt(char *, const char *, const char *); +extern void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t); + + +static void +fail(int place) { + fprintf(stderr, "Something went wrong %d\n", place); + exit(1); +} + +/* These methods came from the Erlang port command tutorial: + * http://www.erlang.org/doc/tutorial/c_port.html#4.2 + */ +static int +read_buf(int fd, char *buf, int len) +{ + int i, got = 0; + do { + if ((i = read(fd, buf+got, len-got)) <= 0) { + if (i == 0) return got; + if (errno != EINTR) + fail(-1); + i = 0; + } + got += i; + } while (got < len); + return (len); +} + +static int +read_cmd(char *buf) +{ + int len; + if (read_buf(0, buf, 2) != 2) + return 0; + len = dec_int16(buf); + if (read_buf(0, buf, len) != len) + return 0; + return 1; +} + +static void +write_buf(int fd, const char *buf, int len) +{ + int i; + int done = 0; + + do { + if ((i = write(fd, buf+done, len-done)) < 0) { + if (errno != EINTR) + fail(-2); + i = 0; + } + done += i; + } while (done < len); +} + +static void +write_cmd(const char *buf, int len) +{ + unsigned char li; + + li = (len >> 8) & 0xff; + write_buf(1, (char *) &li, 1); + li = len & 0xff; + write_buf(1, (char *) &li, 1); + write_buf(1, buf, len); +} + +static void +process_reply(int cmd, const char *result) +{ + ei_x_buff res_buf; + + if (ei_x_new_with_version(&res_buf) != 0) + fail(-10); + if (ei_x_encode_tuple_header(&res_buf, 2) != 0) + fail(-11); + if (ei_x_encode_long(&res_buf, (long) cmd) != 0) + fail(-12); + if (ei_x_encode_binary(&res_buf, result, (long) strlen( (const char *) result)) != 0) + fail(-13); + + write_cmd(res_buf.buff, res_buf.index); + + if (ei_x_free(&res_buf) != 0) + fail(-14); +} + +static void +process_error_reply(int cmd, const char *error) +{ + ei_x_buff res_buf; + + if (ei_x_new_with_version(&res_buf) != 0) + fail(-20); + if (ei_x_encode_tuple_header(&res_buf, 2) != 0) + fail(-21); + if (ei_x_encode_long(&res_buf, (long) cmd) != 0) + fail(-22); + if (ei_x_encode_atom(&res_buf, error) != 0) + fail(-23); + + write_cmd(res_buf.buff, res_buf.index); + + if (ei_x_free(&res_buf) != 0) + fail(-24); +} + +static void +process_encode_salt( + int salt_size, + char *salt, + long rounds) +{ + char encoded_salt[64]; + + if (16 != salt_size) { + process_error_reply(CMD_SALT, "invalid_salt_length"); + } else if (rounds < 4 || rounds > 31) { + process_error_reply(CMD_SALT, "invalid_rounds"); + } else { + memset(encoded_salt, 0, 64); + encode_salt(encoded_salt, (u_int8_t *) salt, (u_int16_t) salt_size, (u_int8_t) rounds); + process_reply(CMD_SALT, encoded_salt); + } +} + +static void +process_hashpw( + int password_size, + char *password, + int salt_size, + char *salt) +{ + char encrypted[DATASIZE+1]; + + memset(encrypted, 0, DATASIZE+1); + if (ts_bcrypt(encrypted, password, salt)) { + process_error_reply(CMD_HASHPW, "invalid_salt"); + } else { + process_reply(CMD_HASHPW, encrypted); + } +} + +static void +process_command(char *buf) +{ + int index = 0; + int version = 0; + int arity = 0; + int type; + long cmd; + long len; + long rounds; + int data_size; + char data[DATASIZE+1]; + int salt_size; + char salt[DATASIZE+1]; + + memset(data, 0, DATASIZE+1); + memset(salt, 0, DATASIZE+1); + + if (ei_decode_version(buf, &index, &version) != 0) + fail(1); + + // Three tuple: {Cmd, Port, Data} + if (ei_decode_tuple_header(buf, &index, &arity) != 0) + fail(2); + if (arity != 2) + fail(3); + if (ei_decode_long(buf, &index, &cmd) != 0) + fail(4); + + // All commands have a two tuple for Data + if (ei_decode_tuple_header(buf, &index, &arity) != 0) + fail(6); + if (arity != 2) + fail(7); + + // First arg is always a binary + if (ei_get_type(buf, &index, &type, &data_size) != 0) + fail(8); + if (type != ERL_BINARY_EXT) + fail(9); + if (data_size < 0 || data_size > DATASIZE) + fail(10); + if (ei_decode_binary(buf, &index, data, &len) != 0) + fail(11); + + switch (cmd) { + case CMD_HASHPW: + // Two tuple: {Pass, Salt} + if (ei_get_type(buf, &index, &type, &salt_size) != 0) + fail(12); + if (type != ERL_BINARY_EXT) + fail(13); + if (salt_size < 0 || salt_size > DATASIZE) + fail(14); + if (ei_decode_binary(buf, &index, salt, &len) != 0) + fail(15); + + process_hashpw(data_size, data, salt_size, salt); + break; + case CMD_SALT: + // Two tuple: {Csalt, LogRounds} + if (ei_decode_long(buf, &index, &rounds) != 0) + fail(16); + + process_encode_salt(data_size, data, rounds); + break; + default: + fail(17); + } +} + +static void +loop(void) +{ + char buf[BUFSIZE]; + + while (read_cmd(buf) == 1) { + process_command(buf); + } +} + +int +main(int argc, char *argv[]) +{ + ei_init(); + loop(); + return 0; +} |