~ubuntu-branches/ubuntu/natty/postgresql-8.4/natty-security

« back to all changes in this revision

Viewing changes to src/backend/commands/foreigncmds.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-11 16:59:35 UTC
  • mfrom: (5.1.1 karmic)
  • Revision ID: james.westby@ubuntu.com-20090711165935-jfwin6gfrxf0gfsi
Tags: 8.4.0-2
* debian/libpq-dev.install: Ship catalog/genbki.h. (Closes: #536139)
* debian/rules: Drop --enable-cassert for final release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 *
8
8
 *
9
9
 * IDENTIFICATION
10
 
 *        $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.7 2009/04/04 21:12:31 tgl Exp $
 
10
 *        $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.8 2009/06/11 14:48:55 momjian Exp $
11
11
 *
12
12
 *-------------------------------------------------------------------------
13
13
 */
47
47
static Datum
48
48
optionListToArray(List *options)
49
49
{
50
 
        ArrayBuildState    *astate = NULL;
51
 
        ListCell                   *cell;
 
50
        ArrayBuildState *astate = NULL;
 
51
        ListCell   *cell;
52
52
 
53
53
        foreach(cell, options)
54
54
        {
76
76
 
77
77
 
78
78
/*
79
 
 * Transform a list of DefElem into text array format.  This is substantially
 
79
 * Transform a list of DefElem into text array format.  This is substantially
80
80
 * the same thing as optionListToArray(), except we recognize SET/ADD/DROP
81
81
 * actions for modifying an existing list of options, which is passed in
82
82
 * Datum form as oldOptions.  Also, if fdwvalidator isn't InvalidOid
92
92
                                                List *options,
93
93
                                                Oid fdwvalidator)
94
94
{
95
 
        List     *resultOptions = untransformRelOptions(oldOptions);
96
 
        ListCell *optcell;
97
 
        Datum     result;
 
95
        List       *resultOptions = untransformRelOptions(oldOptions);
 
96
        ListCell   *optcell;
 
97
        Datum           result;
98
98
 
99
99
        foreach(optcell, options)
100
100
        {
101
 
                DefElem    *od = lfirst(optcell);
 
101
                DefElem    *od = lfirst(optcell);
102
102
                ListCell   *cell;
103
103
                ListCell   *prev = NULL;
104
104
 
105
105
                /*
106
 
                 * Find the element in resultOptions.  We need this for
107
 
                 * validation in all cases.  Also identify the previous element.
 
106
                 * Find the element in resultOptions.  We need this for validation in
 
107
                 * all cases.  Also identify the previous element.
108
108
                 */
109
 
                foreach (cell, resultOptions)
 
109
                foreach(cell, resultOptions)
110
110
                {
111
 
                        DefElem *def = lfirst(cell);
 
111
                        DefElem    *def = lfirst(cell);
112
112
 
113
113
                        if (strcmp(def->defname, od->defname) == 0)
114
114
                                break;
117
117
                }
118
118
 
119
119
                /*
120
 
                 * It is possible to perform multiple SET/DROP actions on the
121
 
                 * same option.  The standard permits this, as long as the
122
 
                 * options to be added are unique.  Note that an unspecified
123
 
                 * action is taken to be ADD.
 
120
                 * It is possible to perform multiple SET/DROP actions on the same
 
121
                 * option.      The standard permits this, as long as the options to be
 
122
                 * added are unique.  Note that an unspecified action is taken to be
 
123
                 * ADD.
124
124
                 */
125
125
                switch (od->defaction)
126
126
                {
174
174
static Oid
175
175
GetUserOidFromMapping(const char *username, bool missing_ok)
176
176
{
177
 
    if (!username)
178
 
        /* PUBLIC user mapping */
179
 
        return InvalidOid;
180
 
 
181
 
    if (strcmp(username, "current_user") == 0)
182
 
        /* map to the owner */
183
 
        return GetUserId();
184
 
 
185
 
    /* map to provided user */
186
 
    return missing_ok ? get_roleid(username) : get_roleid_checked(username);
 
177
        if (!username)
 
178
                /* PUBLIC user mapping */
 
179
                return InvalidOid;
 
180
 
 
181
        if (strcmp(username, "current_user") == 0)
 
182
                /* map to the owner */
 
183
                return GetUserId();
 
184
 
 
185
        /* map to provided user */
 
186
        return missing_ok ? get_roleid(username) : get_roleid_checked(username);
187
187
}
188
188
 
189
189
 
201
201
        Oid                     fdwId;
202
202
        Form_pg_foreign_data_wrapper form;
203
203
 
204
 
    /* Must be a superuser to change a FDW owner */
 
204
        /* Must be a superuser to change a FDW owner */
205
205
        if (!superuser())
206
206
                ereport(ERROR,
207
207
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
209
209
                                                name),
210
210
                                 errhint("Must be superuser to change owner of a foreign-data wrapper.")));
211
211
 
212
 
    /* New owner must also be a superuser */
 
212
        /* New owner must also be a superuser */
213
213
        if (!superuser_arg(newOwnerId))
214
214
                ereport(ERROR,
215
215
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
216
216
                                 errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
217
217
                                                name),
218
 
                                 errhint("The owner of a foreign-data wrapper must be a superuser.")));
 
