• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #5055

17 May 2026 01:15AM UTC coverage: 73.355% (-0.003%) from 73.358%
#5055

push

travis-ci

web-flow
feat (TDgpt): Dynamic Model Synchronization Enhancements (#35344)

* refactor: do some internal refactor.

* fix: fix multiprocess sync issue.

* feat: add dynamic anomaly detection and forecasting services

* fix: log error message for undeploying model in exception handling

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: handle undeploy when model exists only on disk

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/286aafa0-c3ce-4c27-b803-2707571e9dc1

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: guard dynamic registry concurrent access

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: tighten service list locking scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: restore prophet support and update tests per review feedback

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: improve test name and move copy inside lock scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* Potential fix for pull request finding

Co-au... (continued)

281532 of 383795 relevant lines covered (73.35%)

135557734.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.64
/source/libs/parser/src/parAuthenticator.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#include "catalog.h"
17
#include "cmdnodes.h"
18
#include "parInt.h"
19
#include "tconfig.h"
20

21
typedef struct SAuthCxt {
22
  SParseContext*   pParseCxt;
23
  SParseMetaCache* pMetaCache;
24
  int32_t          errCode;
25
  bool             macNruGuaranteed;
26
  bool             macNwdGuaranteed;
27
} SAuthCxt;
28

29
typedef struct SSelectAuthCxt {
30
  SAuthCxt*    pAuthCxt;
31
  SSelectStmt* pSelect;
32
} SSelectAuthCxt;
33

34
typedef struct SAuthRewriteCxt {
35
  STableNode* pTarget;
36
} SAuthRewriteCxt;
37

38
extern SConfig* tsCfg;
39

40
static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt);
41

42
#ifdef TD_ENTERPRISE
43
static int32_t macCheckBySecLvl(SAuthCxt* pCxt, int8_t secLvl, bool checkNWD) {
13,419✔
44
  if (secLvl < 0) {
13,419✔
45
    // Unset security level: not subject to MAC enforcement
46
    return TSDB_CODE_SUCCESS;
×
47
  }
48

49
  if (!pCxt->macNruGuaranteed && pCxt->pParseCxt->maxSecLevel < secLvl) {
13,419✔
50
    return TSDB_CODE_MAC_INSUFFICIENT_LEVEL;  // NRU violation
2,268✔
51
  }
52

53
  if (checkNWD && !pCxt->macNwdGuaranteed && pCxt->pParseCxt->minSecLevel > secLvl) {
11,151✔
54
    return TSDB_CODE_MAC_NO_WRITE_DOWN;  // NWD violation
189✔
55
  }
56

57
  return TSDB_CODE_SUCCESS;
10,962✔
58
}
59

60
/**
61
 * @brief Lightweight MAC check for table-level operations.
62
 *
63
 * Uses a 3-layer fast-path strategy to avoid expensive metadata fetches
64
 * in the common case where MAC is not actively used:
65
 *   Layer 1: User-level — if user's security range covers all levels, skip entirely.
66
 *   Layer 2: (DB-level — handled in checkAuthByOwner for PRIV_DB_USE, zero extra cost.)
67
 *   Layer 3: Table-level — fetch table meta from cache only when needed.
68
 *
69
 * @param pCxt      Auth context
70
 * @param dbName    Database name
71
 * @param tableName Table name
72
 * @param checkNWD  true for INSERT (needs No-Write-Down), false for SELECT/DELETE (NRU only)
73
 * @return TSDB_CODE_SUCCESS or TSDB_CODE_MAC_INSUFFICIENT_LEVEL
74
 */
75
static int32_t macCheckTableAccess(SAuthCxt* pCxt, const char* dbName, const char* tableName, bool checkNWD) {
24,298,132✔
76
  SParseContext* pParseCxt = pCxt->pParseCxt;
24,298,132✔
77

78
  // Fast-path: MAC not yet activated cluster-wide — skip all checks
79
  if (!pParseCxt->macMode) {
24,298,132✔
80
    return TSDB_CODE_SUCCESS;
24,293,218✔
81
  }
82

83
  // Layer 1: User-level fast-path — skip if user's security range guarantees MAC pass
84
  if (pCxt->macNruGuaranteed && (!checkNWD || pCxt->macNwdGuaranteed)) {
4,914✔
85
    return TSDB_CODE_SUCCESS;
×
86
  }
87

88
  // Layer 3: Table-level — fetch secLvl from metadata cache
89
  SName name = {0};
4,914✔
90
  toName(pParseCxt->acctId, dbName, tableName, &name);
4,914✔
91
  STableMeta* pTableMeta = NULL;
4,914✔
92
  int32_t     code = getTargetMetaImpl(pParseCxt, pCxt->pMetaCache, &name, &pTableMeta, true);
4,914✔
93
  if (TSDB_CODE_SUCCESS == code && pTableMeta != NULL) {
4,914✔
94
    int8_t secLvl = pTableMeta->secLvl;
4,347✔
95
    taosMemoryFree(pTableMeta);
4,347✔
96
    return macCheckBySecLvl(pCxt, secLvl, checkNWD);
4,347✔
97
  }
98
  return TSDB_CODE_SUCCESS;
567✔
99
}
100
#endif
101

102
static int32_t setUserAuthInfo(SParseContext* pCxt, const char* pDbName, const char* pTabName, EPrivType privType,
3,182,910✔
103
                               EPrivObjType objType, bool isView, bool effective, SUserAuthInfo* pAuth) {
104
  if (effective) {
3,182,910✔
105
    snprintf(pAuth->user, sizeof(pAuth->user), "%s", pCxt->pEffectiveUser ? pCxt->pEffectiveUser : "");
17,935✔
106
    pAuth->userId = pCxt->effectiveUserId;  // TODO: assign the effective user id
17,935✔
107
  } else {
108
    snprintf(pAuth->user, sizeof(pAuth->user), "%s", pCxt->pUser);
3,164,975✔
109
    pAuth->userId = pCxt->userId;
3,164,975✔
110
  }
111

112
  if (NULL == pTabName) {
3,182,910✔
113
    if (pDbName) {
2,102,389✔
114
      int32_t code = tNameSetDbName(&pAuth->tbName, pCxt->acctId, pDbName, strlen(pDbName));
1,861,468✔
115
      if (TSDB_CODE_SUCCESS != code) return code;
1,861,468✔
116
    } else {
117
      pAuth->tbName.acctId = pCxt->acctId;
240,921✔
118
      pAuth->tbName.type = TSDB_SYS_NAME_T;
240,921✔
119
    }
120
  } else {
121
    toName(pCxt->acctId, pDbName, pTabName, &pAuth->tbName);
1,080,521✔
122
  }
123
  pAuth->privType = privType;
3,182,910✔
124
  pAuth->objType = objType;
3,182,910✔
125
  pAuth->isView = isView;
3,182,910✔
126
  return TSDB_CODE_SUCCESS;
3,182,910✔
127
}
128

129
static int32_t checkAuthByOwner(SAuthCxt* pCxt, SUserAuthInfo* pAuthInfo, SUserAuthRes* pAuthRes, bool *recheck) {
2,715,801✔
130
  SParseContext*   pParseCxt = pCxt->pParseCxt;
2,715,801✔
131
  const SPrivInfo* pPrivInfo = privInfoGet(pAuthInfo->privType);
2,715,801✔
132
  if (NULL == pPrivInfo) {
2,715,801✔
133
    return TSDB_CODE_PAR_INTERNAL_ERROR;
408✔
134
  }
135
  int32_t code = 0;
2,715,393✔
136
  if (pPrivInfo->category == PRIV_CATEGORY_OBJECT || pAuthInfo->objType == PRIV_OBJ_DB) {
2,715,393✔
137
    SPrivInfo privInfoDup = *pPrivInfo;
1,992,321✔
138
    if (privInfoDup.objType <= 0) privInfoDup.objType = PRIV_OBJ_DB;
1,992,321✔
139
    switch (privInfoDup.objType) {
1,992,321✔
140
      case PRIV_OBJ_DB: {
1,496,512✔
141
        SDbCfgInfo dbCfgInfo = {0};
1,496,512✔
142
        char       dbFName[TSDB_DB_FNAME_LEN] = {0};
1,496,512✔
143
        (void)tNameGetFullDbName(&pAuthInfo->tbName, dbFName);
1,496,512✔
144
        code = getDbCfgFromCache(pCxt->pMetaCache, dbFName, &dbCfgInfo);
1,496,512✔
145
        if (TSDB_CODE_SUCCESS != code) {
1,496,512✔
146
          return code;
218,190✔
147
        }
148
#ifdef TD_ENTERPRISE
149
        // Layer 2 MAC: DB-level NRU check — piggybacked on already-fetched SDbCfgInfo
150
        // Only for DB_USE to avoid blocking admin ops (ALTER/DROP by SYSSEC)
151
        // Skip when MAC is not yet activated cluster-wide
152
        if (pParseCxt->macMode && pAuthInfo->privType == PRIV_DB_USE && dbCfgInfo.securityLevel > 0 &&
1,416,430✔
153
            pParseCxt->maxSecLevel < (int8_t)dbCfgInfo.securityLevel) {
8,694✔
154
          pAuthRes->pass[pAuthInfo->isView ? AUTH_RES_VIEW : AUTH_RES_BASIC] = false;
3,024✔
155
          return TSDB_CODE_MAC_INSUFFICIENT_LEVEL;
3,024✔
156
        }
157
#endif
158
        // rewrite privilege for audit db
159
        if (dbCfgInfo.isAudit && pAuthInfo->objType == PRIV_OBJ_DB) {
1,413,406✔
160
          if (pAuthInfo->privType == PRIV_DB_USE) {
×
161
            pAuthInfo->useDb = AUTH_OWNED_MASK;
×
162
            if (recheck) *recheck = true;  // recheck since the cached key is changed
×
163
          } else if (pAuthInfo->privType == PRIV_CM_ALTER) {
×
164
            pAuthInfo->privType = PRIV_AUDIT_DB_ALTER;
×
165
            pAuthInfo->objType = PRIV_OBJ_CLUSTER;
×
166
            if (recheck) *recheck = true;  // recheck since the cached key is changed
×
167
          } else if (pAuthInfo->privType == PRIV_CM_DROP) {
×
168
            pAuthInfo->privType = PRIV_AUDIT_DB_DROP;
×
169
            pAuthInfo->objType = PRIV_OBJ_CLUSTER;
×
170
            if (recheck) *recheck = true;  // recheck since the cached key is changed
×
171
          } else if (pAuthInfo->privType == PRIV_TBL_CREATE) {
×
172
            pAuthInfo->privType = PRIV_AUDIT_TBL_CREATE;
×
173
            pAuthInfo->objType = PRIV_OBJ_CLUSTER;
×
174
            if (recheck) *recheck = true;  // recheck since the cached key is changed
×
175
          }
176
          return TSDB_CODE_SUCCESS;
×
177
        }
178
        if (dbCfgInfo.ownerId == pAuthInfo->userId) {
1,413,406✔
179
          pAuthRes->pass[pAuthInfo->isView ? AUTH_RES_VIEW : AUTH_RES_BASIC] = true;
179,831✔
180
          return TSDB_CODE_SUCCESS;
179,831✔
181
        }
182
        break;
1,233,575✔
183
      }
184
      default:
495,809✔
185
        return TSDB_CODE_SUCCESS;
495,809✔
186
    }
187
  }
188
_exit:
723,072✔
189
  return TSDB_CODE_SUCCESS;
1,956,647✔
190
}
191

