00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "postgres.h"
00014
00015 #include "access/genam.h"
00016 #include "access/heapam.h"
00017 #include "access/htup_details.h"
00018 #include "access/xact.h"
00019 #include "catalog/dependency.h"
00020 #include "catalog/indexing.h"
00021 #include "catalog/objectaccess.h"
00022 #include "catalog/pg_auth_members.h"
00023 #include "catalog/pg_authid.h"
00024 #include "catalog/pg_database.h"
00025 #include "catalog/pg_db_role_setting.h"
00026 #include "commands/comment.h"
00027 #include "commands/dbcommands.h"
00028 #include "commands/seclabel.h"
00029 #include "commands/user.h"
00030 #include "libpq/md5.h"
00031 #include "miscadmin.h"
00032 #include "storage/lmgr.h"
00033 #include "utils/acl.h"
00034 #include "utils/builtins.h"
00035 #include "utils/fmgroids.h"
00036 #include "utils/syscache.h"
00037 #include "utils/timestamp.h"
00038 #include "utils/tqual.h"
00039
00040
00041 Oid binary_upgrade_next_pg_authid_oid = InvalidOid;
00042
00043
00044
00045 extern bool Password_encryption;
00046
00047
00048 check_password_hook_type check_password_hook = NULL;
00049
00050 static List *roleNamesToIds(List *memberNames);
00051 static void AddRoleMems(const char *rolename, Oid roleid,
00052 List *memberNames, List *memberIds,
00053 Oid grantorId, bool admin_opt);
00054 static void DelRoleMems(const char *rolename, Oid roleid,
00055 List *memberNames, List *memberIds,
00056 bool admin_opt);
00057
00058
00059
00060 static bool
00061 have_createrole_privilege(void)
00062 {
00063 return has_createrole_privilege(GetUserId());
00064 }
00065
00066
00067
00068
00069
00070 Oid
00071 CreateRole(CreateRoleStmt *stmt)
00072 {
00073 Relation pg_authid_rel;
00074 TupleDesc pg_authid_dsc;
00075 HeapTuple tuple;
00076 Datum new_record[Natts_pg_authid];
00077 bool new_record_nulls[Natts_pg_authid];
00078 Oid roleid;
00079 ListCell *item;
00080 ListCell *option;
00081 char *password = NULL;
00082 bool encrypt_password = Password_encryption;
00083 char encrypted_password[MD5_PASSWD_LEN + 1];
00084 bool issuper = false;
00085 bool inherit = true;
00086 bool createrole = false;
00087 bool createdb = false;
00088 bool canlogin = false;
00089 bool isreplication = false;
00090 int connlimit = -1;
00091 List *addroleto = NIL;
00092 List *rolemembers = NIL;
00093 List *adminmembers = NIL;
00094 char *validUntil = NULL;
00095 Datum validUntil_datum;
00096 bool validUntil_null;
00097 DefElem *dpassword = NULL;
00098 DefElem *dissuper = NULL;
00099 DefElem *dinherit = NULL;
00100 DefElem *dcreaterole = NULL;
00101 DefElem *dcreatedb = NULL;
00102 DefElem *dcanlogin = NULL;
00103 DefElem *disreplication = NULL;
00104 DefElem *dconnlimit = NULL;
00105 DefElem *daddroleto = NULL;
00106 DefElem *drolemembers = NULL;
00107 DefElem *dadminmembers = NULL;
00108 DefElem *dvalidUntil = NULL;
00109
00110
00111 switch (stmt->stmt_type)
00112 {
00113 case ROLESTMT_ROLE:
00114 break;
00115 case ROLESTMT_USER:
00116 canlogin = true;
00117
00118 break;
00119 case ROLESTMT_GROUP:
00120 break;
00121 }
00122
00123
00124 foreach(option, stmt->options)
00125 {
00126 DefElem *defel = (DefElem *) lfirst(option);
00127
00128 if (strcmp(defel->defname, "password") == 0 ||
00129 strcmp(defel->defname, "encryptedPassword") == 0 ||
00130 strcmp(defel->defname, "unencryptedPassword") == 0)
00131 {
00132 if (dpassword)
00133 ereport(ERROR,
00134 (errcode(ERRCODE_SYNTAX_ERROR),
00135 errmsg("conflicting or redundant options")));
00136 dpassword = defel;
00137 if (strcmp(defel->defname, "encryptedPassword") == 0)
00138 encrypt_password = true;
00139 else if (strcmp(defel->defname, "unencryptedPassword") == 0)
00140 encrypt_password = false;
00141 }
00142 else if (strcmp(defel->defname, "sysid") == 0)
00143 {
00144 ereport(NOTICE,
00145 (errmsg("SYSID can no longer be specified")));
00146 }
00147 else if (strcmp(defel->defname, "superuser") == 0)
00148 {
00149 if (dissuper)
00150 ereport(ERROR,
00151 (errcode(ERRCODE_SYNTAX_ERROR),
00152 errmsg("conflicting or redundant options")));
00153 dissuper = defel;
00154 }
00155 else if (strcmp(defel->defname, "inherit") == 0)
00156 {
00157 if (dinherit)
00158 ereport(ERROR,
00159 (errcode(ERRCODE_SYNTAX_ERROR),
00160 errmsg("conflicting or redundant options")));
00161 dinherit = defel;
00162 }
00163 else if (strcmp(defel->defname, "createrole") == 0)
00164 {
00165 if (dcreaterole)
00166 ereport(ERROR,
00167 (errcode(ERRCODE_SYNTAX_ERROR),
00168 errmsg("conflicting or redundant options")));
00169 dcreaterole = defel;
00170 }
00171 else if (strcmp(defel->defname, "createdb") == 0)
00172 {
00173 if (dcreatedb)
00174 ereport(ERROR,
00175 (errcode(ERRCODE_SYNTAX_ERROR),
00176 errmsg("conflicting or redundant options")));
00177 dcreatedb = defel;
00178 }
00179 else if (strcmp(defel->defname, "canlogin") == 0)
00180 {
00181 if (dcanlogin)
00182 ereport(ERROR,
00183 (errcode(ERRCODE_SYNTAX_ERROR),
00184 errmsg("conflicting or redundant options")));
00185 dcanlogin = defel;
00186 }
00187 else if (strcmp(defel->defname, "isreplication") == 0)
00188 {
00189 if (disreplication)
00190 ereport(ERROR,
00191 (errcode(ERRCODE_SYNTAX_ERROR),
00192 errmsg("conflicting or redundant options")));
00193 disreplication = defel;
00194 }
00195 else if (strcmp(defel->defname, "connectionlimit") == 0)
00196 {
00197 if (dconnlimit)
00198 ereport(ERROR,
00199 (errcode(ERRCODE_SYNTAX_ERROR),
00200 errmsg("conflicting or redundant options")));
00201 dconnlimit = defel;
00202 }
00203 else if (strcmp(defel->defname, "addroleto") == 0)
00204 {
00205 if (daddroleto)
00206 ereport(ERROR,
00207 (errcode(ERRCODE_SYNTAX_ERROR),
00208 errmsg("conflicting or redundant options")));
00209 daddroleto = defel;
00210 }
00211 else if (strcmp(defel->defname, "rolemembers") == 0)
00212 {
00213 if (drolemembers)
00214 ereport(ERROR,
00215 (errcode(ERRCODE_SYNTAX_ERROR),
00216 errmsg("conflicting or redundant options")));
00217 drolemembers = defel;
00218 }
00219 else if (strcmp(defel->defname, "adminmembers") == 0)
00220 {
00221 if (dadminmembers)
00222 ereport(ERROR,
00223 (errcode(ERRCODE_SYNTAX_ERROR),
00224 errmsg("conflicting or redundant options")));
00225 dadminmembers = defel;
00226 }
00227 else if (strcmp(defel->defname, "validUntil") == 0)
00228 {
00229 if (dvalidUntil)
00230 ereport(ERROR,
00231 (errcode(ERRCODE_SYNTAX_ERROR),
00232 errmsg("conflicting or redundant options")));
00233 dvalidUntil = defel;
00234 }
00235 else
00236 elog(ERROR, "option \"%s\" not recognized",
00237 defel->defname);
00238 }
00239
00240 if (dpassword && dpassword->arg)
00241 password = strVal(dpassword->arg);
00242 if (dissuper)
00243 issuper = intVal(dissuper->arg) != 0;
00244 if (dinherit)
00245 inherit = intVal(dinherit->arg) != 0;
00246 if (dcreaterole)
00247 createrole = intVal(dcreaterole->arg) != 0;
00248 if (dcreatedb)
00249 createdb = intVal(dcreatedb->arg) != 0;
00250 if (dcanlogin)
00251 canlogin = intVal(dcanlogin->arg) != 0;
00252 if (disreplication)
00253 isreplication = intVal(disreplication->arg) != 0;
00254 if (dconnlimit)
00255 {
00256 connlimit = intVal(dconnlimit->arg);
00257 if (connlimit < -1)
00258 ereport(ERROR,
00259 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00260 errmsg("invalid connection limit: %d", connlimit)));
00261 }
00262 if (daddroleto)
00263 addroleto = (List *) daddroleto->arg;
00264 if (drolemembers)
00265 rolemembers = (List *) drolemembers->arg;
00266 if (dadminmembers)
00267 adminmembers = (List *) dadminmembers->arg;
00268 if (dvalidUntil)
00269 validUntil = strVal(dvalidUntil->arg);
00270
00271
00272 if (issuper)
00273 {
00274 if (!superuser())
00275 ereport(ERROR,
00276 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00277 errmsg("must be superuser to create superusers")));
00278 }
00279 else if (isreplication)
00280 {
00281 if (!superuser())
00282 ereport(ERROR,
00283 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00284 errmsg("must be superuser to create replication users")));
00285 }
00286 else
00287 {
00288 if (!have_createrole_privilege())
00289 ereport(ERROR,
00290 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00291 errmsg("permission denied to create role")));
00292 }
00293
00294 if (strcmp(stmt->role, "public") == 0 ||
00295 strcmp(stmt->role, "none") == 0)
00296 ereport(ERROR,
00297 (errcode(ERRCODE_RESERVED_NAME),
00298 errmsg("role name \"%s\" is reserved",
00299 stmt->role)));
00300
00301
00302
00303
00304
00305 pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);
00306 pg_authid_dsc = RelationGetDescr(pg_authid_rel);
00307
00308 if (OidIsValid(get_role_oid(stmt->role, true)))
00309 ereport(ERROR,
00310 (errcode(ERRCODE_DUPLICATE_OBJECT),
00311 errmsg("role \"%s\" already exists",
00312 stmt->role)));
00313
00314
00315 if (validUntil)
00316 {
00317 validUntil_datum = DirectFunctionCall3(timestamptz_in,
00318 CStringGetDatum(validUntil),
00319 ObjectIdGetDatum(InvalidOid),
00320 Int32GetDatum(-1));
00321 validUntil_null = false;
00322 }
00323 else
00324 {
00325 validUntil_datum = (Datum) 0;
00326 validUntil_null = true;
00327 }
00328
00329
00330
00331
00332 if (check_password_hook && password)
00333 (*check_password_hook) (stmt->role,
00334 password,
00335 isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
00336 validUntil_datum,
00337 validUntil_null);
00338
00339
00340
00341
00342 MemSet(new_record, 0, sizeof(new_record));
00343 MemSet(new_record_nulls, false, sizeof(new_record_nulls));
00344
00345 new_record[Anum_pg_authid_rolname - 1] =
00346 DirectFunctionCall1(namein, CStringGetDatum(stmt->role));
00347
00348 new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
00349 new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
00350 new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
00351 new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
00352
00353 new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper);
00354 new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
00355 new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
00356 new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
00357
00358 if (password)
00359 {
00360 if (!encrypt_password || isMD5(password))
00361 new_record[Anum_pg_authid_rolpassword - 1] =
00362 CStringGetTextDatum(password);
00363 else
00364 {
00365 if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role),
00366 encrypted_password))
00367 elog(ERROR, "password encryption failed");
00368 new_record[Anum_pg_authid_rolpassword - 1] =
00369 CStringGetTextDatum(encrypted_password);
00370 }
00371 }
00372 else
00373 new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
00374
00375 new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
00376 new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
00377
00378 tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
00379
00380
00381
00382
00383
00384 if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_authid_oid))
00385 {
00386 HeapTupleSetOid(tuple, binary_upgrade_next_pg_authid_oid);
00387 binary_upgrade_next_pg_authid_oid = InvalidOid;
00388 }
00389
00390
00391
00392
00393 roleid = simple_heap_insert(pg_authid_rel, tuple);
00394 CatalogUpdateIndexes(pg_authid_rel, tuple);
00395
00396
00397
00398
00399
00400 if (addroleto || adminmembers || rolemembers)
00401 CommandCounterIncrement();
00402
00403
00404
00405
00406 foreach(item, addroleto)
00407 {
00408 char *oldrolename = strVal(lfirst(item));
00409 Oid oldroleid = get_role_oid(oldrolename, false);
00410
00411 AddRoleMems(oldrolename, oldroleid,
00412 list_make1(makeString(stmt->role)),
00413 list_make1_oid(roleid),
00414 GetUserId(), false);
00415 }
00416
00417
00418
00419
00420
00421 AddRoleMems(stmt->role, roleid,
00422 adminmembers, roleNamesToIds(adminmembers),
00423 GetUserId(), true);
00424 AddRoleMems(stmt->role, roleid,
00425 rolemembers, roleNamesToIds(rolemembers),
00426 GetUserId(), false);
00427
00428
00429 InvokeObjectPostCreateHook(AuthIdRelationId, roleid, 0);
00430
00431
00432
00433
00434 heap_close(pg_authid_rel, NoLock);
00435
00436 return roleid;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 Oid
00448 AlterRole(AlterRoleStmt *stmt)
00449 {
00450 Datum new_record[Natts_pg_authid];
00451 bool new_record_nulls[Natts_pg_authid];
00452 bool new_record_repl[Natts_pg_authid];
00453 Relation pg_authid_rel;
00454 TupleDesc pg_authid_dsc;
00455 HeapTuple tuple,
00456 new_tuple;
00457 ListCell *option;
00458 char *password = NULL;
00459 bool encrypt_password = Password_encryption;
00460 char encrypted_password[MD5_PASSWD_LEN + 1];
00461 int issuper = -1;
00462 int inherit = -1;
00463 int createrole = -1;
00464 int createdb = -1;
00465 int canlogin = -1;
00466 int isreplication = -1;
00467 int connlimit = -1;
00468 List *rolemembers = NIL;
00469 char *validUntil = NULL;
00470 Datum validUntil_datum;
00471 bool validUntil_null;
00472 DefElem *dpassword = NULL;
00473 DefElem *dissuper = NULL;
00474 DefElem *dinherit = NULL;
00475 DefElem *dcreaterole = NULL;
00476 DefElem *dcreatedb = NULL;
00477 DefElem *dcanlogin = NULL;
00478 DefElem *disreplication = NULL;
00479 DefElem *dconnlimit = NULL;
00480 DefElem *drolemembers = NULL;
00481 DefElem *dvalidUntil = NULL;
00482 Oid roleid;
00483
00484
00485 foreach(option, stmt->options)
00486 {
00487 DefElem *defel = (DefElem *) lfirst(option);
00488
00489 if (strcmp(defel->defname, "password") == 0 ||
00490 strcmp(defel->defname, "encryptedPassword") == 0 ||
00491 strcmp(defel->defname, "unencryptedPassword") == 0)
00492 {
00493 if (dpassword)
00494 ereport(ERROR,
00495 (errcode(ERRCODE_SYNTAX_ERROR),
00496 errmsg("conflicting or redundant options")));
00497 dpassword = defel;
00498 if (strcmp(defel->defname, "encryptedPassword") == 0)
00499 encrypt_password = true;
00500 else if (strcmp(defel->defname, "unencryptedPassword") == 0)
00501 encrypt_password = false;
00502 }
00503 else if (strcmp(defel->defname, "superuser") == 0)
00504 {
00505 if (dissuper)
00506 ereport(ERROR,
00507 (errcode(ERRCODE_SYNTAX_ERROR),
00508 errmsg("conflicting or redundant options")));
00509 dissuper = defel;
00510 }
00511 else if (strcmp(defel->defname, "inherit") == 0)
00512 {
00513 if (dinherit)
00514 ereport(ERROR,
00515 (errcode(ERRCODE_SYNTAX_ERROR),
00516 errmsg("conflicting or redundant options")));
00517 dinherit = defel;
00518 }
00519 else if (strcmp(defel->defname, "createrole") == 0)
00520 {
00521 if (dcreaterole)
00522 ereport(ERROR,
00523 (errcode(ERRCODE_SYNTAX_ERROR),
00524 errmsg("conflicting or redundant options")));
00525 dcreaterole = defel;
00526 }
00527 else if (strcmp(defel->defname, "createdb") == 0)
00528 {
00529 if (dcreatedb)
00530 ereport(ERROR,
00531 (errcode(ERRCODE_SYNTAX_ERROR),
00532 errmsg("conflicting or redundant options")));
00533 dcreatedb = defel;
00534 }
00535 else if (strcmp(defel->defname, "canlogin") == 0)
00536 {
00537 if (dcanlogin)
00538 ereport(ERROR,
00539 (errcode(ERRCODE_SYNTAX_ERROR),
00540 errmsg("conflicting or redundant options")));
00541 dcanlogin = defel;
00542 }
00543 else if (strcmp(defel->defname, "isreplication") == 0)
00544 {
00545 if (disreplication)
00546 ereport(ERROR,
00547 (errcode(ERRCODE_SYNTAX_ERROR),
00548 errmsg("conflicting or redundant options")));
00549 disreplication = defel;
00550 }
00551 else if (strcmp(defel->defname, "connectionlimit") == 0)
00552 {
00553 if (dconnlimit)
00554 ereport(ERROR,
00555 (errcode(ERRCODE_SYNTAX_ERROR),
00556 errmsg("conflicting or redundant options")));
00557 dconnlimit = defel;
00558 }
00559 else if (strcmp(defel->defname, "rolemembers") == 0 &&
00560 stmt->action != 0)
00561 {
00562 if (drolemembers)
00563 ereport(ERROR,
00564 (errcode(ERRCODE_SYNTAX_ERROR),
00565 errmsg("conflicting or redundant options")));
00566 drolemembers = defel;
00567 }
00568 else if (strcmp(defel->defname, "validUntil") == 0)
00569 {
00570 if (dvalidUntil)
00571 ereport(ERROR,
00572 (errcode(ERRCODE_SYNTAX_ERROR),
00573 errmsg("conflicting or redundant options")));
00574 dvalidUntil = defel;
00575 }
00576 else
00577 elog(ERROR, "option \"%s\" not recognized",
00578 defel->defname);
00579 }
00580
00581 if (dpassword && dpassword->arg)
00582 password = strVal(dpassword->arg);
00583 if (dissuper)
00584 issuper = intVal(dissuper->arg);
00585 if (dinherit)
00586 inherit = intVal(dinherit->arg);
00587 if (dcreaterole)
00588 createrole = intVal(dcreaterole->arg);
00589 if (dcreatedb)
00590 createdb = intVal(dcreatedb->arg);
00591 if (dcanlogin)
00592 canlogin = intVal(dcanlogin->arg);
00593 if (disreplication)
00594 isreplication = intVal(disreplication->arg);
00595 if (dconnlimit)
00596 {
00597 connlimit = intVal(dconnlimit->arg);
00598 if (connlimit < -1)
00599 ereport(ERROR,
00600 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00601 errmsg("invalid connection limit: %d", connlimit)));
00602 }
00603 if (drolemembers)
00604 rolemembers = (List *) drolemembers->arg;
00605 if (dvalidUntil)
00606 validUntil = strVal(dvalidUntil->arg);
00607
00608
00609
00610
00611 pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);
00612 pg_authid_dsc = RelationGetDescr(pg_authid_rel);
00613
00614 tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
00615 if (!HeapTupleIsValid(tuple))
00616 ereport(ERROR,
00617 (errcode(ERRCODE_UNDEFINED_OBJECT),
00618 errmsg("role \"%s\" does not exist", stmt->role)));
00619
00620 roleid = HeapTupleGetOid(tuple);
00621
00622
00623
00624
00625
00626 if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper || issuper >= 0)
00627 {
00628 if (!superuser())
00629 ereport(ERROR,
00630 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00631 errmsg("must be superuser to alter superusers")));
00632 }
00633 else if (((Form_pg_authid) GETSTRUCT(tuple))->rolreplication || isreplication >= 0)
00634 {
00635 if (!superuser())
00636 ereport(ERROR,
00637 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00638 errmsg("must be superuser to alter replication users")));
00639 }
00640 else if (!have_createrole_privilege())
00641 {
00642 if (!(inherit < 0 &&
00643 createrole < 0 &&
00644 createdb < 0 &&
00645 canlogin < 0 &&
00646 isreplication < 0 &&
00647 !dconnlimit &&
00648 !rolemembers &&
00649 !validUntil &&
00650 dpassword &&
00651 roleid == GetUserId()))
00652 ereport(ERROR,
00653 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00654 errmsg("permission denied")));
00655 }
00656
00657
00658 if (validUntil)
00659 {
00660 validUntil_datum = DirectFunctionCall3(timestamptz_in,
00661 CStringGetDatum(validUntil),
00662 ObjectIdGetDatum(InvalidOid),
00663 Int32GetDatum(-1));
00664 validUntil_null = false;
00665 }
00666 else
00667 {
00668
00669 validUntil_datum = SysCacheGetAttr(AUTHNAME, tuple,
00670 Anum_pg_authid_rolvaliduntil,
00671 &validUntil_null);
00672 }
00673
00674
00675
00676
00677 if (check_password_hook && password)
00678 (*check_password_hook) (stmt->role,
00679 password,
00680 isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
00681 validUntil_datum,
00682 validUntil_null);
00683
00684
00685
00686
00687 MemSet(new_record, 0, sizeof(new_record));
00688 MemSet(new_record_nulls, false, sizeof(new_record_nulls));
00689 MemSet(new_record_repl, false, sizeof(new_record_repl));
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 if (issuper >= 0)
00700 {
00701 new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper > 0);
00702 new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
00703
00704 new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper > 0);
00705 new_record_repl[Anum_pg_authid_rolcatupdate - 1] = true;
00706 }
00707
00708 if (inherit >= 0)
00709 {
00710 new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit > 0);
00711 new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
00712 }
00713
00714 if (createrole >= 0)
00715 {
00716 new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole > 0);
00717 new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
00718 }
00719
00720 if (createdb >= 0)
00721 {
00722 new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb > 0);
00723 new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
00724 }
00725
00726 if (canlogin >= 0)
00727 {
00728 new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin > 0);
00729 new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
00730 }
00731
00732 if (isreplication >= 0)
00733 {
00734 new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication > 0);
00735 new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
00736 }
00737
00738 if (dconnlimit)
00739 {
00740 new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
00741 new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true;
00742 }
00743
00744
00745 if (password)
00746 {
00747 if (!encrypt_password || isMD5(password))
00748 new_record[Anum_pg_authid_rolpassword - 1] =
00749 CStringGetTextDatum(password);
00750 else
00751 {
00752 if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role),
00753 encrypted_password))
00754 elog(ERROR, "password encryption failed");
00755 new_record[Anum_pg_authid_rolpassword - 1] =
00756 CStringGetTextDatum(encrypted_password);
00757 }
00758 new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
00759 }
00760
00761
00762 if (dpassword && dpassword->arg == NULL)
00763 {
00764 new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
00765 new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
00766 }
00767
00768
00769 new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
00770 new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
00771 new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true;
00772
00773 new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record,
00774 new_record_nulls, new_record_repl);
00775 simple_heap_update(pg_authid_rel, &tuple->t_self, new_tuple);
00776
00777
00778 CatalogUpdateIndexes(pg_authid_rel, new_tuple);
00779
00780 InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
00781
00782 ReleaseSysCache(tuple);
00783 heap_freetuple(new_tuple);
00784
00785
00786
00787
00788
00789 if (rolemembers)
00790 CommandCounterIncrement();
00791
00792 if (stmt->action == +1)
00793 AddRoleMems(stmt->role, roleid,
00794 rolemembers, roleNamesToIds(rolemembers),
00795 GetUserId(), false);
00796 else if (stmt->action == -1)
00797 DelRoleMems(stmt->role, roleid,
00798 rolemembers, roleNamesToIds(rolemembers),
00799 false);
00800
00801
00802
00803
00804 heap_close(pg_authid_rel, NoLock);
00805
00806 return roleid;
00807 }
00808
00809
00810
00811
00812
00813 Oid
00814 AlterRoleSet(AlterRoleSetStmt *stmt)
00815 {
00816 HeapTuple roletuple;
00817 Oid databaseid = InvalidOid;
00818 Oid roleid = InvalidOid;
00819
00820 if (stmt->role)
00821 {
00822 roletuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
00823
00824 if (!HeapTupleIsValid(roletuple))
00825 ereport(ERROR,
00826 (errcode(ERRCODE_UNDEFINED_OBJECT),
00827 errmsg("role \"%s\" does not exist", stmt->role)));
00828
00829 roleid = HeapTupleGetOid(roletuple);
00830
00831
00832
00833
00834
00835 shdepLockAndCheckObject(AuthIdRelationId, HeapTupleGetOid(roletuple));
00836
00837
00838
00839
00840
00841 if (((Form_pg_authid) GETSTRUCT(roletuple))->rolsuper)
00842 {
00843 if (!superuser())
00844 ereport(ERROR,
00845 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00846 errmsg("must be superuser to alter superusers")));
00847 }
00848 else
00849 {
00850 if (!have_createrole_privilege() &&
00851 HeapTupleGetOid(roletuple) != GetUserId())
00852 ereport(ERROR,
00853 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00854 errmsg("permission denied")));
00855 }
00856
00857 ReleaseSysCache(roletuple);
00858 }
00859
00860
00861 if (stmt->database != NULL)
00862 {
00863 databaseid = get_database_oid(stmt->database, false);
00864 shdepLockAndCheckObject(DatabaseRelationId, databaseid);
00865
00866 if (!stmt->role)
00867 {
00868
00869
00870
00871
00872 if (!pg_database_ownercheck(databaseid, GetUserId()))
00873 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
00874 stmt->database);
00875 }
00876 }
00877
00878 if (!stmt->role && !stmt->database)
00879 {
00880
00881 if (!superuser())
00882 ereport(ERROR,
00883 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00884 errmsg("must be superuser to alter settings globally")));
00885 }
00886
00887 AlterSetting(databaseid, roleid, stmt->setstmt);
00888
00889 return roleid;
00890 }
00891
00892
00893
00894
00895
00896 void
00897 DropRole(DropRoleStmt *stmt)
00898 {
00899 Relation pg_authid_rel,
00900 pg_auth_members_rel;
00901 ListCell *item;
00902
00903 if (!have_createrole_privilege())
00904 ereport(ERROR,
00905 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00906 errmsg("permission denied to drop role")));
00907
00908
00909
00910
00911
00912 pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);
00913 pg_auth_members_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
00914
00915 foreach(item, stmt->roles)
00916 {
00917 const char *role = strVal(lfirst(item));
00918 HeapTuple tuple,
00919 tmp_tuple;
00920 ScanKeyData scankey;
00921 char *detail;
00922 char *detail_log;
00923 SysScanDesc sscan;
00924 Oid roleid;
00925
00926 tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
00927 if (!HeapTupleIsValid(tuple))
00928 {
00929 if (!stmt->missing_ok)
00930 {
00931 ereport(ERROR,
00932 (errcode(ERRCODE_UNDEFINED_OBJECT),
00933 errmsg("role \"%s\" does not exist", role)));
00934 }
00935 else
00936 {
00937 ereport(NOTICE,
00938 (errmsg("role \"%s\" does not exist, skipping",
00939 role)));
00940 }
00941
00942 continue;
00943 }
00944
00945 roleid = HeapTupleGetOid(tuple);
00946
00947 if (roleid == GetUserId())
00948 ereport(ERROR,
00949 (errcode(ERRCODE_OBJECT_IN_USE),
00950 errmsg("current user cannot be dropped")));
00951 if (roleid == GetOuterUserId())
00952 ereport(ERROR,
00953 (errcode(ERRCODE_OBJECT_IN_USE),
00954 errmsg("current user cannot be dropped")));
00955 if (roleid == GetSessionUserId())
00956 ereport(ERROR,
00957 (errcode(ERRCODE_OBJECT_IN_USE),
00958 errmsg("session user cannot be dropped")));
00959
00960
00961
00962
00963
00964
00965 if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper &&
00966 !superuser())
00967 ereport(ERROR,
00968 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00969 errmsg("must be superuser to drop superusers")));
00970
00971
00972 InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
00973
00974
00975
00976
00977
00978 LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock);
00979
00980
00981 if (checkSharedDependencies(AuthIdRelationId, roleid,
00982 &detail, &detail_log))
00983 ereport(ERROR,
00984 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00985 errmsg("role \"%s\" cannot be dropped because some objects depend on it",
00986 role),
00987 errdetail_internal("%s", detail),
00988 errdetail_log("%s", detail_log)));
00989
00990
00991
00992
00993 simple_heap_delete(pg_authid_rel, &tuple->t_self);
00994
00995 ReleaseSysCache(tuple);
00996
00997
00998
00999
01000
01001
01002
01003 ScanKeyInit(&scankey,
01004 Anum_pg_auth_members_roleid,
01005 BTEqualStrategyNumber, F_OIDEQ,
01006 ObjectIdGetDatum(roleid));
01007
01008 sscan = systable_beginscan(pg_auth_members_rel, AuthMemRoleMemIndexId,
01009 true, SnapshotNow, 1, &scankey);
01010
01011 while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
01012 {
01013 simple_heap_delete(pg_auth_members_rel, &tmp_tuple->t_self);
01014 }
01015
01016 systable_endscan(sscan);
01017
01018 ScanKeyInit(&scankey,
01019 Anum_pg_auth_members_member,
01020 BTEqualStrategyNumber, F_OIDEQ,
01021 ObjectIdGetDatum(roleid));
01022
01023 sscan = systable_beginscan(pg_auth_members_rel, AuthMemMemRoleIndexId,
01024 true, SnapshotNow, 1, &scankey);
01025
01026 while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
01027 {
01028 simple_heap_delete(pg_auth_members_rel, &tmp_tuple->t_self);
01029 }
01030
01031 systable_endscan(sscan);
01032
01033
01034
01035
01036 DeleteSharedComments(roleid, AuthIdRelationId);
01037 DeleteSharedSecurityLabel(roleid, AuthIdRelationId);
01038
01039
01040
01041
01042 DropSetting(InvalidOid, roleid);
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 CommandCounterIncrement();
01054 }
01055
01056
01057
01058
01059 heap_close(pg_auth_members_rel, NoLock);
01060 heap_close(pg_authid_rel, NoLock);
01061 }
01062
01063
01064
01065
01066 Oid
01067 RenameRole(const char *oldname, const char *newname)
01068 {
01069 HeapTuple oldtuple,
01070 newtuple;
01071 TupleDesc dsc;
01072 Relation rel;
01073 Datum datum;
01074 bool isnull;
01075 Datum repl_val[Natts_pg_authid];
01076 bool repl_null[Natts_pg_authid];
01077 bool repl_repl[Natts_pg_authid];
01078 int i;
01079 Oid roleid;
01080
01081 rel = heap_open(AuthIdRelationId, RowExclusiveLock);
01082 dsc = RelationGetDescr(rel);
01083
01084 oldtuple = SearchSysCache1(AUTHNAME, CStringGetDatum(oldname));
01085 if (!HeapTupleIsValid(oldtuple))
01086 ereport(ERROR,
01087 (errcode(ERRCODE_UNDEFINED_OBJECT),
01088 errmsg("role \"%s\" does not exist", oldname)));
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098 roleid = HeapTupleGetOid(oldtuple);
01099
01100 if (roleid == GetSessionUserId())
01101 ereport(ERROR,
01102 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01103 errmsg("session user cannot be renamed")));
01104 if (roleid == GetOuterUserId())
01105 ereport(ERROR,
01106 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01107 errmsg("current user cannot be renamed")));
01108
01109
01110 if (SearchSysCacheExists1(AUTHNAME, CStringGetDatum(newname)))
01111 ereport(ERROR,
01112 (errcode(ERRCODE_DUPLICATE_OBJECT),
01113 errmsg("role \"%s\" already exists", newname)));
01114
01115 if (strcmp(newname, "public") == 0 ||
01116 strcmp(newname, "none") == 0)
01117 ereport(ERROR,
01118 (errcode(ERRCODE_RESERVED_NAME),
01119 errmsg("role name \"%s\" is reserved",
01120 newname)));
01121
01122
01123
01124
01125 if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)
01126 {
01127 if (!superuser())
01128 ereport(ERROR,
01129 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01130 errmsg("must be superuser to rename superusers")));
01131 }
01132 else
01133 {
01134 if (!have_createrole_privilege())
01135 ereport(ERROR,
01136 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01137 errmsg("permission denied to rename role")));
01138 }
01139
01140
01141 for (i = 0; i < Natts_pg_authid; i++)
01142 repl_repl[i] = false;
01143
01144 repl_repl[Anum_pg_authid_rolname - 1] = true;
01145 repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
01146 CStringGetDatum(newname));
01147 repl_null[Anum_pg_authid_rolname - 1] = false;
01148
01149 datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
01150
01151 if (!isnull && isMD5(TextDatumGetCString(datum)))
01152 {
01153
01154 repl_repl[Anum_pg_authid_rolpassword - 1] = true;
01155 repl_null[Anum_pg_authid_rolpassword - 1] = true;
01156
01157 ereport(NOTICE,
01158 (errmsg("MD5 password cleared because of role rename")));
01159 }
01160
01161 newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
01162 simple_heap_update(rel, &oldtuple->t_self, newtuple);
01163
01164 CatalogUpdateIndexes(rel, newtuple);
01165
01166 InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
01167
01168 ReleaseSysCache(oldtuple);
01169
01170
01171
01172
01173 heap_close(rel, NoLock);
01174
01175 return roleid;
01176 }
01177
01178
01179
01180
01181
01182
01183 void
01184 GrantRole(GrantRoleStmt *stmt)
01185 {
01186 Relation pg_authid_rel;
01187 Oid grantor;
01188 List *grantee_ids;
01189 ListCell *item;
01190
01191 if (stmt->grantor)
01192 grantor = get_role_oid(stmt->grantor, false);
01193 else
01194 grantor = GetUserId();
01195
01196 grantee_ids = roleNamesToIds(stmt->grantee_roles);
01197
01198
01199 pg_authid_rel = heap_open(AuthIdRelationId, AccessShareLock);
01200
01201
01202
01203
01204
01205
01206
01207
01208 foreach(item, stmt->granted_roles)
01209 {
01210 AccessPriv *priv = (AccessPriv *) lfirst(item);
01211 char *rolename = priv->priv_name;
01212 Oid roleid;
01213
01214
01215 if (rolename == NULL || priv->cols != NIL)
01216 ereport(ERROR,
01217 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
01218 errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
01219
01220 roleid = get_role_oid(rolename, false);
01221 if (stmt->is_grant)
01222 AddRoleMems(rolename, roleid,
01223 stmt->grantee_roles, grantee_ids,
01224 grantor, stmt->admin_opt);
01225 else
01226 DelRoleMems(rolename, roleid,
01227 stmt->grantee_roles, grantee_ids,
01228 stmt->admin_opt);
01229 }
01230
01231
01232
01233
01234 heap_close(pg_authid_rel, NoLock);
01235 }
01236
01237
01238
01239
01240
01241
01242 void
01243 DropOwnedObjects(DropOwnedStmt *stmt)
01244 {
01245 List *role_ids = roleNamesToIds(stmt->roles);
01246 ListCell *cell;
01247
01248
01249 foreach(cell, role_ids)
01250 {
01251 Oid roleid = lfirst_oid(cell);
01252
01253 if (!has_privs_of_role(GetUserId(), roleid))
01254 ereport(ERROR,
01255 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01256 errmsg("permission denied to drop objects")));
01257 }
01258
01259
01260 shdepDropOwned(role_ids, stmt->behavior);
01261 }
01262
01263
01264
01265
01266
01267
01268 void
01269 ReassignOwnedObjects(ReassignOwnedStmt *stmt)
01270 {
01271 List *role_ids = roleNamesToIds(stmt->roles);
01272 ListCell *cell;
01273 Oid newrole;
01274
01275
01276 foreach(cell, role_ids)
01277 {
01278 Oid roleid = lfirst_oid(cell);
01279
01280 if (!has_privs_of_role(GetUserId(), roleid))
01281 ereport(ERROR,
01282 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01283 errmsg("permission denied to reassign objects")));
01284 }
01285
01286
01287 newrole = get_role_oid(stmt->newrole, false);
01288
01289 if (!has_privs_of_role(GetUserId(), newrole))
01290 ereport(ERROR,
01291 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01292 errmsg("permission denied to reassign objects")));
01293
01294
01295 shdepReassignOwned(role_ids, newrole);
01296 }
01297
01298
01299
01300
01301
01302
01303
01304 static List *
01305 roleNamesToIds(List *memberNames)
01306 {
01307 List *result = NIL;
01308 ListCell *l;
01309
01310 foreach(l, memberNames)
01311 {
01312 char *rolename = strVal(lfirst(l));
01313 Oid roleid = get_role_oid(rolename, false);
01314
01315 result = lappend_oid(result, roleid);
01316 }
01317 return result;
01318 }
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 static void
01333 AddRoleMems(const char *rolename, Oid roleid,
01334 List *memberNames, List *memberIds,
01335 Oid grantorId, bool admin_opt)
01336 {
01337 Relation pg_authmem_rel;
01338 TupleDesc pg_authmem_dsc;
01339 ListCell *nameitem;
01340 ListCell *iditem;
01341
01342 Assert(list_length(memberNames) == list_length(memberIds));
01343
01344
01345 if (!memberIds)
01346 return;
01347
01348
01349
01350
01351
01352 if (superuser_arg(roleid))
01353 {
01354 if (!superuser())
01355 ereport(ERROR,
01356 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01357 errmsg("must be superuser to alter superusers")));
01358 }
01359 else
01360 {
01361 if (!have_createrole_privilege() &&
01362 !is_admin_of_role(grantorId, roleid))
01363 ereport(ERROR,
01364 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01365 errmsg("must have admin option on role \"%s\"",
01366 rolename)));
01367 }
01368
01369
01370 if (grantorId != GetUserId() && !superuser())
01371 ereport(ERROR,
01372 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01373 errmsg("must be superuser to set grantor")));
01374
01375 pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
01376 pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
01377
01378 forboth(nameitem, memberNames, iditem, memberIds)
01379 {
01380 const char *membername = strVal(lfirst(nameitem));
01381 Oid memberid = lfirst_oid(iditem);
01382 HeapTuple authmem_tuple;
01383 HeapTuple tuple;
01384 Datum new_record[Natts_pg_auth_members];
01385 bool new_record_nulls[Natts_pg_auth_members];
01386 bool new_record_repl[Natts_pg_auth_members];
01387
01388
01389
01390
01391
01392
01393
01394
01395 if (is_member_of_role_nosuper(roleid, memberid))
01396 ereport(ERROR,
01397 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
01398 (errmsg("role \"%s\" is a member of role \"%s\"",
01399 rolename, membername))));
01400
01401
01402
01403
01404
01405 authmem_tuple = SearchSysCache2(AUTHMEMROLEMEM,
01406 ObjectIdGetDatum(roleid),
01407 ObjectIdGetDatum(memberid));
01408 if (HeapTupleIsValid(authmem_tuple) &&
01409 (!admin_opt ||
01410 ((Form_pg_auth_members) GETSTRUCT(authmem_tuple))->admin_option))
01411 {
01412 ereport(NOTICE,
01413 (errmsg("role \"%s\" is already a member of role \"%s\"",
01414 membername, rolename)));
01415 ReleaseSysCache(authmem_tuple);
01416 continue;
01417 }
01418
01419
01420 MemSet(new_record, 0, sizeof(new_record));
01421 MemSet(new_record_nulls, false, sizeof(new_record_nulls));
01422 MemSet(new_record_repl, false, sizeof(new_record_repl));
01423
01424 new_record[Anum_pg_auth_members_roleid - 1] = ObjectIdGetDatum(roleid);
01425 new_record[Anum_pg_auth_members_member - 1] = ObjectIdGetDatum(memberid);
01426 new_record[Anum_pg_auth_members_grantor - 1] = ObjectIdGetDatum(grantorId);
01427 new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(admin_opt);
01428
01429 if (HeapTupleIsValid(authmem_tuple))
01430 {
01431 new_record_repl[Anum_pg_auth_members_grantor - 1] = true;
01432 new_record_repl[Anum_pg_auth_members_admin_option - 1] = true;
01433 tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
01434 new_record,
01435 new_record_nulls, new_record_repl);
01436 simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);
01437 CatalogUpdateIndexes(pg_authmem_rel, tuple);
01438 ReleaseSysCache(authmem_tuple);
01439 }
01440 else
01441 {
01442 tuple = heap_form_tuple(pg_authmem_dsc,
01443 new_record, new_record_nulls);
01444 simple_heap_insert(pg_authmem_rel, tuple);
01445 CatalogUpdateIndexes(pg_authmem_rel, tuple);
01446 }
01447
01448
01449 CommandCounterIncrement();
01450 }
01451
01452
01453
01454
01455 heap_close(pg_authmem_rel, NoLock);
01456 }
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469 static void
01470 DelRoleMems(const char *rolename, Oid roleid,
01471 List *memberNames, List *memberIds,
01472 bool admin_opt)
01473 {
01474 Relation pg_authmem_rel;
01475 TupleDesc pg_authmem_dsc;
01476 ListCell *nameitem;
01477 ListCell *iditem;
01478
01479 Assert(list_length(memberNames) == list_length(memberIds));
01480
01481
01482 if (!memberIds)
01483 return;
01484
01485
01486
01487
01488
01489 if (superuser_arg(roleid))
01490 {
01491 if (!superuser())
01492 ereport(ERROR,
01493 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01494 errmsg("must be superuser to alter superusers")));
01495 }
01496 else
01497 {
01498 if (!have_createrole_privilege() &&
01499 !is_admin_of_role(GetUserId(), roleid))
01500 ereport(ERROR,
01501 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01502 errmsg("must have admin option on role \"%s\"",
01503 rolename)));
01504 }
01505
01506 pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
01507 pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
01508
01509 forboth(nameitem, memberNames, iditem, memberIds)
01510 {
01511 const char *membername = strVal(lfirst(nameitem));
01512 Oid memberid = lfirst_oid(iditem);
01513 HeapTuple authmem_tuple;
01514
01515
01516
01517
01518 authmem_tuple = SearchSysCache2(AUTHMEMROLEMEM,
01519 ObjectIdGetDatum(roleid),
01520 ObjectIdGetDatum(memberid));
01521 if (!HeapTupleIsValid(authmem_tuple))
01522 {
01523 ereport(WARNING,
01524 (errmsg("role \"%s\" is not a member of role \"%s\"",
01525 membername, rolename)));
01526 continue;
01527 }
01528
01529 if (!admin_opt)
01530 {
01531
01532 simple_heap_delete(pg_authmem_rel, &authmem_tuple->t_self);
01533 }
01534 else
01535 {
01536
01537 HeapTuple tuple;
01538 Datum new_record[Natts_pg_auth_members];
01539 bool new_record_nulls[Natts_pg_auth_members];
01540 bool new_record_repl[Natts_pg_auth_members];
01541
01542
01543 MemSet(new_record, 0, sizeof(new_record));
01544 MemSet(new_record_nulls, false, sizeof(new_record_nulls));
01545 MemSet(new_record_repl, false, sizeof(new_record_repl));
01546
01547 new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(false);
01548 new_record_repl[Anum_pg_auth_members_admin_option - 1] = true;
01549
01550 tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
01551 new_record,
01552 new_record_nulls, new_record_repl);
01553 simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);
01554 CatalogUpdateIndexes(pg_authmem_rel, tuple);
01555 }
01556
01557 ReleaseSysCache(authmem_tuple);
01558
01559
01560 CommandCounterIncrement();
01561 }
01562
01563
01564
01565
01566 heap_close(pg_authmem_rel, NoLock);
01567 }