diff --git a/htsp.c b/htsp.c index 64688cd2..b49320c1 100644 --- a/htsp.c +++ b/htsp.c @@ -165,7 +165,8 @@ htsp_input(htsp_t *htsp, const void *buf, int len) printf("INPUT:\n"); htsmsg_print(in); - out = rpc_dispatch(&htsp->htsp_rpc, in, NULL, htsp); + out = rpc_dispatch(&htsp->htsp_rpc, in, NULL, htsp, + (struct sockaddr *)&htsp->htsp_tcp_session.tcp_peer_addr); htsmsg_destroy(in); @@ -175,6 +176,7 @@ htsp_input(htsp_t *htsp, const void *buf, int len) htsp_send_msg(htsp, out, 0); if(!was_async && htsp->htsp_rpc.rs_is_async) { + printf("Session went into async mode\n"); /* Session went into async state */ htsp_send_all_channels(htsp); } diff --git a/main.c b/main.c index 47ca3418..d595451c 100644 --- a/main.c +++ b/main.c @@ -277,7 +277,7 @@ main(int argc, char **argv) if(p) http_start(p); - p = atoi(config_get_str("htsp-server-port", "0")); + p = atoi(config_get_str("htsp-server-port", "9910")); if(p) htsp_start(p); diff --git a/rpc.c b/rpc.c index 4902e3c8..27c19647 100644 --- a/rpc.c +++ b/rpc.c @@ -37,6 +37,7 @@ #include "epg.h" #include "pvr.h" #include "rpc.h" +#include "access.h" /** @@ -89,33 +90,50 @@ rpc_error(rpc_session_t *ses, const char *err) -/** - * Login peer, set auth level and do various other stuff +/** + * Simple function to respond with an error */ -static htsmsg_t * -rpc_login(rpc_session_t *ses, htsmsg_t *in, void *opaque) +htsmsg_t * +rpc_unauthorized(rpc_session_t *ses) { - const char *user = htsmsg_get_str(in, "username"); - const char *pass = htsmsg_get_str(in, "password"); - - if(user == NULL || pass == NULL) { - ses->rs_authlevel = 1; - ses->rs_maxweight = 100; - } else { - /* FIXME: user/password database */ - ses->rs_authlevel = 1; - } - - if(htsmsg_get_u32(in, "async", &ses->rs_is_async) < 0) - ses->rs_is_async = 0; - - return rpc_ok(ses); + htsmsg_t *r = htsmsg_create(); + htsmsg_add_u32(r, "seq", ses->rs_seq); + htsmsg_add_u32(r, "_noaccess", 1); + return r; } +/** + * Auth peer + */ +static htsmsg_t * +rpc_auth(rpc_session_t *ses, htsmsg_t *in, void *opaque) +{ + const char *user = htsmsg_get_str(in, "username"); + const char *pass = htsmsg_get_str(in, "password"); + if(user != NULL && pass != NULL) { + free(ses->rs_username); + free(ses->rs_password); + + ses->rs_username = strdup(user); + ses->rs_password = strdup(pass); + } + + return rpc_ok(ses); +} + +/** + * Set client in async mode + */ +static htsmsg_t * +rpc_async(rpc_session_t *ses, htsmsg_t *in, void *opaque) +{ + ses->rs_is_async = 1; + return rpc_ok(ses); +} /* @@ -327,9 +345,10 @@ htsp_subscribe(htsp_connection_t *hc, htsp_msg_t *m) */ static rpc_cmd_t common_rpc[] = { - { "login", rpc_login, 0 }, - { "channelsList", rpc_channels_list, 1 }, - { "eventInfo", rpc_event_info, 1 }, + { "auth", rpc_auth, 0 }, + { "async", rpc_async, ACCESS_STREAMING }, + { "channelsList", rpc_channels_list, ACCESS_STREAMING }, + { "eventInfo", rpc_event_info, ACCESS_STREAMING }, #if 0 { "subscribe", rpc_subscribe, 1 }, { "unsubscribe", rpc_unsubscribe, 1 }, @@ -344,13 +363,14 @@ static rpc_cmd_t common_rpc[] = { */ static htsmsg_t * rpc_dispatch_set(rpc_session_t *ses, htsmsg_t *in, rpc_cmd_t *cmds, - void *opaque, const char *method) + void *opaque, const char *method, struct sockaddr *peer) { for(; cmds->rc_name; cmds++) { if(strcmp(cmds->rc_name, method)) continue; - if(cmds->rc_authlevel < ses->rs_authlevel) - return rpc_error(ses, "Insufficient privileges"); + if(access_verify(ses->rs_username, ses->rs_password, peer, + cmds->rc_privmask)) + return rpc_unauthorized(ses); return cmds->rc_func(ses, in, opaque); } return NULL; @@ -361,7 +381,8 @@ rpc_dispatch_set(rpc_session_t *ses, htsmsg_t *in, rpc_cmd_t *cmds, * */ htsmsg_t * -rpc_dispatch(rpc_session_t *ses, htsmsg_t *in, rpc_cmd_t *cmds, void *opaque) +rpc_dispatch(rpc_session_t *ses, htsmsg_t *in, rpc_cmd_t *cmds, void *opaque, + struct sockaddr *peer) { const char *method; htsmsg_t *out; @@ -372,9 +393,9 @@ rpc_dispatch(rpc_session_t *ses, htsmsg_t *in, rpc_cmd_t *cmds, void *opaque) if((method = htsmsg_get_str(in, "method")) == NULL) return rpc_error(ses, "Method not specified"); - out = rpc_dispatch_set(ses, in, common_rpc, opaque, method); + out = rpc_dispatch_set(ses, in, common_rpc, opaque, method, peer); if(out == NULL && cmds != NULL) - out = rpc_dispatch_set(ses, in, cmds, opaque, method); + out = rpc_dispatch_set(ses, in, cmds, opaque, method, peer); return out ?: rpc_error(ses, "Method not found"); } @@ -396,5 +417,8 @@ rpc_init(rpc_session_t *ses, const char *logname) void rpc_deinit(rpc_session_t *ses) { + free(ses->rs_username); + free(ses->rs_password); + free((void *)ses->rs_logname); } diff --git a/rpc.h b/rpc.h index e0fb3b2f..71e6fc72 100644 --- a/rpc.h +++ b/rpc.h @@ -27,19 +27,21 @@ typedef struct rpc_session { uint32_t rs_seq; - unsigned int rs_authlevel; unsigned int rs_maxweight; unsigned int rs_is_async; struct th_subscription_list rs_subscriptions; + char *rs_username; + char *rs_password; + } rpc_session_t; typedef struct rpc_cmd { const char *rc_name; htsmsg_t *(*rc_func)(rpc_session_t *ses, htsmsg_t *in, void *opaque); - int rc_authlevel; + int rc_privmask; } rpc_cmd_t; @@ -49,10 +51,11 @@ void rpc_init(rpc_session_t *ses, const char *logname); void rpc_deinit(rpc_session_t *ses); htsmsg_t *rpc_dispatch(rpc_session_t *ses, htsmsg_t *in, rpc_cmd_t *cmds, - void *opaque); + void *opaque, struct sockaddr *peer); htsmsg_t *rpc_ok(rpc_session_t *ses); htsmsg_t *rpc_error(rpc_session_t *ses, const char *err); +htsmsg_t *rpc_unauthorized(rpc_session_t *ses); #endif /* RPC_H_ */