diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/auth.c | 39 | ||||
| -rw-r--r-- | src/auth.h | 8 | ||||
| -rw-r--r-- | src/globals.h | 4 | ||||
| -rw-r--r-- | src/main.c | 8 | ||||
| -rw-r--r-- | src/server.c | 28 | ||||
| -rw-r--r-- | src/server.h | 2 |
6 files changed, 61 insertions, 28 deletions
@@ -31,36 +31,33 @@ static char *hash_pass_hex(const char *pass, const char *salt) { size_t pass_len = strlen(pass); - char *salted = gcry_malloc_secure(pass_len + SALT_LEN + 1); + unsigned char *salted = malloc(pass_len + SALT_LEN + 1); memcpy(salted, salt, SALT_LEN); memcpy(salted + SALT_LEN, pass, pass_len); salted[pass_len + SALT_LEN] = '\0'; - unsigned int hash_len = gcry_md_get_algo_dlen(ALGO); - unsigned char *hash = gcry_malloc_secure(hash_len); + unsigned char hash[AUTH_HASHLEN]; - gcry_md_hash_buffer(ALGO, hash, salted, pass_len + SALT_LEN); + SHA512(salted, pass_len + SALT_LEN, hash); - unsigned char *tmp = gcry_malloc_secure(hash_len); + unsigned char tmp[AUTH_HASHLEN]; /* now hash the hash half a million times to slow things down */ for(int i = 0; i < HASH_ITERS - 1; ++i) { - memcpy(tmp, hash, hash_len); - gcry_md_hash_buffer(ALGO, hash, tmp, hash_len); + memcpy(tmp, hash, AUTH_HASHLEN); + AUTH_HASHFUNC(tmp, AUTH_HASHLEN, hash); } - gcry_free(tmp); + memset(tmp, 0, sizeof(tmp)); memset(salted, 0, pass_len + SALT_LEN + 1); - gcry_free(salted); + free(salted); /* convert to hex */ - char *hex = malloc(hash_len * 2 + 1); + char *hex = malloc(AUTH_HASHLEN * 2 + 1); char *ptr = hex; - for(unsigned int i = 0; i < hash_len; ++i, ptr += 2) + for(unsigned int i = 0; i < AUTH_HASHLEN; ++i, ptr += 2) snprintf(ptr, 3, "%02x", hash[i]); - hex[hash_len * 2] = '\0'; - - gcry_free(hash); + hex[AUTH_HASHLEN * 2] = '\0'; return hex; } @@ -87,6 +84,8 @@ static void add_user_internal(const char *name, const char *pass, int authlevel) userdata.priv = authlevel; + userdata.last_login = time(0); + memcpy(userdata.salt, salt, sizeof(salt)); userdb_request_add(&userdata); @@ -121,7 +120,6 @@ bool auth_user_add(const char *user2, const char *pass2, int level) return false; } - /* add user to end of temp file */ add_user_internal(user, pass, level); free(user); @@ -196,10 +194,17 @@ struct userdata_t *auth_check(const char *name2, const char *pass2) if(data) { debugf("auth module: user %s found\n", name2); - char *new_hash_hex = hash_pass_hex(pass, salt); /* hashes are in HEX to avoid the Trucha bug */ - bool success = !memcmp(new_hash_hex, hash, strlen(hash)); + char *new_hash_hex = hash_pass_hex(pass, salt); + + bool success = true; + /* constant-time comparison to a timing attack */ + for(int i = 0; i < AUTH_HASHLEN; ++i) + { + if(new_hash_hex[i] != hash[i]) + success = false; + } free(new_hash_hex); @@ -21,10 +21,10 @@ #include "globals.h" #define SALT_LEN 12 -#define ALGO GCRY_MD_SHA512 -#define AUTH_HASHLEN (512/8) -#define HASH_ITERS 500000 -//#define HASH_ITERS 1 +#define AUTH_HASHLEN SHA512_DIGEST_LENGTH +#define AUTH_HASHFUNC SHA512 +//#define HASH_ITERS 500000 +#define HASH_ITERS 1 struct authinfo_t { bool success; diff --git a/src/globals.h b/src/globals.h index 141b362..9fb2e5d 100644 --- a/src/globals.h +++ b/src/globals.h @@ -22,7 +22,8 @@ #define _GNU_SOURCE #include <ev.h> -#include <gcrypt.h> +#include <openssl/sha.h> +#include <openssl/opensslv.h> #include <arpa/inet.h> #include <assert.h> @@ -33,6 +34,7 @@ #include <netdb.h> #include <netinet/in.h> #include <poll.h> +#include <pwd.h> #include <signal.h> #include <stdarg.h> #include <stdbool.h> diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..3de3d89 --- /dev/null +++ b/src/main.c @@ -0,0 +1,8 @@ +#include "globals.h" + +#include "server.h" + +int main(int argc, char *argv[]) +{ + server_main(argc, argv); +} diff --git a/src/server.c b/src/server.c index c8fa8c3..4430f7e 100644 --- a/src/server.c +++ b/src/server.c @@ -337,16 +337,14 @@ static void init_signals(void) error("sigaction"); } -int main(int argc, char *argv[]) +int server_main(int argc, char *argv[]) { - debugf("*** Starting NetCosm "NETCOSM_VERSION" (libev %d.%d, libgcrypt "GCRYPT_VERSION") ***\n", - EV_VERSION_MAJOR, EV_VERSION_MINOR); + debugf("*** Starting NetCosm %s (libev %d.%d, %s) ***\n", + NETCOSM_VERSION, EV_VERSION_MAJOR, EV_VERSION_MINOR, OPENSSL_VERSION_TEXT); assert(ev_version_major() == EV_VERSION_MAJOR && ev_version_minor() >= EV_VERSION_MINOR); - assert(!strcmp(GCRYPT_VERSION, gcry_check_version(GCRYPT_VERSION))); - if(argc != 2) port = PORT; else @@ -372,9 +370,27 @@ int main(int argc, char *argv[]) struct ev_loop *loop = EV_DEFAULT; - /* we initialize signals after creating the default event loop */ + /* we initialize signals after creating the default event loop + * because libev grabs SIGCHLD */ init_signals(); + /* drop root privileges */ + if(getuid() == 0) + { + struct passwd *nobody = getpwnam("nobody"); + if(!nobody) + error("couldn't get unprivileged user"); + if(setgid(nobody->pw_gid) != 0) + error("setgid"); + if(setuid(nobody->pw_uid) != 0) + error("setuid"); + if(setuid(0) >= 0) + error("failed to drop root"); + if(access(USERFILE, R_OK) >= 0) + error("failed to drop root"); + debugf("Dropped root privileges.\n"); + } + ev_io server_watcher; ev_io_init(&server_watcher, new_connection_cb, server_socket, EV_READ); ev_set_priority(&server_watcher, EV_MAXPRI); diff --git a/src/server.h b/src/server.h index 21f2076..d7b7419 100644 --- a/src/server.h +++ b/src/server.h @@ -44,3 +44,5 @@ struct child_data { extern volatile int num_clients; extern void *child_map; extern bool are_child; + +int server_main(int argc, char *argv[]); |