Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

cracklib is not threadsafe O_o

Add locks around calls into libcrack to avoid nasty segfault.
  • Loading branch information...
commit d8c53eef727ea44429485f721e2264ee85ccc54c 1 parent f901b8c
@msantos authored
Showing with 36 additions and 4 deletions.
  1. +3 −3 README
  2. +33 −1 c_src/cerck.c
View
6 README
@@ -23,9 +23,9 @@ ok
*** WARNING ***
-Do NOT call check/2 without checking the .pwi, .pwd and .hwm files exit
-for the passed in dictionary path. cracklib calls exit(-1) if these
-files do not exist. This will cause the Erlang VM to exit.
+Do NOT call check/2 without ensuring the dictionnary files (.pwi, .pwd
+and .hwm extensions) exist. If the files do not exist, cracklib calls
+exit(-1), causing the Erlang VM to exit.
TODO
View
34 c_src/cerck.c
@@ -38,32 +38,62 @@ static ERL_NIF_TERM atom_error;
static ERL_NIF_TERM atom_enomem;
static ERL_NIF_TERM string_dictpath;
+/* cracklib is not thread safe */
+typedef struct {
+ ErlNifMutex *lock;
+} PRIV;
+
static ERL_NIF_TERM error_tuple(ErlNifEnv *env, char *err);
static int
load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info)
{
+ PRIV *priv = NULL;
+
atom_ok = enif_make_atom(env, "ok");
atom_error = enif_make_atom(env, "error");
atom_enomem = enif_make_atom(env, "enomem");
string_dictpath = enif_make_string(env, GetDefaultCracklibDict(), ERL_NIF_LATIN1);
+ priv = (PRIV *)enif_alloc(sizeof(PRIV));
+ if (priv == NULL)
+ return (-1);
+
+ priv->lock = enif_mutex_create("cerck_lock");
+ if (priv->lock == NULL)
+ return (-1);
+
+ *priv_data = priv;
+
return (0);
}
+ void
+unload(ErlNifEnv *env, void *priv_data)
+{
+ PRIV *priv = NULL;
+
+ priv = (PRIV *)enif_priv_data(env);
+ enif_mutex_destroy(priv->lock);
+ enif_free(priv);
+}
/* 1: password, 2: dictpath */
static ERL_NIF_TERM
nif_check(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
+ PRIV *priv = NULL;
+
ErlNifBinary passwd;
ErlNifBinary path;
char *err = NULL;
+ priv = (PRIV *)enif_priv_data(env);
+
if (!enif_inspect_iolist_as_binary(env, argv[0], &passwd))
return enif_make_badarg(env);
@@ -79,7 +109,9 @@ nif_check(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
passwd.data[passwd.size-1] = '\0';
path.data[path.size-1] = '\0';
+ enif_mutex_lock(priv->lock);
err = (char *)FascistCheck((char *)passwd.data, (char *)path.data);
+ enif_mutex_unlock(priv->lock);
enif_release_binary(&passwd);
enif_release_binary(&path);
@@ -107,6 +139,6 @@ static ErlNifFunc nif_funcs[] = {
{"dictpath", 0, nif_dictpath}
};
-ERL_NIF_INIT(cerck, nif_funcs, load, NULL, NULL, NULL)
+ERL_NIF_INIT(cerck, nif_funcs, load, NULL, NULL, unload)
Please sign in to comment.
Something went wrong with that request. Please try again.