218
                errhint("The owner of a foreign-data wrapper must be a superuser.")));
219
219
 
220
220
        rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
221
221
 
226
226
        if (!HeapTupleIsValid(tup))
227
227
                ereport(ERROR,
228
228
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
229
 
                                errmsg("foreign-data wrapper \"%s\" does not exist", name)));
 
229
                                 errmsg("foreign-data wrapper \"%s\" does not exist", name)));
230
230
 
231
231
        fdwId = HeapTupleGetOid(tup);
232
232
        form = (Form_pg_foreign_data_wrapper) GETSTRUCT(tup);
268
268
                                                         0, 0, 0);
269
269
 
270
270
        if (!HeapTupleIsValid(tup))
271
 
        ereport(ERROR,
272
 
                (errcode(ERRCODE_UNDEFINED_OBJECT),
273
 
                errmsg("server \"%s\" does not exist", name)));
 
271
                ereport(ERROR,
 
272
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
273
                                 errmsg("server \"%s\" does not exist", name)));
274
274
 
275
275
        srvId = HeapTupleGetOid(tup);
276
276
        form = (Form_pg_foreign_server) GETSTRUCT(tup);
334
334
void
335
335
CreateForeignDataWrapper(CreateFdwStmt *stmt)
336
336
{
337
 
        Relation                rel;
338
 
        Datum                   values[Natts_pg_foreign_data_wrapper];
339
 
        bool                    nulls[Natts_pg_foreign_data_wrapper];
340
 
        HeapTuple               tuple;
341
 
        Oid                             fdwId;
342
 
        Oid                             fdwvalidator;
343
 
        Datum                   fdwoptions;
344
 
        Oid                             ownerId;
 
337
        Relation        rel;
 
338
        Datum           values[Natts_pg_foreign_data_wrapper];
 
339
        bool            nulls[Natts_pg_foreign_data_wrapper];
 
340
        HeapTuple       tuple;
 
341
        Oid                     fdwId;
 
342
        Oid                     fdwvalidator;
 
343
        Datum           fdwoptions;
 
344
        Oid                     ownerId;
345
345
 
346
346
        /* Must be super user */
347
347
        if (!superuser())
348
348
                ereport(ERROR,
349
349
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
350
 
                                 errmsg("permission denied to create foreign-data wrapper \"%s\"",
351
 
                                                stmt->fdwname),
352
 
                                 errhint("Must be superuser to create a foreign-data wrapper.")));
 
350
                        errmsg("permission denied to create foreign-data wrapper \"%s\"",
 
351
                                   stmt->fdwname),
 
352
                        errhint("Must be superuser to create a foreign-data wrapper.")));
353
353
 
354
354
        /* For now the owner cannot be specified on create. Use effective user ID. */
355
355
        ownerId = GetUserId();
440
440
        if (!superuser())
441
441
                ereport(ERROR,
442
442
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
443
 
                                 errmsg("permission denied to alter foreign-data wrapper \"%s\"",
444
 
                                                stmt->fdwname),
445
 
                                 errhint("Must be superuser to alter a foreign-data wrapper.")));
 
443
                         errmsg("permission denied to alter foreign-data wrapper \"%s\"",
 
444
                                        stmt->fdwname),
 
445
                         errhint("Must be superuser to alter a foreign-data wrapper.")));
446
446
 
447
447
        tp = SearchSysCacheCopy(FOREIGNDATAWRAPPERNAME,
448
448
                                                        CStringGetDatum(stmt->fdwname),
451
451
        if (!HeapTupleIsValid(tp))
452
452
                ereport(ERROR,
453
453
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
454
 
                                errmsg("foreign-data wrapper \"%s\" does not exist", stmt->fdwname)));
 
454
                errmsg("foreign-data wrapper \"%s\" does not exist", stmt->fdwname)));
455
455
 
456
456
        fdwId = HeapTupleGetOid(tp);
457
457
 
467
467
 