192
static int32_t checkAuthImpl(SAuthCxt* pCxt, const char* pDbName, const char* pTabName, EPrivType privType,
679,957,406✔
193
                             EPrivObjType objType, SNode** pCond, SArray** pPrivCols, bool isView, bool effective) {
194
  SParseContext* pParseCxt = pCxt->pParseCxt;
679,957,406✔
195
  if (pParseCxt->isSuperUser) {
679,965,843✔
196
    return TSDB_CODE_SUCCESS;
676,787,499✔
197
  }
198

199
  AUTH_RES_TYPE auth_res_type = isView ? AUTH_RES_VIEW : AUTH_RES_BASIC;
3,182,808✔
200
  SUserAuthInfo authInfo = {0};
3,182,808✔
201
  int32_t code = setUserAuthInfo(pCxt->pParseCxt, pDbName, pTabName, privType, objType, isView, effective, &authInfo);
3,182,808✔
202
  if (TSDB_CODE_SUCCESS != code) return code;
3,182,910✔
203
  SUserAuthRes authRes = {0};
3,182,910✔
204
  bool         recheck = false;
3,182,910✔
205
  if (NULL != pCxt->pMetaCache && privType != PRIV_VIEW_SELECT && privType != PRIV_AUDIT_TBL_SELECT) {
3,182,910✔
206
    code = checkAuthByOwner(pCxt, &authInfo, &authRes, &recheck);
2,715,801✔
207
#ifdef TD_ENTERPRISE
208
    // MAC enforcement: do NOT let DAC grants override a MAC NRU/NWD block
209
    if (code == TSDB_CODE_MAC_INSUFFICIENT_LEVEL || code == TSDB_CODE_MAC_NO_WRITE_DOWN) {
2,715,801✔
210
      return code;
3,024✔
211
    }
212
#endif
213
    if (code == TSDB_CODE_SUCCESS && authRes.pass[auth_res_type]) {
2,712,777✔
214
      goto _exit;
179,831✔
215
    }
216
    code = getUserAuthFromCache(pCxt->pMetaCache, &authInfo, &authRes);
2,532,946✔
217
#ifdef TD_ENTERPRISE
218
    if (isView && TSDB_CODE_PAR_INTERNAL_ERROR == code) {
2,532,946✔
219
      authInfo.isView = false;
×
220
      code = getUserAuthFromCache(pCxt->pMetaCache, &authInfo, &authRes);
×
221
    }
222
#endif
223
  } else {
224
    recheck = true;  // recheck since the cached key is changed
467,109✔
225
  }
226
  if (recheck) {  // the priv type of view and audit may be rewritten, need to recheck from catalog
3,000,055✔
227
    SRequestConnInfo conn = {.pTrans = pParseCxt->pTransporter,
499,290✔
228
                             .requestId = pParseCxt->requestId,
467,109✔
229
                             .requestObjRefId = pParseCxt->requestRid,
467,109✔
230
                             .mgmtEps = pParseCxt->mgmtEpSet};
231
    code = catalogChkAuth(pParseCxt->pCatalog, &conn, &authInfo, &authRes);
467,109✔
232
  }
233

234
_exit:
2,606,850✔
235
  if (TSDB_CODE_SUCCESS == code) {
3,179,886✔
236
    if (pCond) *pCond = authRes.pCond[auth_res_type];
3,179,886✔
237
    if (pPrivCols) *pPrivCols = authRes.pCols;
3,179,886✔
238
    if (taosArrayGetSize(authRes.pCols) > 0) {
3,179,886✔
239
      pCxt->pParseCxt->hasPrivCols = 1; // used later in translateCheckPrivCols for select *
61,257✔
240
    }
241
  }
242
  return TSDB_CODE_SUCCESS == code ? (authRes.pass[auth_res_type] ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED)
3,179,886✔
243
                                   : code;
5,751,801✔
244
}
245

246
static int32_t checkAuth(SAuthCxt* pCxt, const char* pDbName, const char* pTabName, EPrivType privType,
679,622,162✔
247
                         EPrivObjType objType, SNode** pCond, SArray** pPrivCols) {
248
#ifdef TD_ENTERPRISE
249
  return checkAuthImpl(pCxt, pDbName, pTabName, privType, objType, pCond, pPrivCols, false, false);
679,622,162✔
250
#else
251
  return TSDB_CODE_SUCCESS;
252
#endif
253
}
254

255
static int32_t authSysPrivileges(SAuthCxt* pCxt, SNode* pStmt, EPrivType type) {
6,439,199✔
256
  return checkAuth(pCxt, NULL, NULL, type, 0, NULL, NULL);
6,439,199✔
257
}
258

259
static int32_t authObjPrivileges(SAuthCxt* pCxt, const char* pDbName, const char* pTabName, EPrivType privType,
327,414,016✔
260
                                 EPrivObjType objType) {
261
  if (!pDbName) {
327,414,016✔
262
    return TSDB_CODE_PAR_INTERNAL_ERROR;
×
263
  }
264

265
  return checkAuth(pCxt, pDbName, pTabName, privType, objType, NULL, NULL);
327,414,016✔
266
}
267

268
// Checks DB_USE privilege and maps non-MAC errors to PAR_DB_USE_PERMISSION_DENIED.
269
// Callers use PAR_ERR_RET(checkDbUseAuth(pCxt, dbName)) for the common pattern.
270
static int32_t checkDbUseAuth(SAuthCxt* pCxt, const char* pDbName) {
309,971,822✔
271
  int32_t code = checkAuth(pCxt, pDbName, NULL, PRIV_DB_USE, PRIV_OBJ_DB, NULL, NULL);
309,971,822✔
272
#ifdef TD_ENTERPRISE
273
  if (code == TSDB_CODE_MAC_INSUFFICIENT_LEVEL || code == TSDB_CODE_MAC_NO_WRITE_DOWN) return code;
309,953,270✔
274
#endif
275
  return code == TSDB_CODE_SUCCESS ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_DB_USE_PERMISSION_DENIED;
309,956,282✔
276
}
277

278
static int32_t checkEffectiveAuth(SAuthCxt* pCxt, const char* pDbName, const char* pTabName, EPrivType privType,
15,189✔
279
                                  EPrivObjType objType, SNode** pCond) {
280
  return checkAuthImpl(pCxt, pDbName, pTabName, privType, objType, NULL, NULL, false, true);
15,189✔
281
}
282

283
static int32_t checkViewAuth(SAuthCxt* pCxt, const char* pDbName, const char* pTabName, EPrivType privType,
323,362✔
284
                             EPrivObjType objType, SNode** pCond) {
285
  return checkAuthImpl(pCxt, pDbName, pTabName, privType, objType, pCond, NULL, true, false);
323,362✔
286
}
287

288
static int32_t checkViewEffectiveAuth(SAuthCxt* pCxt, const char* pDbName, const char* pTabName, EPrivType privType,
2,746✔
289
                                      EPrivObjType objType, SNode** pCond) {
290
  return checkAuthImpl(pCxt, pDbName, pTabName, privType, objType, pCond, NULL, true, true);
2,746✔
291
}
292

293
static EDealRes authSubquery(SAuthCxt* pCxt, SNode* pStmt) {
27,048,896✔
294
  return TSDB_CODE_SUCCESS == authQuery(pCxt, pStmt) ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
27,048,896✔
295
}
296

297
static int32_t mergeStableTagCond(SNode** pWhere, SNode* pTagCond) {
577✔
298
  SLogicConditionNode* pLogicCond = NULL;
577✔
299
  int32_t              code = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION, (SNode**)&pLogicCond);
577✔
300
  if (NULL == pLogicCond) {
577✔
301
    return code;
×
302
  }
303
  pLogicCond->node.resType.type = TSDB_DATA_TYPE_BOOL;
577✔
304
  pLogicCond->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
577✔
305
  pLogicCond->condType = LOGIC_COND_TYPE_AND;
577✔
306
  code = nodesListMakeStrictAppend(&pLogicCond->pParameterList, pTagCond);
577✔
307
  if (TSDB_CODE_SUCCESS == code) {
577✔
308
    code = nodesListMakeAppend(&pLogicCond->pParameterList, *pWhere);
577✔
309
  }
310
  if (TSDB_CODE_SUCCESS == code) {
577✔
311
    *pWhere = (SNode*)pLogicCond;
577✔
312
  } else {
313
    nodesDestroyNode((SNode*)pLogicCond);
×
314
  }
315
  return code;
577✔
316
}
317

318
EDealRes rewriteAuthTable(SNode* pNode, void* pContext) {
60,600✔
319
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
60,600✔
320
    SColumnNode*     pCol = (SColumnNode*)pNode;
18,457✔
321
    SAuthRewriteCxt* pCxt = (SAuthRewriteCxt*)pContext;
18,457✔
322
    tstrncpy(pCol->tableName, pCxt->pTarget->tableName, TSDB_TABLE_NAME_LEN);
18,457✔
323
    tstrncpy(pCol->tableAlias, pCxt->pTarget->tableAlias, TSDB_TABLE_NAME_LEN);
18,457✔
324
    pCol->appendByPrivCond = 1;
18,457✔
325
  }
326

327
  return DEAL_RES_CONTINUE;
60,600✔
328
}
329

330
static int32_t rewriteAppendStableTagCond(SNode** pWhere, SNode* pTagCond, STableNode* pTable) {
13,228✔
331
  SNode*  pTagCondCopy = NULL;
13,228✔
332
  int32_t code = nodesCloneNode(pTagCond, &pTagCondCopy);
13,228✔
333
  if (NULL == pTagCondCopy) {
13,228✔
334
    return code;
×
335
  }
336

337
  SAuthRewriteCxt cxt = {.pTarget = pTable};
13,228✔
338
  nodesWalkExpr(pTagCondCopy, rewriteAuthTable, &cxt);
13,228✔
339

340
  if (NULL == *pWhere) {
13,228✔
341
    *pWhere = pTagCondCopy;
12,460✔
342
    return TSDB_CODE_SUCCESS;
12,460✔
343
  }
344

345
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pWhere) &&
768✔
346
      LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)*pWhere)->condType) {
191✔
347
    return nodesListStrictAppend(((SLogicConditionNode*)*pWhere)->pParameterList, pTagCondCopy);
191✔
348
  }
349

350
  return mergeStableTagCond(pWhere, pTagCondCopy);
577✔
351
}
352
#if 0
353
/**
354
 * @brief Fast fail path if no star(*) specified in select clause
355
 */
356
static int32_t authSelectTblCols(SSelectStmt* pSelect, STableNode* pTable, SArray* pPrivCols) {
357
  int32_t    code = 0;
358
  SNodeList* pRetrievedCols = NULL;
359
  int32_t    nCols = taosArrayGetSize(pPrivCols);
360

361
  if (nCols <= 0) {
362
    goto _return;
363
  }
364

365
  PAR_ERR_JRET(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, NULL, COLLECT_COL_TYPE_ALL, &pRetrievedCols));
366

367
  int32_t i = 0, j = 0, k = 0;
368
  SNode*  pNode = NULL;
369
  FOREACH(pNode, pRetrievedCols) {
370
    SColumnNode* pColNode = (SColumnNode*)pNode;
371

372
    j = i;
373

374
    // search in the remaining columns first for better performance if ordered
375
    bool found = false;
376
    for (; i < nCols; ++i) {
377
      SColNameFlag* pColNameFlag = (SColNameFlag*)TARRAY_GET_ELEM(pPrivCols, i);
378
      if (strcmp(pColNode->colName, pColNameFlag->colName) == 0) {
379
        found = true;
380
        ++i;
381
        break;
382
      }
383
    }
384
    if (!found) {
385
      for (k = 0; k < j; ++k) {
386
        SColNameFlag* pColNameFlag = (SColNameFlag*)TARRAY_GET_ELEM(pPrivCols, k);
387
        if (strcmp(pColNode->colName, pColNameFlag->colName) == 0) {
388
          found = true;
389
          break;
390
        }
391
      }
392
    }
393
    if (!found) {
394
      code = TSDB_CODE_PAR_COL_PERMISSION_DENIED;
395
      goto _return;
396
    }
397
  }
398
_return:
399
  nodesDestroyList(pRetrievedCols);
400
  return code;
401
}
402
#endif
403

