~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to contrib/sepgsql/relation.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -------------------------------------------------------------------------
 
2
 *
 
3
 * contrib/sepgsql/label.c
 
4
 *
 
5
 * Routines corresponding to relation/attribute objects
 
6
 *
 
7
 * Copyright (c) 2010-2011, PostgreSQL Global Development Group
 
8
 *
 
9
 * -------------------------------------------------------------------------
 
10
 */
 
11
#include "postgres.h"
 
12
 
 
13
#include "access/genam.h"
 
14
#include "access/heapam.h"
 
15
#include "access/sysattr.h"
 
16
#include "catalog/indexing.h"
 
17
#include "catalog/dependency.h"
 
18
#include "catalog/pg_attribute.h"
 
19
#include "catalog/pg_class.h"
 
20
#include "catalog/pg_namespace.h"
 
21
#include "commands/seclabel.h"
 
22
#include "utils/fmgroids.h"
 
23
#include "utils/lsyscache.h"
 
24
#include "utils/tqual.h"
 
25
 
 
26
#include "sepgsql.h"
 
27
 
 
28
/*
 
29
 * sepgsql_attribute_post_create
 
30
 *
 
31
 * This routine assigns a default security label on a newly defined
 
32
 * column, using ALTER TABLE ... ADD COLUMN.
 
33
 * Note that this routine is not invoked in the case of CREATE TABLE,
 
34
 * although it also defines columns in addition to table.
 
35
 */
 
36
void
 
37
sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
 
38
{
 
39
        char       *scontext = sepgsql_get_client_label();
 
40
        char       *tcontext;
 
41
        char       *ncontext;
 
42
        ObjectAddress object;
 
43
 
 
44
        /*
 
45
         * Only attributes within regular relation have individual security
 
46
         * labels.
 
47
         */
 
48
        if (get_rel_relkind(relOid) != RELKIND_RELATION)
 
49
                return;
 
50
 
 
51
        /*
 
52
         * Compute a default security label when we create a new procedure object
 
53
         * under the specified namespace.
 
54
         */
 
55
        scontext = sepgsql_get_client_label();
 
56
        tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
 
57
        ncontext = sepgsql_compute_create(scontext, tcontext,
 
58
                                                                          SEPG_CLASS_DB_COLUMN);
 
59
 
 
60
        /*
 
61
         * Assign the default security label on a new procedure
 
62
         */
 
63
        object.classId = RelationRelationId;
 
64
        object.objectId = relOid;
 
65
        object.objectSubId = attnum;
 
66
        SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
 
67
 
 
68
        pfree(tcontext);
 
69
        pfree(ncontext);
 
70
}
 
71
 
 
72
/*
 
73
 * sepgsql_attribute_relabel
 
74
 *
 
75
 * It checks privileges to relabel the supplied column
 
76
 * by the `seclabel'.
 
77
 */
 
78
void
 
79
sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
 
80
                                                  const char *seclabel)
 
81
{
 
82
        char       *scontext = sepgsql_get_client_label();
 
83
        char       *tcontext;
 
84
        char       *audit_name;
 
85
        ObjectAddress object;
 
86
 
 
87
        if (get_rel_relkind(relOid) != RELKIND_RELATION)
 
88
                ereport(ERROR,
 
89
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
 
90
                                 errmsg("cannot set security label on non-regular columns")));
 
91
 
 
92
        object.classId = RelationRelationId;
 
93
        object.objectId = relOid;
 
94
        object.objectSubId = attnum;
 
95
        audit_name = getObjectDescription(&object);
 
96
 
 
97
        /*
 
98
         * check db_column:{setattr relabelfrom} permission
 
99
         */
 
100
        tcontext = sepgsql_get_label(RelationRelationId, relOid, attnum);
 
101
        sepgsql_check_perms(scontext,
 
102
                                                tcontext,
 
103
                                                SEPG_CLASS_DB_COLUMN,
 
104
                                                SEPG_DB_COLUMN__SETATTR |
 
105
                                                SEPG_DB_COLUMN__RELABELFROM,
 
106
                                                audit_name,
 
107
                                                true);
 
108
 
 
109
        /*
 
110
         * check db_column:{relabelto} permission
 
111
         */
 
112
        sepgsql_check_perms(scontext,
 
113
                                                seclabel,
 
114
                                                SEPG_CLASS_DB_COLUMN,
 
115
                                                SEPG_DB_PROCEDURE__RELABELTO,
 
116
                                                audit_name,
 
117
                                                true);
 
118
 
 
119
        pfree(tcontext);
 
120
        pfree(audit_name);
 
121
}
 
122
 
 
123
/*
 
124
 * sepgsql_relation_post_create
 
125
 *
 
126
 * The post creation hook of relation/attribute
 
127
 */
 
128
void
 
129
sepgsql_relation_post_create(Oid relOid)
 
