mgmtUser.c 13.0 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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/>.
 */

S
slguan 已提交
16
#define _DEFAULT_SOURCE
17
#include "os.h"
S
slguan 已提交
18
#include "trpc.h"
19
#include "ttime.h"
S
slguan 已提交
20
#include "tutil.h"
S
slguan 已提交
21 22
#include "mgmtAcct.h"
#include "mgmtGrant.h"
S
slguan 已提交
23
#include "mgmtMnode.h"
S
slguan 已提交
24
#include "mgmtSdb.h"
S
slguan 已提交
25
#include "mgmtShell.h"
S
#1177  
slguan 已提交
26
#include "mgmtUser.h"
S
slguan 已提交
27

S
slguan 已提交
28
static void   *tsUserSdb = NULL;
S
slguan 已提交
29
static int32_t tsUserUpdateSize = 0;
H
hzcheng 已提交
30

S
slguan 已提交
31 32 33 34 35
static int32_t mgmtCreateUser(SAcctObj *pAcct, char *name, char *pass);
static int32_t mgmtDropUser(SAcctObj *pAcct, char *name);
static int32_t mgmtUpdateUser(SUserObj *pUser);
static int32_t mgmtGetUserMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn);
static int32_t mgmtRetrieveUsers(SShowObj *pShow, char *data, int32_t rows, void *pConn);
S
slguan 已提交
36

37 38 39
static void mgmtProcessCreateUserMsg(SQueuedMsg *pMsg);
static void mgmtProcessAlterUserMsg(SQueuedMsg *pMsg);
static void mgmtProcessDropUserMsg(SQueuedMsg *pMsg);
S
slguan 已提交
40

S
slguan 已提交
41 42
static int32_t mgmtUserActionDestroy(SSdbOperDesc *pOper) {
  tfree(pOper->pObj);
S
slguan 已提交
43 44 45
  return TSDB_CODE_SUCCESS;
}

S
slguan 已提交
46 47
static int32_t mgmtUserActionInsert(SSdbOperDesc *pOper) {
  SUserObj *pUser = pOper->pObj;
S
slguan 已提交
48
  SAcctObj *pAcct = mgmtGetAcct(pUser->acct);
49 50 51 52 53 54 55 56 57

  if (pAcct != NULL) {
    mgmtAddUserIntoAcct(pAcct, pUser);
  }
  else {
    mError("user:%s, acct:%s info not exist in sdb", pUser->user, pUser->acct);
    return TSDB_CODE_INVALID_ACCT;
  }

S
slguan 已提交
58 59 60
  return TSDB_CODE_SUCCESS;
}

S
slguan 已提交
61 62
static int32_t mgmtUserActionDelete(SSdbOperDesc *pOper) {
  SUserObj *pUser = pOper->pObj;
S
slguan 已提交
63 64 65 66 67 68 69
  SAcctObj *pAcct = mgmtGetAcct(pUser->acct);

  mgmtRemoveUserFromAcct(pAcct, pUser);

  return TSDB_CODE_SUCCESS;
}

S
slguan 已提交
70
static int32_t mgmtUserActionUpdate(SSdbOperDesc *pOper) {
S
slguan 已提交
71 72 73
  return TSDB_CODE_SUCCESS;
}

S
slguan 已提交
74 75
static int32_t mgmtUserActionEncode(SSdbOperDesc *pOper) {
  SUserObj *pUser = pOper->pObj;
S
slguan 已提交
76

S
slguan 已提交
77
  if (pOper->maxRowSize < tsUserUpdateSize) {
S
slguan 已提交
78 79
    return -1;
  } else {
S
slguan 已提交
80 81 82
    memcpy(pOper->rowData, pUser, tsUserUpdateSize);
    pOper->rowSize = tsUserUpdateSize;
    return TSDB_CODE_SUCCESS;
S
slguan 已提交
83 84 85
  }
}

S
slguan 已提交
86 87
static int32_t mgmtUserActionDecode(SSdbOperDesc *pOper) {
  SUserObj *pUser = (SUserObj *) calloc(1, sizeof(SUserObj));
88
  if (pUser == NULL) return TSDB_CODE_SERV_OUT_OF_MEMORY;
S
slguan 已提交
89

S
slguan 已提交
90 91 92
  memcpy(pUser, pOper->rowData, tsUserUpdateSize);
  pOper->pObj = pUser;
  return TSDB_CODE_SUCCESS;
S
slguan 已提交
93
}
H
hzcheng 已提交
94

