Inhaltsverzeichnis

Lua

Lua wurde 1993 von der Computer Graphics Technology Group der Päpstlichen Katholischen Universität von Rio de Janeiro in Brasilien entwickelt. Lua ist freie Software und wurde bis zur Version 4 unter einer eigenen BSD-Lizenz veröffentlicht, seit Version 5 unter der MIT-Lizenz.

Lua kann sowohl zur Erstellung eigenständiger Programme verwendet werden als auch als eingebettete Sprache dienen.

Einführung

lua_start.lua
local parameter = "root";
print("Parameter: ", parameter)
 
local pfaddatei = ("/usr/bin/id " .. parameter)
print("Kammando: ", pfaddatei)
 
datei = assert (io.popen (pfaddatei))
print ("Temp-Datei-Händler: ", datei)
 
ausgabe = datei:read ("*l") -- read one line
print ("Rückgabewert: ", ausgabe)
 
for line in io.lines(pfaddatei) do print (line) end
 
local myFile = io.open( pfaddatei, "r+b" )
dateigroesse = (myFile:seek("end"))
print ("die Datei ist so groß: " .. dateigroesse)
> lua lua_start.lua
Parameter:      root
Kammando:       /usr/bin/id root
Temp-Datei-Händler:     file (0x1657270)
Rückgabewert:   uid=0(root) gid=0(root) groups=0(root)

Argumentenübergabe

/tmp/test_args.lua
print('eigener Skriptname wird ausgegeben:')
print(arg[0])
print()
print('erstes Argument wird ausgegeben:')
print(arg[1])
print()
print('alle Argumente werden ausgegeben:')
print(...)

Beispiel:

> lua /tmp/test_args.lua 0 1 2 3 4
eigener Skriptname wird ausgegeben:
/tmp/test.lua

erstes Argument wird ausgegeben:
0

alle Argumente werden ausgegeben:
0       1       2       3       4

Datenbankzugriff

/tmp/test_db.lua
local dbConf = {}
dbConf.database = 'mitglieder'
dbConf.username = 'fritz'
dbConf.passwort = 'geheim'
dbConf.hostname = '10.234.123.45'
dbConf.port = "3306"
 
require("mime")
luasql = require("luasql.mysql")
 
local env = assert(luasql.mysql())
local con = assert(env:connect ( dbConf.database, dbConf.username, dbConf.passwort, dbConf.hostname, dbConf.port ))
 
 
function rows (connection, sql_statement)
  local cursor = assert (connection:execute (sql_statement))
  return function ()
    return cursor:fetch()
  end 
end
 
 
for id, name, address in rows (con, "select * from dealer_logins") do
        -- "id" und "name" sind Spaltennamen in der Tabelle
        print (string.format ("%s: %s", id, name))
end
 
 
con:close()
env:close()

ausführen

> lua /tmp/test_db.lua

LighttpD + Lua

Voraussetzungen:

/etc/lighttpd/conf-enabled/99-lua.conf
$HTTP["host"] =~ "10.10.69.69" {
                magnet.attract-physical-path-to = ( "/etc/lighttpd/test.lua" )
}
/etc/lighttpd/test.lua
datei = io.open("/tmp/lua_env.txt","w")
datei:write("uri.authority: ", string.format('%s', lighty.env["uri.authority"]), "\n")
datei:write("uri.path: ", string.format('%s', lighty.env["uri.path"]), "\n")
datei:write("uri.path-raw: ", string.format('%s', lighty.env["uri.path-raw"]), "\n")
datei:write("uri.scheme: ", string.format('%s', lighty.env["uri.scheme"]), "\n")
datei:write("physical.path: ", string.format('%s', lighty.env["physical.path"]), "\n")
datei:write("physical.rel-path: ", string.format('%s', lighty.env["physical.rel-path"]), "\n")
datei:write("physical.doc-root: ", string.format('%s', lighty.env["physical.doc-root"]), "\n")
datei:close()
> cat /tmp/lua_env.txt
uri.authority: 10.123.234.56
uri.path: /test.php
uri.path-raw: /test.php
uri.scheme: https
physical.path: /var/www/test.php
physical.rel-path: /test.php
physical.doc-root: /var/www/

MySQL-Auth mit LighttpD

Leider gibt es für LighttpD kein Modul um die Passwortabfrage auf eine DB zu realisieren, wie man es vom Apache kennt. Um eine derartige Funktionalität in LighttpD umzusetzten, muss man ein entsprechendes LUA-Skript einbinden.

Die Dateien, die Passwörter enthalten, dürfen nicht für die Welt lesbar sein!

> chown 33:33 /etc/lighttpd/sha512crypt.php /etc/lighttpd/mysql_auth.lua
> chmod 0640 /etc/lighttpd/sha512crypt.php /etc/lighttpd/mysql_auth.lua

Die individuellen Daten sehen wie folgt aus, sie können (und müssen) den persönlichen Gegebenheiten angepasst werden:

/etc/lighttpd/conf-enabled/20-mysql_auth.conf
# bei Zugriffen auf diesen Web-Server soll das LUA-Skript aktiviert werden
$HTTP["host"] =~ "10.10.69.69" {
                magnet.attract-physical-path-to = ( "/etc/lighttpd/mysql_auth.lua" )
}
/etc/lighttpd/mysql_auth.lua
-- nur "/geheim.php" soll passwortgeschützt sein
if ( string.format('%s', lighty.env["uri.path"]) == "/geheim.php" ) then
 
-- Passwörter dürfen nur per https eingegeben werden
if (lighty.env["uri.scheme"] == "http") then
    lighty.header["Location"] = "https://" .. lighty.env["uri.authority"] .. lighty.env["request.uri"]
    return 302
end
 
--[[
    Config Variables
]]
local dbConf = {}
dbConf.database = 'pwdb'
dbConf.username = 'fritz'
dbConf.passwort = 'geheim'
dbConf.hostname = '10.123.45.67'
dbConf.port = "3306"
 
--[[
    Requires
]]
 
-- Debian package: liblua5.1-socket2
 
-- required for Base64 De-/encoding. See: http://w3.impa.br/~diego/software/luasocket/home.html
require("mime")
 
-- Debian package: liblua5.1-sql-mysql-2
 
-- Lua Mysql Driver
luasql = require("luasql.mysql")
 
--[[
    Function to send HTTP-Auth request
]]
 
function doAuth()
    lighty.header["WWW-Authenticate"] = string.format('Basic realm="%s"', lighty.env["uri.authority"])
    return 401
end
 
--[[
    Function to check Auth Creds against MySQL Database
]]
local env = assert(luasql.mysql())
local con = assert(env:connect (
        dbConf.database
        ,dbConf.username
        ,dbConf.passwort
        ,dbConf.hostname
        ,dbConf.port
))
 
function checkAuthMySQL(user,pass)
        local res = con:execute(string.format([[
                SELECT *
                FROM `pwtab`
                WHERE `name` = '%s'
                AND `passwort` = '%s'
                ]], user, pass)
        )
 
        -- Die Tabelle wir in ein Array gespeichert
        local row = res:fetch ({}, "a")
 
        -- print(type(row))
 
 
        -- close everything
        -- res:close()  -- already closed because all the result set was consumed
        con:close()
        -- env:close()
 
 
        if (not row) then
                return false
        else
                lighty.req_env['REMOTE_USER'] = user
                return true
        end
end
 
 
-- MAIN
 
--[[
    Check for Authorization Header
    and force Basic Auth if not set.
]]
 
if (not lighty.request.Authorization) then
    return doAuth()
end
 
--[[
    Header found: check string for "Basic" and base64 encoded username & password
    - upb = User Password Base64 encoded
]]
_, _, upb = string.find(lighty.request.Authorization, "^Basic%s+(.+)$")
up = mime.unb64(upb) -- Base64 Decode
_, _, username, passwort = string.find(up, "^(.+):(.+)$") -- split by ":" to get username and password supplied
 
 
-- =============================================================================
-- In der DB steht das Passwort nicht im klartext drin, sondern verschlüsselt
-- deshalb muss auch der Passwort-Hash und nicht das Passwort verglichen werden.
--
-- hier wird aus dem Passwort der Passwort-Hash generiert
--
 
local kommando = ("/usr/bin/php /etc/lighttpd/sha512crypt.php " .. passwort)
ausgabe = assert (io.popen (kommando))
pwhash = ausgabe:read ("*l") -- read one line
 
-- =============================================================================
 
if (not checkAuthMySQL(username, pwhash)) then
        return doAuth()
end
 
 
end
 
-- return nothing to proceed normal operation
return

Leider gibt es nur für eine SHA256-Verschlüsselung eine native LUA-Umsetzung. Für SHA512 müssen wir uns eines externen Programmes (in diesem Fall ein PHP-Skript) bedienen.

/etc/lighttpd/sha512crypt.php
<?php
$salt = 'tuqu7Cua_ox1jieW';
echo hash('sha512', $salt . $argv[1]);
?>