Skip to content

Commit

Permalink
Replace Titan's master password with globally authorized certificates.
Browse files Browse the repository at this point in the history
  • Loading branch information
ardek66 committed Jun 12, 2022
1 parent 6e18eb2 commit c9387d2
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 25 deletions.
12 changes: 4 additions & 8 deletions geminim.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,10 @@ rootDir = "pub/"
homeDir = "/home/$#/pub"

[titan]
# Password that the client must provide in order to get write access
# to files on the server. Defaults to "titanpassword" --
# FOR OBVIOUS REASONS YOU SHOULD DEFINITELY CHANGE IT
password = "titanpassword"

# Whether the password is required. Defaults to "true".
# It is recommended that it stays that way.
passwordRequired = "true"
# Authority file for certificates that provide authorization for uploading data through Titan.
# If the file doesn't exist, GemiNim will always forbid Titan uploads.
# Defaults to "titan_certs".
authorisedCerts = "titan_certs"

# Maximum size that the server will accept for Titan uploads, in bytes.
# Defaults to 10485760 (10 MiB)
Expand Down
9 changes: 3 additions & 6 deletions src/config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ type
titanSettings*: TitanSettings

TitanSettings* = object
password*: string
passwordRequired*: bool
authorisedCerts*: string
uploadLimit*: int
redirect*: bool

Expand Down Expand Up @@ -123,8 +122,7 @@ proc readSettings*(path: string): Settings =
homeDir: defaultHome,
dirHeader: "header.gemini",
titanSettings: TitanSettings(
password: "titanpassword",
passwordRequired: true,
authorisedCerts: "titan_certs",
uploadLimit: 10485760,
redirect: true)
)
Expand Down Expand Up @@ -156,8 +154,7 @@ proc readSettings*(path: string): Settings =
of "dirheader": result.dirHeader = e.value
elif section == "titan":
case e.key.toLowerAscii
of "password": result.titanSettings.password = e.value
of "passwordrequired": result.titanSettings.passwordRequired = e.value.parseBool
of "authorisedCerts": result.titanSettings.authorisedCerts = e.value
of "uploadlimit": result.titanSettings.uploadLimit = e.value.parseInt
of "redirect": result.titanSettings.redirect = e.value.parseBool
else:
Expand Down
26 changes: 15 additions & 11 deletions src/geminim.nim
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,21 @@ proc processTitanRequest(server: Server, req: Request): Future[Response] {.async
let maybeZone = await server.processGeminiUri(req)
if maybeZone.isSome(): return maybeZone.get()

var
size: int
token: string
let titanSettings = server.settings.titanSettings

var authorised = false
if fileExists(titanSettings.authorisedCerts) and req.cert.len > 0:
withAuthorityFile(titanSettings.authorisedCerts, auth):
let certDigest = req.cert.getDigest(auth.typ)
if certDigest == auth.digest:
authorised = true
break

if not authorised:
return response(StatusNotAuthorised,
"The connection is unauthorised for uploading resources.")

var size: int

for i in 1..req.params.high:
let keyVal = req.params[i].split("=")
Expand All @@ -181,21 +193,13 @@ proc processTitanRequest(server: Server, req: Request): Future[Response] {.async
if size <= 0: raise newException(ValueError, "Negative size")
except ValueError:
return response(StatusMalformedRequest, &"Size '{keyVal[1]}' is invalid.")

if keyVal[0] == "token":
token = keyVal[1].decodeUrl

if size == 0:
return response(StatusMalformedRequest, "No file size specified.")

let titanSettings = server.settings.titanSettings

if size > titanSettings.uploadLimit:
return response(StatusError, &"File size exceeds limit of {titanSettings.uploadLimit} bytes.")

if token != titanSettings.password and titanSettings.passwordRequired:
return response(StatusNotAuthorised, "Token not recognized.")

var filePath = req.res.filePath
let (parent, _ ) = filePath.splitPath

Expand Down

0 comments on commit c9387d2

Please sign in to comment.