404
static EDealRes authSelectImpl(SNode* pNode, void* pContext) {
2,147,483,647✔
405
  SSelectAuthCxt* pCxt = pContext;
2,147,483,647✔
406
  SAuthCxt*       pAuthCxt = pCxt->pAuthCxt;
2,147,483,647✔
407
  bool            isView = false;
2,147,483,647✔
408
  bool            isAudit = false;
2,147,483,647✔
409
  if (QUERY_NODE_REAL_TABLE == nodeType(pNode)) {
2,147,483,647✔
410
    SNode*      pTagCond = NULL;
220,333,589✔
411
    // SArray*     pPrivCols = NULL;
412
    STableNode* pTable = (STableNode*)pNode;
220,333,472✔
413
    if ((pAuthCxt->pParseCxt->enableSysInfo == 0) && IS_INFORMATION_SCHEMA_DB(pTable->dbName) &&
220,333,472✔
414
        (strcmp(pTable->tableName, TSDB_INS_TABLE_VGROUPS) == 0)) {
25,947✔
415
      pAuthCxt->errCode = TSDB_CODE_PAR_PERMISSION_DENIED;
828✔
416
      return DEAL_RES_ERROR;
828✔
417
    }
418
    int32_t dbUseCode = checkDbUseAuth(pAuthCxt, pTable->dbName);
220,332,966✔
419
    if (dbUseCode != TSDB_CODE_SUCCESS) {
220,329,771✔
420
      pAuthCxt->errCode = dbUseCode;
7,107✔
421
      return DEAL_RES_ERROR;
7,107✔
422
    }
423
#ifdef TD_ENTERPRISE
424
    SName name = {0};
220,322,664✔
425
    toName(pAuthCxt->pParseCxt->acctId, pTable->dbName, pTable->tableName, &name);
220,323,270✔
426
    STableMeta* pTableMeta = NULL;
220,325,149✔
427
    int32_t code = getTargetMetaImpl(pAuthCxt->pParseCxt, pAuthCxt->pMetaCache, &name, &pTableMeta, true);
220,325,356✔
428
    if (TSDB_CODE_SUCCESS == code) {
220,324,777✔
429
      // MAC NRU: user.maxSecLevel must be >= table.securityLevel for SELECT.
430
      // Reuse secLvl from this already-fetched table meta to avoid extra metadata round-trips.
431
      if (pAuthCxt->pParseCxt->macMode && macCheckBySecLvl(pAuthCxt, pTableMeta->secLvl, false) != TSDB_CODE_SUCCESS) {
219,660,918✔
432
        taosMemoryFree(pTableMeta);
1,323✔
433
        pAuthCxt->errCode = TSDB_CODE_MAC_INSUFFICIENT_LEVEL;
1,323✔
434
        return DEAL_RES_ERROR;
1,323✔
435
      }
436
      if (pTableMeta->isAudit) {
219,658,633✔
437
        isAudit = true;
1,074✔
438
      } else if (!pTableMeta->isAudit && (pTableMeta->ownerId == pAuthCxt->pParseCxt->userId)) {
219,658,698✔
439
        // owner has all privileges on the table he owns except audit table
440
        taosMemoryFree(pTableMeta);
212,429,991✔
441
        return DEAL_RES_CONTINUE;
212,427,477✔
442
      }
443
      if (TSDB_VIEW_TABLE == pTableMeta->tableType) {
7,227,225✔
444
        isView = true;
55,175✔
445
      }
446
    }
447
    taosMemoryFree(pTableMeta);
7,893,947✔
448
#endif
449
    if (!isView) {
7,893,414✔
450
      pAuthCxt->errCode =
7,839,409✔
451
          checkAuth(pAuthCxt, pTable->dbName, pTable->tableName, isAudit ? PRIV_AUDIT_TBL_SELECT : PRIV_TBL_SELECT,
7,838,239✔
452
                    PRIV_OBJ_TBL, &pTagCond, NULL);  //&pPrivCols);
453
      if (TSDB_CODE_SUCCESS != pAuthCxt->errCode && NULL != pAuthCxt->pParseCxt->pEffectiveUser) {
7,839,409✔
454
        pAuthCxt->errCode = checkEffectiveAuth(pAuthCxt, pTable->dbName, pTable->tableName,
15,189✔
455
                                               isAudit ? PRIV_AUDIT_TBL_SELECT : PRIV_TBL_SELECT, PRIV_OBJ_TBL, NULL);
456
      }
457
#if 0
458
      if (TSDB_CODE_SUCCESS == pAuthCxt->errCode && NULL != pPrivCols) {
459
        pAuthCxt->errCode = authSelectTblCols(pCxt->pSelect, pTable, pPrivCols);
460
      }
461
#endif
462
      if (TSDB_CODE_SUCCESS == pAuthCxt->errCode && NULL != pTagCond) {
7,838,824✔
463
        pAuthCxt->errCode = rewriteAppendStableTagCond(&pCxt->pSelect->pWhere, pTagCond, pTable);
13,228✔
464
      }
465
    } else {
466
      pAuthCxt->errCode =
55,175✔
467
          checkViewAuth(pAuthCxt, pTable->dbName, pTable->tableName, PRIV_VIEW_SELECT, PRIV_OBJ_VIEW, NULL);
55,175✔
468
      if (TSDB_CODE_SUCCESS != pAuthCxt->errCode && NULL != pAuthCxt->pParseCxt->pEffectiveUser) {
55,175✔
469
        pAuthCxt->errCode =
2,746✔
470
            checkViewEffectiveAuth(pAuthCxt, pTable->dbName, pTable->tableName, PRIV_VIEW_SELECT, PRIV_OBJ_VIEW, NULL);
2,746✔
471
      }
472
    }
473
    return TSDB_CODE_SUCCESS == pAuthCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
7,893,999✔
474
  } else if (QUERY_NODE_TEMP_TABLE == nodeType(pNode)) {
1,988,370,206✔
475
    return authSubquery(pAuthCxt, ((STempTableNode*)pNode)->pSubquery);
27,048,416✔
476
  }
477
  return DEAL_RES_CONTINUE;
1,961,319,546✔
478
}
479

480
static int32_t authSelect(SAuthCxt* pCxt, SSelectStmt* pSelect) {
235,194,243✔
481
  SSelectAuthCxt cxt = {.pAuthCxt = pCxt, .pSelect = pSelect};
235,194,243✔
482
  nodesWalkSelectStmt(pSelect, SQL_CLAUSE_FROM, authSelectImpl, &cxt);
235,194,526✔
483
  return pCxt->errCode;
235,196,361✔
484
}
485

486
static int32_t authSetOperator(SAuthCxt* pCxt, SSetOperator* pSetOper) {
10,370,409✔
487
  int32_t code = authQuery(pCxt, pSetOper->pLeft);
10,370,409✔
488
  if (TSDB_CODE_SUCCESS == code) {
10,370,409✔
489
    code = authQuery(pCxt, pSetOper->pRight);
10,367,835✔
490
  }
491
  return code;
10,370,409✔
492
}
493

494
static int32_t authDropUser(SAuthCxt* pCxt, SDropUserStmt* pStmt) {
66,378✔
495
  // if (!pCxt->pParseCxt->isSuperUser || 0 == strcmp(pStmt->userName, TSDB_DEFAULT_USER)) {
496
  //   return TSDB_CODE_PAR_PERMISSION_DENIED;
497
  // }
498
  if (0 == strcmp(pStmt->userName, TSDB_DEFAULT_USER)) {
66,378✔
499
    return TSDB_CODE_PAR_PERMISSION_DENIED;
213✔
500
  }
501
  return authSysPrivileges(pCxt, (void*)pStmt, PRIV_USER_DROP);  // root has SYSDBA role with USER_DROP privilege
66,165✔
502
}
503

504
static int32_t authDelete(SAuthCxt* pCxt, SDeleteStmt* pDelete) {
2,063,038✔
505
  SNode*      pTagCond = NULL;
2,063,038✔
506
  STableNode* pTable = (STableNode*)pDelete->pFromTable;
2,063,038✔
507
  int32_t     code = checkDbUseAuth(pCxt, pTable->dbName);
2,063,038✔
508
  if (TSDB_CODE_SUCCESS == code) {
2,063,038✔
509
    code = checkAuth(pCxt, pTable->dbName, pTable->tableName, PRIV_TBL_DELETE, PRIV_OBJ_TBL, &pTagCond, NULL);
2,062,849✔
510
  }
511
#ifdef TD_ENTERPRISE
512
  // MAC clearance check: user.maxSecLevel must be >= table.secLvl for DELETE
513
  if (TSDB_CODE_SUCCESS == code) {
2,063,038✔
514
    code = macCheckTableAccess(pCxt, pTable->dbName, pTable->tableName, false);
2,062,285✔
515
  }
516
#endif
517
  if (TSDB_CODE_SUCCESS == code && NULL != pTagCond) {
2,063,038✔
518
    code = rewriteAppendStableTagCond(&pDelete->pWhere, pTagCond, pTable);
×
519
  }
520
  return code;
2,063,038✔
521
}
522

523
static int32_t authInsert(SAuthCxt* pCxt, SInsertStmt* pInsert) {
539,829✔
524
  SNode*      pTagCond = NULL;
539,829✔
525
  SArray*     pPrivCols = NULL;
539,829✔
526
  STableNode* pTable = (STableNode*)pInsert->pTable;
539,829✔
527
  // todo check tag condition for subtable
528
  int32_t code = checkDbUseAuth(pCxt, pTable->dbName);
539,829✔
529
  if (TSDB_CODE_SUCCESS == code) {
539,829✔
530
    code = checkAuth(pCxt, pTable->dbName, pTable->tableName, PRIV_TBL_INSERT, PRIV_OBJ_TBL, &pTagCond, &pPrivCols);
539,829✔
531
  }
532
#ifdef TD_ENTERPRISE
533
  // MAC NWD+NRU: for INSERT, user.minSecLevel <= table.secLvl <= user.maxSecLevel
534
  if (TSDB_CODE_SUCCESS == code) {
539,829✔
535
    code = macCheckTableAccess(pCxt, pTable->dbName, pTable->tableName, true);
539,829✔
536
  }
537
  // INSERT INTO ... SELECT: check read privileges on source tables
538
  if (TSDB_CODE_SUCCESS == code && NULL != pInsert->pQuery) {
539,829✔
539
    code = authQuery(pCxt, pInsert->pQuery);
539,640✔
540
  }
541
#endif
542
  return code;
539,829✔
543
}
544

545
static int32_t authShowTables(SAuthCxt* pCxt, SShowStmt* pStmt) {
626,368✔
546
  // return checkAuth(pCxt, ((SValueNode*)pStmt->pDbName)->literal, NULL, AUTH_TYPE_READ_OR_WRITE, NULL);
547
  // stb: more check in server, child table(TODO): more check when filter query result
548
  PAR_ERR_RET(checkDbUseAuth(pCxt, ((SValueNode*)pStmt->pDbName)->literal));
626,368✔
549
  return 0;
620,535✔
550
}
551

552
static int32_t authShowVtables(SAuthCxt* pCxt, SShowStmt* pStmt) { return authShowTables(pCxt, pStmt); }
67,817✔
553

554
static int32_t authShowUsage(SAuthCxt* pCxt, SShowStmt* pStmt) {
406✔
555
  PAR_ERR_RET(checkDbUseAuth(pCxt, ((SValueNode*)pStmt->pDbName)->literal));
406✔
556
  return 0;
406✔
557
}
558

559
static int32_t authShowCreateTable(SAuthCxt* pCxt, SShowCreateTableStmt* pStmt) {
120,516✔
560
  // SNode* pTagCond = NULL;
561
  // todo check tag condition for subtable
562
  // return checkAuth(pCxt, pStmt->dbName, pStmt->tableName, AUTH_TYPE_READ, &pTagCond);
563
  PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->dbName));
120,516✔
564
#ifdef TD_ENTERPRISE
565
  // MAC NRU: table-level check — user.maxSecLevel must be >= table.securityLevel