130
{
 
131
        Relation        rel;
 
132
        ScanKeyData skey;
 
133
        SysScanDesc sscan;
 
134
        HeapTuple       tuple;
 
135
        Form_pg_class classForm;
 
136
        ObjectAddress object;
 
137
        uint16          tclass;
 
138
        char       *scontext;           /* subject */
 
139
        char       *tcontext;           /* schema */
 
140
        char       *rcontext;           /* relation */
 
141
        char       *ccontext;           /* column */
 
142
 
 
143
        /*
 
144
         * Fetch catalog record of the new relation. Because pg_class entry is not
 
145
         * visible right now, we need to scan the catalog using SnapshotSelf.
 
146
         */
 
147
        rel = heap_open(RelationRelationId, AccessShareLock);
 
148
 
 
149
        ScanKeyInit(&skey,
 
150
                                ObjectIdAttributeNumber,
 
151
                                BTEqualStrategyNumber, F_OIDEQ,
 
152
                                ObjectIdGetDatum(relOid));
 
153
 
 
154
        sscan = systable_beginscan(rel, ClassOidIndexId, true,
 
155
                                                           SnapshotSelf, 1, &skey);
 
156
 
 
157
        tuple = systable_getnext(sscan);
 
158
        if (!HeapTupleIsValid(tuple))
 
159
                elog(ERROR, "catalog lookup failed for relation %u", relOid);
 
160
 
 
161
        classForm = (Form_pg_class) GETSTRUCT(tuple);
 
162
 
 
163
        if (classForm->relkind == RELKIND_RELATION)
 
164
                tclass = SEPG_CLASS_DB_TABLE;
 
165
        else if (classForm->relkind == RELKIND_SEQUENCE)
 
166
                tclass = SEPG_CLASS_DB_SEQUENCE;
 
167
        else if (classForm->relkind == RELKIND_VIEW)
 
168
                tclass = SEPG_CLASS_DB_VIEW;
 
169
        else
 
170
                goto out;                               /* No need to assign individual labels */
 
171
 
 
172
        /*
 
173
         * Compute a default security label when we create a new relation object
 
174
         * under the specified namespace.
 
175
         */
 
176
        scontext = sepgsql_get_client_label();
 
177
        tcontext = sepgsql_get_label(NamespaceRelationId,
 
178
                                                                 classForm->relnamespace, 0);
 
179
        rcontext = sepgsql_compute_create(scontext, tcontext, tclass);
 
180
 
 
181
        /*
 
182
         * Assign the default security label on the new relation
 
183
         */
 
184
        object.classId = RelationRelationId;
 
185
        object.objectId = relOid;
 
186
        object.objectSubId = 0;
 
187
        SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, rcontext);
 
188
 
 
189
        /*
 
190
         * We also assigns a default security label on columns of the new regular
 
191
         * tables.
 
192
         */
 
193
        if (classForm->relkind == RELKIND_RELATION)
 
194
        {
 
195
                AttrNumber      index;
 
196
 
 
197
                ccontext = sepgsql_compute_create(scontext, rcontext,
 
198
                                                                                  SEPG_CLASS_DB_COLUMN);
 
199
                for (index = FirstLowInvalidHeapAttributeNumber + 1;
 
200
                         index <= classForm->relnatts;
 
201
                         index++)
 
202
                {
 
203
                        if (index == InvalidAttrNumber)
 
204
                                continue;
 
205
 
 
206
                        if (index == ObjectIdAttributeNumber && !classForm->relhasoids)
 
207
                                continue;
 
208
 
 
209
                        object.classId = RelationRelationId;
 
210
                        object.objectId = relOid;
 
211
                        object.objectSubId = index;
 
212
                        SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ccontext);
 
213
                }
 
214
                pfree(ccontext);
 
215
        }
 
216
        pfree(rcontext);
 
217
out:
 
218
        systable_endscan(sscan);
 
219
        heap_close(rel, AccessShareLock);
 
220
}
 
221
 
 
222
/*
 
223
 * sepgsql_relation_relabel
 
224
 *
 
225
 * It checks privileges to relabel the supplied relation by the `seclabel'.
 
226
 */
 
227
void
 
228
sepgsql_relation_relabel(Oid relOid, const char *seclabel)
 
229
{
 
230
        char       *scontext = sepgsql_get_client_label();
 
231
        char       *tcontext;
 
232
        char       *audit_name;
 
233
        char            relkind;
 
234
        uint16_t        tclass = 0;
 
235
 
 
236
        relkind = get_rel_relkind(relOid);
 
237
        if (relkind == RELKIND_RELATION)
 
238
                tclass = SEPG_CLASS_DB_TABLE;
 
239
        else if (relkind == RELKIND_SEQUENCE)
 
240
                tclass = SEPG_CLASS_DB_SEQUENCE;
 
241
        else if (relkind == RELKIND_VIEW)
 
242
                tclass = SEPG_CLASS_DB_VIEW;
 
243
        else
 
244
                ereport(ERROR,
 
245
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
 
246
                                 errmsg("cannot set security labels on relations except "
 
247
                                                "for tables, sequences or views")));
 
248
 
 
249
        audit_name = getObjectDescriptionOids(RelationRelationId, relOid);
 
250
 
 
251
        /*
 
252
         * check db_xxx:{setattr relabelfrom} permission
 
253
         */
 
254
        tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
 
255
 
 
256
        sepgsql_check_perms(scontext,
 
257
                                                tcontext,
 
258
                                                tclass,
 
259
                                                SEPG_DB_TABLE__SETATTR |
 
260
                                                SEPG_DB_TABLE__RELABELFROM,
 
261
                                                audit_name,
 
262
                                                true);
 
263
 
 
264
        /*
 
265
         * check db_xxx:{relabelto} permission
 
266
         */
 
267
        sepgsql_check_perms(scontext,
 
268
                                                seclabel,
 
269
                                                tclass,
 
270
                                                SEPG_DB_TABLE__RELABELTO,
 
271
                                                audit_name,
 
272
                                                true);
 
273
 
 
274
        pfree(tcontext);
 
275
        pfree(audit_name);
 
276
}