summaryrefslogtreecommitdiffstats
path: root/auth/shadow.lua
blob: 3a4a534376319fc5390b4f1a5cb20a39599613fd (plain)
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

local posix = require('posix')
local db = {}

db.file = "/etc/shadow"
db.fields = { 'name', 'passwd', 'lastchanged', 'minimum', 'maximum', 'warn', 'inactive', 'expire', 'dummy' }

function db.splitent(line)
	local ent = {}
	local i = 1
	for value in string.gmatch(line or "", "([^:]*):?") do
		ent[db.fields[i]] = value
		i = i + 1
	end
	return ent
end

function db.getent(username)
	local f = io.open(db.file)
	if f == nil then
		return nil
	end
	for line in f:lines() do
		local ent = db.splitent(line)
		if ent.name == username then
			f:close()
			return ent
		end
	end
	f:close()
	return nil, db.file..": user '"..tostring(username).."' not found"
end

function db.verify_passwd(cleartext, pwhash)
	--[[
	from man crypt(3):

	If  salt is a character string starting with the characters "$id$" fol-
	lowed by a string terminated by "$":

	      $id$salt$encrypted

	then instead of using the DES machine,  id  identifies  the  encryption
	method  used  and  this  then  determines  how the rest of the password
	string is interpreted.  The following values of id are supported:

	      ID  | Method
	      ---------------------------------------------------------
	      1   | MD5
	      2a  | Blowfish (not in mainline glibc; added in some
		  | Linux distributions)
	      5   | SHA-256 (since glibc 2.7)
	      6   | SHA-512 (since glibc 2.7)
	]]--
	local algo_salt, hash = string.match(pwhash, "^(%$%d%$[a-zA-Z0-9./]+%$)(.*)")
	local userhash = posix.crypt(cleartext, algo_salt)
	print("user hash:", userhash)
	print("db hash:", pwhash)
	return (pwhash == userhash)
end

function db.authenticate(username, cleartextpw)
	local ent = db.getent(username)
	if ent == nil then
		return nil, tostring(username)..": no such user"
	end
	return db.verify_passwd(cleartextpw, ent.passwd)
end

return db