566
  PAR_ERR_RET(macCheckTableAccess(pCxt, pStmt->dbName, pStmt->tableName, false));
115,980✔
567
#endif
568
  return authObjPrivileges(pCxt, pStmt->dbName, pStmt->tableName, PRIV_CM_SHOW_CREATE, PRIV_OBJ_TBL);
115,980✔
569
}
570

571
static int32_t authShowCreateView(SAuthCxt* pCxt, SShowCreateViewStmt* pStmt) {
10,442✔
572
#ifndef TD_ENTERPRISE
573
  return TSDB_CODE_OPS_NOT_SUPPORT;
574
#else
575
  int32_t code = checkDbUseAuth(pCxt, ((SShowCreateViewStmt*)pStmt)->dbName);
10,442✔
576
  if (TSDB_CODE_SUCCESS == code) {
10,442✔
577
    code = checkViewAuth(pCxt, ((SShowCreateViewStmt*)pStmt)->dbName, ((SShowCreateViewStmt*)pStmt)->viewName,
10,442✔
578
                         PRIV_CM_SHOW_CREATE, PRIV_OBJ_VIEW, NULL);
579
  }
580
  if (code == 0) pStmt->hasPrivilege = true;
10,442✔
581
  return 0;  // return 0 and check owner later in translateShowCreateView
10,442✔
582
#endif
583
}
584

585
static int32_t authCreateTable(SAuthCxt* pCxt, SCreateTableStmt* pStmt) {
10,324,589✔
586
  // SNode* pTagCond = NULL;
587
  // todo check tag condition for subtable
588
  // return checkAuth(pCxt, pStmt->dbName, NULL, AUTH_TYPE_WRITE, &pTagCond);
589
  PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->dbName));
10,324,589✔
590
  int32_t code = authObjPrivileges(pCxt, pStmt->dbName, NULL, PRIV_TBL_CREATE, PRIV_OBJ_DB);
10,323,143✔
591
#ifdef TD_ENTERPRISE
592
  // Per FS §4.2.1.4: specifying SECURITY_LEVEL > 0 requires PRIV_SECURITY_POLICY_ALTER regardless
593
  // of MAC activation state. SECURITY_LEVEL = 0 is equivalent to the default and always allowed.
594
  if (TSDB_CODE_SUCCESS == code) {
10,323,143✔
595
    if (pStmt->pOptions && pStmt->pOptions->securityLevel > 0) {
10,322,415✔
596
      if (pCxt->pParseCxt->macMode && pCxt->pParseCxt->maxSecLevel < pStmt->pOptions->securityLevel) {
×
597
        code = TSDB_CODE_MAC_INSUFFICIENT_LEVEL;
×
598
      } else {
599
        code = authSysPrivileges(pCxt, (SNode*)pStmt, PRIV_SECURITY_POLICY_ALTER);
×
600
      }
601
    }
602
  }
603
#endif
604
  return code;
10,323,143✔
605
}
606

607
static int32_t authCreateVTable(SAuthCxt* pCxt, SCreateVTableStmt* pStmt) {
249,875✔
608
  PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->dbName));
249,875✔
609
  PAR_ERR_RET(authObjPrivileges(pCxt, pStmt->dbName, NULL, PRIV_TBL_CREATE, PRIV_OBJ_DB));
249,875✔
610
  SNode* pCol = NULL;
238,147✔
611
  FOREACH(pCol, pStmt->pCols) {
164,855,669✔
612
    SColumnDefNode* pColDef = (SColumnDefNode*)pCol;
164,626,318✔
613
    if (NULL == pColDef) {
164,626,318✔
614
      PAR_ERR_RET(TSDB_CODE_PAR_INVALID_COLUMN);
×
615
    }
616
    SColumnOptions* pOptions = (SColumnOptions*)pColDef->pOptions;
164,626,318✔
617
    if (pOptions && pOptions->hasRef) {
164,626,318✔
618
      if (authObjPrivileges(pCxt, pOptions->refDb, pOptions->refTable, PRIV_TBL_SELECT, PRIV_OBJ_TBL)) {
102,698,597✔
619
        return TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
8,796✔
620
      }
621
    }
622
  }
623
  return TSDB_CODE_SUCCESS;
229,351✔
624
}
625

626
static int32_t authCreateVSubTable(SAuthCxt* pCxt, SCreateVSubTableStmt* pStmt) {
435,308✔
627
  SNode*     pNode = NULL;
435,308✔
628
  SNodeList* pTmpList = pStmt->pSpecificColRefs ? pStmt->pSpecificColRefs : pStmt->pColRefs;
435,308✔
629
  PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->dbName));
435,308✔
630
  PAR_ERR_RET(authObjPrivileges(pCxt, pStmt->dbName, NULL, PRIV_TBL_CREATE, PRIV_OBJ_DB));
435,308✔
631
  if (NULL == pTmpList) {
423,580✔
632
    // no column reference
633
    return TSDB_CODE_SUCCESS;
27,554✔
634
  }
635

636
  FOREACH(pNode, pTmpList) {
63,338,034✔
637
    SColumnRefNode* pColRef = (SColumnRefNode*)pNode;
62,950,804✔
638
    if (NULL == pColRef) {
62,950,804✔
639
      PAR_ERR_RET(TSDB_CODE_PAR_INVALID_COLUMN);
×
640
    }
641
    if (authObjPrivileges(pCxt, pColRef->refDbName, pColRef->refTableName, PRIV_TBL_SELECT, PRIV_OBJ_TBL)) {
62,950,804✔
642
      return TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
8,796✔
643
    }
644
  }
645
  return TSDB_CODE_SUCCESS;
387,230✔
646
}
647

648
static int32_t authCreateStream(SAuthCxt* pCxt, SCreateStreamStmt* pStmt) {
477,445✔
649
  int32_t code = TSDB_CODE_SUCCESS;
477,445✔
650

651
  if (IS_SYS_DBNAME(pStmt->streamDbName)) {
477,445✔
652
    return TSDB_CODE_PAR_PERMISSION_DENIED;
×
653
  }
654
  if (IS_SYS_DBNAME(pStmt->targetDbName)) {
477,445✔
655
    return TSDB_CODE_PAR_PERMISSION_DENIED;
43✔
656
  }
657
  if (pStmt->pTrigger) {
477,402✔
658
    SStreamTriggerNode* pTrigger = (SStreamTriggerNode*)pStmt->pTrigger;
477,402✔
659
    STableNode*         pTriggerTable = (STableNode*)pTrigger->pTrigerTable;
477,402✔
660
    if (pTriggerTable) {
477,402✔
661
      if (IS_SYS_DBNAME(pTriggerTable->dbName)) return TSDB_CODE_PAR_PERMISSION_DENIED;
463,933✔
662
      if (authObjPrivileges(pCxt, pTriggerTable->dbName, pTriggerTable->tableName, PRIV_TBL_SELECT, PRIV_OBJ_TBL)) {
463,890✔
663
        return TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
1,032✔
664
      }
665
      PAR_ERR_RET(checkDbUseAuth(pCxt, pTriggerTable->dbName));
462,858✔
666
    }
667
  }
668

669
  PAR_ERR_RET(checkDbUseAuth(pCxt, ((SCreateStreamStmt*)pStmt)->streamDbName));
476,327✔
670
  PAR_ERR_RET(
476,327✔
671
      authObjPrivileges(pCxt, ((SCreateStreamStmt*)pStmt)->streamDbName, NULL, PRIV_STREAM_CREATE, PRIV_OBJ_DB));
672
  if (pStmt->targetDbName[0] != '\0') {
475,553✔
673
    PAR_ERR_RET(checkDbUseAuth(pCxt, ((SCreateStreamStmt*)pStmt)->targetDbName));
471,566✔
674
    if (authObjPrivileges(pCxt, ((SCreateStreamStmt*)pStmt)->targetDbName, NULL, PRIV_TBL_CREATE, PRIV_OBJ_DB)) {
471,566✔
675
      return TSDB_CODE_PAR_TB_CREATE_PERMISSION_DENIED;
258✔
676
    }
677
  }
678
  if (pStmt->pQuery) {
475,295✔
679
    PAR_ERR_RET(authQuery(pCxt, pStmt->pQuery));
471,512✔
680
  }
681
  return code;
474,779✔
682
}
683

684
static int32_t authCreateTopic(SAuthCxt* pCxt, SCreateTopicStmt* pStmt) {
221,017✔
685
  int32_t code = TSDB_CODE_SUCCESS;
221,017✔
686

687
  if (IS_SYS_DBNAME(pStmt->subDbName)) {
221,017✔
688
    return TSDB_CODE_PAR_PERMISSION_DENIED;
×
689
  }
690
  if (NULL != pStmt->pQuery) {
221,017✔
691
    PAR_ERR_RET(authQuery(pCxt, pStmt->pQuery));
170,503✔
692
  }
693
  if (NULL != pStmt->pWhere) {
220,482✔
694
    if (authObjPrivileges(pCxt, ((SCreateTopicStmt*)pStmt)->subDbName, ((SCreateTopicStmt*)pStmt)->subSTbName,
10,571✔
695
                          PRIV_TBL_SELECT, PRIV_OBJ_TBL)) {
696
      return TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
×
697
    }
698
  }
699
  if (((SCreateTopicStmt*)pStmt)->subDbName[0] != '\0') {
220,482✔
700
    PAR_ERR_RET(checkDbUseAuth(pCxt, ((SCreateTopicStmt*)pStmt)->subDbName));
50,514✔
701
  }
702

703
  return code;
220,482✔
704
}
705

706
static int32_t authCreateMultiTable(SAuthCxt* pCxt, SCreateMultiTablesStmt* pStmt) {
39,710,432✔
707
  int32_t code = TSDB_CODE_SUCCESS;
39,710,432✔
708
  SNode*  pNode = NULL;
39,710,432✔
709
  FOREACH(pNode, pStmt->pSubTables) {
87,458,900✔
710
    if (pNode->type == QUERY_NODE_CREATE_SUBTABLE_CLAUSE) {
47,750,852✔
711
      SCreateSubTableClause* pClause = (SCreateSubTableClause*)pNode;
47,745,744✔
712
      code = checkDbUseAuth(pCxt, pClause->dbName);
47,745,744✔
713
      if (TSDB_CODE_SUCCESS != code) break;
47,744,615✔
714
      code = authObjPrivileges(pCxt, pClause->dbName, NULL, PRIV_TBL_CREATE, PRIV_OBJ_DB);
47,744,408✔
715
      if (TSDB_CODE_SUCCESS != code) {
47,749,321✔
716
        break;
×
717
      }
718
    } else {
719
      SCreateSubTableFromFileClause* pClause = (SCreateSubTableFromFileClause*)pNode;
×
720
      code = checkDbUseAuth(pCxt, pClause->useDbName);
×
721
      if (TSDB_CODE_SUCCESS != code) break;
×
722
      code = authObjPrivileges(pCxt, pClause->useDbName, NULL, PRIV_TBL_CREATE, PRIV_OBJ_DB);
×
723
      if (TSDB_CODE_SUCCESS != code) {
×
724
        break;
×
725
      }
726
    }
727
  }
728
  return code;
39,709,813✔
729
}
730

731
static int32_t authDropTable(SAuthCxt* pCxt, SDropTableStmt* pStmt) {
2,732,966✔
732
  int32_t code = TSDB_CODE_SUCCESS;
2,732,966✔
733
  if (pStmt->withOpt && !pCxt->pParseCxt->isSuperUser) {
2,732,966✔
734
    return TSDB_CODE_PAR_PERMISSION_DENIED;
300✔
735
  }
736
  SNode* pNode = NULL;
2,732,666✔
737
  FOREACH(pNode, pStmt->pTables) {
5,598,323✔
738
    SDropTableClause* pClause = (SDropTableClause*)pNode;
2,867,531✔
739
    code = checkDbUseAuth(pCxt, pClause->dbName);
2,867,531✔
740
    if (TSDB_CODE_SUCCESS != code) break;
2,867,531✔
741

742
    if (!pStmt->withOpt) {
2,866,769✔
743
      // for child table, check privileges of its super table later
744
      if (checkAuth(pCxt, pClause->dbName, pClause->tableName, PRIV_CM_DROP, PRIV_OBJ_TBL, NULL, NULL)) {
2,695,511✔
745
        code = TSDB_CODE_PAR_PERMISSION_DENIED;
1,112✔
746
        break;
1,112✔
747
      }
748
    }
749
  }
750

751
  return code;
2,732,666✔
752
}
753

