The following commit fixes a memory leak caused by untrusted user input:
commit 953210bd1930e1734f1acde86eadd7a1997bb7c3
Author: Xavier Del Campo Romero
Date: Sun Oct 26 20:12:46 2025 +0100
form.c: Fix leak on invalid form
When one or more entries have been appended to a struct form instance,
but then an error occurs, those valid entries must be deallocated, too.
|
||
|---|---|---|
| cmake | ||
| doc | ||
| fdzipstream | ||
| libweb@953210bd19 | ||
| thumbnail | ||
| .gitignore | ||
| .gitmodules | ||
| auth.c | ||
| auth.h | ||
| cftw.c | ||
| cftw.h | ||
| CMakeLists.txt | ||
| configure | ||
| crealpath.c | ||
| crealpath.h | ||
| hex.c | ||
| hex.h | ||
| jwt.c | ||
| jwt.h | ||
| LICENSE | ||
| main.c | ||
| page.c | ||
| page.h | ||
| README.md | ||
| style.c | ||
| style.h | ||
| usergen.c | ||
| wildcard_cmp.c | ||
| wildcard_cmp.h | ||
| zip.c | ||
| zip.h | ||
slcl, a simple and lightweight cloud
slcl is a simple and lightweight implementation of a web file server,
commonly known as "cloud storage" or simply "cloud", written in C99 plus
POSIX.1-2008 extensions.
Screenshots
Disclaimer
Intentionally, slcl does not share some of the philosophical views from the
suckless project. However, it still strives towards
portability, minimalism, simplicity and efficiency.
Features
- Private access directory with file uploading, with configurable quota.
- Read-only public file sharing.
- Download directories as
.zipfiles. - Uses
libweb, a tiny web framework. - A simple JSON file as the credentials database.
- No JavaScript.
- Thumbnail generation can be optionally provided via a
separate application and enabled by
slclvia a command line option. Inter-process communication is achieved via a named pipe.
TLS
In order to maintain simplicity and reduce the risk for security bugs, slcl
does not implement TLS support. Instead, this should be provided by a
reverse proxy, such as caddy.
Root permissions
slcl is expected to listen to connections from any port number so that root
access is not required. So, in order to avoid the risk for security bugs,
please do not run slcl as root.
Encryption
Since no client-side JavaScript is used, files are uploaded unencrypted
to slcl. If required, encryption should be done before uploading e.g.: using
gpg.
Requirements
- A POSIX environment.
libsodium.- cJSON >= 1.7.15.
- ZLIB.
dynstr(provided as agitsubmodule bylibweb).libweb(provided as agitsubmodule).fdzipstream(provided as agitsubmodule).- ImageMagick >= 6.0 (optional, for
thumbnailonly). - CMake (optional).
Ubuntu / Debian
Mandatory packages
sudo apt install build-essential libcjson-dev libsodium-dev zlib1g
Optional packages
sudo apt install cmake libmagickcore-6.q16-dev
How to use
Build
Two build environments are provided for slcl - feel free to choose any of
them:
- A
configurePOSIX shell and mostly POSIX-compliantMakefile. - A
CMakeLists.txt.
slcl can be built using the standard build process:
Make
$ ./configure
$ make
To enable the thumbnail generation program:
$ ./configure --thumbnail
$ make
CMake
$ cmake -B build
$ cmake --build build/
To enable the thumbnail generation program:
$ cmake -B build -DTHUMBNAIL=ON
$ cmake --build build/
Setting up
slcl consumes a path to a directory with the following tree structure:
.
├── db.json
├── public
└── user
Where:
db.jsonis the credentials database. Details are explained below.- Note:
slclcreates a database with no users if not found, with file mode bits set to0600.
- Note:
publicis a directory containing read-only files that can be accessed without authentication. Internally, they are implemented as simlinks to other files.- Note:
slclcreates this directory if it does not exist, with directory mode bits set to0700.
- Note:
useris a directory containing user directories, which in turn contain anything users put into them.- Note:
slclcreates this directory if it does not exist, with directory mode bits set to0700.
- Note:
Note: slcl creates the given directory if it does not exist.
Generated thumbnails are stored into another directory,
namely thumbnails, which is automatically created with directory mode bits
set to 0700.
.
├── db.json
├── public
├── thumbnails
└── user
A more complete example:
.
├── db.json
├── public
│ └── 44e03ab1bc3b0eff1567c76619186596 -> user/alice/file.jpg
├── thumbnails
│ ├── alice
│ │ └── file.jpg
│ └── john
└── user
├── alice
│ └── file.jpg
└── john
└── file2.txt
Credentials database
slcl reads credentials from the db.json database, with the following
schema:
{
"users": [{
"name": "...",
"password": "...",
"salt": "...",
"key": "...",
"quota": "..."
}]
}
usergen is an interactive program that consumes a directory,
a username, a password and, optionally, a user quota in MiB. A salt is
randomly generated using openssl and passwords are hashed multiple times
beforehand - see usergen and auth.c for further
reference. Also, a random key is generated that is later used to sign HTTP
cookies.
Then, usergen appends a JSON object to the users JSON array in
the db.json file located inside the given directory. Also,
usergen creates the user directory inside the user/ directory.
When users authenticate from a web browser, slcl sends a SHA256HMAC-signed
JSON Web Token, using the random key generated by
usergen. No session data is kept on the server.
Running
To run slcl, simply run the executable with the path to a directory including
the files listed above. By default, slcl will listen to incoming connections
on a random TCP port number. To set a specific port number, use the -p
command line option. For example:
slcl -p 7822 ~/my-db/
slcl requires a temporary directory where files uploaded by users are
temporarily stored until moved to the user directory. By default, slcl
attempts to retrieve the path to the temporary directory by inspecting the
TMPDIR environment variable, and falls back to /tmp if undefined.
If a custom temporary directory is required, it can be defined via command
line option -t. For example:
slcl -t ~/my-tmp -p 7822 ~/my-db
Note: system-level temporary directories such as /tmp might reside
on a filesytem different than the one where the database resides. This
would force slcl to copy the contents from uploaded files from the
temporary directory to the database, which might be an expensive operation.
Therefore, in order to avoid expensive copies, define a custom temporary
directory that resides on the same filesystem.
Thumbnail generation and rendering
Optionally, slcl displays thumbnails when listing a directory, if available
from the thumbnails/ directory. In order to update these thumbnails when
files are added/removed to/from the database, a separate application must be
executed. See its README.md for further reference.
slcl provides the -F command line option to enable the use of a named pipe
that shall be used by the thumbnail generation tool.
Why this project?
Previously, I had been recommended Nextcloud as an alternative to proprietary services like Dropbox. Unfortunately, despite being a very flexible piece of software, Nextcloud is way too heavy on resources, specially on lower end hardware such as the Raspberry Pi 3:
- It uses around 30% RAM on my Raspberry Pi 3, configured with 973 MiB of RAM, and of course it gets worse with several simultaneous users.
- Simple operations like searching and previewing files cause large amounts of I/O and RAM usage, so much that it locks the whole server up more often than not.
- Nextcloud pages are bloated. Even the login page is over 15 MiB (!).
- Requires clients to run JavaScript, which also has a significant performance penalty on the web browser. Also, some users do not feel comfortable running JavaScript from their web browsers, and thus prefer to disable it.
After years of recurring frustration as a Nextcloud administrator and user, I looked for alternatives that stripped out most of the unneeded bloat from Nextcloud, while providing the required features listed above. However, I could not find any that fit them, so I felt challenged to design a new implementation.
On the other hand, command line-based solutions like rsync might not be as
convenient for non-technical people, compared to a web browser, or might not
be even available e.g.: phones.
License
slcl, a simple and lightweight cloud.
Copyright (C) 2023-2025 Xavier Del Campo Romero
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also, see LICENSE.

