234 lines
7.4 KiB
C
234 lines
7.4 KiB
C
#include "tor_ctl.h"
|
|
|
|
int tor_ctl_connect(struct tor_ctl* ctx, char* addr, char* service) {
|
|
int sock = create_tcp_client (addr, service);
|
|
int sock2 = dup(sock);
|
|
ctx->rsock = NULL;
|
|
ctx->wsock = NULL;
|
|
|
|
ctx->rsock = fdopen(sock, "r");
|
|
if (ctx->rsock == NULL) {
|
|
return -1;
|
|
}
|
|
setbuf(ctx->rsock, NULL);
|
|
|
|
ctx->wsock = fdopen(sock2, "w");
|
|
if (ctx->wsock == NULL) {
|
|
return -1;
|
|
}
|
|
setbuf(ctx->wsock, NULL);
|
|
|
|
fprintf (ctx->wsock, "authenticate \"\"\n");
|
|
int error_code = 0;
|
|
fscanf (ctx->rsock, "%d", &error_code);
|
|
if (error_code != 250) {
|
|
tor_ctl_close (ctx);
|
|
return -1;
|
|
}
|
|
fscanf(ctx->rsock," OK");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void tor_ctl_list_onions(struct tor_ctl* ctx) {
|
|
fprintf(ctx->wsock, "getinfo onions/current\n");
|
|
|
|
char delimiter, buffer[1024] = {0};
|
|
fscanf(ctx->rsock, " 250%c", &delimiter);
|
|
if (delimiter == '-') {
|
|
fscanf(ctx->rsock, "onions/current=%s", buffer);
|
|
if (strlen(buffer) > 0) printf("key: %s\n", buffer);
|
|
} else if (delimiter == '+') {
|
|
fscanf(ctx->rsock, "onions/current= ");
|
|
while (1) {
|
|
fgets(buffer, 1024, ctx->rsock);
|
|
if (strcmp(buffer, "250 OK\r\n") == 0) break;
|
|
if (strcmp(buffer, ".\r\n") == 0) continue;
|
|
printf("line: %s", buffer);
|
|
}
|
|
} else {
|
|
printf("deli:%c\n", delimiter);
|
|
}
|
|
}
|
|
|
|
int tor_ctl_add_onion(struct tor_ctl* ctx, struct tor_os_str* tos, uint16_t* port, uint64_t port_per_os, enum TOR_ONION_FLAGS flags) {
|
|
int err = 0;
|
|
char buffer1[1024] = {0};
|
|
char buffer2[1024] = {0};
|
|
int to_create = tos->size - tos->filled;
|
|
|
|
/* Add onion services loaded from file */
|
|
for (int i = 0; i < tos->filled; i++) {
|
|
fprintf(ctx->wsock, "add_onion %s ", tos->keys[i].priv);
|
|
for (int j = 0; j < port_per_os; j++) {
|
|
fprintf(ctx->wsock, "Port=%d,127.13.3.7:%d ", port[i*port_per_os+j], port[i*port_per_os+j]);
|
|
}
|
|
if (flags == TOR_ONION_FLAG_NONE) fprintf(ctx->wsock, "\n");
|
|
else {
|
|
fprintf(ctx->wsock, "Flags=");
|
|
if (flags & TOR_ONION_FLAG_NON_ANONYMOUS) fprintf(ctx->wsock, "NonAnonymous,");
|
|
fprintf(ctx->wsock, "\n");
|
|
}
|
|
|
|
fscanf(ctx->rsock, "%d", &err);
|
|
if (err != 250) {
|
|
printf("err: %d\n", err);
|
|
return -1;
|
|
}
|
|
fscanf(ctx->rsock, "-ServiceID=%s\n", buffer1);
|
|
printf("Added onion service %s.onion from file\n", buffer1);
|
|
fscanf(ctx->rsock, "250 OK");
|
|
}
|
|
|
|
/* Complete by creating new onion services */
|
|
for (int i = tos->filled; i < tos->size; i++) {
|
|
fprintf(ctx->wsock, "add_onion NEW:ED25519-V3 ");
|
|
for (int j = 0; j < port_per_os; j++) {
|
|
fprintf(ctx->wsock, "Port=%d,127.13.3.7:%d ", port[i*port_per_os+j], port[i*port_per_os+j]);
|
|
}
|
|
if (flags == TOR_ONION_FLAG_NONE) fprintf(ctx->wsock, "\n");
|
|
else {
|
|
fprintf(ctx->wsock, "Flags=");
|
|
if (flags & TOR_ONION_FLAG_NON_ANONYMOUS) fprintf(ctx->wsock, "NonAnonymous,");
|
|
fprintf(ctx->wsock, "\n");
|
|
}
|
|
|
|
//fprintf(ctx->wsock, "add_onion NEW:RSA1024 Port=%d\n", port[i]);
|
|
|
|
err = 0;
|
|
fscanf(ctx->rsock, "%d", &err);
|
|
|
|
if (err != 250) {
|
|
fprintf(stderr, "Got error %d instead of 250\n", err);
|
|
return -2;
|
|
}
|
|
err = fscanf(ctx->rsock, "-ServiceID=%s\n", buffer1);
|
|
if (err <= 0) return -3;
|
|
printf("Created onion service %s.onion\n", buffer1);
|
|
err = fscanf(ctx->rsock, "250-PrivateKey=%s\n", buffer2);
|
|
if (err <= 0) return -4;
|
|
//printf("Onion service private key: %s\n", buffer);
|
|
if (tor_os_append(tos, buffer1, buffer2) != 0) return -5;
|
|
err = fscanf(ctx->rsock, "250 OK");
|
|
if (err < 0) return -6;
|
|
}
|
|
|
|
if (to_create > 0) {
|
|
tor_os_persist(tos);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void tor_ctl_close(struct tor_ctl* ctx) {
|
|
fclose(ctx->rsock);
|
|
fclose(ctx->wsock);
|
|
}
|
|
|
|
int on_torctl_server_auth_read(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) {
|
|
char *expected = "authenticate \"\"\n";
|
|
size_t to_read = strlen(expected);
|
|
char buffer[128] = {0};
|
|
ssize_t nread = recv(fdinfo->fd, buffer, to_read, MSG_PEEK);
|
|
if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED;
|
|
if (nread != to_read) return EVT_CORE_FD_EXHAUSTED;
|
|
|
|
recv(fdinfo->fd, buffer, to_read, 0);
|
|
if (strstr(buffer, "authenticate") == NULL) {
|
|
fprintf(stderr, "Unable to find string 'authenticate' in receveived command: '%s'\n", buffer);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
evt_core_mv_fd2 (ctx, fdinfo, "torctl-server-auth-write");
|
|
return EVT_CORE_FD_EXHAUSTED;
|
|
}
|
|
|
|
int on_torctl_server_auth_write(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) {
|
|
char *response = "250 OK\r\n";
|
|
ssize_t nwrite = send(fdinfo->fd, response, sizeof(response), 0);
|
|
if (nwrite != sizeof(response)) {
|
|
perror("@FIXME: Unproper handling of sockets in torctl_server_auth_write.");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
evt_core_mv_fd2 (ctx, fdinfo, "torctl-server-add-onion-read");
|
|
return EVT_CORE_FD_EXHAUSTED;
|
|
}
|
|
|
|
int on_torctl_server_add_onion_read(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) {
|
|
char buffer[1024] = {0};
|
|
|
|
ssize_t nread = recv(fdinfo->fd, buffer, sizeof(buffer), MSG_PEEK);
|
|
if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED;
|
|
if (nread == -1) {
|
|
perror("an error occured...");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (buffer[nread-1] != '\n') return EVT_CORE_FD_EXHAUSTED;
|
|
nread = recv(fdinfo->fd, buffer, sizeof(buffer), 0);
|
|
|
|
printf("[%s][torctl] Received command: %s\n", current_human_datetime (), buffer);
|
|
evt_core_mv_fd2 (ctx, fdinfo, "torctl-server-add-onion-write");
|
|
return EVT_CORE_FD_EXHAUSTED;
|
|
}
|
|
|
|
int on_torctl_server_add_onion_write(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) {
|
|
char *answer = "250-ServiceID=iu7aeep42k5ky3fwcfag5el2raelfcwuilsstqhcz3c6bmxilr2nuayd\r\n250-PrivateKey=ED25519-V3:ULk3Q/TFqngKCDDzeM93YC80IDOjz13PKTx718UjE0Svf+u/QZmN9EHzUCqCa1ZkNAXSQJIzcOVeJ8OL8Zg5Xg==\r\n250 OK\r\n";
|
|
|
|
ssize_t nwrite;
|
|
nwrite = send(fdinfo->fd, answer, strlen(answer), 0);
|
|
if (nwrite != strlen(answer)) goto error;
|
|
|
|
printf("[%s][torctl] Sent add-onion reply\n", current_human_datetime ());
|
|
evt_core_mv_fd2(ctx,fdinfo,"torctl-server-add-onion-read");
|
|
return EVT_CORE_FD_EXHAUSTED;
|
|
|
|
error:
|
|
perror("@FIXME: unproper handling of non blocking sockets, you have been bitten in torctl server add onion write\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
void tor_ctl_server_init(struct evt_core_ctx *ctx) {
|
|
struct evt_core_cat template = {0};
|
|
|
|
template.cb = on_torctl_server_auth_read;
|
|
template.err_cb = NULL;
|
|
template.name = "torctl-server-auth-read";
|
|
template.flags = EPOLLIN | EPOLLET;
|
|
evt_core_add_cat (ctx, &template);
|
|
|
|
template.cb = on_torctl_server_auth_write;
|
|
template.err_cb = NULL;
|
|
template.name = "torctl-server-auth-write";
|
|
template.flags = EPOLLOUT | EPOLLET;
|
|
evt_core_add_cat (ctx, &template);
|
|
|
|
template.cb = on_torctl_server_add_onion_read;
|
|
template.err_cb = NULL;
|
|
template.name = "torctl-server-add-onion-read";
|
|
template.flags = EPOLLIN | EPOLLET;
|
|
evt_core_add_cat (ctx, &template);
|
|
|
|
template.cb = on_torctl_server_add_onion_write;
|
|
template.err_cb = NULL;
|
|
template.name = "torctl-server-add-onion-write";
|
|
template.flags = EPOLLOUT | EPOLLET;
|
|
evt_core_add_cat (ctx, &template);
|
|
}
|
|
|
|
void tor_ctl_server_handle(struct evt_core_ctx *ctx, int fd) {
|
|
struct evt_core_fdinfo *reg_fdinfo;
|
|
struct evt_core_fdinfo fdinfo;
|
|
struct evt_core_cat cat;
|
|
char url[256];
|
|
|
|
fdinfo.cat = &cat;
|
|
fdinfo.cat->name = "torctl-server-auth-read";
|
|
fdinfo.fd = fd;
|
|
fdinfo.other = NULL;
|
|
fdinfo.free_other = NULL;
|
|
sprintf(url, "tor-ctl-server:%d", fd);
|
|
fdinfo.url = url;
|
|
|
|
reg_fdinfo = evt_core_add_fd (ctx, &fdinfo);
|
|
}
|