468
468
                /*
469
469
                 * It could be that the options for the FDW, SERVER and USER MAPPING
470
 
                 * are no longer valid with the new validator.  Warn about this.
 
470
                 * are no longer valid with the new validator.  Warn about this.
471
471
                 */
472
472
                if (stmt->validator)
473
473
                        ereport(WARNING,
474
 
                                        (errmsg("changing the foreign-data wrapper validator can cause "
475
 
                                                        "the options for dependent objects to become invalid")));
 
474
                         (errmsg("changing the foreign-data wrapper validator can cause "
 
475
                                         "the options for dependent objects to become invalid")));
476
476
        }
477
477
        else
478
478
        {
479
479
                /*
480
 
                 * Validator is not changed, but we need it for validating
481
 
                 * options.
 
480
                 * Validator is not changed, but we need it for validating options.
482
481
                 */
483
482
                datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
484
483
                                                                tp,
517
516
        rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
518
517
 
519
518
        tp = heap_modify_tuple(tp, RelationGetDescr(rel),
520
 
                                                  repl_val, repl_null, repl_repl);
 
519
                                                   repl_val, repl_null, repl_repl);
521
520
 
522
521
        simple_heap_update(rel, &tp->t_self, tp);
523
522
        CatalogUpdateIndexes(rel, tp);
533
532
void
534
533
RemoveForeignDataWrapper(DropFdwStmt *stmt)
535
534
{
536
 
        Oid                                     fdwId;
537
 
        ObjectAddress           object;
 
535
        Oid                     fdwId;
 
536
        ObjectAddress object;
538
537
 
539
538
        fdwId = GetForeignDataWrapperOidByName(stmt->fdwname, true);
540
539
 
541
540
        if (!superuser())
542
541
                ereport(ERROR,
543
542
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
544
 
                                errmsg("permission denied to drop foreign-data wrapper \"%s\"",
545
 
                                        stmt->fdwname),
546
 
                                errhint("Must be superuser to drop a foreign-data wrapper.")));
 
543
                          errmsg("permission denied to drop foreign-data wrapper \"%s\"",
 
544
                                         stmt->fdwname),
 
545
                          errhint("Must be superuser to drop a foreign-data wrapper.")));
547
546
 
548
547
        if (!OidIsValid(fdwId))
549
548
        {
550
549
                if (!stmt->missing_ok)
551
550
                        ereport(ERROR,
552
551
                                        (errcode(ERRCODE_UNDEFINED_OBJECT),
553
 
                                        errmsg("foreign-data wrapper \"%s\" does not exist",
554
 
                                        stmt->fdwname)));
 
552
                                         errmsg("foreign-data wrapper \"%s\" does not exist",
 
553
                                                        stmt->fdwname)));
555
554
 
556
555
                /* IF EXISTS specified, just note it */
557
556
                ereport(NOTICE,
558
 
                                (errmsg("foreign-data wrapper \"%s\" does not exist, skipping",
559
 
                                        stmt->fdwname)));
 
557
                          (errmsg("foreign-data wrapper \"%s\" does not exist, skipping",
 
558
                                          stmt->fdwname)));
560
559
                return;
561
560
        }
562
561
 
603
602
void
604
603
CreateForeignServer(CreateForeignServerStmt *stmt)
605
604
{
606
 
        Relation                rel;
607
 
        Datum                   srvoptions;
608
 
        Datum                   values[Natts_pg_foreign_server];
609
 
        bool                    nulls[Natts_pg_foreign_server];
610
 
        HeapTuple               tuple;
611
 
        Oid                             srvId;
612
 
        Oid                             ownerId;
613
 
        AclResult               aclresult;
614
 
        ObjectAddress   myself;
615
 
        ObjectAddress   referenced;
 
605
        Relation        rel;
 
606
        Datum           srvoptions;
 
607
        Datum           values[Natts_pg_foreign_server];
 
608
        bool            nulls[Natts_pg_foreign_server];
 
609
        HeapTuple       tuple;
 
610
        Oid                     srvId;
 
611
        Oid                     ownerId;
 
612
        AclResult       aclresult;
 
613
        ObjectAddress myself;
 
614
        ObjectAddress referenced;
616
615
        ForeignDataWrapper *fdw;
617
616
 
618
617
        /* For now the owner cannot be specified on create. Use effective user ID. */
628
627
                                                stmt->servername)));
629
628
 
630
629
        /*
631
 
         * Check that the FDW exists and that we have USAGE on it.
632
 
         * Also get the actual FDW for option validation etc.
 
630
         * Check that the FDW exists and that we have USAGE on it. Also get the
 
631
         * actual FDW for option validation etc.
633
632
         */
