Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API: Support HTTP basic authentication for API. v6.0.4, v5.0.152 #3458

Merged
merged 11 commits into from
Apr 1, 2023
13 changes: 13 additions & 0 deletions trunk/conf/full.conf
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,19 @@ http_api {
# Always off by https://github.com/ossrs/srs/issues/2653
#allow_update off;
}
# the auth is authentication for http api
auth {
# whether enable the HTTP AUTH.
# Overwrite by env SRS_HTTP_API_AUTH_ENABLED
# default: off
enabled on;
# The username of Basic authentication:
# Overwrite by env SRS_HTTP_API_AUTH_USERNAME
username admin;
# The password of Basic authentication:
# Overwrite by env SRS_HTTP_API_AUTH_PASSWORD
password admin;
}
# For https_api or HTTPS API.
https {
# Whether enable HTTPS API.
Expand Down
83 changes: 82 additions & 1 deletion trunk/src/app/srs_app_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2284,7 +2284,7 @@ srs_error_t SrsConfig::check_normal_config()
for (int i = 0; conf && i < (int)conf->directives.size(); i++) {
SrsConfDirective* obj = conf->at(i);
string n = obj->name;
if (n != "enabled" && n != "listen" && n != "crossdomain" && n != "raw_api" && n != "https") {
if (n != "enabled" && n != "listen" && n != "crossdomain" && n != "raw_api" && n != "auth" && n != "https") {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal http_api.%s", n.c_str());
}

Expand All @@ -2296,6 +2296,15 @@ srs_error_t SrsConfig::check_normal_config()
}
}
}

if (n == "auth") {
for (int j = 0; j < (int)obj->directives.size(); j++) {
string m = obj->at(j)->name;
if (m != "enabled" && m != "username" && m != "password") {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal http_api.auth.%s", m.c_str());
}
}
}
}
}
if (true) {
Expand Down Expand Up @@ -7600,6 +7609,78 @@ bool SrsConfig::get_raw_api_allow_update()
return false;
}

bool SrsConfig::get_http_api_auth_enabled()
{
SRS_OVERWRITE_BY_ENV_BOOL("srs.http_api.auth.enabled"); // SRS_HTTP_API_AUTH_ENABLED

static bool DEFAULT = false;

SrsConfDirective* conf = root->get("http_api");
if (!conf) {
return DEFAULT;
}

conf = conf->get("auth");
if (!conf) {
return DEFAULT;
}

conf = conf->get("enabled");
if (!conf || conf->arg0().empty()) {
return DEFAULT;
}

return SRS_CONF_PERFER_FALSE(conf->arg0());
}

std::string SrsConfig::get_http_api_auth_username()
{
SRS_OVERWRITE_BY_ENV_STRING("srs.http_api.auth.username"); // SRS_HTTP_API_AUTH_USERNAME

static string DEFAULT = "";

SrsConfDirective* conf = root->get("http_api");
if (!conf) {
return DEFAULT;
}

conf = conf->get("auth");
if (!conf) {
return DEFAULT;
}

conf = conf->get("username");
if (!conf) {
return DEFAULT;
}

return conf->arg0();
}

std::string SrsConfig::get_http_api_auth_password()
{
SRS_OVERWRITE_BY_ENV_STRING("srs.http_api.auth.password"); // SRS_HTTP_API_AUTH_PASSWORD

static string DEFAULT = "";

SrsConfDirective* conf = root->get("http_api");
if (!conf) {
return DEFAULT;
}

conf = conf->get("auth");
if (!conf) {
return DEFAULT;
}

conf = conf->get("password");
if (!conf) {
return DEFAULT;
}

return conf->arg0();
}

