36 Commits

Author SHA1 Message Date
solusipse
4bba916e0f Added instructions for FreeBSD Ports 2018-12-20 14:15:52 +01:00
solusipse
21ff9787e8 Merge pull request #78 from larsks/feature/listen_addr
It's now possible to bind to a specific address
2018-12-20 14:05:00 +01:00
solusipse
6f3edbdfd9 Merge pull request #79 from ohnx/patch-1
Fixed slug example with six characters
2018-12-20 13:42:54 +01:00
Mason'); DROP TABLE Users; --
e3c7ce0604 Update README.md
fix typos in slug size configuration info
2018-03-05 21:47:03 -05:00
Lars Kellogg-Stedman
441debc4c7 teach fiche about binding to a specific address
Add the -L <listen_addr> option which permits fiche to bind to a
specific local address rather than INADDR_ANY.
2018-02-27 11:24:58 -05:00
solusipse
9206dce65f Merge pull request #77 from Hasimir/secret-sauce
Use the Source
2018-02-22 23:20:40 +01:00
Ben McGinnes
038a9176d5 Use the Source
* Friends don't let friends reset their terms when they can just
  reload their shell rc file.  ;)
2018-02-18 04:17:35 +11:00
solusipse
10129c8302 Simplified mechanism for null-terminating main buffer 2017-10-19 22:18:57 +02:00
solusipse
288bf2ef84 Added info about beautification service 2017-10-16 16:34:00 +02:00
solusipse
6d292a3001 Fixed #63 2017-10-12 01:28:35 +02:00
solusipse
680bb77f2c Blocked dir traversal 2017-10-09 20:15:22 +02:00
solusipse
1220515107 Merge branch 'master' of github.com:solusipse/fiche 2017-10-09 19:58:42 +02:00
solusipse
801231514c Created very simple script for serving pastes with numbering (#51) 2017-10-09 19:58:21 +02:00
solusipse
4537a6897a Merge pull request #62 from dotlambda/patch-1
Move /bin suffix to $prefix
2017-10-09 19:22:40 +02:00
Robert Schütz
e3f7005180 Move /bin suffix to $prefix
This makes it a lot more portable. For example, on NixOS, there is no `bin` directory.
2017-10-02 19:03:43 +02:00
solusipse
e2daffecd3 Added additional example for -d switch 2017-09-18 02:27:24 +02:00
solusipse
9e3986fa66 Updated usage info 2017-09-17 15:14:35 +02:00
solusipse
ef12b5d54f Added instructions for -S option 2017-09-17 15:13:17 +02:00
solusipse
cdd910b150 Re-added support for https (#33) 2017-09-17 14:34:44 +02:00
solusipse
1cba8ad493 Adding lacking dependency for python's port of scan-build 2017-09-06 01:13:57 +02:00
solusipse
9bab68e44a Trying to resolve scan-build dependencies 2017-09-06 01:10:18 +02:00
solusipse
5abe89fc9c Added lacking clang package for scan-build 2017-09-06 00:59:09 +02:00
solusipse
f4114ce2a6 Added scan-build 2017-09-06 00:55:57 +02:00
solusipse
a2fb9ab838 Added cppcheck 2017-09-06 00:39:00 +02:00
solusipse
10cb524891 Reworked date function to take buffer as an argument 2017-09-05 22:04:21 +02:00
solusipse
99b45b93f2 Changed method of touching logfile before using 2017-09-02 22:20:08 +02:00
solusipse
c1725790bb Update README.md 2017-09-02 21:39:15 +02:00
solusipse
b554845749 Added pure-bash alias alternative to nc 2017-09-02 21:38:03 +02:00
solusipse
7ad6a82fd4 Added some aliases, performed minor cleanup 2017-09-02 21:22:35 +02:00
solusipse
53c0027b3c Extra checks, fixed cleanup in file generating routine 2017-09-02 19:48:02 +02:00
solusipse
7575609c41 Fixed null dereference, renamed argument to match declaration 2017-09-02 19:44:08 +02:00
solusipse
319bd73273 Failure on slug generation is now properly handled 2017-09-02 19:30:08 +02:00
solusipse
2c88f3c990 Merge branch 'master' of github.com:solusipse/fiche 2017-09-02 19:15:48 +02:00
solusipse
bd1751693b Fixed wrong order of cleanup calls 2017-09-02 19:12:10 +02:00
solusipse
54838f5dab Major cleanup 2017-09-02 18:53:43 +02:00
solusipse
8ff08a0409 Entirely rewritten fiche 2017-09-02 17:51:43 +02:00
9 changed files with 1262 additions and 776 deletions

6
.gitignore vendored
View File

@@ -1,2 +1,8 @@
# ignore binaries
/fiche
# ignore default outpit dir
code/
# ignore log files
*.log

View File

@@ -1,2 +1,21 @@
language: c
script: make
compiler:
- gcc
- clang
addons:
apt:
packages:
- cppcheck
- clang-3.5
install:
- export PYTHONUSERBASE=~/.local
- easy_install --user scan-build
- easy_install --user typing
script:
- cppcheck --enable=all --error-exitcode=1 --inconclusive main.c fiche.c
- make
- scan-build --status-bugs make -B

View File

@@ -1,16 +1,12 @@
# -----------------------------------
# Fiche MAKEFILE
# https://github.com/solusipse/fiche
# solusipse.net
# -----------------------------------
# for debug add -g -O0 to line below
CFLAGS+=-pthread -O2 -Wall -Wextra -Wpedantic -Wstrict-overflow -fno-strict-aliasing -std=gnu11 -g -O0
prefix=/usr/local/bin
CFLAGS+=-pthread -O2
prefix=/usr/local
all: fiche
all:
${CC} main.c fiche.c $(CFLAGS) -o fiche
install: fiche
install -m 0755 fiche $(prefix)/bin
install -m 0755 fiche $(prefix)
clean:
rm -f fiche

346
README.md
View File

@@ -3,15 +3,123 @@ fiche [![Build Status](https://travis-ci.org/solusipse/fiche.svg?branch=master)]
Command line pastebin for sharing terminal output.
## Installation ##
# Client-side usage
1. Clone into repository:
Self-explanatory live examples (using public server):
```
echo just testing! | nc termbin.com 9999
```
```
cat file.txt | nc termbin.com 9999
```
In case you installed and started fiche on localhost:
```
ls -la | nc localhost 9999
```
You will get an url to your paste as a response, e.g.:
```
http://termbin.com/ydxh
```
You can use our beautification service to get any paste colored and numbered. Just ask for it using `l.termbin.com` subdomain, e.g.:
```
http://l.termbin.com/ydxh
```
-------------------------------------------------------------------------------
## Useful aliases
You can make your life easier by adding a termbin alias to your rc file. We list some of them here:
-------------------------------------------------------------------------------
### Pure-bash alternative to netcat
__Linux/macOS:__
```
alias tb="(exec 3<>/dev/tcp/termbin.com/9999; cat >&3; cat <&3; exec 3<&-)"
```
```
echo less typing now! | tb
```
_See [#42](https://github.com/solusipse/fiche/issues/42), [#43](https://github.com/solusipse/fiche/issues/43) for more info._
-------------------------------------------------------------------------------
### `tb` alias
__Linux (Bash):__
```
echo 'alias tb="nc termbin.com 9999"' >> .bashrc
```
```
echo less typing now! | tb
```
__macOS:__
```
echo 'alias tb="nc termbin.com 9999"' >> .bash_profile
```
```
echo less typing now! | tb
```
-------------------------------------------------------------------------------
### Copy output to clipboard
__Linux (Bash):__
```
echo 'alias tbc="netcat termbin.com 9999 | xclip -selection c"' >> .bashrc
```
```
echo less typing now! | tbc
```
__macOS:__
```
echo 'alias tbc="nc termbin.com 9999 | pbcopy"' >> .bash_profile
```
```
echo less typing now! | tbc
```
__Remember__ to reload the shell with `source ~/.bashrc` or `source ~/.bash_profile` after adding any of provided above!
-------------------------------------------------------------------------------
## Requirements
To use fiche you have to have netcat installed. You probably already have it - try typing `nc` or `netcat` into your terminal!
-------------------------------------------------------------------------------
# Server-side usage
## Installation
1. Clone:
```
https://github.com/solusipse/fiche.git
git clone https://github.com/solusipse/fiche.git
```
2. Build program:
2. Build:
```
make
@@ -23,71 +131,49 @@ Command line pastebin for sharing terminal output.
sudo make install
```
## Client-side usage ##
### Using Ports on FreeBSD
Self explanatory live examples:
To install the port: `cd /usr/ports/net/fiche/ && make install clean`. To add the package: `pkg install fiche`.
```
ls -la | nc localhost 9999
```
_See [#86](https://github.com/solusipse/fiche/issues/86) for more info._
```
cat file.txt | nc solusipse.net 9999
```
-------------------------------------------------------------------------------
```
echo just testing! | nc code.solusipse.net 9999
```
If you haven't already set up your server on localhost, try second or third command. My personal server is
providing fiche-based service all the time on this address `solusipse.net` and this port `9999`.
- To upload text you need to have netcat installed (to check if netcat is installed, simply type ```nc``` in terminal).
## Server-side usage ##
## Usage
```
usage: fiche [-D6epbsdSolBuw].
[-d domain] [-p port] [-s slug size]
[-d domain] [-L listen_addr ] [-p port] [-s slug size]
[-o output directory] [-B buffer size] [-u user name]
[-l log file] [-b banlist] [-w whitelist]
[-l log file] [-b banlist] [-w whitelist] [-S]
```
These are command line arguments. You don't have to provide any, but providing basic is recommended. Without them, program
will use these default settings:
These are command line arguments. You don't have to provide any of them to run the application. Default settings will be used in such case. See section below for more info.
### Settings
-------------------------------------------------------------------------------
#### Output directory `-o`
Relative or absolute path to the directory where you want to store user-posted pastes.
```
domain = "http://localhost/";
basedir= "~/code/";
port = 9999;
slug_size = 4;
buffer_size = 8192;
```
### Arguments ###
Most important is providing **basedir** and **domain**.
-----------------
#### Basedir ####
Basedir should be **absolute** path to directory where you would like to store text files.
```
fiche -o /absolute/path/to/directory/
fiche -o ./code
```
```
fiche -o /home/www/code/
```
-----------------
__Default value:__ `./code`
#### Domain ####
-------------------------------------------------------------------------------
Domain should be provided in such format ```domain.com```.
#### Domain `-d`
This will be used as a prefix for an output received by the client.
Value will be prepended with `http`.
```
fiche -d domain.com
@@ -97,158 +183,140 @@ fiche -d domain.com
fiche -d subdomain.domain.com
```
-----------------
```
fiche -d subdomain.domain.com/some_directory
```
#### Slug size ####
__Default value:__ `localhost`
This will force fiche to create random slugs with given length, example:
-------------------------------------------------------------------------------
#### Slug size `-s`
This will force slugs to be of required length:
```
fiche -s 6
```
__Output url with default value__: `http://localhost/xxxx`,
where x is a randomized character
__Output url with example value 6__: `http://localhost/xxxxxx`,
where x is a randomized character
__Default value:__ 4
-------------------------------------------------------------------------------
#### HTTPS `-S`
If set, fiche returns url with https prefix instead of http
```
http://domain.com/abcdef/
fiche -S
```
-----------------
__Output url with this parameter__: `https://localhost/xxxx`,
where x is a randomized character
#### User name ####
-------------------------------------------------------------------------------
Set the user that fiche runs as using the `-u` option, example:
#### User name `-u`
Fiche will try to switch to the requested user on startup if any is provided.
```
fiche -u _fiche
```
This option has effect only if fiche was started by root, otherwise it is ignored and fiche runs under the
current user id.
__Default value:__ not set
-----------------
__WARNING:__ This requires that fiche is started as a root.
#### Buffersize ####
-------------------------------------------------------------------------------
This parameter defines max file size uploaded by user, by default it is set to `32768`.
Use `-B` parameter to change it:
#### Buffer size `-B`
This parameter defines size of the buffer used for getting data from the user.
Maximum size (in bytes) of all input files is defined by this value.
```
fiche -B 2048
```
-----------------
__Default value:__ 32768
#### Log file ###
-------------------------------------------------------------------------------
Path to file where all logs will be stored:
#### Log file `-l`
```
fiche -l /home/www/fiche-log.txt
```
-----------------
__Default value:__ not set
#### Ban list ###
__WARNING:__ this file has to be user-writable
Path to file where you provided all banned IP adresses:
-------------------------------------------------------------------------------
#### Ban list `-b`
Relative or absolute path to a file containing IP addresses of banned users.
```
fiche -b /home/www/fiche-bans.txt
fiche -b fiche-bans.txt
```
-----------------
__Format of the file:__ this file should contain only addresses, one per line.
#### White list ####
__Default value:__ not set
If whitelist mode is enabled, only addresses from list will be able to upload files. There's example:
__WARNING:__ not implemented yet
-------------------------------------------------------------------------------
#### White list `-w`
If whitelist mode is enabled, only addresses from the list will be able
to upload files.
```
fiche -w /home/www/fiche-whitelist.txt
fiche -w fiche-whitelist.txt
```
-----------------
__Format of the file:__ this file should contain only addresses, one per line.
#### Whitelist and banlist syntax ####
__Default value:__ not set
There is no specific syntax, there files may contain not only addresses.
__WARNING:__ not implemented yet
-----------------
-------------------------------------------------------------------------------
#### Daemonize ####
Fork fiche to the background:
fiche -D
-----------------
#### Extended character set for the URL ####
Fork can extend the charcter set for the URL:
fiche -e
-----------------
#### Use IPv6 ####
this will allow fiche to accept connections from IPv6 clients:
fiche -6
-----------------
#### Examples ####
Logging connections with banlist:
```
fiche -d domain.com -l /home/www/log.txt -b /home/www/bans.txt
```
-----------------
Only for personal use with whitelist
```
fiche -d domain.com -w /home/www/whitelist.txt
```
-----------------
Custom output directory, bigger slug size, reduced buffer, custom port:
```
fiche -d domain.com -o /media/disk/fiche/ -s 8 -B 2048 -p 6666
```
## Running as service ##
You can run fiche as service, there is simple systemd example:
### Running as a service
There's a simple systemd example:
```
[Unit]
Description=FICHE-SERVER
[Service]
ExecStart=/usr/local/bin/fiche -d code.solusipse.net -o /home/www/code/ -l /home/www/log.txt -u _fiche
ExecStart=/usr/local/bin/fiche -d yourdomain.com -o /path/to/output -l /path/to/log -u youruser
[Install]
WantedBy=multi-user.target
```
In service mode you have to set output directory with `-o` parameter, there's example:
__WARNING:__ In service mode you have to set output directory with `-o` parameter.
```
fiche -o /home/www/code/
```
-------------------------------------------------------------------------------
## Webserver ##
### Example nginx config
To make files available for users, you need to host them somehow. Http server is easiest option. Just set root
directory to ```BASEDIR```.
Fiche has no http server built-in, thus you need to setup one if you want to make files available through http.
There is sample configuration for nginx:
There's a sample configuration for nginx:
```
server {
@@ -263,6 +331,6 @@ server {
}
```
## License ##
## License
Fiche is MIT licensed.

0
extras/lines/__init__.py Normal file
View File

51
extras/lines/lines.py Normal file
View File

@@ -0,0 +1,51 @@
from flask import Flask, abort, redirect
app = Flask(__name__)
import argparse, os, pygments
from pygments import highlight
from pygments.lexers import guess_lexer
from pygments.formatters import HtmlFormatter
parser = argparse.ArgumentParser()
parser.add_argument("root_dir", help="Path to directory with pastes")
args = parser.parse_args()
@app.route('/')
def main():
return redirect("http://termbin.com", code=302)
@app.route('/<slug>')
def beautify(slug):
# Return 404 in case of urls longer than 64 chars
if len(slug) > 64:
abort(404)
# Create path for the target dir
target_dir = os.path.join(args.root_dir, slug)
# Block directory traversal attempts
if not target_dir.startswith(args.root_dir):
abort(404)
# Check if directory with requested slug exists
if os.path.isdir(target_dir):
target_file = os.path.join(target_dir, "index.txt")
# File index.txt found inside that dir
with open(target_file) as f:
code = f.read()
# Identify language
lexer = guess_lexer(code)
# Create formatter with line numbers
formatter = HtmlFormatter(linenos=True, full=True)
# Return parsed code
return highlight(code, lexer, formatter)
# Not found
abort(404)
if __name__ == '__main__':
app.run()

1281
fiche.c

File diff suppressed because it is too large Load Diff

170
fiche.h
View File

@@ -5,7 +5,7 @@ Fiche - Command line pastebin for sharing terminal output.
License: MIT (http://www.opensource.org/licenses/mit-license.php)
Repository: https://github.com/solusipse/fiche/
Live example: http://code.solusipse.net/
Live example: http://termbin.com
-------------------------------------------------------------------------------
@@ -14,15 +14,7 @@ usage: fiche [-DepbsdolBuw].
[-o output directory] [-B buffer size] [-u user name]
[-l log file] [-b banlist] [-w whitelist]
-D option is for daemonizing fiche
-e option is for using an extended character set for the URL
Compile with Makefile or manually with -O2 and -pthread flags.
To install use `make install` command.
Use netcat to push text - example:
$ cat fiche.c | nc localhost 9999
-------------------------------------------------------------------------------
@@ -31,91 +23,97 @@ $ cat fiche.c | nc localhost 9999
#ifndef FICHE_H
#define FICHE_H
#ifndef HAVE_INET6
#define HAVE_INET6 1
#endif
#include <stdint.h>
#include <stdbool.h>
#include <pwd.h>
#include <time.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int UID = -1;
int GID = -1;
char *LOG;
char *BASEDIR;
char *BANLIST;
char *BANFILE;
char *WHITEFILE;
char *WHITELIST;
int DAEMON = 0;
int HTTPS = 0;
int PORT = 9999;
int IPv6 = 0;
int SLUG_SIZE = 4;
int BUFSIZE = 32768;
int QUEUE_SIZE = 500;
char DOMAIN[128] = "localhost/";
char symbols[67] = "abcdefghijklmnopqrstuvwxyz0123456789";
/**
* @brief Used as a container for fiche settings. Create before
* the initialization
*
*/
typedef struct Fiche_Settings {
/**
* @brief Domain used in output links
*/
char *domain;
unsigned int time_seed;
/**
* @brief Path to directory used for storing uploaded pastes
*/
char *output_dir_path;
struct thread_arguments
{
int connection_socket;
struct sockaddr_in client_address;
#if (HAVE_INET6)
struct sockaddr_in6 client_address6;
#endif
};
/**
* @brief Address on which fiche is waiting for connections
*/
char *listen_addr;
struct client_data
{
char *ip_address;
char *hostname;
};
/**
* @brief Port on which fiche is waiting for connections
*/
uint16_t port;
int create_socket();
int create_directory(char *slug);
int check_protocol(char *buffer);
/**
* @brief Length of a paste's name
*/
uint8_t slug_len;
void bind_to_port(int listen_socket, struct sockaddr_in serveraddr);
#if (HAVE_INET6)
void bind_to_port6(int listen_socket, struct sockaddr_in6 serveraddr6);
#endif
void error(char *buffer);
void perform_connection(int listen_socket);
void generate_url(char *buffer, char *slug, size_t slug_length, struct client_data data);
void save_to_file(char *buffer, char *slug, struct client_data data);
void display_info(struct client_data data, char *slug, char *message);
void startup_message();
void set_basedir();
void set_domain_name();
void load_list(char *file_path, int type);
void parse_parameters(int argc, char **argv);
void save_log(char *slug, char *hostaddrp, char *h_name);
void set_uid_gid();
/**
* @brief If set, returns url with https prefix instead of http
*/
bool https;
char *check_banlist(char *ip_address);
char *check_whitelist(char *ip_address);
char *get_date();
/**
* @brief Connection buffer length
*
* @remarks Length of this buffer limits max size of uploaded files
*/
uint32_t buffer_len;
/**
* @brief Name of the user that runs fiche process
*/
char *user_name;
/**
* @brief Path to the log file
*/
char *log_file_path;
/**
* @brief Path to the file with banned IPs
*/
char *banlist_path;
/**
* @brief Path to the file with whitelisted IPs
*/
char *whitelist_path;
} Fiche_Settings;
/**
* @brief Initializes Fiche_Settings instance
*/
void fiche_init(Fiche_Settings *settings);
/**
* @brief Runs fiche server
*
* @return 0 if it was able to start, any other value otherwise
*/
int fiche_run(Fiche_Settings settings);
/**
* @brief array of symbols used in slug generation
* @remarks defined in fiche.c
*/
extern const char *Fiche_Symbols;
struct sockaddr_in set_address(struct sockaddr_in serveraddr);
#if (HAVE_INET6)
struct sockaddr_in6 set_address6(struct sockaddr_in6 serveraddr6);
#endif
struct client_data get_client_address(struct sockaddr_in client_address);
#if (HAVE_INET6)
struct client_data get_client_address6(struct sockaddr_in6 client_address6);
#endif
#endif

147
main.c Normal file
View File

@@ -0,0 +1,147 @@
/*
Fiche - Command line pastebin for sharing terminal output.
-------------------------------------------------------------------------------
License: MIT (http://www.opensource.org/licenses/mit-license.php)
Repository: https://github.com/solusipse/fiche/
Live example: http://termbin.com
-------------------------------------------------------------------------------
usage: fiche [-DepbsdolBuw].
[-D] [-e] [-d domain] [-p port] [-s slug size]
[-o output directory] [-B buffer size] [-u user name]
[-l log file] [-b banlist] [-w whitelist]
Use netcat to push text - example:
$ cat fiche.c | nc localhost 9999
-------------------------------------------------------------------------------
*/
#include "fiche.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
int main(int argc, char **argv) {
// Fiche settings instance
Fiche_Settings fs;
// Initialize settings instance to default values
fiche_init(&fs);
// Note: fiche_run is responsible for checking if these values
// were set correctly
// Note: according to getopt documentation, we don't need to
// copy strings, so we decided to go with pointer approach for these
// Parse input arguments
int c;
while ((c = getopt(argc, argv, "D6eSL:p:b:s:d:o:l:B:u:w:")) != -1) {
switch (c) {
// domain
case 'd':
{
fs.domain = optarg;
}
break;
// port
case 'p':
{
fs.port = atoi(optarg);
}
break;
// listen_addr
case 'L':
{
fs.listen_addr = optarg;
}
break;
// slug size
case 's':
{
fs.slug_len = atoi(optarg);
}
break;
// https
case 'S':
{
fs.https = true;
}
break;
// output directory path
case 'o':
{
fs.output_dir_path = optarg;
}
break;
// buffer size
case 'B':
{
fs.buffer_len = atoi(optarg);
}
break;
// user name
case 'u':
{
fs.user_name = optarg;
}
break;
// log file path
case 'l':
{
fs.log_file_path = optarg;
}
break;
// banlist file path
case 'b':
{
fs.banlist_path = optarg;
}
break;
// whitelist file path
case 'w':
{
fs.whitelist_path = optarg;
}
break;
// Display help in case of any unsupported argument
default:
{
printf("usage: fiche [-dLpsSoBulbw].\n");
printf(" [-d domain] [-L listen_addr] [-p port] [-s slug size]\n");
printf(" [-o output directory] [-B buffer size] [-u user name]\n");
printf(" [-l log file] [-b banlist] [-w whitelist] [-S]\n");
return 0;
}
break;
}
}
fiche_run(fs);
return 0;
}