95
int32_t mgmtInitUsers() {
S
slguan 已提交
96
  SUserObj tObj;
S
slguan 已提交
97
  tsUserUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj;
S
slguan 已提交
98

S
slguan 已提交
99 100 101 102
  SSdbTableDesc tableDesc = {
    .tableName    = "users",
    .hashSessions = TSDB_MAX_USERS,
    .maxRowSize   = tsUserUpdateSize,
S
slguan 已提交
103
    .keyType      = SDB_KEY_TYPE_STRING,
S
slguan 已提交
104 105 106 107 108 109 110 111 112
    .insertFp     = mgmtUserActionInsert,
    .deleteFp     = mgmtUserActionDelete,
    .updateFp     = mgmtUserActionUpdate,
    .encodeFp     = mgmtUserActionEncode,
    .decodeFp     = mgmtUserActionDecode,
    .destroyFp    = mgmtUserActionDestroy,
  };

  tsUserSdb = sdbOpenTable(&tableDesc);
113
  if (tsUserSdb == NULL) {
H
hzcheng 已提交
114 115 116 117
    mError("failed to init user data");
    return -1;
  }

S
slguan 已提交
118
  SAcctObj *pAcct = mgmtGetAcct("root");
S
slguan 已提交
119 120 121 122
  mgmtCreateUser(pAcct, "root", "taosdata");
  mgmtCreateUser(pAcct, "monitor", tsInternalPass);
  mgmtCreateUser(pAcct, "_root", tsInternalPass);

S
slguan 已提交
123 124 125
  mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_CREATE_USER, mgmtProcessCreateUserMsg);
  mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_ALTER_USER, mgmtProcessAlterUserMsg);
  mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_DROP_USER, mgmtProcessDropUserMsg);
S
slguan 已提交
126 127 128
  mgmtAddShellShowMetaHandle(TSDB_MGMT_TABLE_USER, mgmtGetUserMeta);
  mgmtAddShellShowRetrieveHandle(TSDB_MGMT_TABLE_USER, mgmtRetrieveUsers);
  
H
hzcheng 已提交
129 130 131 132
  mTrace("user data is initialized");
  return 0;
}

S
slguan 已提交
133 134 135 136
void mgmtCleanUpUsers() {
  sdbCloseTable(tsUserSdb);
}

137 138 139
SUserObj *mgmtGetUser(char *name) {
  return (SUserObj *)sdbGetRow(tsUserSdb, name);
}
H
hzcheng 已提交
140

S
slguan 已提交
141
static int32_t mgmtUpdateUser(SUserObj *pUser) {
S
slguan 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154 155
  SSdbOperDesc oper = {
    .type = SDB_OPER_TYPE_GLOBAL,
    .table = tsUserSdb,
    .pObj = pUser,
    .rowSize = tsUserUpdateSize
  };

  int32_t code = sdbUpdateRow(&oper);
  if (code != TSDB_CODE_SUCCESS) {
    tfree(pUser);
    code = TSDB_CODE_SDB_ERROR;
  }

  return code;
156
}
H
hzcheng 已提交
157

