Initial commit

This commit is contained in:
furo 2022-01-15 18:47:56 +01:00
commit ffa3b34739
7 changed files with 431 additions and 0 deletions

5
.env.template Normal file
View File

@ -0,0 +1,5 @@
# Where is the GLAuth sqlite DB located?
GLAUTH_DB=""
# Which port should the server run on?
PORT=8080

134
.gitignore vendored Normal file
View File

@ -0,0 +1,134 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
captcha.png
package-lock.json

62
README.md Normal file
View File

@ -0,0 +1,62 @@
# qwik-register
## GLAuth installation
```
git clone https://github.com/glauth/glauth.git
cd glauth
make fast
make plugins
```
## GLAuth config
```ini
[ldap]
enabled = true
listen = "0.0.0.0:3893"
[ldaps]
enabled = false
listen = "0.0.0.0:3894"
cert = "certs/server.crt"
key = "certs/server.key"
[backend]
datastore = "plugin"
plugin = "sqlite.so"
pluginhandler = "NewSQLiteHandler"
baseDN = "dc=glauth,dc=com"
database = "users.db"
nameformat = "cn"
groupformat = "ou"
```
## Pre database setup
```sql
CREATE TABLE users (
uidnumber INTEGER PRIMARY KEY autoincrement,
id INTEGER,
name TEXT NOT NULL,
primarygroup INTEGER NOT NULL,
othergroups TEXT DEFAULT '',
givenname TEXT DEFAULT '',
sn TEXT DEFAULT '',
mail TEXT DEFAULT '',
loginshell TYEXT DEFAULT '',
homedirectory TEXT DEFAULT '',
disabled SMALLINT DEFAULT 0,
passsha256 TEXT DEFAULT '',
passbcrypt TEXT DEFAULT '',
otpsecret TEXT DEFAULT '',
yubikey TEXT DEFAULT '',
custattr TEXT DEFAULT '{}');
INSERT INTO groups(name, gidnumber) VALUES('users', 0);
INSERT INTO groups(name, gidnumber) VALUES('admins', 10);
INSERT INTO groups(name, gidnumber) VALUES('root', 100);
INSERT INTO includegroups(parentgroupid, includegroupid) VALUES(10, 0);
```

93
captcha.sh Executable file
View File

@ -0,0 +1,93 @@
#!/bin/sh
# This script is an example captcha script.
# It takes the text to recognize in the captcha image as a parameter.
# It return the image binary as a result. ejabberd support PNG, JPEG and GIF.
# The whole idea of the captcha script is to let server admins adapt it to
# their own needs. The goal is to be able to make the captcha generation as
# unique as possible, to make the captcha challenge difficult to bypass by
# a bot.
# Server admins are thus supposed to write and use their own captcha generators.
# This script relies on ImageMagick.
# It is NOT compliant with ImageMagick forks like GraphicsMagick.
INPUT=$1
for n in $(od -A n -t u2 -N 48 /dev/urandom); do RL="$RL$n "; done
get_random ()
{
R=${RL%% *}
RL=${RL#* }
}
get_random
WAVE1_AMPLITUDE=$((2 + R % 5))
get_random
WAVE1_LENGTH=$((50 + R % 25))
get_random
WAVE2_AMPLITUDE=$((2 + R % 5))
get_random
WAVE2_LENGTH=$((50 + R % 25))
get_random
WAVE3_AMPLITUDE=$((2 + R % 5))
get_random
WAVE3_LENGTH=$((50 + R % 25))
get_random
W1_LINE_START_Y=$((10 + R % 40))
get_random
W1_LINE_STOP_Y=$((10 + R % 40))
get_random
W2_LINE_START_Y=$((10 + R % 40))
get_random
W2_LINE_STOP_Y=$((10 + R % 40))
get_random
W3_LINE_START_Y=$((10 + R % 40))
get_random
W3_LINE_STOP_Y=$((10 + R % 40))
get_random
B1_LINE_START_Y=$((R % 40))
get_random
B1_LINE_STOP_Y=$((R % 40))
get_random
B2_LINE_START_Y=$((R % 40))
get_random
B2_LINE_STOP_Y=$((R % 40))
#B3_LINE_START_Y=$((R % 40))
#B3_LINE_STOP_Y=$((R % 40))
get_random
B1_LINE_START_X=$((R % 20))
get_random
B1_LINE_STOP_X=$((100 + R % 40))
get_random
B2_LINE_START_X=$((R % 20))
get_random
B2_LINE_STOP_X=$((100 + R % 40))
#B3_LINE_START_X=$((R % 20))
#B3_LINE_STOP_X=$((100 + R % 40))
get_random
ROLL_X=$((R % 40))
convert -size 180x60 xc:none -pointsize 40 \
\( -clone 0 -fill white \
-stroke black -strokewidth 4 -annotate +0+40 "$INPUT" \
-stroke white -strokewidth 2 -annotate +0+40 "$INPUT" \
-roll +$ROLL_X+0 \
-wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \
-roll -$ROLL_X+0 \) \
\( -clone 0 -stroke black \
-strokewidth 1 -draw \
"line $B1_LINE_START_X,$B1_LINE_START_Y $B1_LINE_STOP_X,$B1_LINE_STOP_Y" \
-strokewidth 1 -draw \
"line $B2_LINE_START_X,$B2_LINE_START_Y $B2_LINE_STOP_X,$B2_LINE_STOP_Y" \
-wave "$WAVE2_AMPLITUDE"x"$WAVE2_LENGTH" \) \
\( -clone 0 -stroke white \
-strokewidth 2 -draw "line 0,$W1_LINE_START_Y 140,$W1_LINE_STOP_Y" \
-strokewidth 2 -draw "line 0,$W2_LINE_START_Y 140,$W2_LINE_STOP_Y" \
-strokewidth 2 -draw "line 0,$W3_LINE_START_Y 140,$W3_LINE_STOP_Y" \
-wave "$WAVE3_AMPLITUDE"x"$WAVE3_LENGTH" \) \
-flatten -crop 140x60 +repage -quality 90 -depth 8 png:-

102
index.js Normal file
View File

@ -0,0 +1,102 @@
import Database from 'better-sqlite3'
import express from 'express'
import crypto from 'crypto'
import dotenv from 'dotenv'
import { exec } from 'child_process'
dotenv.config()
const app = express()
const port = process.env.PORT
let valid = {}
let glauth = undefined
console.log(process.env)
dbInit()
app.use(express.urlencoded({
extended: true
}))
app.use(express.static('public'))
app.post('/register', (req, res) => {
// Was input sent?
if(!req.body.username)
return(res.send("No username entered!"))
if(!req.body.password)
return(res.send("No password entered!"))
if(!req.body.password)
return(res.send("No captcha entered!"))
// does the username match the requirements
if(!(/^(?=[a-zA-Z0-9]{2,20}$).*$/.test(req.body.username)))
return(res.send("Username does not match the requirements"))
// is captcha valid
if(!valid[req.body.captcha])
return(res.send("Invalid captcha!"))
const captchaAge = Math.abs((valid[req.body.captcha].getTime() - new Date().getTime())/1000)
if(captchaAge > 600)
return(res.send("Invalid captcha!"))
// expire the captcha
delete valid[req.body.captcha]
// Does user already exist?
if(glauth.prepare(`SELECT * FROM users WHERE name = ?`).get(req.body.username))
return(res.send("User already exists"))
// Create the user!
glauth.prepare(`
INSERT INTO users(
name, primarygroup, passsha256
) VALUES(?, 0, ?)
`).run(req.body.username, crypto.createHash('sha256').update(req.body.password).digest('hex'))
console.log(`>>> User: ${req.body.username} was succesfully created!`)
res.send("Account registered!")
res.end()
})
app.get('/captcha', async (req, res) => {
const captcha = crypto.randomBytes(3).toString('hex')
await execawait(`./captcha.sh ${captcha} > captcha.png`)
// Make it valid for 10 minutes
valid[captcha] = new Date()
// Send the captcha image
res.contentType('image/png');
res.sendFile('captcha.png', {
root: './'
});
})
app.listen(port);
console.log('Server started at http://localhost:' + port);
function execawait(cmd) {
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) {
console.warn(error);
}
resolve(stdout ? stdout : stderr);
});
});7
}
function dbInit() {
glauth = new Database(process.env.GLAUTH_DB, {})
console.log(`Loaded in GLAuth - users.db`)
}

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "qwik-register",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"better-sqlite3": "^7.4.6",
"dotenv": "^12.0.3",
"express": "^4.17.2",
"expresss": "^0.0.0"
}
}

17
public/index.html Normal file
View File

@ -0,0 +1,17 @@
<img src="./captcha">
<ul>
<li>2-20 character in length</li>
<li>only a-zA-Z0-9 characters only</li>
</ul>
<form method="POST" action="/register">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username"><br>
<label for="password">Password:</label><br>
<input type="password" id="password" name="password">
<br>
<label for="captcha">Captcha:</label><br>
<input type="text" id="captcha" name="captcha">
<br>
<input type="submit" value="Register!" />
</form>