Add support for pastebin.stratumzero.date.

- use -s flag to enable it
- required support for Content-Type: multipart/form-data
This commit is contained in:
Érico Nogueira 2021-12-09 00:58:44 -03:00
parent 1e7d2a5517
commit cd14bff782
6 changed files with 79 additions and 12 deletions

View File

@ -57,7 +57,8 @@ Instead of using Ninja, you can use
This is a pure C client for the
[PurritoBin](https://github.com/PurritoBin/PurritoBin) pastebin server, and uses
PurritoBin's author's instance in <https://bsd.ac> by default.
PurritoBin's author's instance at <https://bsd.ac> by default. It also supports
[zdykstra's pastebin](https://github.com/zdykstra/pastebin).
It supports symmetric paste encryption (as supported by PurritoBin's online
interface and its [suggested

8
comm.c
View File

@ -70,7 +70,13 @@ int send_and_receive(struct connection_information *ci)
fprintf(stderr, _("wrote %lu bytes!\n"), sent);
}
}
if (ti.ssl) br_sslio_flush(ci->ioc);
if (ti.ssl) {
br_sslio_write_all(ci->ioc, ci->footer, ci->footer_size);
br_sslio_flush(ci->ioc);
} else {
fwrite(ci->footer, 1, ci->footer_size, ti.socket_write_stream);
}
ti.file = ci->output;

View File

@ -170,6 +170,7 @@ msgid ""
" -u <url>: URL to use for send functionality\n"
" -p <port>: port to use for send\n"
" -o <output_file>: use file instead of stdout\n"
" -s: use settings for pastebin.stratumzero.date\n"
" -n: don't strip HTTP header from response\n"
" -e: encrypt content: limited to 128KiB files\n"
" -d: debug\n"
@ -181,6 +182,7 @@ msgstr ""
" -u <url>: URL utilizada para envio\n"
" -p <porta>: porta utilizada para envio\n"
" -o <arquivo_de_saída>: utilize esse arquivo ao invés da saída padrão\n"
" -s: utilizar configurações para pastebin.stratumzero.date\n"
" -n: não esconder cabeçalho HTTP da resposta\n"
" -e: encriptar conteúdo: limitado a aquivos de 128KiB\n"
" -d: rodar em modo de debug\n"

View File

@ -151,6 +151,7 @@ msgid ""
" -u <url>: URL to use for send functionality\n"
" -p <port>: port to use for send\n"
" -o <output_file>: use file instead of stdout\n"
" -s: use settings for pastebin.stratumzero.date\n"
" -n: don't strip HTTP header from response\n"
" -e: encrypt content: limited to 128KiB files\n"
" -d: debug\n"

73
purr.c
View File

@ -1,4 +1,5 @@
#define _POSIX_C_SOURCE 200112L /* getopt */
#include <libgen.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@ -38,6 +39,7 @@ static void usage(bool fail)
" -u <url>: URL to use for send functionality\n"
" -p <port>: port to use for send\n"
" -o <output_file>: use file instead of stdout\n"
" -s: use settings for " "pastebin" /*garbage*/ ".stratumzero." /*garbage*/ "date\n"
" -n: don't strip HTTP header from response\n"
" -e: encrypt content: limited to 128KiB files\n"
" -d: debug\n"
@ -55,7 +57,7 @@ int main (int argc, char **argv)
int rv = EXIT_SUCCESS;
char *algo = NULL, *url_opt = NULL, *port_opt = NULL, *output_file = NULL;
bool no_strip = false, encrypt = false, debug = false;
bool no_strip = false, encrypt = false, debug = false, stratum = false;
bool send = false, recv = false;
@ -76,7 +78,7 @@ int main (int argc, char **argv)
}
int c;
while ((c = getopt(argc, argv, "a:u:p:o:nedh")) != -1) {
while ((c = getopt(argc, argv, "a:u:p:o:snedh")) != -1) {
switch (c) {
case 'a':
algo = optarg;
@ -93,6 +95,10 @@ int main (int argc, char **argv)
case 'o':
output_file = optarg;
break;
case 's':
stratum = true;
url_opt = "https://" /*garbage*/ "pastebin" /*garbage*/ ".stratumzero." /*garbage*/ "date/" /*garbage*/ "upload";
break;
case 'n':
no_strip = true;
break;
@ -154,6 +160,7 @@ int main (int argc, char **argv)
exit(EXIT_FAILURE);
}
bool using_stdin = false;
char *url;
if (recv) {
if (argc != 2) {
@ -165,7 +172,6 @@ int main (int argc, char **argv)
}
url = argv[1];
} else if (send) {
bool using_stdin = false;
if (argc > 2) {
usage(true);
} else if (argc == 2 && strcmp(argv[1], "-")) {
@ -308,6 +314,7 @@ int main (int argc, char **argv)
const int going_to_write = HEADER_MAX_LEN;
char request[HEADER_MAX_LEN];
char footer[HEADER_MAX_LEN] = "";
int written = 0;
if (recv) {
written = snprintf(
@ -319,18 +326,58 @@ int main (int argc, char **argv)
"\r\n",
path, http_ver, link);
} else if (send) {
char multipart[HEADER_MAX_LEN];
int multipart_written = 0;
if (stratum) {
#define PURR_BOUNDARY_MIN "----purr-boundary"
#define PURR_BOUNDARY "--" PURR_BOUNDARY_MIN "\r\n"
multipart_written = snprintf(
multipart, going_to_write,
"Content-Type: multipart/form-data; boundary=" PURR_BOUNDARY_MIN "\r\n"
"\r\n");
multipart_written = snprintf(
multipart + multipart_written, going_to_write - multipart_written,
PURR_BOUNDARY
"Content-Disposition: form-data; name=\"s\"\r\n"
"\r\n"
"1\r\n"
PURR_BOUNDARY
"Content-Disposition: form-data; name=\"o\"\r\n"
"\r\n"
"0\r\n"
PURR_BOUNDARY
"Content-Disposition: form-data; name=\"p\"; filename=\"%s\"\r\n"
"Content-Type: application/octet-stream\r\n"
"\r\n",
using_stdin ? "stream" : basename(argv[1]));
multipart_written += snprintf(footer, going_to_write, "\r\n--" PURR_BOUNDARY_MIN "\r\n");
}
if (multipart_written >= going_to_write) goto truncate_request;
written = snprintf(
request, going_to_write,
"POST %s %s\r\n"
"Host: %s\r\n"
"Accept: */*\r\n"
"Content-Length: %lu\r\n" // required in most cases and good practice
"Content-Type: application/octet-stream\r\n" // can be any file type
"\r\n",
path, http_ver, link, input.size);
"Content-Length: %lu\r\n", // required in most cases and good practice
path, http_ver, link, input.size + multipart_written);
if (written < going_to_write) {
if (stratum) {
written += snprintf(request + written, going_to_write - written, "%s", multipart);
} else {
written += snprintf(
request + written, going_to_write - written,
"Content-Type: application/octet-stream\r\n"
"\r\n");
}
}
}
if (written >= going_to_write) {
truncate_request:
fputs(_("error: truncated request!\n"), stderr);
goto out;
}
@ -338,11 +385,18 @@ int main (int argc, char **argv)
fputs("request header: -------------\n", stderr);
fputs(request, stderr);
fputs("-----------------------------\n", stderr);
if (footer[0]) {
fputs("request footer: -------------\n", stderr);
fputs(footer, stderr);
fputs("-----------------------------\n", stderr);
}
}
struct connection_information ci =
{.ioc = &ioc, .sc = &sc,
.request = request, .request_size = written,
.footer = footer, .footer_size = strlen(footer),
.input = &input, .output = &output,
.socket = socket,
.send = send, .ssl = ssl,
@ -405,7 +459,10 @@ int main (int argc, char **argv)
free(key);
free(iv);
early_out:
if (output_print != stdout) fclose(output_print);
// will be fclosed in free_mmap sometimes, figure out the leakage
// if stdout, we don't want free_mmap to kill it, I think
// but if not stdout, we don't want to have to worry about closing it either
//if (output_print != stdout) fclose(output_print);
free_mmap(&input);
free_mmap(&output);

4
purr.h
View File

@ -40,8 +40,8 @@ typedef void (*header_callback_def)(int, const char *);
struct connection_information {
br_sslio_context *ioc;
br_ssl_client_context *sc;
const char *request;
size_t request_size;
const char *request, *footer;
size_t request_size, footer_size;
struct mmap_file *input, *output;
int socket;
bool send, ssl;