aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/auth.c39
-rw-r--r--src/auth.h8
-rw-r--r--src/globals.h4
-rw-r--r--src/main.c8
-rw-r--r--src/server.c28
-rw-r--r--src/server.h2
6 files changed, 61 insertions, 28 deletions
diff --git a/src/auth.c b/src/auth.c
index 42af3ed..2018273 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -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);
diff --git a/src/auth.h b/src/auth.h
index b77a711..0d5293a 100644
--- a/src/auth.h
+++ b/src/auth.h
@@ -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[]);