Exemple #1
0
static struct evbuffer *httpc_mkconnect(redsocks_client *client)
{
	struct evbuffer *buff = NULL, *retval = NULL;
	int len;

	buff = evbuffer_new();
	if (!buff) {
		redsocks_log_errno(client, LOG_ERR, "evbuffer_new");
		goto fail;
	}

	http_auth *auth = (void*)(client->instance + 1);
	++auth->last_auth_count;

	const char *auth_scheme = NULL;
	char *auth_string = NULL;

	if (auth->last_auth_query != NULL) {
		/* find previous auth challange */

		if (strncasecmp(auth->last_auth_query, "Basic", 5) == 0) {
			auth_string = basic_authentication_encode(client->instance->config.login, client->instance->config.password);
			auth_scheme = "Basic";
		} else if (strncasecmp(auth->last_auth_query, "Digest", 6) == 0) {
			/* calculate uri */
			char uri[128];
			snprintf(uri, 128, "%s:%u", inet_ntoa(client->destaddr.sin_addr), ntohs(client->destaddr.sin_port));

			/* prepare an random string for cnounce */
			char cnounce[17];
			srand(time(0));
			for (int i = 0; i < 16; i += 4)
				sprintf(cnounce + i, "%02x", rand() & 65535);

			auth_string = digest_authentication_encode(auth->last_auth_query + 7, //line
					client->instance->config.login, client->instance->config.password, //user, pass
					"CONNECT", uri, auth->last_auth_count, cnounce); // method, path, nc, cnounce
			auth_scheme = "Digest";
		}
	}

	if (auth_string == NULL) {
		len = evbuffer_add_printf(buff,
			"CONNECT %s:%u HTTP/1.0\r\n\r\n",
			inet_ntoa(client->destaddr.sin_addr),
			ntohs(client->destaddr.sin_port)
		);
	} else {
		len = evbuffer_add_printf(buff,
			"CONNECT %s:%u HTTP/1.0\r\n%s %s %s\r\n\r\n",
			inet_ntoa(client->destaddr.sin_addr),
			ntohs(client->destaddr.sin_port),
			auth_response_header,
			auth_scheme,
			auth_string
		);
	}

	free(auth_string);

	if (len < 0) {
		redsocks_log_errno(client, LOG_ERR, "evbufer_add_printf");
		goto fail;
	}

	retval = buff;
	buff = NULL;

fail:
	if (buff)
		evbuffer_free(buff);
	return retval;
}
Exemple #2
0
static void httpr_relay_write_cb(struct bufferevent *buffev, void *_arg)
{
	redsocks_client *client = _arg;
	httpr_client *httpr = (void*)(client + 1);
	int len = 0;

	assert(client->state >= httpr_recv_request_headers);

	redsocks_touch_client(client);

	if (client->state == httpr_recv_request_headers) {
		if (httpr->firstline) {
			len = bufferevent_write(client->relay, httpr->firstline, strlen(httpr->firstline));
			if (len < 0) {
				redsocks_log_errno(client, LOG_ERR, "bufferevent_write");
				redsocks_drop_client(client);
				return;
			}
		}


		http_auth *auth = (void*)(client->instance + 1);
		++auth->last_auth_count;

		const char *auth_scheme = NULL;
		char *auth_string = NULL;

		if (auth->last_auth_query != NULL) {
			/* find previous auth challange */

			if (strncasecmp(auth->last_auth_query, "Basic", 5) == 0) {
				auth_string = basic_authentication_encode(client->instance->config.login, client->instance->config.password);
				auth_scheme = "Basic";
			} else if (strncasecmp(auth->last_auth_query, "Digest", 6) == 0 && httpr->firstline) {
				/* calculate method & uri */
				char *ptr = strchr(httpr->firstline, ' '), *ptr2;
				char *method = calloc(ptr - httpr->firstline + 1, 1);
				memcpy(method, httpr->firstline, ptr - httpr->firstline);
				method[ptr - httpr->firstline] = 0;

				ptr = strchr(httpr->firstline, '/');
				if (!ptr || *++ptr != '/') {
					free(method);
					redsocks_log_error(client, LOG_NOTICE, "malformed request came");
					redsocks_drop_client(client);
					return;
				}
				if (!(ptr = strchr(++ptr, '/')) || !(ptr2 = strchr(ptr, ' '))) {
					free(method);
					redsocks_log_error(client, LOG_NOTICE, "malformed request came");
					redsocks_drop_client(client);
					return;
				}
				char *uri = calloc(ptr2 - ptr + 1, 1);
				memcpy(uri, ptr, ptr2 - ptr);
				uri[ptr2 - ptr] = 0;

				/* prepare an random string for cnounce */
				char cnounce[17];
				snprintf(cnounce, sizeof(cnounce), "%08x%08x", red_randui32(), red_randui32());

				auth_string = digest_authentication_encode(auth->last_auth_query + 7, //line
						client->instance->config.login, client->instance->config.password, //user, pass
						method, uri, auth->last_auth_count, cnounce); // method, path, nc, cnounce

				free(method);
				free(uri);
				auth_scheme = "Digest";
			}
		}

		if (auth_string != NULL) {
			len = 0;
			len |= bufferevent_write(client->relay, auth_response_header, strlen(auth_response_header));
			len |= bufferevent_write(client->relay, " ", 1);
			len |= bufferevent_write(client->relay, auth_scheme, strlen(auth_scheme));
			len |= bufferevent_write(client->relay, " ", 1);
			len |= bufferevent_write(client->relay, auth_string, strlen(auth_string));
			len |= bufferevent_write(client->relay, "\r\n", 2);
			if (len) {
				redsocks_log_errno(client, LOG_ERR, "bufferevent_write");
				redsocks_drop_client(client);
				return;
			}
		}

		free(auth_string);

		len = bufferevent_write(client->relay, httpr->client_buffer.buff, httpr->client_buffer.len);
		if (len < 0) {
			redsocks_log_errno(client, LOG_ERR, "bufferevent_write");
			redsocks_drop_client(client);
			return;
		}

		client->state = httpr_request_sent;

		buffev->wm_read.low = 1;
		buffev->wm_read.high = HTTP_HEAD_WM_HIGH;
		bufferevent_enable(buffev, EV_READ);
	}
}
Exemple #3
0
static struct evbuffer *httpc_mkconnect(redsocks_client *client)
{
	struct evbuffer *buff = NULL, *retval = NULL;
	char *auth_string = NULL;
	int len;