S
slguan 已提交
158
static int32_t mgmtCreateUser(SAcctObj *pAcct, char *name, char *pass) {
S
slguan 已提交
159
  int32_t code = mgmtCheckUserLimit(pAcct);
S
slguan 已提交
160 161
  if (code != 0) {
    return code;
H
hzcheng 已提交
162 163
  }

S
slguan 已提交
164 165 166 167 168
  if (name[0] == 0 || pass[0] == 0) {
    return TSDB_CODE_INVALID_MSG;
  }

  SUserObj *pUser = (SUserObj *)sdbGetRow(tsUserSdb, name);
H
hzcheng 已提交
169
  if (pUser != NULL) {
170
    mTrace("user:%s is already there", name);
H
hzcheng 已提交
171 172 173
    return TSDB_CODE_USER_ALREADY_EXIST;
  }

S
slguan 已提交
174 175 176 177 178
  code = mgmtCheckUserGrant();
  if (code != 0) {
    return code;
  }

S
slguan 已提交
179
  pUser = calloc(1, sizeof(SUserObj));
H
hzcheng 已提交
180
  strcpy(pUser->user, name);
S
slguan 已提交
181
  taosEncryptPass((uint8_t*) pass, strlen(pass), pUser->pass);
H
hzcheng 已提交
182 183 184 185 186 187 188 189
  strcpy(pUser->acct, pAcct->user);
  pUser->createdTime = taosGetTimestampMs();
  pUser->superAuth = 0;
  pUser->writeAuth = 1;
  if (strcmp(pUser->user, "root") == 0 || strcmp(pUser->user, pUser->acct) == 0) {
    pUser->superAuth = 1;
  }

S
slguan 已提交
190 191 192 193 194 195 196 197 198
  SSdbOperDesc oper = {
    .type = SDB_OPER_TYPE_GLOBAL,
    .table = tsUserSdb,
    .pObj = pUser,
    .rowSize = sizeof(SUserObj)
  };

  code = sdbInsertRow(&oper);
  if (code != TSDB_CODE_SUCCESS) {
H
hzcheng 已提交
199 200 201 202 203 204 205
    tfree(pUser);
    code = TSDB_CODE_SDB_ERROR;
  }

  return code;
}

S
slguan 已提交
206
static int32_t mgmtDropUser(SAcctObj *pAcct, char *name) {
H
hzcheng 已提交
207 208
  SUserObj *pUser;

209
  pUser = (SUserObj *)sdbGetRow(tsUserSdb, name);
H
hzcheng 已提交
210 211 212 213 214
  if (pUser == NULL) {
    mWarn("user:%s is not there", name);
    return TSDB_CODE_INVALID_USER;
  }

215 216 217
  if (strcmp(pAcct->user, pUser->acct) != 0) {
    return TSDB_CODE_NO_RIGHTS;
  }
H
hzcheng 已提交
218

S
slguan 已提交
219 220 221 222 223
  SSdbOperDesc oper = {
    .type = SDB_OPER_TYPE_GLOBAL,
    .table = tsUserSdb,
    .pObj = pUser
  };
H
hzcheng 已提交
224

S
slguan 已提交
225 226 227 228 229 230
  int32_t code = sdbDeleteRow(&oper);
  if (code != TSDB_CODE_SUCCESS) {
    code = TSDB_CODE_SDB_ERROR;
  }

  return code;
H
hzcheng 已提交
231 232
}

H
hjxilinx 已提交
233
static int32_t mgmtGetUserMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) {
S
slguan 已提交
234
  SUserObj *pUser = mgmtGetUserFromConn(pConn, NULL);
S
slguan 已提交
235 236 237 238 239
  if (pUser == NULL) {
    return TSDB_CODE_INVALID_USER;
  }

  int32_t cols     = 0;
H
hjxilinx 已提交
240
  SSchema *pSchema = pMeta->schema;
S
slguan 已提交
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

  pShow->bytes[cols] = TSDB_USER_LEN;
  pSchema[cols].type = TSDB_DATA_TYPE_BINARY;
  strcpy(pSchema[cols].name, "name");
  pSchema[cols].bytes = htons(pShow->bytes[cols]);
  cols++;

  pShow->bytes[cols] = 6;
  pSchema[cols].type = TSDB_DATA_TYPE_BINARY;
  strcpy(pSchema[cols].name, "privilege");
  pSchema[cols].bytes = htons(pShow->bytes[cols]);
  cols++;

  pShow->bytes[cols] = 8;
  pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP;
H
hjxilinx 已提交
256
  strcpy(pSchema[cols].name, "created_time");
S
slguan 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
  pSchema[cols].bytes = htons(pShow->bytes[cols]);
  cols++;

  pMeta->numOfColumns = htons(cols);
  strcpy(pMeta->tableId, "show users");
  pShow->numOfColumns = cols;

  pShow->offset[0] = 0;
  for (int32_t i = 1; i < cols; ++i) {
    pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1];
  }

  pShow->numOfRows = pUser->pAcct->acctInfo.numOfUsers;
  pShow->pNode = pUser->pAcct->pUser;
  pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1];
H
hzcheng 已提交
272 273 274 275

  return 0;
}

