8 Commits

Author SHA1 Message Date
solusipse
68635bd0f5 Update README.md 2017-10-30 07:31:55 +01:00
solusipse
8e6cf66b3d Update README.md 2015-09-23 19:48:58 +02:00
solusipse
1a7d443843 mergerd renaudallard:master (#17) 2015-09-23 19:36:37 +02:00
solusipse
9b2f73678d Merge branch 'master' of git://github.com/renaudallard/fiche into renaudallard-master 2015-09-23 19:09:41 +02:00
solusipse
95f1cacfbe Merge branch 'master' of git://github.com/ALSchwalm/fiche into ALSchwalm-master 2015-09-23 18:27:18 +02:00
Renaud Allard
39aa6a7a53 Chnage the travis script so that it builds 2015-09-07 13:18:05 +02:00
Renaud Allard
6743d0e6b7 Use ./configure to detect arc4random and use it if present 2015-09-03 16:11:12 +02:00
Adam Schwalm
b6d1c91f71 Make file paths unpredictable 2015-09-02 18:16:23 -05:00
13 changed files with 4482 additions and 1360 deletions

6
.gitignore vendored
View File

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

View File

@@ -1,21 +1,2 @@
language: c language: c
script: ./configure && 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,14 +0,0 @@
# 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
all:
${CC} main.c fiche.c $(CFLAGS) -o fiche
install: fiche
install -m 0755 fiche $(prefix)
clean:
rm -f fiche
.PHONY: clean

18
Makefile.in Normal file
View File

@@ -0,0 +1,18 @@
# -----------------------------------
# Fiche MAKEFILE
# https://github.com/solusipse/fiche
# solusipse.net
# -----------------------------------
CFLAGS+=-pthread -O2
CFLAGS+=@LIBS@
all: fiche
install: fiche
install -m 0755 fiche ${PREFIX}/bin
clean:
rm -f fiche
.PHONY: clean

337
README.md
View File

@@ -1,336 +1,9 @@
fiche [![Build Status](https://travis-ci.org/solusipse/fiche.svg?branch=master)](https://travis-ci.org/solusipse/fiche) # fiche
=====
Command line pastebin for sharing terminal output. ## Warning
# Client-side usage Do not use code from this branch. Please use code from [master](https://github.com/solusipse/fiche) instead.
Self-explanatory live examples (using public server):
``` ## Secure branch (legacy note)
echo just testing! | nc termbin.com 9999 This branch is the result of merging two pull requests: [#16](https://github.com/solusipse/fiche/pull/16) by [Adam Schwalm](https://github.com/ALSchwalm) and [#17](https://github.com/solusipse/fiche/pull/17) by [Renaud Allard](https://github.com/renaudallard), which contained some security-related improvements. It is recommended for `BSD` users or for those who would like to `arc4random`.
```
```
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:
```
git clone https://github.com/solusipse/fiche.git
```
2. Build:
```
make
```
3. Install:
```
sudo make install
```
### Using Ports on FreeBSD
To install the port: `cd /usr/ports/net/fiche/ && make install clean`. To add the package: `pkg install fiche`.
_See [#86](https://github.com/solusipse/fiche/issues/86) for more info._
-------------------------------------------------------------------------------
## Usage
```
usage: fiche [-D6epbsdSolBuw].
[-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] [-S]
```
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.
```
fiche -o ./code
```
```
fiche -o /home/www/code/
```
__Default value:__ `./code`
-------------------------------------------------------------------------------
#### 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
```
```
fiche -d subdomain.domain.com
```
```
fiche -d subdomain.domain.com/some_directory
```
__Default value:__ `localhost`
-------------------------------------------------------------------------------
#### 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
```
fiche -S
```
__Output url with this parameter__: `https://localhost/xxxx`,
where x is a randomized character
-------------------------------------------------------------------------------
#### User name `-u`
Fiche will try to switch to the requested user on startup if any is provided.
```
fiche -u _fiche
```
__Default value:__ not set
__WARNING:__ This requires that fiche is started as a root.
-------------------------------------------------------------------------------
#### 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 `-l`
```
fiche -l /home/www/fiche-log.txt
```
__Default value:__ not set
__WARNING:__ this file has to be user-writable
-------------------------------------------------------------------------------
#### Ban list `-b`
Relative or absolute path to a file containing IP addresses of banned users.
```
fiche -b fiche-bans.txt
```
__Format of the file:__ this file should contain only addresses, one per line.
__Default value:__ not set
__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 fiche-whitelist.txt
```
__Format of the file:__ this file should contain only addresses, one per line.
__Default value:__ not set
__WARNING:__ not implemented yet
-------------------------------------------------------------------------------
### Running as a service
There's a simple systemd example:
```
[Unit]
Description=FICHE-SERVER
[Service]
ExecStart=/usr/local/bin/fiche -d yourdomain.com -o /path/to/output -l /path/to/log -u youruser
[Install]
WantedBy=multi-user.target
```
__WARNING:__ In service mode you have to set output directory with `-o` parameter.
-------------------------------------------------------------------------------
### Example nginx config
Fiche has no http server built-in, thus you need to setup one if you want to make files available through http.
There's a sample configuration for nginx:
```
server {
listen 80;
server_name mysite.com www.mysite.com;
charset utf-8;
location / {
root /home/www/code/;
index index.txt index.html;
}
}
```
## License
Fiche is MIT licensed.

2
config.h.in Normal file
View File

@@ -0,0 +1,2 @@
#undef HAVE_ARC4RANDOM

3987
configure vendored Executable file

File diff suppressed because it is too large Load Diff

20
configure.in Normal file
View File

@@ -0,0 +1,20 @@
AC_INIT([fiche], [0.99])
AC_CONFIG_SRCDIR([fiche.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Function arc4random() is in BSD standard C or GNU systems -lbsd
AC_SEARCH_LIBS([arc4random], [bsd], [HAVE_ARC4RANDOM="yes"])
# Checks for library functions.
AC_CHECK_FUNCS([bzero arc4random])
AC_SUBST(HAVE_ARC4RANDOM)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View File

@@ -1,51 +0,0 @@
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()

1112
fiche.c

File diff suppressed because it is too large Load Diff

153
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) License: MIT (http://www.opensource.org/licenses/mit-license.php)
Repository: https://github.com/solusipse/fiche/ Repository: https://github.com/solusipse/fiche/
Live example: http://termbin.com Live example: http://code.solusipse.net/
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -14,7 +14,15 @@ usage: fiche [-DepbsdolBuw].
[-o output directory] [-B buffer size] [-u user name] [-o output directory] [-B buffer size] [-u user name]
[-l log file] [-b banlist] [-w whitelist] [-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: Use netcat to push text - example:
$ cat fiche.c | nc localhost 9999 $ cat fiche.c | nc localhost 9999
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -23,97 +31,72 @@ $ cat fiche.c | nc localhost 9999
#ifndef FICHE_H #ifndef FICHE_H
#define FICHE_H #define FICHE_H
#include <stdint.h> #include <pwd.h>
#include <stdbool.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 PORT = 9999;
int SLUG_SIZE = 4;
int BUFSIZE = 32768;
int QUEUE_SIZE = 500;
char DOMAIN[128] = "http://localhost/";
char symbols[67] = "abcdefghijklmnopqrstuvwxyz0123456789";
/** unsigned int time_seed;
* @brief Used as a container for fiche settings. Create before
* the initialization
*
*/
typedef struct Fiche_Settings {
/**
* @brief Domain used in output links
*/
char *domain;
/** struct thread_arguments
* @brief Path to directory used for storing uploaded pastes {
*/ int connection_socket;
char *output_dir_path; struct sockaddr_in client_address;
};
/** struct client_data
* @brief Address on which fiche is waiting for connections {
*/ char *ip_address;
char *listen_addr; char *hostname;
};
/** int create_socket();
* @brief Port on which fiche is waiting for connections int create_directory(char *slug);
*/ int check_protocol(char *buffer);
uint16_t port;
/** void bind_to_port(int listen_socket, struct sockaddr_in serveraddr);
* @brief Length of a paste's name void error(char *buffer);
*/ void perform_connection(int listen_socket);
uint8_t slug_len; 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 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();
/** char *check_banlist(char *ip_address);
* @brief If set, returns url with https prefix instead of http char *check_whitelist(char *ip_address);
*/ char *get_date();
bool https;
/**
* @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);
struct client_data get_client_address(struct sockaddr_in client_address);
#endif #endif

147
main.c
View File

@@ -1,147 +0,0 @@
/*
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;
}