	buff = evbuffer_new();
	if (!buff) {
		redsocks_log_errno(client, LOG_ERR, "evbuffer_new");
		goto fail;
	}

	http_auth *auth = red_http_auth(client->instance);
	++auth->last_auth_count;

	const char *auth_scheme = NULL;

	if (auth->last_auth_query != NULL) {
		/* find previous auth challange */

		if (strncasecmp(auth->last_auth_query, "Basic", 5) == 0) {
			auth_string = basic_authentication_encode(client->instance->config.login, client->instance->config.password);
			auth_scheme = "Basic";
		} else if (strncasecmp(auth->last_auth_query, "Digest", 6) == 0) {
			/* calculate uri */
			char uri[128];
			snprintf(uri, 128, "%s:%u", inet_ntoa(client->destaddr.sin_addr), ntohs(client->destaddr.sin_port));

			/* prepare an random string for cnounce */
			char cnounce[17];
			snprintf(cnounce, sizeof(cnounce), "%08x%08x", red_randui32(), red_randui32());

			auth_string = digest_authentication_encode(auth->last_auth_query + 7, //line
					client->instance->config.login, client->instance->config.password, //user, pass
					"CONNECT", uri, auth->last_auth_count, cnounce); // method, path, nc, cnounce
			auth_scheme = "Digest";
		}
	}

	// TODO: do accurate evbuffer_expand() while cleaning up http-auth
	len = evbuffer_add_printf(buff, "CONNECT %s:%u HTTP/1.0\r\n",
		inet_ntoa(client->destaddr.sin_addr),
		ntohs(client->destaddr.sin_port));
	if (len < 0) {
		redsocks_log_errno(client, LOG_ERR, "evbufer_add_printf");
		goto fail;
	}

	if (auth_string) {
		len = evbuffer_add_printf(buff, "%s %s %s\r\n",
			auth_response_header, auth_scheme, auth_string);
		if (len < 0) {
			redsocks_log_errno(client, LOG_ERR, "evbufer_add_printf");
			goto fail;
		}
		free(auth_string);
		auth_string = NULL;
	}

	const enum disclose_src_e disclose_src = client->instance->config.disclose_src;
	if (disclose_src != DISCLOSE_NONE) {
		char clientip[INET_ADDRSTRLEN];
		const char *ip = inet_ntop(client->clientaddr.sin_family, &client->clientaddr.sin_addr, clientip, sizeof(clientip));
		if (!ip) {
			redsocks_log_errno(client, LOG_ERR, "inet_ntop");
			goto fail;
		}
		if (disclose_src == DISCLOSE_X_FORWARDED_FOR) {
			len = evbuffer_add_printf(buff, "X-Forwarded-For: %s\r\n", ip);
		} else if (disclose_src == DISCLOSE_FORWARDED_IP) {
			len = evbuffer_add_printf(buff, "Forwarded: for=%s\r\n", ip);
		} else if (disclose_src == DISCLOSE_FORWARDED_IPPORT) {
			len = evbuffer_add_printf(buff, "Forwarded: for=\"%s:%d\"\r\n", ip,
				ntohs(client->clientaddr.sin_port));
		}
		if (len < 0) {
			redsocks_log_errno(client, LOG_ERR, "evbufer_add_printf");
			goto fail;
		}
	}

	len = evbuffer_add(buff, "\r\n", 2);
	if (len < 0) {
		redsocks_log_errno(client, LOG_ERR, "evbufer_add");
		goto fail;
	}

	retval = buff;
	buff = NULL;

fail:
	if (auth_string)
		free(auth_string);
	if (buff)
		evbuffer_free(buff);
	return retval;
}