SrsConfDirective* SrsConfig::get_https_api()
{
SrsConfDirective* conf = root->get("http_api");
Expand Down
6 changes: 6 additions & 0 deletions trunk/src/app/srs_app_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,12 @@ class SrsConfig
virtual bool get_raw_api_allow_query();
// Whether allow rpc update.
virtual bool get_raw_api_allow_update();
// Whether http api auth enabled.
virtual bool get_http_api_auth_enabled();
// Get the http api auth username.
virtual std::string get_http_api_auth_username();
// Get the http api auth password.
virtual std::string get_http_api_auth_password();
// https api section
private:
SrsConfDirective* get_https_api();
Expand Down
38 changes: 35 additions & 3 deletions trunk/src/app/srs_app_http_conn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ SrsHttpConn::SrsHttpConn(ISrsHttpConnOwner* handler, ISrsProtocolReadWriter* fd,
{
parser = new SrsHttpParser();
cors = new SrsHttpCorsMux();
auth = new SrsHttpAuthMux();

http_mux = m;
handler_ = handler;

Expand All @@ -74,6 +76,7 @@ SrsHttpConn::~SrsHttpConn()

srs_freep(parser);
srs_freep(cors);
srs_freep(auth);

srs_freep(delta_);
}
Expand Down Expand Up @@ -228,8 +231,12 @@ srs_error_t SrsHttpConn::process_request(ISrsHttpResponseWriter* w, ISrsHttpMess
srs_trace("HTTP #%d %s:%d %s %s, content-length=%" PRId64 "", rid, ip.c_str(), port,
r->method_str().c_str(), r->url().c_str(), r->content_length());

// use cors server mux to serve http request, which will proxy to http_remux.
if ((err = cors->serve_http(w, r)) != srs_success) {
return srs_error_wrap(err, "cors serve");
}

// use auth server mux to serve http request, which will proxy to http_remux.
if ((err = auth->serve_http(w, r)) != srs_success) {
return srs_error_wrap(err, "mux serve");
}

Expand All @@ -256,14 +263,35 @@ srs_error_t SrsHttpConn::set_crossdomain_enabled(bool v)
{
srs_error_t err = srs_success;

// initialize the cors, which will proxy to mux.
if ((err = cors->initialize(http_mux, v)) != srs_success) {
// initialize the cors, which will proxy to auth.
if ((err = cors->initialize(v)) != srs_success) {
return srs_error_wrap(err, "init cors");
}

return err;
}

srs_error_t SrsHttpConn::set_auth_enabled()
{
srs_error_t err = srs_success;

// there are 2 class type of http_mux:
// SrsHttpServer for http_server, listen on 8080 by default;
// ISrsHttpServeMux for http_api, listen on 1985 by default;
// auth only for http_api
SrsHttpServer* mux = dynamic_cast<SrsHttpServer*>(http_mux);
bool auth_enabled = _srs_config->get_http_api_auth_enabled() && (!mux);

// initialize the auth, which will proxy to mux.
if ((err = auth->initialize(http_mux, auth_enabled,
_srs_config->get_http_api_auth_username(),
_srs_config->get_http_api_auth_password())) != srs_success) {
return srs_error_wrap(err, "init auth");
}

return err;
}

srs_error_t SrsHttpConn::set_jsonp(bool v)
{
parser->set_jsonp(v);
Expand Down Expand Up @@ -451,6 +479,10 @@ srs_error_t SrsHttpxConn::start()
return srs_error_wrap(err, "set cors=%d", v);
}

if ((err = conn->set_auth_enabled()) != srs_success) {
return srs_error_wrap(err, "set auth");
}

return conn->start();
}

Expand Down
3 changes: 3 additions & 0 deletions trunk/src/app/srs_app_http_conn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class SrsHttpConn : public ISrsConnection, public ISrsStartable, public ISrsCoro
SrsHttpParser* parser;
ISrsHttpServeMux* http_mux;
SrsHttpCorsMux* cors;
SrsHttpAuthMux* auth;
ISrsHttpConnOwner* handler_;
protected:
ISrsProtocolReadWriter* skt;
Expand Down Expand Up @@ -111,6 +112,8 @@ class SrsHttpConn : public ISrsConnection, public ISrsStartable, public ISrsCoro
virtual srs_error_t pull();
// Whether enable the CORS(cross-domain).
virtual srs_error_t set_crossdomain_enabled(bool v);
// Whether enable the Auth.
virtual srs_error_t set_auth_enabled();
// Whether enable the JSONP.
virtual srs_error_t set_jsonp(bool v);
// Interface ISrsConnection.
Expand Down
51 changes: 51 additions & 0 deletions trunk/src/kernel/srs_kernel_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1303,3 +1303,54 @@ int srs_chunk_header_c3(int perfer_cid, uint32_t timestamp, char* cache, int nb_
return (int)(p - cache);
}


inline bool is_base64(unsigned char c)
{
return (std::isalnum(c) || (c == '+') || (c == '/'));
}

std::string base64_decode(const std::string &encoded_string)
duiniuluantanqin marked this conversation as resolved.
Show resolved Hide resolved
{
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;

while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_];
in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);

char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}

if (i) {
for (j = i; j < 4; j++)
char_array_4[j] = 0;

for (j = 0; j < 4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);

char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

for (j = 0; (j < i - 1); j++)
ret += char_array_3[j];
}

return ret;
}
3 changes: 3 additions & 0 deletions trunk/src/kernel/srs_kernel_utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,5 +167,8 @@ extern int srs_chunk_header_c3(int perfer_cid, uint32_t timestamp, char* cache,
typedef int (*srs_gettimeofday_t) (struct timeval* tv, struct timezone* tz);
#endif

//
extern std::string base64_decode(const std::string &encoded_string);

#endif

Loading