Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.*.sw?
.lock-wscript
build
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
0.2.0 ():
* Node.js v0.8 support
* async crypt

0.1.3 (Tue Nov 8 14:50:59 MYT 2011):
* Node.js v0.6 support, fixes issue #3
* Updated demos, fixed miscellaneos typos
Expand Down
23 changes: 23 additions & 0 deletions binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"targets": [
{
"target_name": "unixlib",
"include_dirs": [ "security/pam_appl.h","crypt.h" ],
"direct_dependent_settings": {
"linkflags": [ "-lpam", "-lcrypt" ]
},
'link_settings': {
'libraries': ["-lpam", "-lcrypt"],
},

"conditions": [
[ "OS=='win'", {

}, { # OS != win
"cflags": [ "-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall" ]
}
] ],
"sources": [ "unixlib.cc" ]
}
]
}
2 changes: 1 addition & 1 deletion demo/flock.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var fs = require("fs");
var unixlib = require("../build/Release/unixlib");
var unixlib = require("../build/Release/unixlib.node");
var filename = "/tmp/flock.example";

// Let's try flocking
Expand Down
2 changes: 1 addition & 1 deletion demo/mkstemp.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var unixlib = require("../build/Release/unixlib");
var unixlib = require("../build/Release/unixlib.node");
var goodstrtemplate = "/tmp/mkstempXXXXXX";
var badstrtemplate = "/tmp/mkstempXXX";

Expand Down
2 changes: 1 addition & 1 deletion demo/pam.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var unixlib = require("../build/Release/unixlib");
var unixlib = require("../build/Release/unixlib.node");

// Change accordingly or write your own.
var service = "system-auth";
Expand Down
17 changes: 17 additions & 0 deletions demo/testcrypt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var unixlib = require("../build/Release/unixlib.node");


var res = unixlib.crypt("testpasswd");
console.log("without salt : ",res);

res = unixlib.crypt("testpasswd","12");
console.log("with salt : ",res);

