|
|
1.1 root 1: # include <ingres.h>
2: # include <aux.h>
3: # include <catalog.h>
4: # include <access.h>
5: # include <tree.h>
6: # include <symbol.h>
7: # include <lock.h>
8: # include <pv.h>
9: # include <func.h>
10: # include "qrymod.h"
11: # include <sccs.h>
12:
13: SCCSID(@(#)d_prot.c 7.2 8/15/83)
14:
15:
16:
17: /*
18: ** D_PROT -- define protection constraint
19: **
20: ** A protection constraint as partially defined by the last tree
21: ** defined by d_tree is defined.
22: **
23: ** The stuff that comes through the pipe as parameters is complex.
24: ** It comes as a sequence of strings:
25: ** # The operation set, already encoded in the parser into a
26: ** bit map. If the PRO_RETR permission is set, the PRO_TEST
27: ** and PRO_AGGR permissions will also be set.
28: ** # The relation name.
29: ** # The relation owner.
30: ** # The user name. This must be a user name as specified in
31: ** the 'users' file, or the keyword 'all', meaning all users.
32: ** # The terminal id. Must be a string of the form 'ttyx' or
33: ** the keyword 'all'.
34: ** # The starting time of day, as minutes-since-midnight.
35: ** # The ending time of day.
36: ** # The starting day-of-week, with 0 = Sunday.
37: ** # The ending dow.
38: **
39: ** The domain reference set is build automatically from the
40: ** target list of the tree. Thus, the target list must exist,
41: ** but it is not inserted into the tree. The target list must
42: ** be a flat sequence of RESDOM nodes with VAR nodes hanging
43: ** of the rhs; also, the VAR nodes must all be for Qt.qt_resvar.
44: ** If there is no target list on the tree, the set of all var-
45: ** iables is assumed.
46: **
47: ** The relstat field in the relation relation is updated to
48: ** reflect any changes.
49: **
50: ** It only makes sense for the DBA to execute this command.
51: **
52: ** If there is one of the special cases
53: ** permit all to all
54: ** permit retrieve to all
55: ** it is caught, and the effect is achieved by diddling
56: ** relstat bits instead of inserting into the protect catalog.
57: **
58: ** Parameters:
59: ** none
60: **
61: ** Returns:
62: ** none
63: **
64: ** Side Effects:
65: ** Activity in 'protect' and 'relation' catalogs.
66: **
67: ** Trace Flags:
68: ** 59
69: */
70:
71: extern struct admin Admin;
72: extern DESC Prodes;
73: extern DESC Reldes;
74:
75: extern d_prot(), null_fn();
76: extern short tTqm[80];
77:
78: struct fn_def DefProFn =
79: {
80: "DPROT",
81: d_prot,
82: null_fn,
83: null_fn,
84: NULL,
85: 0,
86: tTqm,
87: 80,
88: 'Q',
89: 0
90: };
91:
92: d_prot(pc, pv)
93: int pc;
94: PARM *pv;
95: {
96: struct protect protup;
97: struct tup_id protid;
98: struct protect prokey;
99: struct protect proxtup;
100: char buf[30];
101: char ubuf[MAXLINE + 1];
102: register int i;
103: auto int ix;
104: int treeid;
105: register QTREE *t;
106: QTREE *root;
107: register char *p;
108: struct relation reltup;
109: struct relation relkey;
110: struct tup_id reltid;
111: int relstat;
112: int all_pro;
113:
114: /*
115: ** Fill in the protection tuple with the information
116: ** from the parser, validating as we go.
117: **
118: ** Also, determine if we have a PERMIT xx to ALL
119: ** with no further qualification case. The variable
120: ** 'all_pro' is set to reflect this.
121: */
122:
123: clr_tuple(&Prodes, &protup);
124: all_pro = TRUE;
125:
126: /* read operation set */
127: if (pv->pv_type != PV_INT)
128: syserr("d_prot: opset");
129: protup.proopset = pv->pv_val.pv_int;
130: if ((protup.proopset & PRO_RETR) != 0)
131: protup.proopset |= PRO_TEST | PRO_AGGR;
132: pv++;
133:
134: /* read relation name */
135: if (pv->pv_type != PV_STR)
136: syserr("d_prot: relid");
137: pmove(pv->pv_val.pv_str, protup.prorelid, MAXNAME, ' ');
138: pv++;
139:
140: /* read relation owner */
141: if (pv->pv_type != PV_STR)
142: syserr("d_prot: relid");
143: bmove(pv->pv_val.pv_str, protup.prorelown, 2);
144: pv++;
145:
146: /* read user name */
147: if (pv->pv_type != PV_STR)
148: syserr("d_prot: user");
149: if (sequal(pv->pv_val.pv_str, "all"))
150: bmove(" ", protup.prouser, 2);
151: else
152: {
153: /* look up user in 'users' file */
154: if (getnuser(pv->pv_val.pv_str, ubuf))
155: qmerror(3591, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);
156: for (p = ubuf; *p != ':' && *p != 0; p++)
157: continue;
158: bmove(++p, protup.prouser, 2);
159: if (p[0] == ':' || p[1] == ':' || p[2] != ':')
160: syserr("d_prot: users %s", ubuf);
161: all_pro = FALSE;
162: }
163: pv++;
164:
165: /* read terminal id */
166: if (pv->pv_type != PV_STR)
167: syserr("d_prot: user");
168: if (sequal(pv->pv_val.pv_str, "all"))
169: pmove("", protup.proterm, sizeof protup.proterm, ' ');
170: else
171: {
172: pmove(pv->pv_val.pv_str, protup.proterm, sizeof protup.proterm, ' ');
173: if (!isttyname(pv->pv_val.pv_str))
174: qmerror(3590, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);
175: all_pro = FALSE;
176: }
177: pv++;
178:
179: /* read starting time of day */
180: if (pv->pv_type != PV_INT)
181: syserr("d_prot: btod");
182: protup.protodbgn = pv->pv_val.pv_int;
183: if (pv->pv_val.pv_int > 0)
184: all_pro = FALSE;
185: pv++;
186:
187: /* read ending time of day */
188: if (pv->pv_type != PV_INT)
189: syserr("d_prot: etod");
190: protup.protodend = pv->pv_val.pv_int;
191: if (pv->pv_val.pv_int < 24 * 60 - 1)
192: all_pro = FALSE;
193: pv++;
194:
195: /* read beginning day of week */
196: if (pv->pv_type != PV_STR)
197: syserr("d_prot: bdow");
198: i = cvt_dow(pv->pv_val.pv_str);
199: if (i < 0)
200: qmerror(3594, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0); /* bad dow */
201: protup.prodowbgn = i;
202: if (i > 0)
203: all_pro = FALSE;
204: pv++;
205:
206: /* read ending day of week */
207: if (pv->pv_type != PV_STR)
208: syserr("d_prot: edow");
209: i = cvt_dow(pv->pv_val.pv_str);
210: if (i < 0)
211: qmerror(3594, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0); /* bad dow */
212: protup.prodowend = i;
213: if (i < 6)
214: all_pro = FALSE;
215: pv++;
216:
217: /*
218: ** Check for valid tree:
219: ** There must be a tree defined, and all variables
220: ** referenced must be owned by the current user; this
221: ** is because you could otherwise get at data by
222: ** mentioning it in a permit statement; see protect.c
223: ** for a better explanation of this.
224: */
225:
226: if (pv->pv_type != PV_QTREE)
227: syserr("d_prot: tree");
228: root = (QTREE *) pv->pv_val.pv_qtree;
229: pv++;
230:
231: for (i = 0; i < MAXVAR + 1; i++)
232: {
233: if (Qt.qt_rangev[i].rngvdesc == NULL)
234: continue;
235: if (!bequal(Qt.qt_rangev[i].rngvdesc->reldum.relowner, Usercode, 2))
236: qmerror(3592, -1, i, 0);
237: }
238:
239: /* test for dba */
240: if (!bequal(Usercode, Admin.adhdr.adowner, 2))
241: qmerror(3595, -1, Qt.qt_resvar, 0);
242:
243: /* get domain reference set from target list */
244: /* (also, find the TREE node) */
245: t = root->left;
246: if (t->sym.type == TREE)
247: {
248: for (i = 0; i < 8; i++)
249: protup.prodomset[i] = -1;
250: }
251: else
252: {
253: for (i = 0; i < 8; i++)
254: protup.prodomset[i] = 0;
255: for (; t->sym.type != TREE; t = t->left)
256: {
257: if (t->right->sym.type != VAR ||
258: t->sym.type != RESDOM ||
259: t->right->sym.value.sym_var.varno != Qt.qt_resvar)
260: syserr("d_prot: garbage tree");
261: lsetbit(t->right->sym.value.sym_var.attno, protup.prodomset);
262: }
263: all_pro = FALSE;
264: }
265:
266: /* trim off the target list, since it isn't used again */
267: root->left = t;
268:
269: /*
270: ** Check out the target relation.
271: ** We first save the varno of the relation which is
272: ** getting the permit stuff. Also, we check to see
273: ** that the relation mentioned is a base relation,
274: ** and not a view, since that tuple would never do
275: ** anything anyway. Finally, we clear the Qt.qt_resvar
276: ** so that it does not get output to the tree catalog.
277: ** This would result in a 'syserr' when we tried to
278: ** read it.
279: */
280:
281: protup.proresvar = Qt.qt_resvar;
282: # ifdef xQTR3
283: if (Qt.qt_resvar < 0)
284: syserr("d_prot: Rv %d", Qt.qt_resvar);
285: # endif
286: if (bitset(S_VIEW, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat))
287: qmerror(3593, -1, Qt.qt_resvar, 0); /* is a view */
288:
289: /* clear the (unused) Qt.qt_qmode */
290: # ifdef xQTR3
291: if (Qt.qt_qmode != mdPROT)
292: syserr("d_prot: Qt.qt_qmode %d", Qt.qt_qmode);
293: # endif
294: Qt.qt_qmode = -1;
295:
296: /*
297: ** Check for PERMIT xx to ALL case.
298: ** The relstat bits will be adjusted as necessary
299: ** to reflect these special cases.
300: **
301: ** This is actually a little tricky, since we cannot
302: ** afford to turn off any permissions. If we already
303: ** have some form of PERMIT xx to ALL access, we must
304: ** leave it.
305: */
306:
307: relstat = Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat;
308: if (all_pro && (protup.proopset & PRO_RETR) != 0)
309: {
310: if (protup.proopset == -1)
311: relstat &= ~S_PROTALL;
312: else
313: {
314: relstat &= ~S_PROTRET;
315: if ((protup.proopset & ~(PRO_RETR|PRO_AGGR|PRO_TEST)) != 0)
316: {
317: /* some special case: still insert prot tuple */
318: all_pro = FALSE;
319: }
320: }
321: }
322: else
323: all_pro = FALSE;
324:
325: /* see if we are adding any tuples */
326: if (!all_pro)
327: relstat |= S_PROTUPS;
328:
329: /*
330: ** Change relstat field in relation catalog if changed
331: */
332:
333: if (relstat != Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat)
334: {
335: opencatalog("relation", 2);
336: setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relid, RELID);
337: setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relowner, RELOWNER);
338: i = getequal(&Reldes, &relkey, &reltup, &reltid);
339: if (i != 0)
340: syserr("d_prot: geteq %d", i);
341: reltup.relstat = relstat;
342: i = replace(&Reldes, &reltid, &reltup, FALSE);
343: if (i != 0)
344: syserr("d_prot: repl %d", i);
345: if (noclose(&Reldes) != 0)
346: syserr("d_prot: noclose(rel)");
347: }
348:
349: Qt.qt_resvar = -1;
350:
351: if (!all_pro)
352: {
353: /*
354: ** Output the created tuple to the protection catalog
355: ** after making other internal adjustments and deter-
356: ** mining a unique sequence number (with the protect
357: ** catalog locked).
358: */
359:
360: if (root->right->sym.type != QLEND)
361: protup.protree = puttree(root, protup.prorelid, protup.prorelown, mdPROT);
362: else
363: protup.protree = -1;
364:
365: /* compute unique permission id */
366: opencatalog("protect", 2);
367: setrll(A_SLP, Prodes.reltid.ltid, M_EXCL);
368: setkey(&Prodes, &prokey, protup.prorelid, PRORELID);
369: setkey(&Prodes, &prokey, protup.prorelown, PRORELOWN);
370: for (ix = 2; ; ix++)
371: {
372: setkey(&Prodes, &prokey, &ix, PROPERMID);
373: i = getequal(&Prodes, &prokey, &proxtup, &protid);
374: if (i < 0)
375: syserr("d_prot: geteq");
376: else if (i > 0)
377: break;
378: }
379: protup.propermid = ix;
380:
381: /* do actual insert */
382: i = insert(&Prodes, &protid, &protup, FALSE);
383: if (i < 0)
384: syserr("d_prot: insert");
385: if (noclose(&Prodes) != 0)
386: syserr("d_prot: noclose(pro)");
387:
388: /* clear the lock */
389: unlrl(Prodes.reltid.ltid);
390: }
391: }
392: /*
393: ** CVT_DOW -- convert day of week
394: **
395: ** Converts the day of the week from string form to a number.
396: **
397: ** Parameters:
398: ** sdow -- dow in string form.
399: **
400: ** Returns:
401: ** 0 -> 6 -- the encoded day of the week.
402: ** -1 -- error.
403: **
404: ** Side Effects:
405: ** none
406: **
407: ** Defines:
408: ** Dowlist -- a mapping from day of week to number.
409: ** cvt_dow
410: **
411: ** Called By:
412: ** d_prot
413: */
414:
415: struct downame
416: {
417: char *dow_name;
418: int dow_num;
419: };
420:
421: struct downame Dowlist[] =
422: {
423: "sun", 0,
424: "sunday", 0,
425: "mon", 1,
426: "monday", 1,
427: "tue", 2,
428: "tues", 2,
429: "tuesday", 2,
430: "wed", 3,
431: "wednesday", 3,
432: "thu", 4,
433: "thurs", 4,
434: "thursday", 4,
435: "fri", 5,
436: "friday", 5,
437: "sat", 6,
438: "saturday", 6,
439: NULL
440: };
441:
442: cvt_dow(sdow)
443: char *sdow;
444: {
445: register struct downame *d;
446: register char *s;
447:
448: s = sdow;
449:
450: for (d = Dowlist; d->dow_name != NULL; d++)
451: if (sequal(d->dow_name, s))
452: return (d->dow_num);
453: return (-1);
454: }
455: /*
456: ** ISTTYNAME -- "is a legal terminal name" predicate
457: **
458: ** Returns TRUE if the argument is a legal terminal name,
459: ** otherwise FALSE.
460: **
461: ** It may make sense to have this routine check if the given
462: ** file name really exists.
463: **
464: ** WARNING:
465: ** This routine may be installation-dependent!
466: **
467: ** Parameters:
468: ** n -- the name to check.
469: **
470: ** Returns:
471: ** TRUE -- n is a legal tty name at this installation.
472: ** FALSE -- otherwise.
473: **
474: ** Side Effects:
475: ** none
476: **
477: ** History:
478: ** 8/1/79 (eric) -- written.
479: */
480:
481:
482: isttyname(n)
483: register char *n;
484: {
485: return (sequal(n, "console") || bequal(n, "tty", 3));
486: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.