154 lines
2.8 KiB
C
154 lines
2.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
#include <openssl/bio.h>
|
|
#include <openssl/err.h>
|
|
#include <openssl/ssl.h>
|
|
|
|
#include "gemlib.h"
|
|
|
|
void GEM_init (void)
|
|
{
|
|
SSL_load_error_strings();
|
|
SSL_library_init();
|
|
}
|
|
|
|
GEM_Request *GEM_new_request(const char *request_content)
|
|
{
|
|
int i = 0, len = 0, len_req = strlen(request_content);
|
|
GEM_Request *request = malloc(sizeof(GEM_Request));
|
|
|
|
if (request == NULL)
|
|
return NULL;
|
|
|
|
memset(request, 0, sizeof(GEM_Request));
|
|
|
|
strcpy(request->request_content, request_content);
|
|
strcat(request->request_content, "\r\n");
|
|
|
|
/* We are trying to determine the protocol */
|
|
while (i <= len_req - 3)
|
|
if (request_content[i] != ':' || request_content[i + 1] != '/' || request_content[i + 2] != '/')
|
|
{
|
|
i++;
|
|
len++;
|
|
}
|
|
else
|
|
{
|
|
strncpy(request->scheme, request_content + i - len, len);
|
|
break;
|
|
}
|
|
|
|
/* If no protocol found error */
|
|
if (request->scheme[0] == 0)
|
|
{
|
|
free(request);
|
|
return NULL;
|
|
}
|
|
|
|
/* We skip the :// */
|
|
i += 3;
|
|
len = 0;
|
|
|
|
/* We try to determine hostname + port */
|
|
while (i < len_req && request_content[i] != '/')
|
|
{
|
|
i++;
|
|
len++;
|
|
}
|
|
|
|
strncpy(request->hostname, request_content + i - len, len);
|
|
|
|
/* if no hostname error */
|
|
if (request->hostname[0] == 0)
|
|
{
|
|
free(request);
|
|
return NULL;
|
|
}
|
|
|
|
/* now fill path in request struct */
|
|
strncpy(request->path, request_content + i, strlen(request_content) - i);
|
|
|
|
/* if path is empty, so path is root */
|
|
if (request->path[0] == 0)
|
|
strcpy(request->path, "/");
|
|
|
|
return request;
|
|
}
|
|
|
|
void GEM_print_request_info (GEM_Request *request)
|
|
{
|
|
printf("Request content : %s\nRequest scheme : %s\nRequest hostname : %s\nRequest path : %s\n", request->request_content, request->scheme, request->hostname, request->path);
|
|
}
|
|
|
|
int GEM_send_request (GEM_Request *request, FILE *answerFile)
|
|
{
|
|
const SSL_METHOD *method = TLS_client_method();
|
|
SSL *ssl = NULL;
|
|
SSL_CTX *ctx = NULL;
|
|
BIO *bio = NULL;
|
|
int n;
|
|
char buffer[1024];
|
|
|
|
if (method == NULL)
|
|
{
|
|
perror("Method");
|
|
ERR_print_errors_fp(stderr);
|
|
return -1;
|
|
}
|
|
|
|
ctx = SSL_CTX_new(method);
|
|
|
|
if (ctx == NULL)
|
|
{
|
|
perror("ctx");
|
|
ERR_print_errors_fp(stderr);
|
|
return -1;
|
|
}
|
|
|
|
bio = BIO_new_ssl_connect(ctx);
|
|
|
|
if (bio == NULL)
|
|
{
|
|
perror("bio");
|
|
ERR_print_errors_fp(stderr);
|
|
SSL_CTX_free(ctx);
|
|
return -1;
|
|
}
|
|
|
|
BIO_get_ssl(bio, &ssl);
|
|
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
|
|
BIO_set_conn_hostname(bio, request->hostname);
|
|
|
|
if (BIO_do_connect(bio) <= 0)
|
|
{
|
|
BIO_free_all(bio);
|
|
SSL_CTX_free(ctx);
|
|
perror("bio connect");
|
|
ERR_print_errors_fp(stderr);
|
|
return -1;
|
|
}
|
|
|
|
BIO_puts(bio, request->request_content);
|
|
|
|
n = BIO_read(bio, buffer, 1023);
|
|
|
|
while (n > 0)
|
|
{
|
|
fwrite(buffer, sizeof(char), n, answerFile);
|
|
n = BIO_read(bio, buffer, 1024);
|
|
}
|
|
|
|
BIO_free_all(bio);
|
|
SSL_CTX_free(ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void GEM_free_request (GEM_Request *request)
|
|
{
|
|
free(request);
|
|
}
|