754
static int32_t authDropStable(SAuthCxt* pCxt, SDropSuperTableStmt* pStmt) {
112,066✔
755
  if (pStmt->withOpt && !pCxt->pParseCxt->isSuperUser) {
112,066✔
756
    return TSDB_CODE_PAR_PERMISSION_DENIED;
150✔
757
  }
758
  PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->dbName));
111,916✔
759
  if (!pStmt->withOpt) {
111,916✔
760
    PAR_ERR_RET(checkAuth(pCxt, pStmt->dbName, pStmt->tableName, PRIV_CM_DROP, PRIV_OBJ_TBL, NULL, NULL));
45,409✔
761
  }
762
  return 0;
111,916✔
763
}
764

765
static int32_t authDropVtable(SAuthCxt* pCxt, SDropVirtualTableStmt* pStmt) {
83,057✔
766
  if (pStmt->withOpt && !pCxt->pParseCxt->isSuperUser) {
83,057✔
767
    return TSDB_CODE_PAR_PERMISSION_DENIED;
×
768
  }
769
  PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->dbName));
83,057✔
770
  if (!pStmt->withOpt) {
83,057✔
771
    PAR_ERR_RET(checkAuth(pCxt, pStmt->dbName, pStmt->tableName, PRIV_CM_DROP, PRIV_OBJ_TBL, NULL, NULL));
83,057✔
772
  }
773
  return 0;
71,297✔
774
}
775

776
static int32_t authAlterTable(SAuthCxt* pCxt, SAlterTableStmt* pStmt) {
21,564,792✔
777
  // TODO: if alterType is TSDB_ALTER_TABLE_UPDATE_CHILD_TABLE_TAG_VAL, the tables to
778
  // change tag value are child tables but we only have the super table name here.
779
  // the auth logic below haven't handled this case, but as this case is only for internal
780
  // use and not exposed to users, we can live with this for now and improve it later if needed.
781

782
  if (pStmt->alterType == TSDB_ALTER_TABLE_UPDATE_MULTI_TABLE_TAG_VAL) {
21,564,792✔
783
    int32_t code = 0;
9,184,368✔
784
    SNode* pTableNode = NULL;
9,184,368✔
785
    FOREACH(pTableNode, pStmt->pList) {
18,389,276✔
786
      SAlterTableUpdateTagValClause* pClause = (SAlterTableUpdateTagValClause*)pTableNode;
9,205,286✔
787
      PAR_ERR_RET(checkDbUseAuth(pCxt, pClause->dbName));
9,205,286✔
788
      code = checkAuth(pCxt, pClause->dbName, pClause->tableName, PRIV_CM_ALTER, PRIV_OBJ_TBL, NULL, NULL);
9,205,286✔
789
#ifdef TD_ENTERPRISE
790
      // MAC clearance check: child table inherits secLvl from STB; user clearance must dominate object level
791
      if (TSDB_CODE_SUCCESS == code) {
9,205,286✔
792
        code = macCheckTableAccess(pCxt, pClause->dbName, pClause->tableName, false);
9,205,286✔
793
      }
794
#endif
795
      if (code != TSDB_CODE_SUCCESS) {
9,205,286✔
796
        break;
378✔
797
      }
798
    }
799
    return code;
9,184,368✔
800
  } else {
801
    // todo check tag condition for subtable
802
#ifdef TD_ENTERPRISE
803
    // MAC domain: security_level changes require only PRIV_SECURITY_POLICY_ALTER (no CM_ALTER needed)
804
    if (pStmt->alterType == TSDB_ALTER_TABLE_UPDATE_OPTIONS && pStmt->pOptions && pStmt->pOptions->securityLevel >= 0) {
12,380,424✔
805
      // Trusted subject: PRIV_SECURITY_POLICY_ALTER holder is exempt from maxSecLevel constraint
806
      return authSysPrivileges(pCxt, (SNode*)pStmt, PRIV_SECURITY_POLICY_ALTER);
3,969✔
807
    }
808
#endif
809
    // DAC domain: non-security ALTER requires DB_USE + CM_ALTER + MAC clearance
810
    PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->dbName));
12,376,455✔
811
    int32_t code = checkAuth(pCxt, pStmt->dbName, pStmt->tableName, PRIV_CM_ALTER, PRIV_OBJ_TBL, NULL, NULL);
12,375,096✔
812
#ifdef TD_ENTERPRISE
813
    if (TSDB_CODE_SUCCESS == code) {
12,375,096✔
814
      // MAC clearance check: secLvl inherited from STB for child tables
815
      code = macCheckTableAccess(pCxt, pStmt->dbName, pStmt->tableName, false);
12,374,752✔
816
    }
817
#endif
818
    return code;
12,375,096✔
819
  }
820
}
821

822
static int32_t authAlterVTable(SAuthCxt* pCxt, SAlterTableStmt* pStmt) {
475,608✔
823
  // TODO: if alterType is TSDB_ALTER_TABLE_UPDATE_CHILD_TABLE_TAG_VAL, the tables to
824
  // change tag value are child tables but we only have the super table name here.
825
  // the auth logic below haven't handled this case, but as this case is only for internal
826
  // use and not exposed to users, we can live with this for now and improve it later if needed.
827

828
  if (pStmt->alterType == TSDB_ALTER_TABLE_UPDATE_MULTI_TABLE_TAG_VAL) {
475,608✔
829
    int32_t code = 0;
48,992✔
830
    SNode* pTableNode = NULL;
48,992✔
831
    FOREACH(pTableNode, pStmt->pList) {
107,813✔
832
      SAlterTableUpdateTagValClause* pClause = (SAlterTableUpdateTagValClause*)pTableNode;
64,701✔
833
      PAR_ERR_RET(checkDbUseAuth(pCxt, pClause->dbName));
64,701✔
834
      code = checkAuth(pCxt, pClause->dbName, pClause->tableName, PRIV_CM_ALTER, PRIV_OBJ_TBL, NULL, NULL);
64,701✔
835
      if (code != TSDB_CODE_SUCCESS) {
64,701✔
836
        break;
5,880✔
837
      }
838
    }
839
    PAR_RET(code);
48,992✔
840
  }
841

842
  PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->dbName));
426,616✔
843
  PAR_ERR_RET(checkAuth(pCxt, pStmt->dbName, pStmt->tableName, PRIV_CM_ALTER, PRIV_OBJ_TBL, NULL, NULL));
426,616✔
844
  if (pStmt->alterType == TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COLUMN_REF ||
367,816✔
845
      pStmt->alterType == TSDB_ALTER_TABLE_ALTER_COLUMN_REF) {
331,417✔
846
    PAR_ERR_RET(checkDbUseAuth(pCxt, pStmt->refDbName));
150,001✔
847
    if (checkAuth(pCxt, pStmt->refDbName, pStmt->refTableName, PRIV_TBL_SELECT, PRIV_OBJ_TBL, NULL, NULL)) {
150,001✔
848
      return TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
23,520✔
849
    }
850
  }
851
  PAR_RET(TSDB_CODE_SUCCESS);
344,296✔
852
}
853

854
static int32_t authCreateView(SAuthCxt* pCxt, SCreateViewStmt* pStmt) {
325,513✔
855
#ifndef TD_ENTERPRISE
856
  return TSDB_CODE_OPS_NOT_SUPPORT;
857
#else
858
  int32_t code = checkDbUseAuth(pCxt, pStmt->dbName);
325,513✔
859
  if (TSDB_CODE_SUCCESS == code) {
325,513✔
860
    code = checkAuth(pCxt, pStmt->dbName, NULL, PRIV_VIEW_CREATE, PRIV_OBJ_DB, NULL, NULL);
325,513✔
861
    if (code != TSDB_CODE_SUCCESS && pStmt->orReplace) {
325,513✔
862
      code = checkAuth(pCxt, pStmt->dbName, pStmt->viewName, PRIV_CM_ALTER, PRIV_OBJ_VIEW, NULL, NULL);
344✔
863
    }
864
  }
865
  if (TSDB_CODE_SUCCESS == code) {
325,513✔
866
    if ((code = authQuery(pCxt, pStmt->pQuery))) {
325,169✔
867
      if (code == TSDB_CODE_PAR_PERMISSION_DENIED) code = TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
×
868
    }
869
  }
870
  return code;
325,513✔
871
#endif
872
}
873

874
static int32_t authDropView(SAuthCxt* pCxt, SDropViewStmt* pStmt) {
257,745✔
875
#ifndef TD_ENTERPRISE
876
  return TSDB_CODE_OPS_NOT_SUPPORT;
877
#else
878
  int32_t code = checkDbUseAuth(pCxt, pStmt->dbName);
257,745✔
879
  if (TSDB_CODE_SUCCESS == code) {
257,745✔
880
    code = checkViewAuth(pCxt, pStmt->dbName, pStmt->viewName, PRIV_CM_DROP, PRIV_OBJ_VIEW, NULL);
257,745✔
881
  }
882
  if (code == 0) {
257,745✔
883
    pStmt->hasPrivilege = true;
255,919✔
884
  } else {
885
    code = 0;  // check owner in parTranslater
1,826✔
886
  }
887
  return code;
257,745✔
888
#endif
889
}
890

891
static int32_t authCreateIndex(SAuthCxt* pCxt, SCreateIndexStmt* pStmt) {
24,810✔
892
  int32_t code = checkDbUseAuth(pCxt, ((SCreateIndexStmt*)pStmt)->dbName);
24,810✔
893

894
  if (TSDB_CODE_SUCCESS == code) {
24,810✔
895
    if (authObjPrivileges(pCxt, ((SCreateIndexStmt*)pStmt)->dbName, ((SCreateIndexStmt*)pStmt)->tableName,
24,810✔
896
                          PRIV_TBL_SELECT, PRIV_OBJ_TBL)) {
897
      code = TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
172✔
898
    }
899
  }
900

901
  if (TSDB_CODE_SUCCESS == code) {
24,810✔
902
    code = authObjPrivileges(pCxt, ((SCreateIndexStmt*)pStmt)->dbName, ((SCreateIndexStmt*)pStmt)->tableName,
24,638✔
903
                             PRIV_IDX_CREATE, PRIV_OBJ_TBL);
904
  }
905

906
  return code;
24,810✔
907
}
908

909
static int32_t authDropIndex(SAuthCxt* pCxt, SDropIndexStmt* pStmt) {
12,095✔
910
  int32_t code = checkDbUseAuth(pCxt, ((SDropIndexStmt*)pStmt)->indexDbName);
12,095✔
911
  if (TSDB_CODE_SUCCESS == code) {
12,095✔
912
    code = authObjPrivileges(pCxt, ((SDropIndexStmt*)pStmt)->indexDbName, ((SDropIndexStmt*)pStmt)->indexName,
12,095✔
913
                             PRIV_CM_DROP, PRIV_OBJ_IDX);
914
  }
915
  return code;
12,095✔
916
}
917

918
static int32_t authShowIndexes(SAuthCxt* pCxt, SShowStmt* pStmt) { return authShowTables(pCxt, pStmt); }
8,166✔
919

