Write webserver part in C

It is a probably working FastCGI program.
Other parts will be ready later.

clang -g doskast-trigger-connect.c -o t -l fcgi -l gnutls
master
Mikhail Novosyolov 3 years ago
parent 8636aab44b
commit fcd29a4974
  1. 130
      webserver/doskast-trigger-connect.c

@ -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…
Cancel
Save