diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index edf0ab24a169c0a24ab1f8e554e7c0282c92a47f..99e42377eef1135871b335d187fecda8c7d8b9cd 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -138,8 +138,9 @@ extern "C" { #define TSDB_CODE_FAILED_TO_LOCK_RESOURCES 117 #define TSDB_CODE_TABLE_ID_MISMATCH 118 #define TSDB_CODE_QUERY_CACHE_ERASED 119 +#define TSDB_CODE_AUTH_BANNED_PERIOD 120 -#define TSDB_CODE_MAX_ERROR_CODE 120 +#define TSDB_CODE_MAX_ERROR_CODE 121 #ifdef __cplusplus } diff --git a/src/inc/tglobalcfg.h b/src/inc/tglobalcfg.h index 35cf6a42443ef40135c3937867339c6634c32140..462d488a6ba0c5334f70cd07e2284131df0867f6 100644 --- a/src/inc/tglobalcfg.h +++ b/src/inc/tglobalcfg.h @@ -150,6 +150,7 @@ extern int tsHttpMaxThreads; extern int tsHttpEnableCompress; extern int tsHttpEnableRecordSql; extern int tsTelegrafUseFieldNum; +extern int tsMaxAuthRetry; extern int tsTscEnableRecordSql; extern int tsAnyIp; @@ -255,7 +256,7 @@ extern int tsGlobalConfigNum; extern char * tsCfgStatusStr[]; SGlobalConfig *tsGetConfigOption(const char *option); -#define TSDB_CFG_MAX_NUM 110 +#define TSDB_CFG_MAX_NUM 111 #define TSDB_CFG_PRINT_LEN 23 #define TSDB_CFG_OPTION_LEN 24 #define TSDB_CFG_VALUE_LEN 41 diff --git a/src/inc/trpc.h b/src/inc/trpc.h index 97a0c905f8c3584fee0de46b064f79a78db19f15..fb5cc20908a3b7ac708ad5983762f762bd606570 100644 --- a/src/inc/trpc.h +++ b/src/inc/trpc.h @@ -62,6 +62,7 @@ typedef struct { void (*efp)(int cid); // call back function to process not activated chann int (*afp)(char *meterId, char *spi, char *encrypt, uint8_t *secret, uint8_t *ckey); // call back to retrieve auth info + int (*ufp)(char *user, int32_t *failCount, int32_t *allowTime, bool opSet); // callback to update auth retry info } SRpcInit; typedef struct { diff --git a/src/inc/ttime.h b/src/inc/ttime.h index 34c241cbc0f22afc511660cee475c82d08466599..6302f1a9c67a4ac7e07fc55c1b58c59b7f905e56 100644 --- a/src/inc/ttime.h +++ b/src/inc/ttime.h @@ -44,6 +44,7 @@ int32_t getTimestampInUsFromStr(char* token, int32_t tokenlen, int64_t* ts); int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec); void deltaToUtcInitOnce(); +int32_t taosTimeSecToString(time_t ts, char* outstr); #ifdef __cplusplus } #endif diff --git a/src/rpc/src/trpc.c b/src/rpc/src/trpc.c index 87506861b1a660fa7745012a45120942a2772ec4..d8f0cac87415e2bf94b0a7596d700c8f218e85f1 100755 --- a/src/rpc/src/trpc.c +++ b/src/rpc/src/trpc.c @@ -30,6 +30,7 @@ #include "tudp.h" #include "tutil.h" #include "lz4.h" +#include "tglobalcfg.h" typedef struct _msg_node { struct _msg_node *next; @@ -101,6 +102,7 @@ typedef struct rpc_server { void *(*fp)(char *, void *ahandle, void *thandle); void (*efp)(int); // FP to report error int (*afp)(char *meterId, char *spi, char *encrypt, uint8_t *secret, uint8_t *ckey); // FP to retrieve auth info + int (*ufp)(char *user, int32_t *failCount, int32_t *allowTime, bool opSet); // FP to update auth fail retry info SRpcChann *channList; } STaosRpc; @@ -408,6 +410,7 @@ void *taosOpenRpc(SRpcInit *pRpc) { pServer->qhandle = pRpc->qhandle; pServer->efp = pRpc->efp; pServer->afp = pRpc->afp; + pServer->ufp = pRpc->ufp; int size = (int)sizeof(SRpcChann) * pRpc->numOfChanns; pServer->channList = (SRpcChann *)malloc((size_t)size); @@ -894,9 +897,11 @@ int taosProcessMsgHeader(STaosHeader *pHeader, SRpcConn **ppConn, STaosRpc *pSer // authentication STaosDigest *pDigest = (STaosDigest *)((char *)pHeader + dataLen - sizeof(STaosDigest)); - int32_t delta; + int32_t delta, authTime,failedCount,authAllowTime; delta = (int32_t)htonl(pDigest->timeStamp); delta -= (int32_t)taosGetTimestampSec(); + authTime = (int32_t)taosGetTimestampSec(); + if (abs(delta) > 900) { tWarn("%s cid:%d sid:%d id:%s, time diff:%d is too big, msg discarded pConn:%p, timestamp:%d", pServer->label, chann, sid, pConn->meterId, delta, pConn, htonl(pDigest->timeStamp)); @@ -904,10 +909,37 @@ int taosProcessMsgHeader(STaosHeader *pHeader, SRpcConn **ppConn, STaosRpc *pSer code = TSDB_CODE_INVALID_TIME_STAMP; goto _exit; } - + + if (pServer->ufp) { + int ret = (*pServer->ufp)(pHeader->meterId,&failedCount,&authAllowTime,false); + if (0 == ret) { + if (authTime < authAllowTime) { + char ipstr[24]; + tinet_ntoa(ipstr, ip); + char timestr[50]; + taosTimeSecToString((time_t)authAllowTime,timestr); + mLError("user:%s login from %s, authentication not allowed until %s", pHeader->meterId, ipstr,timestr); + tTrace("%s cid:%d sid:%d id:%s, auth not allowed because failed authentication exceeds max limit, msg discarded pConn:%p, until %s", pServer->label, chann, sid, + pConn->meterId, pConn, timestr); + code = TSDB_CODE_AUTH_BANNED_PERIOD; + goto _exit; + } + }else { + code = ret; + goto _exit; + } + } + if (taosAuthenticateMsg((uint8_t *)pHeader, dataLen - TSDB_AUTH_LEN, pDigest->auth, pConn->secret) < 0) { char ipstr[24]; tinet_ntoa(ipstr, ip); + failedCount++; + if (failedCount >= tsMaxAuthRetry) { + authAllowTime = authTime + 600;//ban the user for 600 seconds + failedCount = 0; + } + (*pServer->ufp)(pHeader->meterId,&failedCount,&authAllowTime,true); + mLError("user:%s login from %s, authentication failed", pHeader->meterId, ipstr); tError("%s cid:%d sid:%d id:%s, authentication failed, msg discarded pConn:%p", pServer->label, chann, sid, pConn->meterId, pConn); diff --git a/src/rpc/src/tstring.c b/src/rpc/src/tstring.c index a254ceecfd1f6ce13b1cc30f8c0c87b6b8edfca9..827942b0e2d44191824e0c694125467715d685f3 100644 --- a/src/rpc/src/tstring.c +++ b/src/rpc/src/tstring.c @@ -244,4 +244,5 @@ char *tsError[] = {"success", "failed to lock resources", "table id/uid mismatch", "client query cache erased", // 119 + "too many authentication failed, try 10 minutes later", //120 }; diff --git a/src/system/detail/inc/mgmt.h b/src/system/detail/inc/mgmt.h index 24f9822f1616529801ef2eee8ce3ec3dc5fc6f5d..3fb3522c859c9d2d4817b36e58a1e39d7ef5a2ef 100644 --- a/src/system/detail/inc/mgmt.h +++ b/src/system/detail/inc/mgmt.h @@ -177,6 +177,8 @@ typedef struct _user_obj { char reserved[16]; char updateEnd[1]; struct _user_obj *prev, *next; + int32_t authAllowTime; + int32_t authFailCount; } SUserObj; typedef struct { @@ -272,6 +274,7 @@ int mgmtSendOneFreeVnodeMsg(SVnodeGid *pVnodeGid); int mgmtInitShell(); void mgmtCleanUpShell(); int mgmtRetriveUserAuthInfo(char *user, char *spi, char *encrypt, uint8_t *secret, uint8_t *ckey); +int mgmtGetSetUserAuthFailInfo(char *user, int32_t *failedCount, int32_t *allowTime, bool opSet); // acct API int mgmtInitAccts(); diff --git a/src/system/detail/src/mgmtShell.c b/src/system/detail/src/mgmtShell.c index 2300cdaddcb9cac2ccc2c42b24e3b911c8db14d0..af54ce9bf38c079a35a3e9566491a60654db6399 100644 --- a/src/system/detail/src/mgmtShell.c +++ b/src/system/detail/src/mgmtShell.c @@ -87,6 +87,7 @@ int mgmtInitShell() { rpcInit.idleTime = tsShellActivityTimer * 2000; rpcInit.qhandle = mgmtQhandle; rpcInit.afp = mgmtRetriveUserAuthInfo; + rpcInit.ufp = mgmtGetSetUserAuthFailInfo; pShellConn = taosOpenRpc(&rpcInit); if (pShellConn == NULL) { @@ -1271,6 +1272,21 @@ int mgmtRetriveUserAuthInfo(char *user, char *spi, char *encrypt, uint8_t *secre return 0; } +int mgmtGetSetUserAuthFailInfo(char *user, int32_t *failCount, int32_t *allowTime, bool opSet) { + SUserObj *pUser = NULL; + + pUser = mgmtGetUser(user); + if (pUser == NULL) return TSDB_CODE_INVALID_USER; + if (opSet) { + pUser->authAllowTime = *allowTime; + pUser->authFailCount = *failCount; + }else { + *allowTime = pUser->authAllowTime; + *failCount = pUser->authFailCount; + } + return 0; +} + int mgmtProcessConnectMsg(char *pMsg, int msgLen, SConnObj *pConn) { STaosRsp * pRsp; SConnectRsp *pConnectRsp; diff --git a/src/util/src/tglobalcfg.c b/src/util/src/tglobalcfg.c index 400bce32e755c0ab683ee0d54c1151219515c7b3..813c66241a820da886392db38775705544879774 100644 --- a/src/util/src/tglobalcfg.c +++ b/src/util/src/tglobalcfg.c @@ -134,6 +134,7 @@ int tsEnableHttpModule = 1; int tsEnableMonitorModule = 1; int tsRestRowLimit = 10240; int tsMaxSQLStringLen = TSDB_MAX_SQL_LEN; +int tsMaxAuthRetry = 5; // the maximum number of results for projection query on super table that are returned from // one virtual node, to order according to timestamp @@ -689,7 +690,11 @@ static void doInitGlobalConfig() { tsInitConfigOption(cfg++, "maxSQLLength", &tsMaxSQLStringLen, TSDB_CFG_VTYPE_INT, TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_CLIENT | TSDB_CFG_CTYPE_B_SHOW, TSDB_MAX_SQL_LEN, TSDB_MAX_ALLOWED_SQL_LEN, 0, TSDB_CFG_UTYPE_BYTE); - + + tsInitConfigOption(cfg++, "maxAuthRetryTime", &tsMaxAuthRetry, TSDB_CFG_VTYPE_INT, + TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_CLIENT | TSDB_CFG_CTYPE_B_SHOW, + 1, 10, 0, TSDB_CFG_UTYPE_BYTE); + tsInitConfigOption(cfg++, "maxNumOfOrderedRes", &tsMaxNumOfOrderedResults, TSDB_CFG_VTYPE_INT, TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_CLIENT | TSDB_CFG_CTYPE_B_SHOW, TSDB_MAX_SQL_LEN, TSDB_MAX_ALLOWED_SQL_LEN, 0, TSDB_CFG_UTYPE_NONE); diff --git a/src/util/src/ttime.c b/src/util/src/ttime.c index 2656c6deb0461b1bcc794d6cd8698842c8c07386..9e0f92475e4420a147d8f822a54b7ee182d31a97 100644 --- a/src/util/src/ttime.c +++ b/src/util/src/ttime.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "tsdb.h" #include "ttime.h" @@ -158,6 +159,19 @@ int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePre } } +int32_t taosTimeSecToString(time_t ts,char* outstr) { + if (NULL == outstr) { + return 1; + } + struct tm *t; + t = localtime(&ts); + if (NULL == t) return 1; + + sprintf(outstr,"%4d-%02d-%02d %02d:%02d:%02d\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + return 0; + +} + char* forwardToTimeStringEnd(char* str) { int32_t i = 0; int32_t numOfSep = 0;