634
633
        fdw = GetForeignDataWrapperByName(stmt->fdwname, false);
635
634
 
712
711
        bool            repl_null[Natts_pg_foreign_server];
713
712
        bool            repl_repl[Natts_pg_foreign_server];
714
713
        Oid                     srvId;
715
 
        Form_pg_foreign_server  srvForm;
 
714
        Form_pg_foreign_server srvForm;
716
715
 
717
716
        tp = SearchSysCacheCopy(FOREIGNSERVERNAME,
718
717
                                                        CStringGetDatum(stmt->servername),
721
720
        if (!HeapTupleIsValid(tp))
722
721
                ereport(ERROR,
723
722
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
724
 
                                errmsg("server \"%s\" does not exist", stmt->servername)));
 
723
                                 errmsg("server \"%s\" does not exist", stmt->servername)));
725
724
 
726
725
        srvId = HeapTupleGetOid(tp);
727
726
        srvForm = (Form_pg_foreign_server) GETSTRUCT(tp);
754
753
        if (stmt->options)
755
754
        {
756
755
                ForeignDataWrapper *fdw = GetForeignDataWrapper(srvForm->srvfdw);
757
 
                Datum                           datum;
758
 
                bool                            isnull;
 
756
                Datum           datum;
 
757
                bool            isnull;
759
758
 
760
759
                /* Extract the current srvoptions */
761
760
                datum = SysCacheGetAttr(FOREIGNSERVEROID,
782
781
        rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
783
782
 
784
783
        tp = heap_modify_tuple(tp, RelationGetDescr(rel),
785
 
                                                  repl_val, repl_null, repl_repl);
 
784
                                                   repl_val, repl_null, repl_repl);
786
785
 
787
786
        simple_heap_update(rel, &tp->t_self, tp);
788
787
        CatalogUpdateIndexes(rel, tp);
798
797
void
799
798
RemoveForeignServer(DropForeignServerStmt *stmt)
800
799
{
801
 
        Oid                             srvId;
802
 
        ObjectAddress   object;
 
800
        Oid                     srvId;
 
801
        ObjectAddress object;
803
802
 
804
803
        srvId = GetForeignServerOidByName(stmt->servername, true);
805
804
 
809
808
                if (!stmt->missing_ok)
810
809
                        ereport(ERROR,
811
810
                                        (errcode(ERRCODE_UNDEFINED_OBJECT),
812
 
                                        errmsg("server \"%s\" does not exist", stmt->servername)));
 
811
                                  errmsg("server \"%s\" does not exist", stmt->servername)));
813
812
 
814
813
                /* IF EXISTS specified, just note it */
