const char *srv_check_authorized(const AUTH_CREDENTIALS_STORE_T *pAuthStore, const HTTP_REQ_T *pReq, char *authbuf) { if(pAuthStore && IS_AUTH_CREDENTIALS_SET(pAuthStore)) { if(srvauth_authenticate(pAuthStore, pReq, NULL, NULL, NULL, authbuf, AUTH_BUF_SZ) < 0) { return (const char *) authbuf; } } return NULL; }
static void srvlisten_media_proc(void *pArg) { SRV_LISTENER_CFG_T *pListenCfg = (SRV_LISTENER_CFG_T *) pArg; NETIO_SOCK_T netsocksrv; struct sockaddr_storage sa; CLIENT_CONN_T *pConnTmp; char tmp[128]; char bufses[32]; const int backlog = NET_BACKLOG_DEFAULT; unsigned int tsMax = 0; unsigned int flvMax = 0; unsigned int mkvMax = 0; unsigned int rtmpMax = 0; unsigned int rtspMax = 0; int haveAuth = 0; int haveRtmpAuth = 0; int haveRtspAuth = 0; int haveToken = 0; int rc = 0; logutil_tid_add(pthread_self(), pListenCfg->tid_tag); if((pListenCfg->urlCapabilities & (URL_CAP_TSLIVE | URL_CAP_TSHTTPLIVE | URL_CAP_FLVLIVE | URL_CAP_MKVLIVE | URL_CAP_LIVE | URL_CAP_STATUS | URL_CAP_MOOFLIVE | URL_CAP_PIP | URL_CAP_CONFIG | URL_CAP_BROADCAST | URL_CAP_RTMPLIVE | URL_CAP_RTMPTLIVE | URL_CAP_RTSPLIVE)) == 0) { LOG(X_WARNING("Server listener exiting because no capabilities enabled on %s:%d"), FORMAT_NETADDR(pListenCfg->sa, tmp, sizeof(tmp)), ntohs(INET_PORT(pListenCfg->sa))); logutil_tid_remove(pthread_self()); return; } else if(!(pConnTmp = (CLIENT_CONN_T *) pListenCfg->pConnPool->pElements)) { return; } memset(&netsocksrv, 0, sizeof(netsocksrv)); memcpy(&sa, &pListenCfg->sa, sizeof(pListenCfg->sa)); netsocksrv.flags = pListenCfg->netflags; if((NETIOSOCK_FD(netsocksrv) = net_listen((const struct sockaddr *) &sa, backlog)) == INVALID_SOCKET) { logutil_tid_remove(pthread_self()); return; } pthread_mutex_lock(&pListenCfg->mtx); pListenCfg->pnetsockSrv = &netsocksrv; pthread_mutex_unlock(&pListenCfg->mtx); if(pListenCfg->pAuthStore && IS_AUTH_CREDENTIALS_SET(pListenCfg->pAuthStore)) { haveAuth = 1; } if(pListenCfg->pAuthTokenId && pListenCfg->pAuthTokenId[0] != '\0') { haveToken = 1; } tsMax = pConnTmp->pStreamerCfg0->liveQs[0].max; flvMax = pConnTmp->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_FLV].max; mkvMax = pConnTmp->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_MKV].max; rtmpMax = pConnTmp->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_RTMP].max; rtspMax = pConnTmp->pStreamerCfg0->pRtspSessions->max; if(HAVE_URL_CAP_RTMP(pListenCfg->urlCapabilities)) { if(IS_AUTH_CREDENTIALS_SET(&pConnTmp->pStreamerCfg0->creds[STREAMER_AUTH_IDX_RTMP].stores[pListenCfg->idxCfg])) { // // RTMP server streaming credentials not implemented // //haveRtmpAuth = 1; } LOG(X_INFO("rtmp %s%s available at "URL_RTMP_FMT_STR"%s max:%d"), ((pListenCfg->netflags & NETIO_FLAG_PLAINTEXT) && (pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ) ? "(SSL) " : ((pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ? "(SSL only) " : ""), ((pListenCfg->urlCapabilities & URL_CAP_RTMPTLIVE) && !(pListenCfg->urlCapabilities & URL_CAP_RTMPLIVE) ? "(tunneled only) " : ((pListenCfg->urlCapabilities & URL_CAP_RTMPTLIVE) ? "(tunneled) " : "")), URL_PROTO_FMT2_ARGS( (pListenCfg->netflags & NETIO_FLAG_SSL_TLS), FORMAT_NETADDR(sa, tmp, sizeof(tmp))), ntohs(INET_PORT(sa)), (haveRtmpAuth ? " (Using auth)" : ""), rtmpMax); } if(pListenCfg->urlCapabilities & URL_CAP_RTSPLIVE) { if(IS_AUTH_CREDENTIALS_SET(&pConnTmp->pStreamerCfg0->creds[STREAMER_AUTH_IDX_RTSP].stores[pListenCfg->idxCfg])) { haveRtspAuth = 1; } if(pListenCfg->pCfg->prtspsessiontimeout && *pListenCfg->pCfg->prtspsessiontimeout != 0) { snprintf(bufses, sizeof(bufses), ", timeout:%u sec", *pListenCfg->pCfg->prtspsessiontimeout); } else { bufses[0] = '\0'; } LOG(X_INFO("rtsp %s available at "URL_RTSP_FMT_STR"%s max:%d%s"), ((pListenCfg->netflags & NETIO_FLAG_PLAINTEXT) && (pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ) ? "(SSL) " : ((pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ? "(SSL only) " : ""), URL_PROTO_FMT2_ARGS( (pListenCfg->netflags & NETIO_FLAG_SSL_TLS), FORMAT_NETADDR(sa, tmp, sizeof(tmp))), ntohs(INET_PORT(sa)), (haveRtspAuth ? " (Using auth)" : ""), rtspMax, bufses); } if((pListenCfg->urlCapabilities & URL_CAP_ROOTHTML)) { LOG(X_INFO("broadcast interface available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_ROOT_URL, (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max); } if((pListenCfg->urlCapabilities & URL_CAP_LIVE)) { LOG(X_INFO("live available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_LIVE_URL, (haveAuth ? " (Using auth)" : ""), (haveToken ? " (Using token)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max); } if((pListenCfg->urlCapabilities & URL_CAP_TSLIVE)) { LOG(X_INFO("tslive available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_TSLIVE_URL, (haveAuth ? " (Using auth)" : ""), (haveToken ? " (Using token)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), tsMax); } if((pListenCfg->urlCapabilities & URL_CAP_TSHTTPLIVE)) { LOG(X_INFO("httplive available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_HTTPLIVE_URL, (haveAuth ? " (Using auth)" : ""), (haveToken ? " (Using token)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max); } if((pListenCfg->urlCapabilities & URL_CAP_FLVLIVE)) { LOG(X_INFO("flvlive available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_FLVLIVE_URL, (haveAuth ? " (Using auth)" : ""), (haveToken ? " (Using token)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), flvMax); } if((pListenCfg->urlCapabilities & URL_CAP_MKVLIVE)) { LOG(X_INFO("mkvlive available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_MKVLIVE_URL, (haveAuth ? " (Using auth)" : ""), (haveToken ? " (Using token)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), mkvMax); } if((pListenCfg->urlCapabilities & URL_CAP_MOOFLIVE)) { LOG(X_INFO("dash available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_DASH_URL, (haveAuth ? " (Using auth)" : ""), (haveToken ? " (Using token)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max); } if((pListenCfg->urlCapabilities & URL_CAP_STATUS)) { LOG(X_INFO("status available at "URL_HTTP_FMT_STR"%s%s%s"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_STATUS_URL, (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : "")); } if((pListenCfg->urlCapabilities & URL_CAP_PIP)) { LOG(X_INFO("pip available at "URL_HTTP_FMT_STR"%s%s%s"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_PIP_URL, (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : "")); } if((pListenCfg->urlCapabilities & URL_CAP_CONFIG)) { LOG(X_INFO("config available at "URL_HTTP_FMT_STR"%s%s%s"), URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_CONFIG_URL, (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : "")); } //fprintf(stderr, "LISTENER THREAD %s %s:%d active:%d cap: 0x%x\n", pListenCfg->netflags & NETIO_FLAG_SSL_TLS ? "SSL" : "", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port), pListenCfg->active, pListenCfg->urlCapabilities); // // Service any client connections on the live listening port // rc = srvlisten_loop(pListenCfg, srv_cmd_proc); pthread_mutex_lock(&pListenCfg->mtx); pListenCfg->pnetsockSrv = NULL; netio_closesocket(&netsocksrv); pthread_mutex_unlock(&pListenCfg->mtx); LOG(X_WARNING("HTTP listener thread exiting with code: %d"), rc); logutil_tid_remove(pthread_self()); return; }
static void srvlisten_rtsplive_proc(void *pArg) { SRV_LISTENER_CFG_T *pListenCfg = (SRV_LISTENER_CFG_T *) pArg; CLIENT_CONN_T *pConn = NULL; NETIO_SOCK_T netsocksrv; struct sockaddr_in sa; int haveRtspAuth = 0; char buf[SAFE_INET_NTOA_LEN_MAX]; char bufses[32]; int rc = 0; logutil_tid_add(pthread_self(), pListenCfg->tid_tag); memset(&sa, 0, sizeof(sa)); memset(&netsocksrv, 0, sizeof(netsocksrv)); sa.sin_family = PF_INET; sa.sin_addr = pListenCfg->sain.sin_addr; sa.sin_port = pListenCfg->sain.sin_port; netsocksrv.flags = pListenCfg->netflags; if((NETIOSOCK_FD(netsocksrv) = net_listen(&sa, 5)) == INVALID_SOCKET) { logutil_tid_remove(pthread_self()); return; } pConn = (CLIENT_CONN_T *) pListenCfg->pConnPool->pElements; if(pConn) { if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_RTSP].stores[pListenCfg->idxCfg])) { haveRtspAuth = 1; } } pthread_mutex_lock(&pListenCfg->mtx); pListenCfg->pnetsockSrv = &netsocksrv; pthread_mutex_unlock(&pListenCfg->mtx); if(pListenCfg->pCfg->prtspsessiontimeout && *pListenCfg->pCfg->prtspsessiontimeout != 0) { snprintf(bufses, sizeof(bufses), ", timeout:%u sec", *pListenCfg->pCfg->prtspsessiontimeout); } else { bufses[0] = '\0'; } LOG(X_INFO("rtsp %sserver available at "URL_RTSP_FMT_STR"%s max:%d%s"), ((pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ? "(SSL) " : ""), URL_RTSP_FMT2_ARGS( (pListenCfg->netflags & NETIO_FLAG_SSL_TLS), net_inet_ntoa(sa.sin_addr, buf)), ntohs(sa.sin_port), (haveRtspAuth ? " (Using auth)" : ""), pListenCfg->max, bufses); // // Service any client connections on the rtsp listening port // rc = srvlisten_loop(pListenCfg, srv_rtsp_proc); pthread_mutex_lock(&pListenCfg->mtx); pListenCfg->pnetsockSrv = NULL; netio_closesocket(&netsocksrv); pthread_mutex_unlock(&pListenCfg->mtx); LOG(X_DEBUG("rtsp listener thread exiting with code: %d"), rc); logutil_tid_remove(pthread_self()); return ; }
static void srvlisten_http_proc(void *pArg) { SRV_LISTENER_CFG_T *pListenCfg = (SRV_LISTENER_CFG_T *) pArg; NETIO_SOCK_T netsocksrv; struct sockaddr_in sa; CLIENT_CONN_T *pConn; unsigned int tsMax = 0; unsigned int flvMax = 0; unsigned int mkvMax = 0; /* int haveMkvAuth = 0; int haveFlvAuth = 0; int haveTsliveAuth = 0; int haveHttpliveAuth = 0; int haveMoofAuth = 0; int haveConfigAuth = 0; int havePipAuth = 0; int haveStatusAuth = 0; int haveRootAuth = 0; */ int haveAuth = 0; int rc = 0; char buf[SAFE_INET_NTOA_LEN_MAX]; logutil_tid_add(pthread_self(), pListenCfg->tid_tag); if((pListenCfg->urlCapabilities & (URL_CAP_TSLIVE | URL_CAP_TSHTTPLIVE | URL_CAP_FLVLIVE | URL_CAP_MKVLIVE | URL_CAP_LIVE | URL_CAP_STATUS | URL_CAP_MOOFLIVE | URL_CAP_PIP | URL_CAP_CONFIG | URL_CAP_BROADCAST)) == 0) { LOG(X_WARNING("http listener exiting because no capabilities enabled on %s:%d"), inet_ntoa(pListenCfg->sain.sin_addr), ntohs(pListenCfg->sain.sin_port)); logutil_tid_remove(pthread_self()); return; } memset(&sa, 0, sizeof(sa)); memset(&netsocksrv, 0, sizeof(netsocksrv)); sa.sin_family = PF_INET; sa.sin_addr = pListenCfg->sain.sin_addr; sa.sin_port = pListenCfg->sain.sin_port; netsocksrv.flags = pListenCfg->netflags; if((NETIOSOCK_FD(netsocksrv) = net_listen(&sa, 5)) == INVALID_SOCKET) { logutil_tid_remove(pthread_self()); return; } pthread_mutex_lock(&pListenCfg->mtx); pListenCfg->pnetsockSrv = &netsocksrv; pthread_mutex_unlock(&pListenCfg->mtx); if(pListenCfg->pAuthStore && IS_AUTH_CREDENTIALS_SET(pListenCfg->pAuthStore)) { haveAuth = 1; } pConn = (CLIENT_CONN_T *) pListenCfg->pConnPool->pElements; if(pConn) { tsMax = pConn->pStreamerCfg0->liveQs[0].max; flvMax = pConn->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_FLV].max; mkvMax = pConn->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_MKV].max; /* if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_FLV].stores[pListenCfg->idxCfg])) { haveFlvAuth = 1; } if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_MKV].stores[pListenCfg->idxCfg])) { haveMkvAuth = 1; } if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_TSLIVE].stores[pListenCfg->idxCfg])) { haveTsliveAuth = 1; } if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_HTTPLIVE].stores[pListenCfg->idxCfg])) { haveHttpliveAuth = 1; } if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_MOOFLIVE].stores[pListenCfg->idxCfg])) { haveMoofAuth = 1; } if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_CONFIG].stores[pListenCfg->idxCfg])) { haveConfigAuth = 1; } if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_PIP].stores[pListenCfg->idxCfg])) { havePipAuth = 1; } if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_STATUS].stores[pListenCfg->idxCfg])) { haveStatusAuth = 1; } if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_ROOT].stores[pListenCfg->idxCfg])) { haveRootAuth = 1; } */ //if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds.auths[STREAMER_AUTH_IDX_ROOT])) { // LOG(X_DEBUG("LIVE/ROOT AUTH ON")); //} } if((pListenCfg->urlCapabilities & URL_CAP_ROOTHTML)) { LOG(X_INFO("broadcast interface available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_ROOT_URL, //(haveRootAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max); } if((pListenCfg->urlCapabilities & URL_CAP_LIVE)) { LOG(X_INFO("live available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_LIVE_URL, //(haveRootAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max); } if((pListenCfg->urlCapabilities & URL_CAP_TSLIVE)) { LOG(X_INFO("tslive available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_TSLIVE_URL, //(haveTsliveAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), tsMax); } if((pListenCfg->urlCapabilities & URL_CAP_TSHTTPLIVE)) { LOG(X_INFO("httplive available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_HTTPLIVE_URL, //(haveHttpliveAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max); } if((pListenCfg->urlCapabilities & URL_CAP_FLVLIVE)) { LOG(X_INFO("flvlive available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_FLVLIVE_URL, //(haveFlvAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), flvMax); } if((pListenCfg->urlCapabilities & URL_CAP_MKVLIVE)) { LOG(X_INFO("mkvlive available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_MKVLIVE_URL, //(haveMkvAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), mkvMax); } if((pListenCfg->urlCapabilities & URL_CAP_MOOFLIVE)) { LOG(X_INFO("dash available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_DASH_URL, // (haveMoofAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max); } if((pListenCfg->urlCapabilities & URL_CAP_STATUS)) { LOG(X_INFO("status available at "URL_HTTP_FMT_STR"%s%s%s"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_STATUS_URL, //(haveStatusAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : "")); } if((pListenCfg->urlCapabilities & URL_CAP_PIP)) { LOG(X_INFO("pip available at "URL_HTTP_FMT_STR"%s%s%s"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_PIP_URL, //(havePipAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : "")); } if((pListenCfg->urlCapabilities & URL_CAP_CONFIG)) { LOG(X_INFO("config available at "URL_HTTP_FMT_STR"%s%s%s"), URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_CONFIG_URL, //(haveConfigAuth ? " (Using auth)" : ""), (haveAuth ? " (Using auth)" : ""), (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : "")); } //fprintf(stderr, "LISTENER THREAD %s %s:%d active:%d cap: 0x%x\n", pListenCfg->netflags & NETIO_FLAG_SSL_TLS ? "SSL" : "", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port), pListenCfg->active, pListenCfg->urlCapabilities); // // Service any client connections on the live listening port // rc = srvlisten_loop(pListenCfg, srv_cmd_proc); pthread_mutex_lock(&pListenCfg->mtx); pListenCfg->pnetsockSrv = NULL; netio_closesocket(&netsocksrv); pthread_mutex_unlock(&pListenCfg->mtx); LOG(X_WARNING("HTTP listener thread exiting with code: %d"), rc); logutil_tid_remove(pthread_self()); return; }
int srvauth_authenticate(const AUTH_CREDENTIALS_STORE_T *pAuthStore, const HTTP_REQ_T *pReq, const char *nonce_srv, const char *opaque_srv, const char *realm_srv, char *bufAuthHdr, unsigned int bufOutSz) { int rc = 0; int ok_auth = 0; int do_basic = 0; char bufAuth[1024]; char tmpH1[KEYVAL_MAXLEN]; char tmpH2[KEYVAL_MAXLEN]; char tmpDigest[KEYVAL_MAXLEN]; char tmps[6][KEYVAL_MAXLEN]; char bufnonce[AUTH_NONCE_MAXLEN]; const char *pAuthHdr = NULL; const char *enc = NULL; const char *realm = NULL; const char *uri_cli = NULL; const char *qop_cli = NULL; const char *nc_cli = NULL; const char *cnonce_cli = NULL; const char *nonce_cli = NULL; const char *resp_cli = NULL; AUTH_LIST_T authList; AUTH_CREDENTIALS_STORE_T authStore; if(!pAuthStore || !pReq) { return -1; } if(!IS_AUTH_CREDENTIALS_SET(pAuthStore)) { // // No username and password has been set // return 0; } if(!(realm = realm_srv)) { realm = pAuthStore->realm; } if(!realm || realm[0] == '\0') { realm = VSX_BINARY; } if(pAuthStore->authtype == HTTP_AUTH_TYPE_FORCE_BASIC) { do_basic = 1; } if(ok_auth >= 0 && !(pAuthHdr = conf_find_keyval((const KEYVAL_PAIR_T *) &pReq->reqPairs, HTTP_HDR_AUTHORIZATION))) { LOG(X_WARNING("Client request doest not include "HTTP_HDR_AUTHORIZATION" header for %s %s"), pReq->method, pReq->url); ok_auth = -1; } if(ok_auth >= 0) { enc = pAuthHdr; MOVE_WHILE_SPACE(enc); if(!strncasecmp(AUTH_STR_BASIC, enc, strlen(AUTH_STR_BASIC))) { enc += strlen(AUTH_STR_BASIC); MOVE_WHILE_SPACE(enc); if(pAuthStore->authtype == HTTP_AUTH_TYPE_ALLOW_BASIC || pAuthStore->authtype == HTTP_AUTH_TYPE_FORCE_BASIC) { do_basic = 1; } else { LOG(X_WARNING("Client wants disabled Basic authentication for %s %s"), pReq->method, pReq->url); ok_auth = -1; } } else if(!strncasecmp(AUTH_STR_DIGEST, enc, strlen(AUTH_STR_DIGEST))) { enc += strlen(AUTH_STR_DIGEST); MOVE_WHILE_SPACE(enc); } else { LOG(X_WARNING("Client request contains unsupported "HTTP_HDR_AUTHORIZATION " header type '%s' for %s %s"), pAuthHdr, pReq->method, pReq->url); ok_auth = -1; } } if(ok_auth >= 0 && do_basic) { // // Basic Auth // memset(&authStore, 0, sizeof(authStore)); // // Parse the header Authorization: Basic <Base64(username:password)> // if(ok_auth >= 0 && auth_basic_decode(enc, authStore.username, sizeof(authStore.username), authStore.pass, sizeof(authStore.pass)) < 0) { LOG(X_WARNING("Client "HTTP_HDR_AUTHORIZATION" Basic Auth decode failed for '%s' for %s %s"), enc, pReq->method, pReq->url); ok_auth = -1; } // // Verify the username and password // if(ok_auth >= 0) { if(((pAuthStore->username[0] != '\0' && !strcmp(pAuthStore->username, authStore.username)) && (pAuthStore->pass[0] != '\0' && !strcmp(pAuthStore->pass, authStore.pass)))) { ok_auth = 1; } else { LOG(X_WARNING("Client "HTTP_HDR_AUTHORIZATION" incorrect Basic auth credentials for " "'%s' for %s %s username: %s"), pAuthHdr, pReq->method, pReq->url, pAuthStore->username); ok_auth = -1; } } } else if(ok_auth >= 0) { // // Parse the Digest Authorization header // if(ok_auth >= 0 && auth_digest_parse(enc, &authList) < 0) { LOG(X_WARNING("Failed to parse client "HTTP_HDR_AUTHORIZATION" '%s' for %s %s"), pAuthHdr, pReq->method, pReq->url); ok_auth = -1; } else if(ok_auth >= 0) { uri_cli = avc_dequote(conf_find_keyval(&authList.list[0], "uri"), tmps[0], sizeof(tmps[0])); qop_cli = avc_dequote(conf_find_keyval(&authList.list[0], "qop"), tmps[1], sizeof(tmps[1])); nc_cli = avc_dequote(conf_find_keyval(&authList.list[0], "nc"), tmps[2], sizeof(tmps[2])); cnonce_cli = avc_dequote(conf_find_keyval(&authList.list[0], "cnonce"), tmps[3], sizeof(tmps[3])); nonce_cli = avc_dequote(conf_find_keyval(&authList.list[0], "nonce"), tmps[4], sizeof(tmps[4])); resp_cli = avc_dequote(conf_find_keyval(&authList.list[0], "response"), tmps[5], sizeof(tmps[5])); // // If nonce_srv is supplied, we try to do nonce validation // (prior generated nonce should not be stored per-connection but globally with matching // client IP and creation time // if(ok_auth >= 0 && (!nonce_cli || (nonce_srv && strcmp(nonce_cli, nonce_srv)))) { LOG(X_WARNING("Invalid nonce from client: '%s', expected: '%s' for %s %s"), nonce_cli, nonce_srv, pReq->method, pReq->url); ok_auth = -1; } if(ok_auth >= 0 && (rc = auth_digest_getH1(pAuthStore->username, realm, pAuthStore->pass, tmpH1, sizeof(tmpH1))) < 0) { ok_auth = -1; } if(ok_auth >= 0 && (rc = auth_digest_getH2(pReq->method, uri_cli, tmpH2, sizeof(tmpH2))) < 0) { ok_auth = -1; } if(ok_auth >= 0 && (rc = auth_digest_getDigest(tmpH1, nonce_srv ? nonce_srv : nonce_cli, tmpH2, nc_cli, cnonce_cli, qop_cli, tmpDigest, sizeof(tmpDigest))) < 0) { ok_auth = -1; } if(ok_auth >= 0 && resp_cli && !strcmp(tmpDigest, resp_cli)) { ok_auth = 1; } else { LOG(X_WARNING("Client "HTTP_HDR_AUTHORIZATION" incorrect Digest auth credentials for '%s' " "for %s %s username: %s"), pAuthHdr, pReq->method, pReq->url, pAuthStore->username); ok_auth = -1; } } } if(ok_auth > 0) { LOG(X_DEBUG("Succesful %s authentication for %s %s username: %s"), do_basic ? "Basic" : "Digest", pReq->method, pReq->url, pAuthStore->username); } else if(ok_auth <= 0 && bufAuthHdr && bufOutSz > 0) { if(do_basic == 1) { // // Basic Auth unauthorized resposne // if((rc = snprintf(bufAuthHdr, bufOutSz, "%s: %s realm=\"%s\"\r\n", HTTP_HDR_WWW_AUTHENTICATE, AUTH_STR_BASIC, realm)) < 0) { return -1; } } else { // // Digest Auth RFC 2069 / RFC 2617 unauthorized response // memset(&authList, 0, sizeof(authList)); if(nonce_srv && nonce_srv[0] == '\0') { auth_digest_gethexrandom(16, (char *) nonce_srv, AUTH_NONCE_MAXLEN); } else { auth_digest_gethexrandom(16, (char *) bufnonce, AUTH_NONCE_MAXLEN); } if(opaque_srv && opaque_srv[0] == '\0') { auth_digest_gethexrandom(16, (char *) opaque_srv, AUTH_OPAQUE_MAXLEN); } //auth_digest_additem(&authList, "qop", "auth", 1); auth_digest_additem(&authList, "realm", realm, 1); auth_digest_additem(&authList, "nonce", nonce_srv ? nonce_srv : bufnonce, 1); if(opaque_srv) { auth_digest_additem(&authList, "opaque", opaque_srv, 1); } if((rc = auth_digest_write(&authList, bufAuth, sizeof(bufAuth))) < 0) { return -1; } if((rc = snprintf(bufAuthHdr, bufOutSz, "%s: %s\r\n", HTTP_HDR_WWW_AUTHENTICATE, bufAuth)) < 0) { return -1; } } //if(rtsp_resp_sendhdr(pRtsp->pSd, statusCode, pReq->cseq, // pRtsp->pSession, 0, NULL, bufAuthHdr) < 0) { // rc = -1; //} } return ok_auth > 0 ? 0 : -1; }