summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-05-30 02:18:27 +0200
committermetamuffin <metamuffin@disroot.org>2024-05-30 02:18:27 +0200
commit2b64fc57bbed04dd8249afcbbc6ac6849e05ba36 (patch)
treedd5f22f70c2996d79399bef4eeeacd25c2d86c69
parent8d58647a5edebe8eb37ee8d24f2ffc2c400a655c (diff)
downloadgnix-2b64fc57bbed04dd8249afcbbc6ac6849e05ba36.tar
gnix-2b64fc57bbed04dd8249afcbbc6ac6849e05ba36.tar.bz2
gnix-2b64fc57bbed04dd8249afcbbc6ac6849e05ba36.tar.zst
implment creds for http basic authv2.0.0
-rw-r--r--readme.md25
-rw-r--r--src/modules/auth/basic.rs9
-rw-r--r--src/modules/auth/mod.rs8
3 files changed, 26 insertions, 16 deletions
diff --git a/readme.md b/readme.md
index 12ee8ec..451f2dd 100644
--- a/readme.md
+++ b/readme.md
@@ -6,6 +6,7 @@ a simple stupid reverse proxy
- HTTP/1.1
- Simple to configure (see below)
+- Somewhat fast (about 150k req/s on a rpi5 for simple routes)
- Composable modules
- Handles connection upgrades correctly by default (websocket, etc.)
- TLS support
@@ -37,14 +38,20 @@ https:
# !hosts multiplexes requests for different hostnames.
handler: !hosts
- # requests for `example.org` are forwarded to 127.0.0.1:8000
+ # requests for `example.org` are forwarded to 127.0.0.1:8000.
"example.org": !proxy { backend: "127.0.0.1:8000" }
- # requests for `mydomain.com` will access files from /srv/http
+ # requests for `mydomain.com` will access files from /srv/http.
"mydomain.com": !files
root: "/srv/http"
index: true
-
+ # requests for `panel.mydomain.com` will be logged, authentificated and passed on to `otherserver`.
"panel.mydomain.com": !access_log
+ file: "/var/log/gnix/panel"
+ next: !cookie_auth
+ users: "/etc/panel_creds"
+ expire: 86400
+ fail: !file { path: "/usr/share/gnix/login.html" }
+ next: !proxy { backend: "otherserver:80" }
```
## Reference
@@ -120,7 +127,7 @@ themselves; in that case the request is passed on.
- **module `http_basic_auth`**
- Filters requests via HTTP Basic Authentification. Unauthorized clients will
- be challenged on every request.
+ be challenged.
- `realm`: describes what the user is logging into (most modern browsers dont
show this anymore -_-)
- `users`: list of valid logins (credentials)
@@ -132,10 +139,10 @@ themselves; in that case the request is passed on.
POST request to `/_gnix_login` with form fields `password` and `username`
(optional, default: "user") in `x-www-form-urlencoded` format. In any case
the users submitting this request will be directed back to the page they
- come from. Successful logins set two cookies: `gnix_username` containing the
- username and `gnix_auth` containing an opaque authentification token. The
- `gnix_username` cookie is authentificated by gnix and can therefore be used
- by applications.
+ come from. For successful logins two cookies are set: `gnix_username`
+ containing the username and `gnix_auth` containing an opaque
+ authentification token. The `gnix_username` cookie is authentificated by
+ gnix and can therefore be used by applications.
- `users`: list of valid logins (credentials)
- `expire`: seconds before logins expire; not setting this option keeps the
login valid forever on the server but cleared after the session on the
@@ -147,7 +154,7 @@ themselves; in that case the request is passed on.
- `fail`: a module to handle the request when a user is not authorized. This
could show an HTML form prompting the user to log in. An implementation of
such a form is provided with the distribution of this software, usually in
- `/usr/share/gnix/login.html`
+ `/usr/share/gnix/login.html` (module)
#### Credentials config format
diff --git a/src/modules/auth/basic.rs b/src/modules/auth/basic.rs
index 08870c4..9af5b01 100644
--- a/src/modules/auth/basic.rs
+++ b/src/modules/auth/basic.rs
@@ -13,7 +13,9 @@ use hyper::{
use log::debug;
use serde::Deserialize;
use serde_yaml::Value;
-use std::{collections::HashSet, pin::Pin, sync::Arc};
+use std::{pin::Pin, sync::Arc};
+
+use super::Credentials;
pub struct HttpBasicAuthKind;
impl NodeKind for HttpBasicAuthKind {
@@ -28,7 +30,7 @@ impl NodeKind for HttpBasicAuthKind {
#[derive(Deserialize)]
pub struct HttpBasicAuth {
realm: String,
- valid: HashSet<String>,
+ users: Credentials,
next: DynNode,
}
@@ -46,7 +48,8 @@ impl Node for HttpBasicAuth {
.ok_or(ServiceError::BadAuth)?;
let k = base64::engine::general_purpose::STANDARD.decode(k)?;
let k = String::from_utf8(k)?;
- if self.valid.contains(&k) {
+ let (username, password) = k.split_once(":").ok_or(ServiceError::BadAuth)?;
+ if self.users.authentificate(username, password) {
debug!("valid auth");
return self.next.handle(context, request).await;
} else {
diff --git a/src/modules/auth/mod.rs b/src/modules/auth/mod.rs
index d6e1a35..715ca97 100644
--- a/src/modules/auth/mod.rs
+++ b/src/modules/auth/mod.rs
@@ -19,12 +19,12 @@ struct Credentials {
}
impl Credentials {
- fn get(&self, usernamme: &str) -> &PasswordHashString {
- self.hashes.get(usernamme).unwrap_or(&self.wrong_user)
+ fn get(&self, username: &str) -> &PasswordHashString {
+ self.hashes.get(username).unwrap_or(&self.wrong_user)
}
- pub fn authentificate(&self, usernamme: &str, password: &str) -> bool {
+ pub fn authentificate(&self, username: &str, password: &str) -> bool {
let algo = Argon2::new(Algorithm::Argon2id, Version::V0x13, Params::default());
- let hash = self.get(usernamme);
+ let hash = self.get(username);
match hash.algorithm().as_str() {
"argon2id" => algo
.verify_password(