920
static int32_t authCreateTsma(SAuthCxt* pCxt, SCreateTSMAStmt* pStmt) {
9,958✔
921
  int32_t code = checkDbUseAuth(pCxt, ((SCreateTSMAStmt*)pStmt)->dbName);
9,958✔
922
  if (TSDB_CODE_SUCCESS == code) {
9,958✔
923
    if (authObjPrivileges(pCxt, ((SCreateTSMAStmt*)pStmt)->dbName, NULL, PRIV_TBL_CREATE, PRIV_OBJ_DB)) {
9,614✔
924
      code = TSDB_CODE_PAR_TB_CREATE_PERMISSION_DENIED;
344✔
925
    }
926
  }
927
  if (!pStmt->pOptions->recursiveTsma) {
9,958✔
928
    if (TSDB_CODE_SUCCESS == code) {
8,473✔
929
      if (authObjPrivileges(pCxt, ((SCreateTSMAStmt*)pStmt)->dbName, ((SCreateTSMAStmt*)pStmt)->tableName,
7,785✔
930
                            PRIV_TBL_SELECT, PRIV_OBJ_TBL)) {
931
        code = TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
×
932
      }
933
    }
934

935
    if (TSDB_CODE_SUCCESS == code) {
8,473✔
936
      if (authObjPrivileges(pCxt, ((SCreateTSMAStmt*)pStmt)->dbName, NULL, PRIV_STREAM_CREATE, PRIV_OBJ_DB)) {
7,785✔
937
        code = TSDB_CODE_PAR_STREAM_CREATE_PERMISSION_DENIED;
344✔
938
      }
939
    }
940
    if (TSDB_CODE_SUCCESS == code) {
8,473✔
941
      code = authObjPrivileges(pCxt, ((SCreateTSMAStmt*)pStmt)->dbName, ((SCreateTSMAStmt*)pStmt)->tableName,
7,441✔
942
                               PRIV_TSMA_CREATE, PRIV_OBJ_TBL);
943
    }
944
  }
945

946
  return code;
9,958✔
947
}
948

949
static int32_t authDropTsma(SAuthCxt* pCxt, SDropTSMAStmt* pStmt) {
4,641✔
950
  int32_t code = checkDbUseAuth(pCxt, ((SDropTSMAStmt*)pStmt)->dbName);
4,641✔
951
  if (TSDB_CODE_SUCCESS == code) {
4,641✔
952
    code = authObjPrivileges(pCxt, ((SDropTSMAStmt*)pStmt)->dbName, ((SDropTSMAStmt*)pStmt)->tsmaName, PRIV_CM_DROP,
4,641✔
953
                             PRIV_OBJ_TSMA);
954
  }
955
  return code;
4,641✔
956
}
957

958
static int32_t authCreateRsma(SAuthCxt* pCxt, SCreateRsmaStmt* pStmt) {
125,448✔
959
  int32_t code = checkDbUseAuth(pCxt, ((SCreateRsmaStmt*)pStmt)->dbName);
125,448✔
960
  if (TSDB_CODE_SUCCESS == code) {
125,448✔
961
    if (authObjPrivileges(pCxt, ((SCreateRsmaStmt*)pStmt)->dbName, ((SCreateRsmaStmt*)pStmt)->tableName,
125,448✔
962
                          PRIV_TBL_SELECT, PRIV_OBJ_TBL)) {
963
      code = TSDB_CODE_PAR_TB_SELECT_PERMISSION_DENIED;
×
964
    }
965
  }
966
  if (TSDB_CODE_SUCCESS == code) {
125,448✔
967
    if (authObjPrivileges(pCxt, ((SCreateRsmaStmt*)pStmt)->dbName, ((SCreateRsmaStmt*)pStmt)->tableName,
125,448✔
968
                          PRIV_TBL_INSERT, PRIV_OBJ_TBL)) {
969
      code = TSDB_CODE_PAR_TB_INSERT_PERMISSION_DENIED;
172✔
970
    }
971
  }
972
  if (TSDB_CODE_SUCCESS == code) {
125,448✔
973
    code = authObjPrivileges(pCxt, ((SCreateRsmaStmt*)pStmt)->dbName, ((SCreateRsmaStmt*)pStmt)->tableName,
125,276✔
974
                             PRIV_RSMA_CREATE, PRIV_OBJ_TBL);
975
  }
976
  return code;
125,448✔
977
}
978

979
static int32_t authDropRsma(SAuthCxt* pCxt, SDropRsmaStmt* pStmt) {
11,426✔
980
  int32_t code = checkDbUseAuth(pCxt, ((SDropRsmaStmt*)pStmt)->dbName);
11,426✔
981
  if (TSDB_CODE_SUCCESS == code) {
11,426✔
982
    code = authObjPrivileges(pCxt, ((SDropRsmaStmt*)pStmt)->dbName, ((SDropRsmaStmt*)pStmt)->rsmaName, PRIV_CM_DROP,
11,426✔
983
                             PRIV_OBJ_RSMA);
984
  }
985
  return code;
11,426✔
986
}
987

988
static int32_t authShowCreateRsma(SAuthCxt* pCxt, SShowCreateRsmaStmt* pStmt) {
3,682✔
989
#ifndef TD_ENTERPRISE
990
  return TSDB_CODE_OPS_NOT_SUPPORT;
991
#else
992
  int32_t code = checkDbUseAuth(pCxt, ((SShowCreateRsmaStmt*)pStmt)->dbName);
3,682✔
993
  if (TSDB_CODE_SUCCESS == code) {
3,682✔
994
    code = authObjPrivileges(pCxt, ((SShowCreateRsmaStmt*)pStmt)->dbName, ((SShowCreateRsmaStmt*)pStmt)->rsmaName,
3,682✔
995
                             PRIV_CM_SHOW_CREATE, PRIV_OBJ_RSMA);
996
  }
997
  if (code == 0) pStmt->hasPrivilege = true;
3,682✔
998
  return 0;  // return 0 and check owner later in translateShowCreateRsma since rsma ctgCatalog not available yet
3,682✔
999
#endif
1000
}
1001

1002
static int32_t authCreateDatabase(SAuthCxt* pCxt, SCreateDatabaseStmt* pStmt) {
1,804,138✔
1003
  int32_t code = authSysPrivileges(pCxt, (SNode*)pStmt, PRIV_DB_CREATE);
1,804,138✔
1004
#ifdef TD_ENTERPRISE
1005
  // Per FS §4.2.1.4: specifying SECURITY_LEVEL > 0 requires PRIV_SECURITY_POLICY_ALTER regardless
1006
  // of MAC activation state. SECURITY_LEVEL = 0 is equivalent to the default and always allowed.
1007
  if (TSDB_CODE_SUCCESS == code) {
1,804,138✔
1008
    if (pStmt->pOptions && pStmt->pOptions->securityLevel > 0) {
1,801,156✔
1009
      // Trusted subject: PRIV_SECURITY_POLICY_ALTER holder is exempt from maxSecLevel constraint
1010
      code = authSysPrivileges(pCxt, (SNode*)pStmt, PRIV_SECURITY_POLICY_ALTER);
×
1011
    }
1012
  }
1013
#endif
1014
  return code;
1,804,138✔
1015
}
1016

1017
static int32_t authAlterDatabase(SAuthCxt* pCxt, SAlterDatabaseStmt* pStmt) {
229,905✔
1018
#ifdef TD_ENTERPRISE
1019
  // MAC domain: security_level changes require only PRIV_SECURITY_POLICY_ALTER (no CM_ALTER needed)
1020
  if (pStmt->pOptions && pStmt->pOptions->securityLevel >= 0) {
229,905✔
1021
    // Trusted subject: PRIV_SECURITY_POLICY_ALTER holder is exempt from maxSecLevel constraint
1022
    return authSysPrivileges(pCxt, (SNode*)pStmt, PRIV_SECURITY_POLICY_ALTER);
3,603✔
1023
  }
1024
#endif
1025
  // DAC domain: non-security ALTER requires CM_ALTER
1026
  return authObjPrivileges(pCxt, ((SAlterDatabaseStmt*)pStmt)->dbName, NULL, PRIV_CM_ALTER, PRIV_OBJ_DB);
226,302✔
1027
}
1028

1029
static int32_t authAlterLocal(SAuthCxt* pCxt, SAlterLocalStmt* pStmt) {
663,933✔
1030
  int32_t privType = cfgGetPrivType(tsCfg, pStmt->config, 0);
663,933✔
1031
  return authSysPrivileges(pCxt, (void*)pStmt, privType);
663,933✔
1032
}
1033

1034
static int32_t authAlterUser(SAuthCxt* pCxt, SAlterUserStmt* pStmt) {
69,390✔
1035
  EPrivType privType = getAlterUserPrivType(pCxt->pParseCxt->pUser, pStmt);
69,390✔
1036
  return authSysPrivileges(pCxt, (void*)pStmt, privType);
69,390✔
1037
}
1038

1039
static int32_t authDropRole(SAuthCxt* pCxt, SDropRoleStmt* pStmt) {
2,255✔
1040
  return authSysPrivileges(pCxt, (SNode*)pStmt, PRIV_ROLE_DROP);
2,255✔
1041
}
1042

1043
static int32_t authDropDatabase(SAuthCxt* pCxt, SDropDatabaseStmt* pStmt) {
1,532,536✔
1044
  return authObjPrivileges(pCxt, ((SDropDatabaseStmt*)pStmt)->dbName, NULL, PRIV_CM_DROP, PRIV_OBJ_DB);
1,532,536✔
1045
}
1046

1047
static int32_t authUseDatabase(SAuthCxt* pCxt, SUseDatabaseStmt* pStmt) {
96,918,863✔
1048
  return authObjPrivileges(pCxt, ((SUseDatabaseStmt*)pStmt)->dbName, NULL, PRIV_DB_USE, PRIV_OBJ_DB);
96,918,863✔
1049
}
1050

1051
static int32_t authGrant(SAuthCxt* pCxt, SGrantStmt* pStmt) {
1,044,477✔
1052
  bool sodInitial = pCxt->pParseCxt->sodInitial;
1,044,477✔
1053
  if (pStmt->optrType == TSDB_ALTER_ROLE_ROLE) {
1,044,477✔
1054
    if (IS_SYS_PREFIX(pStmt->roleName)) {
10,633✔
1055
      if (strcmp(pStmt->roleName, TSDB_ROLE_SYSDBA) == 0) {
9,049✔
1056
        return authSysPrivileges(pCxt, (void*)pStmt, PRIV_GRANT_SYSDBA);
2,650✔
1057
      }
1058
      if (strcmp(pStmt->roleName, TSDB_ROLE_SYSSEC) == 0) {
6,399✔
1059
        return authSysPrivileges(pCxt, (void*)pStmt, PRIV_GRANT_SYSSEC);
2,529✔
1060
      }
1061
      if (strcmp(pStmt->roleName, TSDB_ROLE_SYSAUDIT) == 0) {
3,870✔
1062
        return authSysPrivileges(pCxt, (void*)pStmt, PRIV_GRANT_SYSAUDIT);
1,584✔
1063
      }
1064
    } else if (sodInitial) {
1,584✔
1065
      return TSDB_CODE_MND_SOD_RESTRICTED;
×
1066
    }
1067
  } else if (sodInitial) {
1,033,844✔
1068
    return TSDB_CODE_MND_SOD_RESTRICTED;
×
1069
  }
1070
  return authSysPrivileges(pCxt, (void*)pStmt, PRIV_GRANT_PRIVILEGE);
1,037,714✔
1071
}
1072

