It is a probably working FastCGI program. Other parts will be ready later. clang -g doskast-trigger-connect.c -o t -l fcgi -l gnutlsmaster
parent
8636aab44b
commit
fcd29a4974
@ -0,0 +1,130 @@ |
||||
#include <ctype.h> |
||||
#include <fcntl.h> |
||||
#include <stdlib.h> |
||||
#include <stdint.h> |
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
#include <fcgios.h> |
||||
#include <fcgi_stdio.h> |
||||
#include <gnutls/gnutls.h> |
||||
#include <gnutls/crypto.h> |
||||
|
||||
// allow to redefine as gcc -D...
|
||||
#ifndef DIR |
||||
#define DIR "/tmp" |
||||
#endif |
||||
|
||||
#define HTTP_OK 200 |
||||
#define HTTP_BAD_REQUEST 400 |
||||
#define HTTP_ERROR 500 |
||||
|
||||
/* Here we could verify validity of a IPv4 or IPv6 address,
|
||||
* but that is very complex. Just sanitize input. */ |
||||
int |
||||
_verify_ip(char *ip){ |
||||
int rc = 0; |
||||
for (int i = 0; i < strlen(ip); i++){ |
||||
if (!( (ip[i] == '.') || /* IPv4 dots */ |
||||
(ip[i] == ':') || /* IPv6 */ |
||||
(ip[i] == '/') || /* XXX Is it needed for IPv6? */ |
||||
(isalnum(ip[i]) > 0) /* Numbers (v4 and v6) and letters (v6) */ |
||||
)) { |
||||
rc = i; |
||||
break; |
||||
} |
||||
} |
||||
return rc; |
||||
} |
||||
|
||||
/* Generate a random alphanum sequence
|
||||
* Example: 10841ee0cc4f (12 chars) */ |
||||
int |
||||
_rand(char **rs){ |
||||
// https://books.google.ru/books?id=1nG3BwAAQBAJ
|
||||
// hex.data will be 6x2=12 chars
|
||||
unsigned char buf_rnd[6]; |
||||
gnutls_datum_t rnd = { buf_rnd, sizeof(buf_rnd) }; |
||||
int rc; |
||||
rc = gnutls_rnd(GNUTLS_RND_NONCE, rnd.data, rnd.size); |
||||
if (rc != GNUTLS_E_SUCCESS) { |
||||
printf("Error in gnutls_rnd()"); |
||||
goto out; |
||||
} |
||||
gnutls_datum_t hex; |
||||
rc = gnutls_hex_encode2(&rnd, &hex); |
||||
if (rc != GNUTLS_E_SUCCESS) { |
||||
printf("Error in gnutls_hex_encode2()"); |
||||
goto out; |
||||
} |
||||
*rs = malloc(hex.size); |
||||
rc = sprintf(*rs, "%s", hex.data); |
||||
if (rc < 0) { |
||||
printf("Error in sprintf()"); |
||||
goto out; |
||||
} |
||||
out: |
||||
return rc; |
||||
} |
||||
|
||||
int |
||||
main(){ |
||||
int rc = 0; |
||||
int http_code = HTTP_ERROR; |
||||
if (access(DIR, W_OK) != 0) { |
||||
fprintf(stderr, "Directory %s does not exist or is not writable\n", DIR); |
||||
http_code = HTTP_ERROR; |
||||
goto out; |
||||
} |
||||
// first chdir() and then chroot()!
|
||||
if (!( chdir(DIR) == 0 && chroot(DIR) == 0 )) { |
||||
fprintf(stderr, "Cannot chdir and chroot into %s\n", DIR); |
||||
http_code = HTTP_ERROR; |
||||
goto out; |
||||
} |
||||
while(FCGI_Accept() >= 0) { |
||||
char *ip = getenv("REMOTE_ADDR"); |
||||
if (ip == NULL) { |
||||
fprintf(stderr, "%s\n", "Env REMOTE_ADDR is not set"); |
||||
http_code = HTTP_ERROR; |
||||
goto fcgi_out; |
||||
} |
||||
rc = _verify_ip(ip); |
||||
if (rc != 0) { |
||||
fprintf(stderr, "%s\n", "Incorrect REMOTE_ADDR"); |
||||
http_code = HTTP_BAD_REQUEST; |
||||
goto fcgi_out; |
||||
} |
||||
char *hex; |
||||
int max_try = 10; |
||||
for (int i = 1; i <= max_try; i++) { |
||||
if (i == max_try) { |
||||
fprintf(stderr, "%s\n", "Error in random file loop"); |
||||
http_code = HTTP_ERROR; |
||||
goto fcgi_out; |
||||
} |
||||
rc = _rand(&hex); |
||||
if (rc < 0) { |
||||
fprintf(stderr, "Error in _rand()"); |
||||
continue; |
||||
} |
||||
if (access(hex, F_OK) != 0) { |
||||
break; |
||||
} |
||||
} |
||||
FCGI_FILE *d = fopen(hex, "w"); |
||||
fprintf(d, "%s", ip); |
||||
fclose(d); |
||||
http_code = HTTP_OK; |
||||
fcgi_out: |
||||
printf("Status: %d\n", http_code); |
||||
printf("Content-Type: text/plain; charset=utf-8\n"); |
||||
if (http_code == HTTP_OK) { |
||||
printf("%s\n", "OK"); |
||||
rc = 0; |
||||
} else { |
||||
rc = 1; |
||||
} |
||||
} |
||||
out: |
||||
return rc; |
||||
} |
Loading…
Reference in new issue