Add basic auth to the webserver ##sync

This commit is contained in:
David CARLIER 2019-01-10 09:51:51 +00:00 committed by radare
parent 7185d6ca0a
commit de40266908
6 changed files with 141 additions and 20 deletions

View File

@ -28,6 +28,8 @@ static int usage (int v) {
" -d run in daemon mode (background)\n"
" -h show this help message\n"
" -s run in sandbox mode\n"
" -u enable http Authorization access\n"
" -t user:password authentification file\n"
" -p [port] specify listening port (defaults to 8080)\n");
return !v;
}
@ -39,14 +41,18 @@ static int showversion() {
int main(int argc, char **argv) {
RSocket *s;
RSocketHTTPOptions so;
RSocketHTTPRequest *rs;
int c, timeout = 3;
int c;
int dodaemon = 0;
int dosandbox = 0;
bool listenlocal = true;
const char *port = "8080";
const char *httpauthfile = NULL;
char *pfile = NULL;
memset (&so, 0, sizeof (so));
while ((c = getopt (argc, argv, "adhp:sv")) != -1) {
while ((c = getopt (argc, argv, "adhup:t:sv")) != -1) {
switch (c) {
case 'a':
listenlocal = false;
@ -61,6 +67,12 @@ int main(int argc, char **argv) {
return usage (1);
case 'v':
return showversion ();
case 'u':
so.httpauth = true;
break;
case 't':
httpauthfile = optarg;
break;
case 'p':
port = optarg;
break;
@ -72,6 +84,24 @@ int main(int argc, char **argv) {
return usage (0);
}
so.accept_timeout = 0;
so.timeout = 3;
if (so.httpauth) {
if (!httpauthfile) {
eprintf ("No authentification user list set\n");
return usage (0);
}
int sz;
pfile = r_file_slurp (httpauthfile, &sz);
if (pfile) {
so.authtokens = r_str_split_list (pfile, "\n");
} else {
eprintf ("Empty list of HTTP users\\n");
return usage (0);
}
}
#if USE_IOS_JETSAM
memorystatus_control (MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT, getpid (), 256, NULL, 0);
#endif
@ -95,6 +125,9 @@ int main(int argc, char **argv) {
eprintf ("http://localhost:%d/\n", s->port);
if (dosandbox && !r_sandbox_enable (true)) {
eprintf ("sandbox: Cannot be enabled.\n");
free (pfile);
r_list_free (so.authtokens);
r_socket_free (s);
return 1;
}
@ -104,10 +137,13 @@ int main(int argc, char **argv) {
char *result_heap = NULL;
const char *result = page_index;
rs = r_socket_http_accept (s, 0, timeout);
rs = r_socket_http_accept (s, &so);
if (!rs) {
continue;
}
if (!rs->auth) {
r_socket_http_response (rs, 401, "", 0, NULL);
}
if (!strcmp (rs->method, "GET")) {
if (!strncmp (rs->path, "/proc/kill/", 11)) {
// TODO: show page here?
@ -138,6 +174,8 @@ int main(int argc, char **argv) {
result = result_heap = malloc (1024 + escaped_len);
if (!result) {
perror ("malloc");
free (pfile);
r_list_free (so.authtokens);
return 1;
}
sprintf (result_heap,
@ -155,6 +193,8 @@ int main(int argc, char **argv) {
result_heap = NULL;
}
r_cons_free ();
free (pfile);
r_list_free (so.authtokens);
r_socket_free (s);
return 0;
}

View File

@ -3026,6 +3026,10 @@ R_API int r_core_config_init(RCore *core) {
SETPREF ("http.upget", "false", "/up/ answers GET requests, in addition to POST");
SETPREF ("http.upload", "false", "Enable file uploads to /up/<filename>");
SETPREF ("http.uri", "", "Address of HTTP proxy");
SETPREF ("http.auth", "false", "Enable/Disable HTTP Authentification");
SETPREF ("http.authtok", "r2admin:r2admin", "HTTP Authentification user:password token");
p = r_sys_getenv ("R2_HTTP_AUTHFILE");
SETPREF ("http.authfile", p? p : "", "HTTP Authentification user file");
tmpdir = r_file_tmpdir ();
r_config_set (cfg, "http.uproot", tmpdir);
free (tmpdir);

View File

@ -417,14 +417,17 @@ static int r_core_rtr_http_run(RCore *core, int launch, int browse, const char *
char buf[32];
int ret = 0;
RSocket *s;
RSocketHTTPOptions so;
char *dir;
int iport, timeout = r_config_get_i (core->config, "http.timeout");
int iport;
const char *host = r_config_get (core->config, "http.bind");
const char *root = r_config_get (core->config, "http.root");
const char *homeroot = r_config_get (core->config, "http.homeroot");
const char *port = r_config_get (core->config, "http.port");
const char *allow = r_config_get (core->config, "http.allow");
const char *httpui = r_config_get (core->config, "http.ui");
const char *httpauthfile = r_config_get (core->config, "http.authfile");
char *pfile = NULL;
if (!r_file_is_directory (root)) {
if (!r_file_is_directory (homeroot)) {
@ -480,6 +483,7 @@ static int r_core_rtr_http_run(RCore *core, int launch, int browse, const char *
} else {
s->local = true;
}
memset (&so, 0, sizeof (so));
}
if (!r_socket_listen (s, port, NULL)) {
r_socket_free (s);
@ -493,6 +497,30 @@ static int r_core_rtr_http_run(RCore *core, int launch, int browse, const char *
browser, host, atoi (port), path? path:"");
}
so.httpauth = r_config_get_i (core->config, "http.auth");
if (so.httpauth) {
if (!httpauthfile) {
r_socket_free (s);
eprintf ("No user list set for HTTP Authentification\n");
return 1;
}
int sz;
pfile = r_file_slurp (httpauthfile, &sz);
if (pfile) {
so.authtokens = r_str_split_list (pfile, "\n");
} else {
r_socket_free (s);
eprintf ("Empty list of HTTP users\n");
return 1;
}
so.timeout = r_config_get_i (core->config, "http.timeout");
so.accept_timeout = 1;
}
origcfg = core->config;
newcfg = r_config_clone (core->config);
core->config = newcfg;
@ -523,6 +551,8 @@ static int r_core_rtr_http_run(RCore *core, int launch, int browse, const char *
newblk = malloc (core->blocksize);
if (!newblk) {
r_socket_free (s);
r_list_free (so.authtokens);
free (pfile);
return 1;
}
memcpy (newblk, core->block, core->blocksize);
@ -552,7 +582,7 @@ static int r_core_rtr_http_run(RCore *core, int launch, int browse, const char *
activateDieTime (core);
void *bed = r_cons_sleep_begin ();
rs = r_socket_http_accept (s, 1, timeout);
rs = r_socket_http_accept (s, &so);
r_cons_sleep_end (bed);
origoff = core->offset;
@ -608,6 +638,10 @@ static int r_core_rtr_http_run(RCore *core, int launch, int browse, const char *
}
dir = NULL;
if (!rs->auth) {
r_socket_http_response (rs, 401, "", 0, NULL);
}
if (r_config_get_i (core->config, "http.verbose")) {
char *peer = r_socket_to_string (rs->s);
http_logf (core, "[HTTP] %s %s\n", peer, rs->path);
@ -658,7 +692,7 @@ static int r_core_rtr_http_run(RCore *core, int launch, int browse, const char *
free (path);
}
} else {
r_socket_http_response (rs, 403, "Permission denied\n", 0, NULL);
r_socket_http_response (rs, 403, "", 0, NULL);
}
} else if (!strncmp (rs->path, "/cmd/", 5)) {
char *cmd = rs->path + 5;
@ -862,6 +896,7 @@ the_end:
}
r_cons_break_pop ();
core->http_up = false;
free (pfile);
r_socket_free (s);
r_config_free (newcfg);
if (restoreSandbox) {

View File

@ -8,6 +8,7 @@
#include "r_types.h"
#include "r_bind.h"
#include "r_list.h"
#ifdef __cplusplus
extern "C" {
@ -71,6 +72,14 @@ typedef struct r_socket_t {
#endif
} RSocket;
typedef struct r_socket_http_options {
RList *authtokens;
bool accept_timeout;
int timeout;
bool httpauth;
} RSocketHTTPOptions;
#define R_SOCKET_PROTO_TCP IPPROTO_TCP
#define R_SOCKET_PROTO_UDP IPPROTO_UDP
#define R_SOCKET_PROTO_UNIX 0x1337
@ -136,9 +145,10 @@ typedef struct r_socket_http_request {
char *referer;
ut8 *data;
int data_length;
bool auth;
} RSocketHTTPRequest;
R_API RSocketHTTPRequest *r_socket_http_accept(RSocket *s, int accept_timeout, int timeout);
R_API RSocketHTTPRequest *r_socket_http_accept(RSocket *s, RSocketHTTPOptions *so);
R_API void r_socket_http_response(RSocketHTTPRequest *rs, int code, const char *out, int x, const char *headers);
R_API void r_socket_http_close(RSocketHTTPRequest *rs);
R_API ut8 *r_socket_http_handle_upload(const ut8 *str, int len, int *olen);

View File

@ -1,6 +1,7 @@
/* radare - LGPL - Copyright 2012-2016 - pancake */
#include <r_socket.h>
#include <r_util.h>
static bool *breaked = NULL;
@ -8,7 +9,7 @@ R_API void r_socket_http_server_set_breaked(bool *b) {
breaked = b;
}
R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, int accept_timeout, int timeout) {
R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, RSocketHTTPOptions *so) {
int content_length = 0, xx, yy;
int pxx = 1, first = 0;
char buf[1500], *p, *q;
@ -16,7 +17,7 @@ R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, int accept_timeout,
if (!hr) {
return NULL;
}
if (accept_timeout > 0) {
if (so->accept_timeout) {
hr->s = r_socket_accept_timeout (s, 1);
} else {
hr->s = r_socket_accept (s);
@ -25,9 +26,10 @@ R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, int accept_timeout,
free (hr);
return NULL;
}
if (timeout > 0) {
r_socket_block_time (hr->s, 1, timeout);
if (so->timeout > 0) {
r_socket_block_time (hr->s, 1, so->timeout);
}
hr->auth = !so->httpauth;
for (;;) {
#if __WINDOWS__
if (breaked)
@ -63,15 +65,39 @@ R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, int accept_timeout,
} else {
if (!hr->referer && !strncmp (buf, "Referer: ", 9)) {
hr->referer = strdup (buf + 9);
} else
if (!hr->agent && !strncmp (buf, "User-Agent: ", 12)) {
} else if (!hr->agent && !strncmp (buf, "User-Agent: ", 12)) {
hr->agent = strdup (buf + 12);
} else
if (!hr->host && !strncmp (buf, "Host: ", 6)) {
} else if (!hr->host && !strncmp (buf, "Host: ", 6)) {
hr->host = strdup (buf + 6);
} else
if (!strncmp (buf, "Content-Length: ", 16)) {
content_length = atoi (buf+16);
} else if (!strncmp (buf, "Content-Length: ", 16)) {
content_length = atoi (buf + 16);
} else if (so->httpauth && !strncmp (buf, "Authorization: Basic ", 21)) {
char *authtoken = buf + 21;
size_t authlen = strlen (authtoken);
char *curauthtoken;
RListIter *iter;
char *decauthtoken = calloc (4, authlen + 1);
if (!decauthtoken) {
eprintf ("Could not allocate decoding buffer\n");
return hr;
}
if (r_base64_decode ((ut8 *)decauthtoken, authtoken, authlen) == -1) {
eprintf ("Could not decode authorization token\n");
} else {
r_list_foreach (so->authtokens, iter, curauthtoken) {
if (!strcmp (decauthtoken, curauthtoken)) {
hr->auth = true;
break;
}
}
}
free (decauthtoken);
if (!hr->auth) {
eprintf ("Failed attempt login from '%s'\n", hr->host);
}
}
}
}
@ -88,15 +114,17 @@ R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, int accept_timeout,
R_API void r_socket_http_response (RSocketHTTPRequest *rs, int code, const char *out, int len, const char *headers) {
const char *strcode = \
code==200?"ok":
code==301?"moved permanently":
code==301?"Moved permanently":
code==302?"Found":
code==401?"Unauthorized":
code==403?"Permission denied":
code==404?"not found":
"UNKNOWN";
if (len < 1) {
len = out ? strlen (out) : 0;
}
if (!headers) {
headers = "";
headers = code == 401 ? "WWW-Authenticate: Basic realm=\"R2 Web UI Access\"\n" : "";
}
r_socket_printf (rs->s, "HTTP/1.0 %d %s\r\n%s"
"Connection: close\r\nContent-Length: %d\r\n\r\n",

View File

@ -18,6 +18,10 @@ Run in daemon mode
Show help prompt
.It Fl s, Cm sandbox
Run in sandbox mode
.It Fl u, Cm httpauth
Enable HTTP Authentification support
.It Fl t, Cm httpauthfile
user:password authentification file
.It Fl p, Cm port Ar PORT
Specify listening port for the agent
.It Fl v