#include #include #include #include #include #include #include #include #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); }