815
814
                ereport(NOTICE,
871
870
        {
872
871
                if (umuserid == curuserid)
873
872
                {
874
 
                        AclResult                       aclresult;
 
873
                        AclResult       aclresult;
875
874
 
876
875
                        aclresult = pg_foreign_server_aclcheck(serverid, curuserid, ACL_USAGE);
877
876
                        if (aclresult != ACLCHECK_OK)
890
889
void
891
890
CreateUserMapping(CreateUserMappingStmt *stmt)
892
891
{
893
 
        Relation                        rel;
894
 
        Datum                           useoptions;
895
 
        Datum                           values[Natts_pg_user_mapping];
896
 
        bool                            nulls[Natts_pg_user_mapping];
897
 
        HeapTuple                       tuple;
898
 
        Oid                                     useId;
899
 
        Oid                                     umId;
900
 
        ObjectAddress           myself;
901
 
        ObjectAddress           referenced;
902
 
        ForeignServer      *srv;
 
892
        Relation        rel;
 
893
        Datum           useoptions;
 
894
        Datum           values[Natts_pg_user_mapping];
 
895
        bool            nulls[Natts_pg_user_mapping];
 
896
        HeapTuple       tuple;
 
897
        Oid                     useId;
 
898
        Oid                     umId;
 
899
        ObjectAddress myself;
 
900
        ObjectAddress referenced;
 
901
        ForeignServer *srv;
903
902
        ForeignDataWrapper *fdw;
904
903
 
905
904
        useId = GetUserOidFromMapping(stmt->username, false);
913
912
         * Check that the user mapping is unique within server.
914
913
         */
915
914
        umId = GetSysCacheOid(USERMAPPINGUSERSERVER,
916
 
                                                   ObjectIdGetDatum(useId),
917
 
                                                   ObjectIdGetDatum(srv->serverid),
918
 
                                                   0, 0);
 
915
                                                  ObjectIdGetDatum(useId),
 
916
                                                  ObjectIdGetDatum(srv->serverid),
 
917
                                                  0, 0);
919
918
        if (OidIsValid(umId))
920
919
                ereport(ERROR,
921
920
                                (errcode(ERRCODE_DUPLICATE_OBJECT),
984
983
        bool            repl_repl[Natts_pg_user_mapping];
985
984
        Oid                     useId;
986
985
        Oid                     umId;
987
 
        ForeignServer   *srv;
 
986
        ForeignServer *srv;
988
987
 
989
988
        useId = GetUserOidFromMapping(stmt->username, false);
990
989
        srv = GetForeignServerByName(stmt->servername, false);
996
995
        if (!OidIsValid(umId))
997
996
                ereport(ERROR,
998
997
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
999
 
                                errmsg("user mapping \"%s\" does not exist for the server",
1000
 
                                        MappingUserName(useId))));
 
998
                                 errmsg("user mapping \"%s\" does not exist for the server",
 
999
                                                MappingUserName(useId))));
1001
1000
 
1002
1001
        user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
1003
1002
 
1014
1013
 
1015
1014
        if (stmt->options)
1016
1015
        {
1017
 
                ForeignDataWrapper                 *fdw;
1018
 
                Datum                                           datum;
1019
 
                bool                                            isnull;
 
1016
                ForeignDataWrapper *fdw;
 
1017
                Datum           datum;
 
1018
                bool            isnull;
1020
1019
 
1021
1020
                /*
1022
1021
                 * Process the options.
1048
1047
        rel = heap_open(UserMappingRelationId, RowExclusiveLock);
1049
1048
 
1050
1049
        tp = heap_modify_tuple(tp, RelationGetDescr(rel),
1051
 
                                                  repl_val, repl_null, repl_repl);
 
1050
                                                   repl_val, repl_null, repl_repl);
1052
1051
 
1053
1052
        simple_heap_update(rel, &tp->t_self, tp);
1054
1053
        CatalogUpdateIndexes(rel, tp);
1064
1063
void
1065
1064
RemoveUserMapping(DropUserMappingStmt *stmt)
1066
1065
{
1067
 
        ObjectAddress   object;
1068
 
        Oid                             useId;
1069
 
        Oid                             umId;
1070
 
        ForeignServer  *srv;
 
1066
        ObjectAddress object;
 
1067
        Oid                     useId;
 
1068
        Oid                     umId;
 
1069
        ForeignServer *srv;
1071
1070
 
1072
1071
        useId = GetUserOidFromMapping(stmt->username, stmt->missing_ok);
1073
1072
        srv = GetForeignServerByName(stmt->servername, true);
1075
1074
        if (stmt->username && !OidIsValid(useId))
1076
1075
        {
1077
1076
                /*
1078
 
                 * IF EXISTS specified, role not found and not public.
1079
 
                 * Notice this and leave.
 
1077
                 * IF EXISTS specified, role not found and not public. Notice this and
 
1078
                 * leave.
1080
1079
                 */
1081
1080
                elog(NOTICE, "role \"%s\" does not exist, skipping", stmt->username);
1082
1081
                return;
1087
1086
                if (!stmt->missing_ok)
1088
1087
                        ereport(ERROR,
1089
1088
                                        (errcode(ERRCODE_UNDEFINED_OBJECT),
1090
 
                                        errmsg("server \"%s\" does not exist",
1091
 
                                        stmt->servername)));
 
1089
                                         errmsg("server \"%s\" does not exist",
 
1090
                                                        stmt->servername)));
1092
1091
                /* IF EXISTS, just note it */
1093
1092
                ereport(NOTICE, (errmsg("server does not exist, skipping")));
1094
1093
                return;
1104
1103
                if (!stmt->missing_ok)
1105
1104
                        ereport(ERROR,
1106
1105
                                        (errcode(ERRCODE_UNDEFINED_OBJECT),
1107
 
                                        errmsg("user mapping \"%s\" does not exist for the server",
1108
 
                                                MappingUserName(useId))));
 
1106
                                  errmsg("user mapping \"%s\" does not exist for the server",
 
1107
                                                 MappingUserName(useId))));
1109
1108
 
1110
1109
                /* IF EXISTS specified, just note it */
1111
1110
                ereport(NOTICE,
1112
 
                                (errmsg("user mapping \"%s\" does not exist for the server, skipping",
1113
 
                                        MappingUserName(useId))));
 
1111
                (errmsg("user mapping \"%s\" does not exist for the server, skipping",
 
1112
                                MappingUserName(useId))));
1114
1113
                return;
1115
1114
        }
1116
1115