// async call has unpredictable results here
// TODO: fix bugs in cc impl
unixlib.cryptAsync("testpasswd","12",function(){
console.log("with salt : ", arguments);
});
unixlib.cryptAsync("testpasswd",function(){
console.log("without salt : ",arguments);
});
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
{
"name" : "unixlib",
"version" : "v0.1.3",
"description" : "Native Linux utilities for Node.js, currently PAM authentication, flock() and mkstemp",
"version" : "v0.2.0",
"description" : "Native Linux utilities for Node.js, currently PAM authentication, flock(), mkstemp and crypt()",
"homepage" : "https://github.com/ditesh/node-unixlib",
"keywords": ["linux", "flock", "pam", "authentication", "unix"],
"keywords": ["linux", "flock", "pam", "authentication", "unix","crypt"],
"author" : {
"name" : "Ditesh Shashikant Gathani",
"email" : "ditesh@gathani.org",
"url" : "http://ditesh.gathani.org/blog/"
},
"contributors": [
{ "name": "Nicolas Karageuzian", "email": "nico@karageuzian.com" }
],
"repository" : { "type" : "git", "url" : "https://github.com/ditesh/node-unixlib.git" },
"scripts" : {
"preinstall" : "node-waf configure && node-waf build",
"preinstall" : "node-gyp configure && node-gyp build",
"preuninstall" : "rm -r build/*"
},
"main" : "build/Release/unixlib.node"
Expand Down
129 changes: 129 additions & 0 deletions unixlib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
#include <stdlib.h>
#include <sys/file.h>
#include <stdio.h>
#include <crypt.h>
#include <security/pam_appl.h>

#ifndef NODE_MAX_SALT_LEN
#define NODE_MAX_SALT_LEN 2
#endif

#define REQ_FUN_ARG(I, VAR) \
if (args.Length() <= (I) || !args[I]->IsFunction()) \
return ThrowException(Exception::TypeError( \
Expand All @@ -25,6 +30,10 @@ static int AfterFlock(eio_req *);
static Handle<Value> PAMAuthAsync(const Arguments&);
static void PAMAuth(eio_req *);
static int AfterPAMAuth(eio_req *);
Handle<Value> CryptAsync(const Arguments&);
Handle<Value> CryptSync(const Arguments&);
void Crypt(eio_req *);
int AfterCrypt(eio_req *);
extern "C" void init(Handle<Object>);

extern "C" {
Expand Down Expand Up @@ -85,6 +94,13 @@ struct pam_baton {
const char *password;
Persistent<Function> cb;
};
struct crypt_baton {
char *passwd;
char *salt;
char *result;
Persistent<Function> cb;
};


static Handle<Value> MkstempAsync(const Arguments& args) {

Expand Down Expand Up @@ -165,6 +181,80 @@ static Handle<Value> PAMAuthAsync(const Arguments& args) {

}

Handle<Value> CryptSync(const Arguments& args) {
HandleScope scope;
const char *usage = "usage: cryptSync(password [, salt ])";
char salt[NODE_MAX_SALT_LEN + 1];
salt[0] = salt[NODE_MAX_SALT_LEN] = '\0';
bool salt_def = false;
bool valid_call = false;

strncpy(salt, "$1$", NODE_MAX_SALT_LEN);
if (args.Length() == 1) {
valid_call = true;
}
if (args.Length() == 2) {
valid_call = true;
salt_def = true;
}
if (!valid_call)
return ThrowException(Exception::Error(String::New(usage)));

String::Utf8Value password(args[0]);
if (salt_def) {
String::Utf8Value salt_arg(args[1]);
strncpy(salt, ToCString(salt_arg), NODE_MAX_SALT_LEN);
}
char *result = crypt(ToCString(password),salt);

return scope.Close(String::New(result));
}

Handle<Value> CryptAsync(const Arguments& args) {

HandleScope scope;
const char *usage = "usage: crypt(password [, salt ], callback)";
char salt[NODE_MAX_SALT_LEN + 1];
//Local<Value> salt_def = Local<Value>::New(Boolean::New(false));
bool salt_def = false;
bool valid_call = false;
int cbid = 2;
salt[0] = salt[NODE_MAX_SALT_LEN] = '\0';
strncpy(salt, "$1$", NODE_MAX_SALT_LEN);
if (args.Length() == 2) {
valid_call = true;
cbid = 1;
}
if (args.Length() == 3) {
valid_call = true;
salt_def = true;
cbid = 2;
}
if (!valid_call)
return ThrowException(Exception::Error(String::New(usage)));

REQ_FUN_ARG(cbid, cb);

crypt_baton *baton = new crypt_baton();
baton->result = false;

String::Utf8Value password(args[0]);
if (salt_def) {
String::Utf8Value salt_arg(args[1]);
strncpy(salt, ToCString(salt_arg), NODE_MAX_SALT_LEN);
}
baton->salt = strdup(salt);

baton->passwd = strdup(ToCString(password));

baton->cb = Persistent<Function>::New(cb);

eio_custom(Crypt, EIO_PRI_DEFAULT, AfterCrypt, baton);
ev_ref(EV_DEFAULT_UC);
return scope.Close(Undefined());

}

static void Mkstemp(eio_req *req) {

struct mkstemp_baton * baton = (struct mkstemp_baton *)req->data;
Expand Down Expand Up @@ -203,6 +293,15 @@ static void PAMAuth(eio_req *req) {
if (retval == PAM_SUCCESS)
baton->result = true;

}
void Crypt(eio_req *req) {

struct crypt_baton* baton = (struct crypt_baton*) req->data;
//struct crypt_data buffer;
char *passwd = strdup(baton->passwd);
char *salt = strdup(baton->salt);
baton->result = crypt(passwd, salt);

}

static int AfterMkstemp(eio_req *req) {
Expand Down Expand Up @@ -288,11 +387,41 @@ static int AfterPAMAuth(eio_req *req) {

}

int AfterCrypt(eio_req *req) {

HandleScope scope;
ev_unref(EV_DEFAULT_UC);
crypt_baton *baton = static_cast<crypt_baton *>(req->data);

Local<Value> argv[1];

if (baton->result) {
argv[0] = Local<Boolean>::New(True());
argv[1] = String::New(baton->result);
}
else
argv[0] = Local<Boolean>::New(False());

TryCatch try_catch;

baton->cb->Call(Context::GetCurrent()->Global(), 2, argv);

if (try_catch.HasCaught())
FatalException(try_catch);

baton->cb.Dispose();
delete baton;
return 0;

}

extern "C" void init (Handle<Object> target) {

HandleScope scope;
NODE_SET_METHOD(target, "flock", FlockAsync);
NODE_SET_METHOD(target, "pamauth", PAMAuthAsync);
NODE_SET_METHOD(target, "mkstemp", MkstempAsync);
NODE_SET_METHOD(target, "cryptAsync", CryptAsync);
NODE_SET_METHOD(target, "crypt", CryptSync);

}
5 changes: 3 additions & 2 deletions wscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
srcdir = '.'
blddir = 'build'
VERSION = '0.0.1'
VERSION = '0.2.0'

def set_options(opt):
opt.tool_options('compiler_cxx')
Expand All @@ -9,7 +9,8 @@ def configure(conf):
conf.check_tool('compiler_cxx')
conf.check_tool('node_addon')
conf.check(header_name="security/pam_appl.h", mandatory=True)
conf.env.LINKFLAGS = ["-lpam"]
conf.check(header_name="crypt.h", mandatory=True)
conf.env.LINKFLAGS = ["-lpam","-lcrypt"]

def build(bld):
obj = bld.new_task_gen('cxx', 'shlib', 'node_addon')
Expand Down