S
slguan 已提交
276
static int32_t mgmtRetrieveUsers(SShowObj *pShow, char *data, int32_t rows, void *pConn) {
S
slguan 已提交
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
  int32_t  numOfRows = 0;
  SUserObj *pUser    = NULL;
  int32_t  cols      = 0;
  char     *pWrite;

  while (numOfRows < rows) {
    pUser = (SUserObj *)pShow->pNode;
    if (pUser == NULL) break;
    pShow->pNode = (void *)pUser->next;

    cols = 0;

    pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
    strcpy(pWrite, pUser->user);
    cols++;

    pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
    if (pUser->superAuth) {
      strcpy(pWrite, "super");
    } else if (pUser->writeAuth) {
      strcpy(pWrite, "write");
    } else {
      strcpy(pWrite, "read");
    }
    cols++;

    pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
    *(int64_t *)pWrite = pUser->createdTime;
    cols++;

    numOfRows++;
  }
  pShow->numOfReads += numOfRows;
H
hzcheng 已提交
310 311 312
  return numOfRows;
}

313
SUserObj *mgmtGetUserFromConn(void *pConn, bool *usePublicIp) {
S
slguan 已提交
314
  SRpcConnInfo connInfo;
315
  if (rpcGetConnInfo(pConn, &connInfo) == 0) {
S
slguan 已提交
316 317 318
    if (usePublicIp) {
      *usePublicIp = (connInfo.serverIp == tsPublicIpInt);
    }
319 320
    return mgmtGetUser(connInfo.user);
  }
S
slguan 已提交
321

322
  return NULL;
S
slguan 已提交
323
}
S
slguan 已提交
324

325 326
static void mgmtProcessCreateUserMsg(SQueuedMsg *pMsg) {
  if (mgmtCheckRedirect(pMsg->thandle)) return;
S
slguan 已提交
327

328 329 330
  int32_t code;
  SUserObj *pUser = pMsg->pUser;
  
S
slguan 已提交
331
  if (pUser->superAuth) {
332 333 334
    SCMCreateUserMsg *pCreate = pMsg->pCont;
    code = mgmtCreateUser(pUser->pAcct, pCreate->user, pCreate->pass);
    if (code == TSDB_CODE_SUCCESS) {
S
slguan 已提交
335 336 337
      mLPrint("user:%s is created by %s", pCreate->user, pUser->user);
    }
  } else {
338
    code = TSDB_CODE_NO_RIGHTS;
S
slguan 已提交
339 340
  }

341
  mgmtSendSimpleResp(pMsg->thandle, code);
S
slguan 已提交
342 343
}

344 345
static void mgmtProcessAlterUserMsg(SQueuedMsg *pMsg) {
  if (mgmtCheckRedirect(pMsg->thandle)) return;
S
slguan 已提交
346

347 348 349 350
  int32_t code;
  SUserObj *pOperUser = pMsg->pUser;
  
  SCMAlterUserMsg *pAlter = pMsg->pCont;
S
slguan 已提交
351 352
  SUserObj *pUser = mgmtGetUser(pAlter->user);
  if (pUser == NULL) {
353
    mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_USER);
S
slguan 已提交
354 355 356 357
    return;
  }

  if (strcmp(pUser->user, "monitor") == 0 || (strcmp(pUser->user + 1, pUser->acct) == 0 && pUser->user[0] == '_')) {
358
    mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_NO_RIGHTS);