1073
static int32_t authRevoke(SAuthCxt* pCxt, SRevokeStmt* pStmt) {
542,802✔
1074
  bool sodInitial = pCxt->pParseCxt->sodInitial;
542,802✔
1075
  if (pStmt->optrType == TSDB_ALTER_ROLE_ROLE) {
542,802✔
1076
    if (IS_SYS_PREFIX(pStmt->roleName)) {
10,000✔
1077
      if (strcmp(pStmt->roleName, TSDB_ROLE_SYSDBA) == 0) {
9,828✔
1078
        return authSysPrivileges(pCxt, (void*)pStmt, PRIV_REVOKE_SYSDBA);
739✔
1079
      }
1080
      if (strcmp(pStmt->roleName, TSDB_ROLE_SYSSEC) == 0) {
9,089✔
1081
        return authSysPrivileges(pCxt, (void*)pStmt, PRIV_REVOKE_SYSSEC);
1,306✔
1082
      }
1083
      if (strcmp(pStmt->roleName, TSDB_ROLE_SYSAUDIT) == 0) {
7,783✔
1084
        return authSysPrivileges(pCxt, (void*)pStmt, PRIV_REVOKE_SYSAUDIT);
739✔
1085
      }
1086
    } else if (sodInitial) {
172✔
1087
      return TSDB_CODE_MND_SOD_RESTRICTED;
×
1088
    }
1089
  } else if (sodInitial) {
532,802✔
1090
    return TSDB_CODE_MND_SOD_RESTRICTED;
×
1091
  }
1092
  return authSysPrivileges(pCxt, (void*)pStmt, PRIV_REVOKE_PRIVILEGE);
540,018✔
1093
}
1094

1095
static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) {
538,667,245✔
1096
  int32_t code = TSDB_CODE_SUCCESS;
538,667,245✔
1097
#ifdef TD_ENTERPRISE
1098
  switch (nodeType(pStmt)) {
538,667,245✔
1099
    case QUERY_NODE_SET_OPERATOR:
10,370,409✔
1100
      return authSetOperator(pCxt, (SSetOperator*)pStmt);
10,370,409✔
1101
    case QUERY_NODE_SELECT_STMT:
235,194,288✔
1102
      return authSelect(pCxt, (SSelectStmt*)pStmt);
235,194,288✔
1103
    case QUERY_NODE_CREATE_ROLE_STMT:
5,443✔
1104
      return authSysPrivileges(pCxt, pStmt, PRIV_ROLE_CREATE);
5,443✔
1105
    case QUERY_NODE_DROP_ROLE_STMT:
2,255✔
1106
      return authDropRole(pCxt, (SDropRoleStmt*)pStmt);
2,255✔
1107
    case QUERY_NODE_CREATE_USER_STMT:
129,354✔
1108
      return authSysPrivileges(pCxt, pStmt, PRIV_USER_CREATE);
129,354✔
1109
    case QUERY_NODE_ALTER_USER_STMT:
69,390✔
1110
      return authAlterUser(pCxt, (SAlterUserStmt*)pStmt);
69,390✔
1111
    case QUERY_NODE_DROP_USER_STMT:
66,378✔
1112
      return authDropUser(pCxt, (SDropUserStmt*)pStmt);
66,378✔
1113
    case QUERY_NODE_DELETE_STMT:
2,063,038✔
1114
      return authDelete(pCxt, (SDeleteStmt*)pStmt);
2,063,038✔
1115
    case QUERY_NODE_INSERT_STMT:
539,829✔
1116
      return authInsert(pCxt, (SInsertStmt*)pStmt);
539,829✔
1117
    case QUERY_NODE_CREATE_TABLE_STMT:
10,324,589✔
1118
      return authCreateTable(pCxt, (SCreateTableStmt*)pStmt);
10,324,589✔
1119
    case QUERY_NODE_CREATE_VIRTUAL_TABLE_STMT:
249,875✔
1120
      return authCreateVTable(pCxt, (SCreateVTableStmt*)pStmt);
249,875✔
1121
    case QUERY_NODE_CREATE_VIRTUAL_SUBTABLE_STMT:
435,308✔
1122
      return authCreateVSubTable(pCxt, (SCreateVSubTableStmt*)pStmt);
435,308✔
1123
    case QUERY_NODE_CREATE_MULTI_TABLES_STMT:
39,710,478✔
1124
      return authCreateMultiTable(pCxt, (SCreateMultiTablesStmt*)pStmt);
39,710,478✔
1125
    case QUERY_NODE_CREATE_STREAM_STMT:
477,445✔
1126
      return authCreateStream(pCxt, (SCreateStreamStmt*)pStmt);
477,445✔
1127
    case QUERY_NODE_CREATE_TOPIC_STMT:
221,017✔
1128
      return authCreateTopic(pCxt, (SCreateTopicStmt*)pStmt);
221,017✔
1129
    case QUERY_NODE_DROP_TABLE_STMT:
2,732,966✔
1130
      return authDropTable(pCxt, (SDropTableStmt*)pStmt);
2,732,966✔
1131
    case QUERY_NODE_DROP_SUPER_TABLE_STMT:
112,066✔
1132
      return authDropStable(pCxt, (SDropSuperTableStmt*)pStmt);
112,066✔
1133
    case QUERY_NODE_DROP_VIRTUAL_TABLE_STMT:
83,057✔
1134
      return authDropVtable(pCxt, (SDropVirtualTableStmt*)pStmt);
83,057✔
1135
    case QUERY_NODE_ALTER_TABLE_STMT:
21,564,792✔
1136
    case QUERY_NODE_ALTER_SUPER_TABLE_STMT:
1137
      return authAlterTable(pCxt, (SAlterTableStmt*)pStmt);
21,564,792✔
1138
    case QUERY_NODE_ALTER_VIRTUAL_TABLE_STMT:
475,608✔
1139
      return authAlterVTable(pCxt, (SAlterTableStmt*)pStmt);
475,608✔
1140
    case QUERY_NODE_SHOW_MODULES_STMT:
57,997✔
1141
    case QUERY_NODE_SHOW_BACKUP_NODES_STMT:
1142
    case QUERY_NODE_SHOW_DB_ALIVE_STMT:
1143
    // case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT:
1144
    case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT:  // TODO: check in mnode
1145
    // case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT: // not check local variables
1146
    case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT:
1147
    case QUERY_NODE_SHOW_SCORES_STMT:
1148
    case QUERY_NODE_SHOW_ARBGROUPS_STMT:
1149
    case QUERY_NODE_SHOW_ENCRYPTIONS_STMT:
1150
    case QUERY_NODE_SHOW_ENCRYPT_ALGORITHMS_STMT:
1151
    case QUERY_NODE_SHOW_ENCRYPT_STATUS_STMT:
1152
    case QUERY_NODE_SHOW_CPU_ALLOCATION_STMT:
1153
      return !pCxt->pParseCxt->enableSysInfo ? TSDB_CODE_PAR_PERMISSION_DENIED : TSDB_CODE_SUCCESS;
57,997✔
1154
    case QUERY_NODE_SHOW_CREATE_DATABASE_STMT:
78,204✔
1155
      return authObjPrivileges(pCxt, ((SShowCreateDatabaseStmt*)pStmt)->dbName, NULL, PRIV_CM_SHOW_CREATE, PRIV_OBJ_DB);
78,204✔
1156
    case QUERY_NODE_SHOW_MOUNTS_STMT:
2,276✔
1157
      return authSysPrivileges(pCxt, pStmt, PRIV_MOUNT_SHOW);
2,276✔
1158
    case QUERY_NODE_SHOW_USERS_STMT:
141,975✔
1159
    case QUERY_NODE_SHOW_USERS_FULL_STMT:
1160
      return authSysPrivileges(pCxt, pStmt, PRIV_USER_SHOW);
141,975✔
1161
    case QUERY_NODE_SHOW_ROLES_STMT:
1,584✔
1162
      return authSysPrivileges(pCxt, pStmt, PRIV_ROLE_SHOW);
1,584✔
1163
    case QUERY_NODE_SHOW_USER_PRIVILEGES_STMT:
5,768✔
1164
    case QUERY_NODE_SHOW_ROLE_PRIVILEGES_STMT:
1165
    case QUERY_NODE_SHOW_ROLE_COL_PRIVILEGES_STMT:
1166
      return authSysPrivileges(pCxt, pStmt, PRIV_SHOW_PRIVILEGES);
5,768✔
1167
    case QUERY_NODE_SHOW_DNODES_STMT:
568,891✔
1168
    case QUERY_NODE_SHOW_MNODES_STMT:
1169
    case QUERY_NODE_SHOW_QNODES_STMT:
1170
    case QUERY_NODE_SHOW_SNODES_STMT:
1171
    case QUERY_NODE_SHOW_BNODES_STMT:
1172
    case QUERY_NODE_SHOW_ANODES_STMT:
1173
    case QUERY_NODE_SHOW_ANODES_FULL_STMT:
1174
    case QUERY_NODE_SHOW_XNODES_STMT:
1175
    case QUERY_NODE_SHOW_XNODE_AGENTS_STMT:
1176
      return authSysPrivileges(pCxt, pStmt, PRIV_NODES_SHOW);
568,891✔
1177
    case QUERY_NODE_SHOW_XNODE_TASKS_STMT:
14,040✔
1178
    case QUERY_NODE_SHOW_XNODE_JOBS_STMT:
1179
      return TSDB_CODE_SUCCESS;
14,040✔
1180
    case QUERY_NODE_CREATE_XNODE_STMT:
6,084✔
1181
    case QUERY_NODE_DROP_XNODE_STMT:
1182
      return TSDB_CODE_SUCCESS;
6,084✔
1183
    case QUERY_NODE_SHOW_CLUSTER_MACHINES_STMT:
6,630✔
1184
    // case QUERY_NODE_SHOW_LICENCES_STMT: // do not check auth for basic licence info since it's used for taos logon
1185
    case QUERY_NODE_SHOW_GRANTS_FULL_STMT:
1186
    case QUERY_NODE_SHOW_GRANTS_LOGS_STMT:
1187
      return authSysPrivileges(pCxt, pStmt, PRIV_GRANTS_SHOW);
6,630✔
1188
    case QUERY_NODE_SHOW_TABLES_STMT:
550,385✔
1189
    case QUERY_NODE_SHOW_STABLES_STMT:
1190
      return authShowTables(pCxt, (SShowStmt*)pStmt);
550,385✔
1191
    case QUERY_NODE_SHOW_VTABLES_STMT:
67,817✔
1192
      return authShowVtables(pCxt, (SShowStmt*)pStmt);
67,817✔
1193
    case QUERY_NODE_SHOW_CREATE_TABLE_STMT:
120,516✔
1194
    case QUERY_NODE_SHOW_CREATE_VTABLE_STMT:
1195
    case QUERY_NODE_SHOW_CREATE_STABLE_STMT:
1196
      return authShowCreateTable(pCxt, (SShowCreateTableStmt*)pStmt);
120,516✔
1197
    case QUERY_NODE_SHOW_CREATE_VIEW_STMT:
10,442✔
1198
      return authShowCreateView(pCxt, (SShowCreateViewStmt*)pStmt);
10,442✔
1199
    case QUERY_NODE_CREATE_VIEW_STMT:
325,513✔
1200
      return authCreateView(pCxt, (SCreateViewStmt*)pStmt);
325,513✔
1201
    case QUERY_NODE_DROP_VIEW_STMT:
257,745✔
1202
      return authDropView(pCxt, (SDropViewStmt*)pStmt);
257,745✔
1203
    case QUERY_NODE_CREATE_INDEX_STMT:
24,810✔
1204
      return authCreateIndex(pCxt, (SCreateIndexStmt*)pStmt);
24,810✔
1205
    case QUERY_NODE_DROP_INDEX_STMT:
12,095✔
1206
      return authDropIndex(pCxt, (SDropIndexStmt*)pStmt);
12,095✔
1207
    case QUERY_NODE_SHOW_INDEXES_STMT:
8,166✔
1208
      return authShowIndexes(pCxt, (SShowStmt*)pStmt);
8,166✔
1209
    case QUERY_NODE_CREATE_TSMA_STMT:
9,958✔
1210
      return authCreateTsma(pCxt, (SCreateTSMAStmt*)pStmt);
9,958✔
1211
    case QUERY_NODE_DROP_TSMA_STMT:
4,641✔
1212
      return authDropTsma(pCxt, (SDropTSMAStmt*)pStmt);
4,641✔
1213
    case QUERY_NODE_CREATE_RSMA_STMT:
125,448✔
1214
      return authCreateRsma(pCxt, (SCreateRsmaStmt*)pStmt);
125,448✔
1215
    case QUERY_NODE_DROP_RSMA_STMT:
11,426✔
1216
      return authDropRsma(pCxt, (SDropRsmaStmt*)pStmt);
11,426✔
1217
    case QUERY_NODE_ALTER_RSMA_STMT:
23,334✔
1218
      return authObjPrivileges(pCxt, ((SAlterRsmaStmt*)pStmt)->dbName, ((SAlterRsmaStmt*)pStmt)->rsmaName,
23,334✔
1219
                               PRIV_CM_ALTER, PRIV_OBJ_RSMA);
1220
    case QUERY_NODE_SHOW_CREATE_RSMA_STMT:
3,682✔
1221
      return authShowCreateRsma(pCxt, (SShowCreateRsmaStmt*)pStmt);
3,682✔
1222
    case QUERY_NODE_CREATE_DATABASE_STMT:
1,804,138✔
1223
      return authCreateDatabase(pCxt, (SCreateDatabaseStmt*)pStmt);
1,804,138✔
1224
    case QUERY_NODE_BALANCE_VGROUP_STMT:
13,846✔
1225
      return authSysPrivileges(pCxt, pStmt, PRIV_VG_BALANCE);
13,846✔
1226
    case QUERY_NODE_BALANCE_VGROUP_LEADER_DATABASE_STMT:
4,076✔
1227
    case QUERY_NODE_BALANCE_VGROUP_LEADER_STMT:
1228
      return authSysPrivileges(pCxt, pStmt, PRIV_VG_BALANCE_LEADER);
4,076✔
1229
    case QUERY_NODE_MERGE_VGROUP_STMT:
×
1230
      return authSysPrivileges(pCxt, pStmt, PRIV_VG_MERGE);
×
1231
    case QUERY_NODE_SPLIT_VGROUP_STMT:
26,511✔
1232
      return authSysPrivileges(pCxt, pStmt, PRIV_VG_SPLIT);
26,511✔
1233
    case QUERY_NODE_REDISTRIBUTE_VGROUP_STMT:
51,997✔
1234
      return authSysPrivileges(pCxt, pStmt, PRIV_VG_REDISTRIBUTE);
51,997✔
1235
    case QUERY_NODE_CREATE_FUNCTION_STMT:
17,634✔
1236
      return authSysPrivileges(pCxt, pStmt, PRIV_FUNC_CREATE);
17,634✔
1237
    case QUERY_NODE_DROP_FUNCTION_STMT:
14,346✔
1238
      return authSysPrivileges(pCxt, pStmt, PRIV_FUNC_DROP);
14,346✔
1239
    case QUERY_NODE_SHOW_FUNCTIONS_STMT:
13,098✔
1240
      return authSysPrivileges(pCxt, pStmt, PRIV_FUNC_SHOW);
13,098✔
1241
    case QUERY_NODE_GRANT_STMT:
1,044,477✔
1242
      return authGrant(pCxt, (SGrantStmt*)pStmt);
1,044,477✔
1243
    case QUERY_NODE_REVOKE_STMT:
542,802✔
1244
      return authRevoke(pCxt, (SRevokeStmt*)pStmt);
542,802✔
1245
    case QUERY_NODE_CREATE_DNODE_STMT:
356,970✔
1246
    case QUERY_NODE_CREATE_MNODE_STMT:
1247
    case QUERY_NODE_CREATE_QNODE_STMT:
1248
    case QUERY_NODE_CREATE_SNODE_STMT:
1249
    case QUERY_NODE_CREATE_BNODE_STMT:
1250
    case QUERY_NODE_CREATE_ANODE_STMT:
1251
      return authSysPrivileges(pCxt, pStmt, PRIV_NODE_CREATE);
356,970✔
1252
    case QUERY_NODE_DROP_DNODE_STMT:
114,991✔
1253
    case QUERY_NODE_DROP_MNODE_STMT:
1254
    case QUERY_NODE_DROP_QNODE_STMT:
1255
    case QUERY_NODE_DROP_SNODE_STMT:
1256
    case QUERY_NODE_DROP_BNODE_STMT:
1257
    case QUERY_NODE_DROP_ANODE_STMT:
1258
      return authSysPrivileges(pCxt, pStmt, PRIV_NODE_DROP);
114,991✔
1259
    case QUERY_NODE_SHOW_TRANSACTIONS_STMT:
747,970✔
1260
    case QUERY_NODE_SHOW_TRANSACTION_DETAILS_STMT:
1261
      return authSysPrivileges(pCxt, pStmt, PRIV_TRANS_SHOW);
747,970✔
1262
    case QUERY_NODE_KILL_TRANSACTION_STMT:
689✔
1263
      return authSysPrivileges(pCxt, pStmt, PRIV_TRANS_KILL);
689✔
1264
    case QUERY_NODE_SHOW_QUERIES_STMT:
3,808✔
1265
      return authSysPrivileges(pCxt, pStmt, PRIV_QUERY_SHOW);
3,808✔
1266
    case QUERY_NODE_SHOW_CONNECTIONS_STMT:
2,838✔
1267
      return authSysPrivileges(pCxt, pStmt, PRIV_CONN_SHOW);
2,838✔
1268
    case QUERY_NODE_KILL_QUERY_STMT:
1,612✔
1269
      return authSysPrivileges(pCxt, pStmt, PRIV_QUERY_KILL);
1,612✔
1270
    case QUERY_NODE_KILL_CONNECTION_STMT:
379✔
1271
      return authSysPrivileges(pCxt, pStmt, PRIV_CONN_KILL);
379✔
1272
    case QUERY_NODE_ALTER_DATABASE_STMT:
229,905✔
1273
      return authAlterDatabase(pCxt, (SAlterDatabaseStmt*)pStmt);
229,905✔
1274
    case QUERY_NODE_ALTER_LOCAL_STMT:
663,933✔
1275
      return authAlterLocal(pCxt, (SAlterLocalStmt*)pStmt);
663,933✔
1276
    case QUERY_NODE_DROP_DATABASE_STMT:
1,532,536✔
1277
      return authDropDatabase(pCxt, (SDropDatabaseStmt*)pStmt);
1,532,536✔
1278
    case QUERY_NODE_USE_DATABASE_STMT:
96,919,311✔
1279
      return authUseDatabase(pCxt, (SUseDatabaseStmt*)pStmt);
96,919,311✔
1280
    case QUERY_NODE_FLUSH_DATABASE_STMT:
2,137,527✔
1281
      return authObjPrivileges(pCxt, ((SFlushDatabaseStmt*)pStmt)->dbName, NULL, PRIV_DB_FLUSH, PRIV_OBJ_DB);
2,137,527✔
1282
    case QUERY_NODE_COMPACT_DATABASE_STMT:
35,147✔
1283
      return authObjPrivileges(pCxt, ((SCompactDatabaseStmt*)pStmt)->dbName, NULL, PRIV_DB_COMPACT, PRIV_OBJ_DB);
35,147✔
1284
    case QUERY_NODE_TRIM_DATABASE_STMT:
10,812✔
1285
      return authObjPrivileges(pCxt, ((STrimDatabaseStmt*)pStmt)->dbName, NULL, PRIV_DB_TRIM, PRIV_OBJ_DB);
10,812✔
1286
    case QUERY_NODE_ROLLUP_DATABASE_STMT:
13,318✔
1287
      return authObjPrivileges(pCxt, ((SRollupDatabaseStmt*)pStmt)->dbName, NULL, PRIV_DB_ROLLUP, PRIV_OBJ_DB);
13,318✔
1288
    case QUERY_NODE_SCAN_DATABASE_STMT:
1,004✔
1289
      return authObjPrivileges(pCxt, ((SScanDatabaseStmt*)pStmt)->dbName, NULL, PRIV_DB_SCAN, PRIV_OBJ_DB);
1,004✔
1290
    case QUERY_NODE_SSMIGRATE_DATABASE_STMT:
3,510✔
1291
      return authObjPrivileges(pCxt, ((SSsMigrateDatabaseStmt*)pStmt)->dbName, NULL, PRIV_DB_SSMIGRATE, PRIV_OBJ_DB);
3,510✔
1292
    case QUERY_NODE_SHOW_USAGE_STMT:  // disk info
406✔
1293
      return authShowUsage(pCxt, (SShowStmt*)pStmt);
406✔
1294
    case QUERY_NODE_SHOW_APPS_STMT:
2,184✔
1295
      return authSysPrivileges(pCxt, pStmt, PRIV_APPS_SHOW);
2,184✔
1296
    case QUERY_NODE_SHOW_CLUSTER_STMT:
3,030✔
1297
      return authSysPrivileges(pCxt, pStmt, PRIV_CLUSTER_SHOW);
3,030✔
1298
    case QUERY_NODE_SHOW_SECURITY_POLICIES_STMT:
5,368✔
1299
      return authSysPrivileges(pCxt, pStmt, PRIV_SECURITY_POLICIES_SHOW); 
5,368✔
1300
      // check in mnode
1301
    case QUERY_NODE_SHOW_VGROUPS_STMT:
802,876✔
1302
    case QUERY_NODE_SHOW_VNODES_STMT:
1303
    case QUERY_NODE_SHOW_COMPACTS_STMT:
1304
    case QUERY_NODE_SHOW_RETENTIONS_STMT:
1305
    case QUERY_NODE_SHOW_SCANS_STMT:
1306
    case QUERY_NODE_SHOW_SSMIGRATES_STMT:
1307
      return TSDB_CODE_SUCCESS;
802,876✔
1308
    default:
104,279,594✔
1309
      break;
104,279,594✔
1310
  }
1311
#endif
1312
  return code;
104,279,594✔
1313
}
1314

