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