S
slguan 已提交
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
    return;
  }

  if ((pAlter->flag & TSDB_ALTER_USER_PASSWD) != 0) {
    bool hasRight = false;
    if (strcmp(pOperUser->user, "root") == 0) {
      hasRight = true;
    } else if (strcmp(pUser->user, pOperUser->user) == 0) {
      hasRight = true;
    } else if (pOperUser->superAuth) {
      if (strcmp(pUser->user, "root") == 0) {
        hasRight = false;
      } else if (strcmp(pOperUser->acct, pUser->acct) != 0) {
        hasRight = false;
      } else {
        hasRight = true;
      }
    }

    if (hasRight) {
      memset(pUser->pass, 0, sizeof(pUser->pass));
      taosEncryptPass((uint8_t*)pAlter->pass, strlen(pAlter->pass), pUser->pass);
381
      code = mgmtUpdateUser(pUser);
S
slguan 已提交
382
      mLPrint("user:%s password is altered by %s, result:%d", pUser->user, pOperUser->user, tstrerror(code));
S
slguan 已提交
383
    } else {
384
      code = TSDB_CODE_NO_RIGHTS;
S
slguan 已提交
385 386
    }

387
    mgmtSendSimpleResp(pMsg->thandle, code);
S
slguan 已提交
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
    return;
  }

  if ((pAlter->flag & TSDB_ALTER_USER_PRIVILEGES) != 0) {
    bool hasRight = false;

    if (strcmp(pUser->user, "root") == 0) {
      hasRight = false;
    } else if (strcmp(pUser->user, pUser->acct) == 0) {
      hasRight = false;
    } else if (strcmp(pOperUser->user, "root") == 0) {
      hasRight = true;
    } else if (strcmp(pUser->user, pOperUser->user) == 0) {
      hasRight = false;
    } else if (pOperUser->superAuth) {
      if (strcmp(pUser->user, "root") == 0) {
        hasRight = false;
      } else if (strcmp(pOperUser->acct, pUser->acct) != 0) {
        hasRight = false;
      } else {
        hasRight = true;
      }
    }

    if (pAlter->privilege == 1) { // super
      hasRight = false;
    }

    if (hasRight) {
      if (pAlter->privilege == 2) {  // read
        pUser->superAuth = 0;
        pUser->writeAuth = 0;
      }
      if (pAlter->privilege == 3) {  // write
        pUser->superAuth = 0;
        pUser->writeAuth = 1;
      }

426
      code = mgmtUpdateUser(pUser);
S
slguan 已提交
427
      mLPrint("user:%s privilege is altered by %s, result:%d", pUser->user, pOperUser->user, tstrerror(code));
S
slguan 已提交
428
    } else {
429
      code = TSDB_CODE_NO_RIGHTS;
S
slguan 已提交
430 431
    }

432
    mgmtSendSimpleResp(pMsg->thandle, code);
S
slguan 已提交
433 434 435
    return;
  }

436
  mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_NO_RIGHTS);
S
slguan 已提交
437 438
}

439 440
static void mgmtProcessDropUserMsg(SQueuedMsg *pMsg) {
  if (mgmtCheckRedirect(pMsg->thandle)) return;
S
slguan 已提交
441

442 443
  int32_t code;
  SUserObj *pOperUser = pMsg->pUser;
S
slguan 已提交
444

445
  SCMDropUserMsg *pDrop = pMsg->pCont;
S
slguan 已提交
446 447
  SUserObj *pUser = mgmtGetUser(pDrop->user);
  if (pUser == NULL) {
448
    mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_USER);
S
slguan 已提交
449 450 451 452
    return ;
  }

  if (strcmp(pUser->user, "monitor") == 0 || (strcmp(pUser->user + 1, pUser->acct) == 0 && pUser->user[0] == '_')) {
453
    mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_NO_RIGHTS);
S
slguan 已提交
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
    return ;
  }

  bool hasRight = false;
  if (strcmp(pUser->user, "root") == 0) {
    hasRight = false;
  } else if (strcmp(pOperUser->user, "root") == 0) {
    hasRight = true;
  } else if (strcmp(pUser->user, pOperUser->user) == 0) {
    hasRight = false;
  } else if (pOperUser->superAuth) {
    if (strcmp(pUser->user, "root") == 0) {
      hasRight = false;
    } else if (strcmp(pOperUser->acct, pUser->acct) != 0) {
      hasRight = false;
    } else {
      hasRight = true;
    }
  }

  if (hasRight) {
475 476
    code = mgmtDropUser(pUser->pAcct, pDrop->user);
    if (code == TSDB_CODE_SUCCESS) {
S
slguan 已提交
477
       mLPrint("user:%s is dropped by %s, result:%d", pUser->user, pOperUser->user, tstrerror(code));
S
slguan 已提交
478 479
    }
  } else {
480
    code = TSDB_CODE_NO_RIGHTS;
S
slguan 已提交
481 482
  }

483
  mgmtSendSimpleResp(pMsg->thandle, code);
S
slguan 已提交
484
}