1315
int32_t authenticate(SParseContext* pParseCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
489,370,119✔
1316
  SAuthCxt cxt = {
489,370,119✔
1317
      .pParseCxt = pParseCxt,
1318
      .pMetaCache = pMetaCache,
1319
      .errCode = TSDB_CODE_SUCCESS,
1320
      .macNruGuaranteed = (pParseCxt->maxSecLevel >= SECURITY_LEVEL_TOP_SECRET),
489,376,458✔
1321
      .macNwdGuaranteed = (pParseCxt->minSecLevel == 0),
489,375,274✔
1322
  };
1323
#ifdef TD_ENTERPRISE
1324
  if (pParseCxt->sodInitial) {
489,370,422✔
1325
    int32_t rootNodeType = nodeType(pQuery->pRoot);
×
1326
    if (rootNodeType == QUERY_NODE_SELECT_STMT) {
×
1327
      SSelectStmt* pSelect = (SSelectStmt*)pQuery->pRoot;
×
1328
      STableNode*  pTable = (STableNode*)(pSelect->pFromTable);
×
1329
      if (NULL == pTable || QUERY_NODE_REAL_TABLE != nodeType(pTable) || !IS_INFORMATION_SCHEMA_DB(pTable->dbName) ||
×
1330
          (strcmp(pTable->tableName, TSDB_INS_TABLE_USERS) != 0)) {
×
1331
        return TSDB_CODE_MND_SOD_RESTRICTED;
×
1332
      }
1333
    } else if (rootNodeType != QUERY_NODE_GRANT_STMT && rootNodeType != QUERY_NODE_REVOKE_STMT &&
×
1334
               rootNodeType != QUERY_NODE_CREATE_USER_STMT && rootNodeType != QUERY_NODE_DROP_USER_STMT &&
×
1335
               rootNodeType != QUERY_NODE_ALTER_USER_STMT && rootNodeType != QUERY_NODE_SHOW_USERS_STMT &&
×
1336
               rootNodeType != QUERY_NODE_SHOW_SECURITY_POLICIES_STMT) {
1337
      return TSDB_CODE_MND_SOD_RESTRICTED;
×
1338
    }
1339
  }
1340
#endif
1341
  return authQuery(&cxt, pQuery->pRoot);
489,365,539✔
1342
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc