forked from hexparrot/mineos-node
-
Notifications
You must be signed in to change notification settings - Fork 3
/
auth.js
151 lines (136 loc) · 4.14 KB
/
auth.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
var async = require('async');
var auth = exports;
auth.authenticate_shadow = function(user, plaintext, callback) {
var hash = require('sha512crypt-node');
var fs = require('fs-extra');
function etc_shadow(inner_callback) {
// return true if error, false if auth failed, string for user if successful
var passwd = require('etc-passwd');
fs.stat('/etc/shadow', function(err, stat_info) {
if (err)
inner_callback(true);
else {
passwd.getShadow({username: user}, function(err, shadow_info) {
if (shadow_info && shadow_info.password == '!')
inner_callback(false);
else if (shadow_info) {
var password_parts = shadow_info['password'].split(/\$/);
var salt = password_parts[2];
var new_hash = hash.sha512crypt(plaintext, salt);
var passed = (new_hash == shadow_info['password'] ? user : false);
inner_callback(passed);
} else {
inner_callback(true);
}
})
}
})
}
function posix(inner_callback) {
// return true if error, false if auth failed, string for user if successful
try {
var crypt = require('apache-crypt');
var posix = require('posix');
} catch (e) {
inner_callback(true);
return;
}
try {
var user_data = posix.getpwnam(user);
if (crypt(plaintext, user_data.passwd) == user_data.passwd)
inner_callback(user);
else if (user_data) {
// the crypt hash method fails on FreeNAS so try the sha512
var password_parts = user_data.passwd.split(/\$/);
var salt = password_parts[2];
var new_hash = hash.sha512crypt(plaintext, salt);
var passed = (new_hash == user_data.passwd ? user : false);
inner_callback(passed);
} else
inner_callback(false);
} catch (e) {
inner_callback(true);
}
}
function pam(inner_callback) {
// return true if error, false if auth failed, string for user if successful
try {
var pam = require('authenticate-pam');
} catch (e) {
inner_callback(true);
return;
}
pam.authenticate(user, plaintext, function(err) {
if (err)
inner_callback(false);
else
inner_callback(user);
})
}
pam(function(pam_passed) {
//due to the stack of different auths, a false if auth failed is largely ignored
if (typeof pam_passed == 'string')
callback(pam_passed);
else
etc_shadow(function(etc_passed) {
if (typeof etc_passed == 'string')
callback(etc_passed)
else
posix(function(posix_passed) {
if (typeof posix_passed == 'string')
callback(posix_passed)
else
callback(false);
})
})
})
}
auth.test_membership = function(username, group, callback) {
var passwd = require('etc-passwd');
var userid = require('userid');
var membership_valid = false;
var gg = passwd.getGroups()
.on('group', function(group_data) {
if (group == group_data.groupname)
try {
if (group_data.users.indexOf(username) >= 0 || group_data.gid == userid.gids(username)[0])
membership_valid = true;
} catch (e) {}
})
.on('end', function() {
callback(membership_valid);
})
}
auth.verify_ids = function(uid, gid, callback) {
var passwd = require('etc-passwd');
var uid_present = false;
var gid_present = false;
async.series([
function(cb) {
var gg = passwd.getUsers()
.on('user', function(user_data) {
if (user_data.uid == uid)
uid_present = true;
})
.on('end', function() {
if (!uid_present)
cb('UID ' + uid + ' does not exist on this system');
else
cb();
})
},
function(cb) {
var gg = passwd.getGroups()
.on('group', function(group_data) {
if (group_data.gid == gid)
gid_present = true;
})
.on('end', function() {
if (!gid_present)
cb('GID ' + gid + ' does not exist on this system');
else
cb();
})
}
], callback)
}