mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	API: Support HTTP basic authentication for API. v6.0.4, v5.0.152 (#3458)
PICK 771ae0a1a6
Co-authored-by: winlin <winlin@vip.126.com>
Co-authored-by: john <hondaxiao@tencent.com>
			
			
This commit is contained in:
		
							parent
							
								
									41decbae95
								
							
						
					
					
						commit
						12f3a31175
					
				
					 14 changed files with 658 additions and 49 deletions
				
			
		| 
						 | 
				
			
			@ -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());
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -7605,6 +7614,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");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1021,6 +1021,12 @@ public:
 | 
			
		|||
    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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,7 +54,9 @@ ISrsHttpConnOwner::~ISrsHttpConnOwner()
 | 
			
		|||
SrsHttpConn::SrsHttpConn(ISrsHttpConnOwner* handler, ISrsProtocolReadWriter* fd, ISrsHttpServeMux* m, string cip, int cport)
 | 
			
		||||
{
 | 
			
		||||
    parser = new SrsHttpParser();
 | 
			
		||||
    cors = new SrsHttpCorsMux();
 | 
			
		||||
    auth = new SrsHttpAuthMux(m);
 | 
			
		||||
    cors = new SrsHttpCorsMux(auth);
 | 
			
		||||
 | 
			
		||||
    http_mux = m;
 | 
			
		||||
    handler_ = handler;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -74,6 +76,7 @@ SrsHttpConn::~SrsHttpConn()
 | 
			
		|||
 | 
			
		||||
    srs_freep(parser);
 | 
			
		||||
    srs_freep(cors);
 | 
			
		||||
    srs_freep(auth);
 | 
			
		||||
 | 
			
		||||
    srs_freep(delta_);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -227,10 +230,10 @@ 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.
 | 
			
		||||
 | 
			
		||||
    // proxy to cors-->auth-->http_remux.
 | 
			
		||||
    if ((err = cors->serve_http(w, r)) != srs_success) {
 | 
			
		||||
        return srs_error_wrap(err, "mux serve");
 | 
			
		||||
        return srs_error_wrap(err, "cors serve");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return err;
 | 
			
		||||
| 
						 | 
				
			
			@ -256,14 +259,27 @@ 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) {
 | 
			
		||||
    if ((err = cors->initialize(v)) != srs_success) {
 | 
			
		||||
        return srs_error_wrap(err, "init cors");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
srs_error_t SrsHttpConn::set_auth_enabled(bool auth_enabled)
 | 
			
		||||
{
 | 
			
		||||
    srs_error_t err = srs_success;
 | 
			
		||||
 | 
			
		||||
    // initialize the auth, which will proxy to mux.
 | 
			
		||||
    if ((err = auth->initialize(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);
 | 
			
		||||
| 
						 | 
				
			
			@ -451,6 +467,11 @@ srs_error_t SrsHttpxConn::start()
 | 
			
		|||
        return srs_error_wrap(err, "set cors=%d", v);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool auth_enabled = _srs_config->get_http_api_auth_enabled();
 | 
			
		||||
    if ((err = conn->set_auth_enabled(auth_enabled)) != srs_success) {
 | 
			
		||||
        return srs_error_wrap(err, "set auth");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return conn->start();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,7 @@ protected:
 | 
			
		|||
    SrsHttpParser* parser;
 | 
			
		||||
    ISrsHttpServeMux* http_mux;
 | 
			
		||||
    SrsHttpCorsMux* cors;
 | 
			
		||||
    SrsHttpAuthMux* auth;
 | 
			
		||||
    ISrsHttpConnOwner* handler_;
 | 
			
		||||
protected:
 | 
			
		||||
    ISrsProtocolReadWriter* skt;
 | 
			
		||||
| 
						 | 
				
			
			@ -111,6 +112,8 @@ public:
 | 
			
		|||
    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(bool auth_enabled);
 | 
			
		||||
    // Whether enable the JSONP.
 | 
			
		||||
    virtual srs_error_t set_jsonp(bool v);
 | 
			
		||||
// Interface ISrsConnection.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,6 @@
 | 
			
		|||
 | 
			
		||||
#define VERSION_MAJOR       5
 | 
			
		||||
#define VERSION_MINOR       0
 | 
			
		||||
#define VERSION_REVISION    151
 | 
			
		||||
#define VERSION_REVISION    152
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,9 @@ using namespace std;
 | 
			
		|||
// @see ISrsHttpMessage._http_ts_send_buffer
 | 
			
		||||
#define SRS_HTTP_TS_SEND_BUFFER_SIZE 4096
 | 
			
		||||
 | 
			
		||||
#define SRS_HTTP_AUTH_SCHEME_BASIC "Basic"
 | 
			
		||||
#define SRS_HTTP_AUTH_PREFIX_BASIC SRS_HTTP_AUTH_SCHEME_BASIC " "
 | 
			
		||||
 | 
			
		||||
// get the status text of code.
 | 
			
		||||
string srs_generate_http_status_text(int status)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -861,22 +864,20 @@ bool SrsHttpServeMux::path_match(string pattern, string path)
 | 
			
		|||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SrsHttpCorsMux::SrsHttpCorsMux()
 | 
			
		||||
SrsHttpCorsMux::SrsHttpCorsMux(ISrsHttpHandler* h)
 | 
			
		||||
{
 | 
			
		||||
    next = NULL;
 | 
			
		||||
    enabled = false;
 | 
			
		||||
    required = false;
 | 
			
		||||
    next_ = h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SrsHttpCorsMux::~SrsHttpCorsMux()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
srs_error_t SrsHttpCorsMux::initialize(ISrsHttpServeMux* worker, bool cros_enabled)
 | 
			
		||||
srs_error_t SrsHttpCorsMux::initialize(bool cros_enabled)
 | 
			
		||||
{
 | 
			
		||||
    next = worker;
 | 
			
		||||
    enabled = cros_enabled;
 | 
			
		||||
    
 | 
			
		||||
    return srs_success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -918,9 +919,89 @@ srs_error_t SrsHttpCorsMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessag
 | 
			
		|||
        }
 | 
			
		||||
        return w->final_request();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    srs_assert(next);
 | 
			
		||||
    return next->serve_http(w, r);
 | 
			
		||||
 | 
			
		||||
    return next_->serve_http(w, r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SrsHttpAuthMux::SrsHttpAuthMux(ISrsHttpHandler* h)
 | 
			
		||||
{
 | 
			
		||||
    next_ = h;
 | 
			
		||||
    enabled_ = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SrsHttpAuthMux::~SrsHttpAuthMux()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
srs_error_t SrsHttpAuthMux::initialize(bool enabled, std::string username, std::string password)
 | 
			
		||||
{
 | 
			
		||||
    enabled_ = enabled;
 | 
			
		||||
    username_ = username;
 | 
			
		||||
    password_ = password;
 | 
			
		||||
 | 
			
		||||
    return srs_success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
srs_error_t SrsHttpAuthMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
 | 
			
		||||
{
 | 
			
		||||
    srs_error_t err;
 | 
			
		||||
    if ((err = do_auth(w, r)) != srs_success) {
 | 
			
		||||
        srs_error("do_auth %s", srs_error_desc(err).c_str());
 | 
			
		||||
        srs_freep(err);
 | 
			
		||||
        w->write_header(SRS_CONSTS_HTTP_Unauthorized);
 | 
			
		||||
        return w->final_request();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    srs_assert(next_);
 | 
			
		||||
    return next_->serve_http(w, r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
srs_error_t SrsHttpAuthMux::do_auth(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
 | 
			
		||||
{
 | 
			
		||||
    srs_error_t err = srs_success;
 | 
			
		||||
 | 
			
		||||
    if (!enabled_) {
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // We only apply for api starts with /api/ for HTTP API.
 | 
			
		||||
    // We don't apply for other apis such as /rtc/, for which we use http callback.
 | 
			
		||||
    if (r->path().find("/api/") == std::string::npos) {
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string auth = r->header()->get("Authorization");
 | 
			
		||||
    if (auth.empty()) {
 | 
			
		||||
        w->header()->set("WWW-Authenticate", SRS_HTTP_AUTH_SCHEME_BASIC);
 | 
			
		||||
        return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "empty Authorization");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!srs_string_contains(auth, SRS_HTTP_AUTH_PREFIX_BASIC)) {
 | 
			
		||||
        return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "invalid auth %s, should start with %s", auth.c_str(), SRS_HTTP_AUTH_PREFIX_BASIC);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string token = srs_erase_first_substr(auth, SRS_HTTP_AUTH_PREFIX_BASIC);
 | 
			
		||||
    if (token.empty()) {
 | 
			
		||||
        return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "empty token from auth %s", auth.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string plaintext;
 | 
			
		||||
    if ((err = srs_av_base64_decode(token, plaintext)) != srs_success) {
 | 
			
		||||
        return srs_error_wrap(err, "decode token %s", token.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The token format must be username:password
 | 
			
		||||
    std::vector<std::string> user_pwd = srs_string_split(plaintext, ":");
 | 
			
		||||
    if (user_pwd.size() != 2) {
 | 
			
		||||
        return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "invalid token %s", plaintext.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (username_ != user_pwd[0] || password_ != user_pwd[1]) {
 | 
			
		||||
        w->header()->set("WWW-Authenticate", SRS_HTTP_AUTH_SCHEME_BASIC);
 | 
			
		||||
        return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "invalid token %s:%s", user_pwd[0].c_str(), user_pwd[1].c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ISrsHttpMessage::ISrsHttpMessage()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -482,24 +482,46 @@ private:
 | 
			
		|||
    virtual bool path_match(std::string pattern, std::string path);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// The filter http mux, directly serve the http CORS requests,
 | 
			
		||||
// while proxy to the worker mux for services.
 | 
			
		||||
// The filter http mux, directly serve the http CORS requests
 | 
			
		||||
class SrsHttpCorsMux : public ISrsHttpHandler
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    bool required;
 | 
			
		||||
    bool enabled;
 | 
			
		||||
    ISrsHttpServeMux* next;
 | 
			
		||||
    ISrsHttpHandler* next_;
 | 
			
		||||
public:
 | 
			
		||||
    SrsHttpCorsMux();
 | 
			
		||||
    SrsHttpCorsMux(ISrsHttpHandler* h);
 | 
			
		||||
    virtual ~SrsHttpCorsMux();
 | 
			
		||||
public:
 | 
			
		||||
    virtual srs_error_t initialize(ISrsHttpServeMux* worker, bool cros_enabled);
 | 
			
		||||
    virtual srs_error_t initialize(bool cros_enabled);
 | 
			
		||||
// Interface ISrsHttpServeMux
 | 
			
		||||
public:
 | 
			
		||||
    virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// The filter http mux, directly serve the http AUTH requests,
 | 
			
		||||
// while proxy to the worker mux for services.
 | 
			
		||||
// @see https://www.rfc-editor.org/rfc/rfc7617
 | 
			
		||||
// @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate
 | 
			
		||||
class SrsHttpAuthMux : public ISrsHttpHandler
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    bool enabled_;
 | 
			
		||||
    std::string username_;
 | 
			
		||||
    std::string password_;
 | 
			
		||||
    ISrsHttpHandler* next_;
 | 
			
		||||
public:
 | 
			
		||||
    SrsHttpAuthMux(ISrsHttpHandler* h);
 | 
			
		||||
    virtual ~SrsHttpAuthMux();
 | 
			
		||||
public:
 | 
			
		||||
    virtual srs_error_t initialize(bool enabled, std::string username, std::string password);
 | 
			
		||||
// Interface ISrsHttpServeMux
 | 
			
		||||
public:
 | 
			
		||||
    virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
 | 
			
		||||
private:
 | 
			
		||||
    virtual srs_error_t do_auth(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// A Request represents an HTTP request received by a server
 | 
			
		||||
// or to be sent by a client.
 | 
			
		||||
//
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3639,7 +3639,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig5)
 | 
			
		|||
 | 
			
		||||
    if (true) {
 | 
			
		||||
        MockSrsConfig conf;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "http_api{enabled on;listen xxx;crossdomain off;raw_api {enabled on;allow_reload on;allow_query on;allow_update on;}}"));
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "http_api{enabled on;listen xxx;crossdomain off;auth {enabled on;username admin;password 123456;}raw_api {enabled on;allow_reload on;allow_query on;allow_update on;}}"));
 | 
			
		||||
        EXPECT_TRUE(conf.get_http_api_enabled());
 | 
			
		||||
        EXPECT_STREQ("xxx", conf.get_http_api_listen().c_str());
 | 
			
		||||
        EXPECT_FALSE(conf.get_http_api_crossdomain());
 | 
			
		||||
| 
						 | 
				
			
			@ -3647,6 +3647,9 @@ VOID TEST(ConfigMainTest, CheckVhostConfig5)
 | 
			
		|||
        EXPECT_TRUE(conf.get_raw_api_allow_reload());
 | 
			
		||||
        EXPECT_FALSE(conf.get_raw_api_allow_query()); // Always disabled
 | 
			
		||||
        EXPECT_FALSE(conf.get_raw_api_allow_update()); // Always disabled
 | 
			
		||||
        EXPECT_TRUE(conf.get_http_api_auth_enabled());
 | 
			
		||||
        EXPECT_STREQ("admin", conf.get_http_api_auth_username().c_str());
 | 
			
		||||
        EXPECT_STREQ("123456", conf.get_http_api_auth_password().c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (true) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4112,6 +4115,15 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpApi)
 | 
			
		|||
 | 
			
		||||
        SrsSetEnvConfig(http_api_crossdomain, "SRS_HTTP_API_CROSSDOMAIN", "off");
 | 
			
		||||
        EXPECT_FALSE(conf.get_http_api_crossdomain());
 | 
			
		||||
 | 
			
		||||
        SrsSetEnvConfig(http_api_auth_enabled, "SRS_HTTP_API_AUTH_ENABLED", "on");
 | 
			
		||||
        EXPECT_TRUE(conf.get_http_api_auth_enabled());
 | 
			
		||||
 | 
			
		||||
        SrsSetEnvConfig(http_api_auth_username, "SRS_HTTP_API_AUTH_USERNAME", "admin");
 | 
			
		||||
        EXPECT_STREQ("admin", conf.get_http_api_auth_username().c_str());
 | 
			
		||||
 | 
			
		||||
        SrsSetEnvConfig(http_api_auth_password, "SRS_HTTP_API_AUTH_PASSWORD", "123456");
 | 
			
		||||
        EXPECT_STREQ("123456", conf.get_http_api_auth_password().c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (true) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1059,11 +1059,10 @@ VOID TEST(ProtocolHTTPTest, HTTPServerMuxerCORS)
 | 
			
		|||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/index.html", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpCorsMux cs;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(&s, true));
 | 
			
		||||
        SrsHttpCorsMux cs(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(true));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If CORS enabled, response OPTIONS with ok
 | 
			
		||||
| 
						 | 
				
			
			@ -1079,8 +1078,8 @@ VOID TEST(ProtocolHTTPTest, HTTPServerMuxerCORS)
 | 
			
		|||
        r.set_basic(HTTP_REQUEST, HTTP_OPTIONS, (http_status)200, -1);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/index.html", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpCorsMux cs;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(&s, true));
 | 
			
		||||
        SrsHttpCorsMux cs(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(true));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(200, "", w);
 | 
			
		||||
| 
						 | 
				
			
			@ -1099,11 +1098,10 @@ VOID TEST(ProtocolHTTPTest, HTTPServerMuxerCORS)
 | 
			
		|||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/index.html", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpCorsMux cs;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(&s, false));
 | 
			
		||||
        SrsHttpCorsMux cs(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(false));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If CORS not enabled, response error for options.
 | 
			
		||||
| 
						 | 
				
			
			@ -1119,8 +1117,8 @@ VOID TEST(ProtocolHTTPTest, HTTPServerMuxerCORS)
 | 
			
		|||
        r.set_basic(HTTP_REQUEST, HTTP_OPTIONS, (http_status)200, -1);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/index.html", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpCorsMux cs;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(&s, false));
 | 
			
		||||
        SrsHttpCorsMux cs(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(false));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(405, "", w);
 | 
			
		||||
| 
						 | 
				
			
			@ -1137,10 +1135,253 @@ VOID TEST(ProtocolHTTPTest, HTTPServerMuxerCORS)
 | 
			
		|||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/index.html", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpCorsMux cs;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(&s, true));
 | 
			
		||||
        SrsHttpCorsMux cs(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.initialize(true));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(cs.serve_http(&w, &r));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VOID TEST(ProtocolHTTPTest, HTTPServerMuxerAuth)
 | 
			
		||||
{
 | 
			
		||||
    srs_error_t err;
 | 
			
		||||
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
        
 | 
			
		||||
        SrsHttpHeader h ;
 | 
			
		||||
        h.set("Authorization", "Basic YWRtaW46YWRtaW4="); // admin:admin
 | 
			
		||||
        r.set_header(&h, false);
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/index.html", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(true, "admin", "admin"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // incorrect token
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
 | 
			
		||||
        SrsHttpHeader h ;
 | 
			
		||||
        h.set("Authorization", "Basic YWRtaW46YWRtaW4="); // admin:admin
 | 
			
		||||
        r.set_header(&h, false);
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/api/v1/clients/", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(true, "admin", "123456"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        EXPECT_EQ(401, w.w->status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // incorrect token, duplicate Basic
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
 | 
			
		||||
        SrsHttpHeader h ;
 | 
			
		||||
        h.set("Authorization", "Basic BasicYWRtaW46YWRtaW4="); // duplicate 'Basic'
 | 
			
		||||
        r.set_header(&h, false);
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/api/v1/clients/", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(true, "admin", "admin"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        EXPECT_EQ(401, w.w->status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Authorization NOT start with 'Basic '
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
        
 | 
			
		||||
        SrsHttpHeader h ;
 | 
			
		||||
        h.set("Authorization", "YWRtaW46YWRtaW4="); // admin:admin
 | 
			
		||||
        r.set_header(&h, false);
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/api/v1/clients/", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(true, "admin", "admin"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        EXPECT_EQ(401, w.w->status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // NOT base64
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
        
 | 
			
		||||
        SrsHttpHeader h ;
 | 
			
		||||
        h.set("Authorization", "Basic admin:admin"); // admin:admin
 | 
			
		||||
        r.set_header(&h, false);
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/api/v1/clients/", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(true, "admin", "admin"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        EXPECT_EQ(401, w.w->status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // empty Authorization
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/api/v1/clients/", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(true, "admin", "admin"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        EXPECT_EQ(401, w.w->status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // auth disabled, response with 200 ok, even though empty Authorization
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/api/v1/clients/", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(false, "admin", "admin"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // auth disabled, response with 200 ok, even though wrong token
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
 | 
			
		||||
        SrsHttpHeader h ;
 | 
			
		||||
        h.set("Authorization", "Basic YWRtaW46YWRtaW4="); // admin:admin
 | 
			
		||||
        r.set_header(&h, false);
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/api/v1/clients/", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(false, "admin", "123456"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // always response with 200 ok, for /rtc/*/
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
 | 
			
		||||
        SrsHttpHeader h ;
 | 
			
		||||
        h.set("Authorization", "Basic YWRtaW46YWRtaW4="); // admin:admin
 | 
			
		||||
        r.set_header(&h, false);
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/rtc/play/", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(false, "admin", "123456"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // always response with 200 ok, for /rtc/*/
 | 
			
		||||
    if (true) {
 | 
			
		||||
        SrsHttpServeMux s;
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.initialize());
 | 
			
		||||
 | 
			
		||||
        MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
 | 
			
		||||
 | 
			
		||||
        MockResponseWriter w;
 | 
			
		||||
        SrsHttpMessage r(NULL, NULL);
 | 
			
		||||
        r.set_basic(HTTP_REQUEST, HTTP_POST, (http_status)200, -1);
 | 
			
		||||
 | 
			
		||||
        SrsHttpHeader h ;
 | 
			
		||||
        h.set("Authorization", "Basic YWRtaW46YWRtaW4="); // admin:admin
 | 
			
		||||
        r.set_header(&h, false);
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(r.set_url("/index.html", false));
 | 
			
		||||
 | 
			
		||||
        SrsHttpAuthMux auth(&s);
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.initialize(false, "admin", "123456"));
 | 
			
		||||
 | 
			
		||||
        HELPER_ASSERT_SUCCESS(auth.serve_http(&w, &r));
 | 
			
		||||
        __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5966,4 +5966,33 @@ VOID TEST(KernelUtilityTest, CoverCheckIPAddrValid)
 | 
			
		|||
     ASSERT_FALSE(srs_check_ip_addr_valid("2001:0db8:85a3:0:0:8A2E:0370:7334:"));
 | 
			
		||||
#endif
 | 
			
		||||
    ASSERT_FALSE(srs_check_ip_addr_valid("1e1.4.5.6"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VOID TEST(KernelUtilityTest, Base64Decode)
 | 
			
		||||
{
 | 
			
		||||
    srs_error_t err = srs_success;
 | 
			
		||||
 | 
			
		||||
    if (true) {
 | 
			
		||||
        string plaintext;
 | 
			
		||||
        HELPER_EXPECT_SUCCESS(srs_av_base64_decode("YWRtaW46YWRtaW4=", plaintext));
 | 
			
		||||
        EXPECT_STREQ("admin:admin", plaintext.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (true) {
 | 
			
		||||
        string plaintext;
 | 
			
		||||
        HELPER_EXPECT_SUCCESS(srs_av_base64_decode("YWRtaW46MTIzNDU2", plaintext));
 | 
			
		||||
        EXPECT_STREQ("admin:123456", plaintext.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (true) {
 | 
			
		||||
        string plaintext;
 | 
			
		||||
        HELPER_EXPECT_SUCCESS(srs_av_base64_decode("YWRtaW46MTIzNDU2", plaintext));
 | 
			
		||||
        EXPECT_STRNE("admin:admin", plaintext.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (true) {
 | 
			
		||||
        string plaintext;
 | 
			
		||||
        HELPER_EXPECT_FAILED(srs_av_base64_decode("YWRtaW46YWRtaW", plaintext));
 | 
			
		||||
        EXPECT_STRNE("admin:admin", plaintext.c_str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue