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

#include "catalog.h"
X
Xiaoyu Wang 已提交
17
#include "cmdnodes.h"
18 19 20
#include "parInt.h"

typedef struct SAuthCxt {
21 22 23
  SParseContext*   pParseCxt;
  SParseMetaCache* pMetaCache;
  int32_t          errCode;
24 25
} SAuthCxt;

26 27 28 29 30
typedef struct SSelectAuthCxt {
  SAuthCxt*    pAuthCxt;
  SSelectStmt* pSelect;
} SSelectAuthCxt;

31 32 33 34
typedef struct SAuthRewriteCxt {
  STableNode*  pTarget;
} SAuthRewriteCxt;

35 36
static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt);

X
Xiaoyu Wang 已提交
37 38 39 40 41 42 43 44 45 46 47 48
static void setUserAuthInfo(SParseContext* pCxt, const char* pDbName, const char* pTabName, AUTH_TYPE type,
                            SUserAuthInfo* pAuth) {
  snprintf(pAuth->user, sizeof(pAuth->user), "%s", pCxt->pUser);
  if (NULL == pTabName) {
    tNameSetDbName(&pAuth->tbName, pCxt->acctId, pDbName, strlen(pDbName));
  } else {
    toName(pCxt->acctId, pDbName, pTabName, &pAuth->tbName);
  }
  pAuth->type = type;
}

static int32_t checkAuth(SAuthCxt* pCxt, const char* pDbName, const char* pTabName, AUTH_TYPE type, SNode** pCond) {
49 50
  SParseContext* pParseCxt = pCxt->pParseCxt;
  if (pParseCxt->isSuperUser) {
51 52
    return TSDB_CODE_SUCCESS;
  }
X
Xiaoyu Wang 已提交
53 54 55 56 57

  SUserAuthInfo authInfo = {0};
  setUserAuthInfo(pCxt->pParseCxt, pDbName, pTabName, type, &authInfo);
  int32_t      code = TSDB_CODE_SUCCESS;
  SUserAuthRes authRes = {0};
58
  if (NULL != pCxt->pMetaCache) {
X
Xiaoyu Wang 已提交
59
    code = getUserAuthFromCache(pCxt->pMetaCache, &authInfo, &authRes);
60
  } else {
61
    SRequestConnInfo conn = {.pTrans = pParseCxt->pTransporter,
D
dapan1121 已提交
62 63 64
                             .requestId = pParseCxt->requestId,
                             .requestObjRefId = pParseCxt->requestRid,
                             .mgmtEps = pParseCxt->mgmtEpSet};
D
dapan1121 已提交
65
    code = catalogChkAuth(pParseCxt->pCatalog, &conn, &authInfo, &authRes);
66
  }
X
Xiaoyu Wang 已提交
67 68 69 70
  if (TSDB_CODE_SUCCESS == code && NULL != pCond) {
    *pCond = authRes.pCond;
  }
  return TSDB_CODE_SUCCESS == code ? (authRes.pass ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED) : code;
71 72 73 74 75 76
}

static EDealRes authSubquery(SAuthCxt* pCxt, SNode* pStmt) {
  return TSDB_CODE_SUCCESS == authQuery(pCxt, pStmt) ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
}

X
Xiaoyu Wang 已提交
77
static int32_t mergeStableTagCond(SNode** pWhere, SNode* pTagCond) {
78 79 80 81 82 83 84
  SLogicConditionNode* pLogicCond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION);
  if (NULL == pLogicCond) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  pLogicCond->node.resType.type = TSDB_DATA_TYPE_BOOL;
  pLogicCond->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
  pLogicCond->condType = LOGIC_COND_TYPE_AND;
X
Xiaoyu Wang 已提交
85
  int32_t code = nodesListMakeStrictAppend(&pLogicCond->pParameterList, pTagCond);
86 87 88 89 90 91 92 93 94 95 96
  if (TSDB_CODE_SUCCESS == code) {
    code = nodesListMakeAppend(&pLogicCond->pParameterList, *pWhere);
  }
  if (TSDB_CODE_SUCCESS == code) {
    *pWhere = (SNode*)pLogicCond;
  } else {
    nodesDestroyNode((SNode*)pLogicCond);
  }
  return code;
}

97 98 99 100 101 102 103 104 105 106 107 108
EDealRes rewriteAuthTable(SNode* pNode, void* pContext) {
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
    SColumnNode* pCol = (SColumnNode*)pNode;
    SAuthRewriteCxt* pCxt = (SAuthRewriteCxt*)pContext;
    strcpy(pCol->tableName, pCxt->pTarget->tableName);
    strcpy(pCol->tableAlias, pCxt->pTarget->tableAlias);
  }

  return DEAL_RES_CONTINUE;
}

static int32_t rewriteAppendStableTagCond(SNode** pWhere, SNode* pTagCond, STableNode* pTable) {
X
Xiaoyu Wang 已提交
109 110 111 112 113
  SNode* pTagCondCopy = nodesCloneNode(pTagCond);
  if (NULL == pTagCondCopy) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

114 115 116
  SAuthRewriteCxt cxt = {.pTarget = pTable};
  nodesWalkExpr(pTagCondCopy, rewriteAuthTable, &cxt);

X
Xiaoyu Wang 已提交
117
  if (NULL == *pWhere) {
X
Xiaoyu Wang 已提交
118
    *pWhere = pTagCondCopy;
119 120 121
    return TSDB_CODE_SUCCESS;
  }

X
Xiaoyu Wang 已提交
122 123
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pWhere) &&
      LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)*pWhere)->condType) {
X
Xiaoyu Wang 已提交
124
    return nodesListStrictAppend(((SLogicConditionNode*)*pWhere)->pParameterList, pTagCondCopy);
125 126
  }

X
Xiaoyu Wang 已提交
127
  return mergeStableTagCond(pWhere, pTagCondCopy);
128 129
}

130
static EDealRes authSelectImpl(SNode* pNode, void* pContext) {
131 132
  SSelectAuthCxt* pCxt = pContext;
  SAuthCxt*       pAuthCxt = pCxt->pAuthCxt;
133
  if (QUERY_NODE_REAL_TABLE == nodeType(pNode)) {
X
Xiaoyu Wang 已提交
134 135 136 137
    SNode*      pTagCond = NULL;
    STableNode* pTable = (STableNode*)pNode;
    pAuthCxt->errCode = checkAuth(pAuthCxt, pTable->dbName, pTable->tableName, AUTH_TYPE_READ, &pTagCond);
    if (TSDB_CODE_SUCCESS == pAuthCxt->errCode && NULL != pTagCond) {
138
      pAuthCxt->errCode = rewriteAppendStableTagCond(&pCxt->pSelect->pWhere, pTagCond, pTable);
X
Xiaoyu Wang 已提交
139
    }
140
    return TSDB_CODE_SUCCESS == pAuthCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
141
  } else if (QUERY_NODE_TEMP_TABLE == nodeType(pNode)) {
142
    return authSubquery(pAuthCxt, ((STempTableNode*)pNode)->pSubquery);
143 144 145 146 147
  }
  return DEAL_RES_CONTINUE;
}

static int32_t authSelect(SAuthCxt* pCxt, SSelectStmt* pSelect) {
148 149
  SSelectAuthCxt cxt = {.pAuthCxt = pCxt, .pSelect = pSelect};
  nodesWalkSelectStmt(pSelect, SQL_CLAUSE_FROM, authSelectImpl, &cxt);
150 151 152
  return pCxt->errCode;
}

153 154 155 156 157 158 159 160
static int32_t authSetOperator(SAuthCxt* pCxt, SSetOperator* pSetOper) {
  int32_t code = authQuery(pCxt, pSetOper->pLeft);
  if (TSDB_CODE_SUCCESS == code) {
    code = authQuery(pCxt, pSetOper->pRight);
  }
  return code;
}

X
Xiaoyu Wang 已提交
161
static int32_t authDropUser(SAuthCxt* pCxt, SDropUserStmt* pStmt) {
X
Xiaoyu Wang 已提交
162
  if (!pCxt->pParseCxt->isSuperUser || 0 == strcmp(pStmt->userName, TSDB_DEFAULT_USER)) {
163 164 165 166
    return TSDB_CODE_PAR_PERMISSION_DENIED;
  }
  return TSDB_CODE_SUCCESS;
}
K
kailixu 已提交
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
#if 0
static int32_t authAlterUser(SAuthCxt* pCxt, SAlterUserStmt* pStmt) {
  SParseContext* pParseCxt = pCxt->pParseCxt;

  SUserAuthInfo authInfo = {0};
  snprintf(authInfo.user, sizeof(authInfo.user), "%s", pStmt->userName);
  authInfo.type = AUTH_TYPE_OTHER;

  int32_t          code = TSDB_CODE_SUCCESS;
  SUserAuthRes     authRes = {0};
  SRequestConnInfo conn = {.pTrans = pParseCxt->pTransporter,
                           .requestId = pParseCxt->requestId,
                           .requestObjRefId = pParseCxt->requestRid,
                           .mgmtEps = pParseCxt->mgmtEpSet};
  code = catalogChkAuth(pParseCxt->pCatalog, &conn, &authInfo, &authRes);

  return TSDB_CODE_SUCCESS == code ? (authRes.pass ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED) : code;
}
#endif
186

X
Xiaoyu Wang 已提交
187
static int32_t authDelete(SAuthCxt* pCxt, SDeleteStmt* pDelete) {
X
Xiaoyu Wang 已提交
188 189 190 191
  SNode*      pTagCond = NULL;
  STableNode* pTable = (STableNode*)pDelete->pFromTable;
  int32_t     code = checkAuth(pCxt, pTable->dbName, pTable->tableName, AUTH_TYPE_WRITE, &pTagCond);
  if (TSDB_CODE_SUCCESS == code && NULL != pTagCond) {
192
    code = rewriteAppendStableTagCond(&pDelete->pWhere, pTagCond, pTable);
X
Xiaoyu Wang 已提交
193 194
  }
  return code;
X
Xiaoyu Wang 已提交
195 196
}

197
static int32_t authInsert(SAuthCxt* pCxt, SInsertStmt* pInsert) {
X
Xiaoyu Wang 已提交
198 199 200 201
  SNode*      pTagCond = NULL;
  STableNode* pTable = (STableNode*)pInsert->pTable;
  // todo check tag condition for subtable
  int32_t code = checkAuth(pCxt, pTable->dbName, pTable->tableName, AUTH_TYPE_WRITE, &pTagCond);
202 203 204 205 206 207
  if (TSDB_CODE_SUCCESS == code) {
    code = authQuery(pCxt, pInsert->pQuery);
  }
  return code;
}

208
static int32_t authShowTables(SAuthCxt* pCxt, SShowStmt* pStmt) {
X
Xiaoyu Wang 已提交
209
  return checkAuth(pCxt, ((SValueNode*)pStmt->pDbName)->literal, NULL, AUTH_TYPE_READ_OR_WRITE, NULL);
210 211
}

212
static int32_t authShowCreateTable(SAuthCxt* pCxt, SShowCreateTableStmt* pStmt) {
X
Xiaoyu Wang 已提交
213 214
  SNode* pTagCond = NULL;
  // todo check tag condition for subtable
215
  return checkAuth(pCxt, pStmt->dbName, pStmt->tableName, AUTH_TYPE_READ, &pTagCond);
216 217
}

X
Xiaoyu Wang 已提交
218
static int32_t authCreateTable(SAuthCxt* pCxt, SCreateTableStmt* pStmt) {
X
Xiaoyu Wang 已提交
219 220 221
  SNode* pTagCond = NULL;
  // todo check tag condition for subtable
  return checkAuth(pCxt, pStmt->dbName, NULL, AUTH_TYPE_WRITE, &pTagCond);
X
Xiaoyu Wang 已提交
222 223
}

X
Xiaoyu Wang 已提交
224
static int32_t authCreateMultiTable(SAuthCxt* pCxt, SCreateMultiTablesStmt* pStmt) {
X
Xiaoyu Wang 已提交
225 226 227
  int32_t code = TSDB_CODE_SUCCESS;
  SNode*  pNode = NULL;
  FOREACH(pNode, pStmt->pSubTables) {
X
Xiaoyu Wang 已提交
228 229
    SCreateSubTableClause* pClause = (SCreateSubTableClause*)pNode;
    code = checkAuth(pCxt, pClause->dbName, NULL, AUTH_TYPE_WRITE, NULL);
X
Xiaoyu Wang 已提交
230 231 232 233 234 235 236
    if (TSDB_CODE_SUCCESS != code) {
      break;
    }
  }
  return code;
}

X
Xiaoyu Wang 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
static int32_t authDropTable(SAuthCxt* pCxt, SDropTableStmt* pStmt) {
  int32_t code = TSDB_CODE_SUCCESS;
  SNode*  pNode = NULL;
  FOREACH(pNode, pStmt->pTables) {
    SDropTableClause* pClause = (SDropTableClause*)pNode;
    code = checkAuth(pCxt, pClause->dbName, pClause->tableName, AUTH_TYPE_WRITE, NULL);
    if (TSDB_CODE_SUCCESS != code) {
      break;
    }
  }
  return code;
}

static int32_t authDropStable(SAuthCxt* pCxt, SDropSuperTableStmt* pStmt) {
  return checkAuth(pCxt, pStmt->dbName, pStmt->tableName, AUTH_TYPE_WRITE, NULL);
}

static int32_t authAlterTable(SAuthCxt* pCxt, SAlterTableStmt* pStmt) {
  SNode* pTagCond = NULL;
  // todo check tag condition for subtable
  return checkAuth(pCxt, pStmt->dbName, pStmt->tableName, AUTH_TYPE_WRITE, NULL);
}

260 261 262
static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) {
  switch (nodeType(pStmt)) {
    case QUERY_NODE_SET_OPERATOR:
263
      return authSetOperator(pCxt, (SSetOperator*)pStmt);
264 265
    case QUERY_NODE_SELECT_STMT:
      return authSelect(pCxt, (SSelectStmt*)pStmt);
266
    case QUERY_NODE_DROP_USER_STMT:
X
Xiaoyu Wang 已提交
267
      return authDropUser(pCxt, (SDropUserStmt*)pStmt);
K
kailixu 已提交
268 269
    // case QUERY_NODE_ALTER_USER_STMT:
    //   return authAlterUser(pCxt, (SAlterUserStmt*)pStmt);
X
Xiaoyu Wang 已提交
270 271
    case QUERY_NODE_DELETE_STMT:
      return authDelete(pCxt, (SDeleteStmt*)pStmt);
272 273
    case QUERY_NODE_INSERT_STMT:
      return authInsert(pCxt, (SInsertStmt*)pStmt);
X
Xiaoyu Wang 已提交
274 275
    case QUERY_NODE_CREATE_TABLE_STMT:
      return authCreateTable(pCxt, (SCreateTableStmt*)pStmt);
X
Xiaoyu Wang 已提交
276 277
    case QUERY_NODE_CREATE_MULTI_TABLES_STMT:
      return authCreateMultiTable(pCxt, (SCreateMultiTablesStmt*)pStmt);
X
Xiaoyu Wang 已提交
278 279 280 281 282 283 284
    case QUERY_NODE_DROP_TABLE_STMT:
      return authDropTable(pCxt, (SDropTableStmt*)pStmt);
    case QUERY_NODE_DROP_SUPER_TABLE_STMT:
      return authDropStable(pCxt, (SDropSuperTableStmt*)pStmt);
    case QUERY_NODE_ALTER_TABLE_STMT:
    case QUERY_NODE_ALTER_SUPER_TABLE_STMT:
      return authAlterTable(pCxt, (SAlterTableStmt*)pStmt);
285 286 287 288 289 290 291 292 293
    case QUERY_NODE_SHOW_DNODES_STMT:
    case QUERY_NODE_SHOW_MNODES_STMT:
    case QUERY_NODE_SHOW_MODULES_STMT:
    case QUERY_NODE_SHOW_QNODES_STMT:
    case QUERY_NODE_SHOW_SNODES_STMT:
    case QUERY_NODE_SHOW_BNODES_STMT:
    case QUERY_NODE_SHOW_CLUSTER_STMT:
    case QUERY_NODE_SHOW_LICENCES_STMT:
    case QUERY_NODE_SHOW_VGROUPS_STMT:
294
    case QUERY_NODE_SHOW_DB_ALIVE_STMT:
295
    case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT:
296
    case QUERY_NODE_SHOW_CREATE_DATABASE_STMT:
297 298 299 300
    case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT:
    case QUERY_NODE_SHOW_VNODES_STMT:
    case QUERY_NODE_SHOW_SCORES_STMT:
      return !pCxt->pParseCxt->enableSysInfo ? TSDB_CODE_PAR_PERMISSION_DENIED : TSDB_CODE_SUCCESS;
301 302 303
    case QUERY_NODE_SHOW_TABLES_STMT:
    case QUERY_NODE_SHOW_STABLES_STMT:
      return authShowTables(pCxt, (SShowStmt*)pStmt);
304 305 306
    case QUERY_NODE_SHOW_CREATE_TABLE_STMT:
    case QUERY_NODE_SHOW_CREATE_STABLE_STMT:
      return authShowCreateTable(pCxt, (SShowCreateTableStmt*)pStmt);
307 308 309 310 311 312 313
    default:
      break;
  }

  return TSDB_CODE_SUCCESS;
}

314 315
int32_t authenticate(SParseContext* pParseCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
  SAuthCxt cxt = {.pParseCxt = pParseCxt, .pMetaCache = pMetaCache, .errCode = TSDB_CODE_SUCCESS};
316 317
  return authQuery(&cxt, pQuery->pRoot);
}