From 8d935a892b17613683a3aa493b18c6442fb99cf9 Mon Sep 17 00:00:00 2001 From: liu0x54 Date: Sun, 26 Apr 2020 16:39:55 +0800 Subject: [PATCH] [TD-154] ban authentication based on failure count --- src/inc/taoserror.h | 3 ++- src/inc/tglobalcfg.h | 3 ++- src/inc/trpc.h | 1 + src/inc/ttime.h | 1 + src/rpc/src/trpc.c | 39 ++++++++++++++++++++++++++++++- src/rpc/src/tstring.c | 1 + src/system/detail/inc/mgmt.h | 3 +++ src/system/detail/src/mgmtShell.c | 16 +++++++++++++ src/util/src/tglobalcfg.c | 5 ++++ src/util/src/ttime.c | 14 +++++++++++ 10 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index edf0ab24a1..99e42377ee 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 35cf6a4244..462d488a6b 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 97a0c905f8..fb5cc20908 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 34c241cbc0..6302f1a9c6 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 87506861b1..4f06e214af 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,42 @@ 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; + } + }else { + tError("%s cid:%d sid:%d id:%s, auth update callback not found, msg discarded pConn:%p", pServer->label, chann, sid, + pConn->meterId, pConn); + code = TSDB_CODE_AUTH_FAILURE; + 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 a254ceecfd..59d627c562 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 24f9822f16..219cb99531 100644 --- a/src/system/detail/inc/mgmt.h +++ b/src/system/detail/inc/mgmt.h @@ -172,6 +172,8 @@ typedef struct _user_obj { char pass[TSDB_KEY_LEN]; char acct[TSDB_USER_LEN]; int64_t createdTime; + int32_t authAllowTime; + int16_t authFailCount; char superAuth : 1; char writeAuth : 1; char reserved[16]; @@ -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 2af9d12929..e4311bed3d 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 84b7e67c66..050480ba19 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 @@ -690,6 +691,10 @@ static void doInitGlobalConfig() { 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 5d5b580a89..113d9f3ad7 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(&((time_t)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; -- GitLab