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