# 2.11BSD#431 - /usr/ingres/source/qrymod/protect.c

##### Functions

    dopro             X
    makedset          X
    pr_set            X
    proappl           X
    prochk            X
    protect           X

##### Variables

    Proopmap          X

##### struct's

    qvect             X

       1: # include   "../ingres.h"
       2: # include   "../aux.h"
       3: # include   "../unix.h"
       4: # include   "../catalog.h"
       5: # include   "../symbol.h"
       6: # include   "../tree.h"
       7: # include   "qrymod.h"
       8:
       9: /*
      10: **  PROTECT -- protection algorithm
      11: **
      12: **	This module performs the INGRES protection algorithm, as
      13: **	presented in Stonebraker & Rubinstein, "The INGRES Protection
      14: **	System", with a few modifications.
      15: **
      16: **	The basic algorithm is as follows:
      17: **
      18: **	The algorithm is applied once to each variable used in the
      19: **	query.  Each variable has an initial check performed to
      20: **	determine applicability -- if the current user owns the
      21: **	relation, or if the relation is specially marked as being
      22: **	"all access to everyone", then the algorithm is skipped,
      23: **	thereby having effectively no restriction.
      24: **
      25: **	The set of all such variables is computed in 'protect',
      26: **	and then 'dopro' is called to process each of those.  This
      27: **	is so the protection algorithm does not get applied recursively
      28: **	to constraints which define more than one variable.  Notice
      29: **	that this could in itself be a protection violation, if it
      30: **	were acceptable to reference a relation you do not own in a
      31: **	PERMIT statement.
      32: **
      33: **	The effective query mode for this variable is then computed.
      34: **	This is the same as the query mode of the whole query if
      35: **	the variable in question is the result variable, otherwise
      36: **	it is "retrieve" mode.
      37: **
      38: **	The next step is to scan the query tree and create sets of
      39: **	domains referenced.  Four sets are created:
      40: **		uset -- the set of domains updated (actually,
      41: **			referenced in the target list -- on a
      42: **			retrieve, this will be the set of domains
      43: **			retrieved to the user).
      44: **		rset -- the set of domains retrieved in some
      45: **			context other than the left hand side of
      46: **			an equal sign.
      47: **		aset -- the set of domains aggregated.  This only
      48: **			includes domains aggregated with a simple
      49: **			aggregate (not an aggregate function) with
      50: **			no qualification, since it may be possible
      51: **			to come up with too much information other-
      52: **			wise.
      53: **		qset -- the set of domains retrieved for use in
      54: **			a qualification, but never stored.  This
      55: **			includes domains in a qualification of an
      56: **			aggregate or aggregate function.
      57: **	For more details of domains in each of these sets, look at
      58: **	the routine 'makedset'.
      59: **
      60: **	If we had a retrieve operation in the first place, we will
      61: **	then merge 'uset' into 'rset' and clear 'uset', so that
      62: **	now 'uset' only contains domains which are actually updated,
      63: **	and 'rset' contains all domains which are retrieved.
      64: **
      65: **	Now that we know what is referenced, we can scan the protection
      66: **	catalog.  We scan the entire catalog once for each variable
      67: **	mentioned in the query (except as already taken care of as
      68: **	described above).
      69: **
      70: **	We must create a set of all operations on this variable which
      71: **	are not yet resolved, that is, for which no PERMIT statements
      72: **	which qualify have been issued.  We store this set in the
      73: **	variable "noperm".  As PERMIT statements are found, bits will
      74: **	be cleared.  If the variable is not zero by the end of the
      75: **	scan of the protection catalog, then we reject the query,
      76: **	saying that we don't have permission -- giving us default
      77: **	to deny.
      78: **
      79: **	For each tuple in the protection catalog for this relation,
      80: **	we call "proappl" to see if it applies to this query.  This
      81: **	routine checks the user, terminal, time of day, and so forth
      82: **	(in fact, everything which is query-independent) and tells
      83: **	whether this tuple might apply.
      84: **
      85: **	If the tuple passes this initial check, we then do the query-
      86: **	dependent checking.  This amounts to calling "prochk" once
      87: **	for each operation (and domain set) in the query.  What we
      88: **	get back is a set of operations which this tuple applies to.
      89: **	If zero, the tuple doesn't apply at all; otherwise, it
      90: **	applies to at least one operation.  If it applies to some-
      91: **	thing, we call it "interesting".
      92: **
      93: **	For "interesting" tuples, we now get the corresponding
      94: **	qualification (if one exists), and disjoin it to a set of
      95: **	protection constraints held in "pqual".  Also, we mark
      96: **	any operations we found as having been done, by clearing
      97: **	bits in "noperm".
      98: **
      99: **	When we have completed scanning the protection catalog,
     100: **	we check "noperm".  If it is non-zero, then we have some
     101: **	operation for which a PERMIT statement has not been issued,
     102: **	and we issue an error message.  If this variable is ok,
     103: **	then we go on and try the next variable.
     104: **
     105: **	When all variables have been accounted for, we check to
     106: **	see if we have any qualifications collected from the
     107: **	protection algorithm.  If so, we conjoin them to the
     108: **	query tree.
     109: **
     110: **	Finally, we return the root of the modified tree.  This
     111: **	tree is guaranteed to have no authorization violations,
     112: **	and may be run as a regular query.
     113: **
     114: **	Parameters:
     115: **		root -- the root of the tree.
     116: **
     117: **	Returns:
     118: **		The root of the modified and authorized tree.
     119: **
     120: **	Side Effects:
     121: **		A possible non-local return on access violation.
     122: **
     123: **	Defined Constants:
     124: **		none
     125: **
     126: **	Defines:
     127: **		Proopmap -- a mapping from query modes to operation
     128: **			set bits in the protection catalog.
     129: **		protect -- the driver for the protection algorithm.
     130: **		dopro -- the guts of the algorithm.
     131: **		makedset -- the routine to make the domain sets.
     132: **		proappl -- to check if a protection tuple applies.
     133: **		prochk -- to check what operations it handles.
     134: **		pr_set -- debugging set print.
     135: **
     136: **	Requires:
     137: **		Prodes -- an open descriptor for the protection
     138: **			catalog.
     139: **		access methods.
     140: **		gettree() -- to get the qualification for a particular
     141: **			PERMIT statement.
     142: **		ferror -- to signal an error on a protection
     143: **			violation.
     144: **		appqual() -- to append the protection qualification
     145: **			(conjunctively) to the query tree.
     146: **		Usercode -- set to the current user -- used to
     147: **			determine applicability of a particular
     148: **			protection tuple.
     149: **		Terminal -- set to the terminal id for the current
     150: **			terminal, blank if background.  This is used
     151: **			similarly.
     152: **		localtime() -- system routine to convert a system
     153: **			date to a vector of day, month, day-of-week,
     154: **			etc.
     155: **		tree() -- to create an OR node.
     156: **		norml() -- to renormalize the tree.
     157: **
     158: **	Called By:
     159: **		qrymod()
     160: **
     161: **	Files:
     162: **		'protect' relation -- the relation holding the
     163: **			protection information.
     164: **		'violation' relation -- the relation into which
     165: **			protection violations are logged.
     166: **			Not supported in this version.
     167: **		'tree' relation -- holds the query trees for the
     168: **			PERMIT statements.
     169: **
     170: **	Trace Flags:
     171: **		50 - 59
     172: **
     173: **	Diagnostics:
     174: **		3500 -- Protection violation.
     175: **
     176: **	Syserrs:
     177: **		protect: null tree
     178: **			The tree fetched from the 'tree' catalog
     179: **			was effectively null.
     180: **		protect: get
     181: **			A bad return from the 'get' on the protect
     182: **			catalog.
     183: **
     184: **	History:
     185: **		2/14/79 -- version 6.2 release.
     186: */
     187:
     188: int Proopmap[MAXPROQM + 1] =
     189: {
     190:     PRO_RETR,       /* 0 -- mdRETTERM */
     191:     PRO_RETR,       /* 1 -- mdRETR */
     192:     PRO_APP,        /* 2 -- mdAPP */
     193:     PRO_REPL,       /* 3 -- mdREPL */
     194:     PRO_DEL,        /* 4 -- mdDEL */
     195: };
     196:
     197: extern struct descriptor    Prodes;
     198: # ifndef xV7_UNIX
     199: extern char         Terminal;
     200: # endif
     201: # ifdef xV7_UNIX
     202: extern char         Terminal[3];
     203: # endif
     204: extern QTREE            *gettree();
     205:
     206:
     207: QTREE *protect(root)
     208: QTREE   *root;
     209: {
     210:     QTREE       *r;
     211:     register int    i;
     212:     register int    vn;
     213:     int     qmode;
     214:     int     varset;
     215:
     216:     r = root;
     217:
     218: #	ifdef xQTR1
     219:     tTfp(50, -1, "\n->PROTECT\n\n");
     220: #	endif
     221:
     222:     varset = 0;
     223:
     224:     /*
     225: 	**  Scan the range table and create a set of all variables
     226: 	**  which are 'interesting', that is, on which the protectin
     227: 	**  algorithm should be performed.
     228: 	*/
     229:
     230:     for (vn = 0; vn < MAXVAR + 1; vn++)
     231:     {
     232:         if (!Rangev[vn].rused)
     233:             continue;
     234:
     235:         /* if owner, accept any query */
     236:         if (bequal(Rangev[vn].rowner, Usercode, 2))
     237:             continue;
     238:
     239:         /* check for "no restriction" bit asserted (= clear) */
     240:         if ((Rangev[vn].rstat & S_PROTALL) == 0)
     241:             continue;
     242:         if ((Rangev[vn].rstat & S_PROTRET) == 0 &&
     243:             (Qmode == mdRETR || Qmode == mdRET_UNI))
     244:             continue;
     245:
     246:         varset |= 1 << vn;
     247:     }
     248:
     249:     /*
     250: 	**  For each variable specified in varset (that is, for each
     251: 	**  variable in the initial query), do the real algorithm.
     252: 	*/
     253:
     254:     for (vn = 0; vn < MAXVAR + 1; vn++)
     255:     {
     256:         if ((varset & (1 << vn)) == 0)
     257:             continue;
     258:
     259: #		ifdef xQTR1
     260:         if (tTf(50, 1))
     261:             printf("\nvn=%d: %.12s\n", vn, Rangev[vn].relid);
     262: #		endif
     263:
     264:         /*
     265: 		**  Determine the query mode for this variable.  This
     266: 		**  is not the query mode of the original query,
     267: 		**  unless the variable is the result variable.
     268: 		*/
     269:
     270:         qmode = Qmode;
     271:         if (vn != Resultvar || qmode == mdRET_UNI)
     272:             qmode = mdRETTERM;
     273:
     274: #		ifdef xQTR3
     275:         if (qmode == 1 || qmode > 4 || qmode < 0)
     276:             syserr("protect: bad qmode %d", qmode);
     277: #		endif
     278:
     279:         /* do the interesting part of the algorithm */
     280:         dopro(vn, r, qmode, NULL);
     281:     }
     282:
     283:     /* return the (authorized) tree */
     284: #	ifdef xQTR1
     285:     if (tTf(50, 15))
     286:         treepr(r, "PROTECT->");
     287: #	endif
     288:     return (r);
     289: }
     290: /*
     291: **  DOPRO -- actually do the protection algorithm
     292: **
     293: **	This is the guts of it, broken off because it must be called
     294: **	recursively on aggregates.  The algorithm is as discussed
     295: **	in the module header.
     296: **
     297: **	Parameters:
     298: **		varno -- the variable number of interest.
     299: **		root -- the root of the tree to modify.
     300: **		qmode -- the effective query mode for this relation.
     301: **		byset -- if non-NULL, a set of domains passed back
     302: **			which gets bound out of the aggregate func,
     303: **			in other words, the by list.
     304: **
     305: **	Returns:
     306: **		none
     307: **
     308: **	Side Effects:
     309: **		The tree pointed at by 'root' gets modified.
     310: **		Quite possibly 'Rangev' and 'Remap' get clobbered.
     311: **
     312: **	Requires:
     313: **		makedset -- to create domain usage sets, also
     314: **			detects aggregates and calls 'dopro'
     315: **			recursively.
     316: **		proappl -- to do query-independent checking for
     317: **			protection tuple applicability.
     318: **		prochk -- to do query-dependent checking for protection
     319: **			tuple applicability.
     320: **		appqual -- to add the protection qualification.
     321: **		norml -- to renormalize the tree, what with all those
     322: **			messy OR nodes and all.
     323: **		trimqlend -- to adjust the tree for norml.
     324: **
     325: **	Called By:
     326: **		protect
     327: **		makedset -- on aggregates and aggregate functions.
     328: **
     329: **	Trace Flags:
     330: **		51
     331: */
     332:
     333: dopro(varno, root, qmode, byset)
     334: int varno;
     335: QTREE   *root;
     336: int qmode;
     337: int byset[8];
     338: {
     339:     int     qset[8];
     340:     int     uset[8];
     341:     int     aset[8];
     342:     int     rset[8];
     343:     int     zeros[8];
     344:     QTREE       *p;
     345:     QTREE       *pqual;
     346:     register int    i;
     347:     register int    vn;
     348:     register QTREE  *t;
     349:     int     noperm;
     350:     int     noqual;
     351:     struct protect  prokey, protup;
     352:     struct tup_id   lotid, hitid;
     353:     struct qvect
     354:     {
     355:         QTREE   *q_qual;
     356:         int q_mode;
     357:     };
     358:     struct qvect    quals[4];
     359:     int     j;
     360:     QTREE       *trimqlend(), *tree(), *norml();
     361:
     362:     t = root;
     363:     vn = varno;
     364:
     365:     /* create domain usage sets */
     366:     for (i = 0; i < 8; i++)
     367:     {
     368:         zeros[i] = uset[i] = rset[i] = qset[i] = aset[i] = 0;
     369:         if (byset != NULL)
     370:             byset[i] = 0;
     371:     }
     372:
     373:     /*
     374: 	**  Create domain usage set for target list side.  There are
     375: 	**  two general cases: this is the root of the tree, or this
     376: 	**  is the head of an aggregate.
     377: 	*/
     378:
     379:     switch (t->sym.type)
     380:     {
     381:       case AGHEAD:
     382:         /*
     383: 		**  An aggregate head falls into two classes: simple
     384: 		**  aggregate and aggregate function.  In an aggregate
     385: 		**  function, care must be taken to bind the variables
     386: 		**  in the by-list outside of the aggregate.  We use
     387: 		**  'rset' as a temporary here.
     388: 		*/
     389:
     390:         if (t->left->sym.type == BYHEAD)
     391:         {
     392:             /* make by-list set */
     393:             makedset(vn, t->left->left, NULL, rset, aset, qset);
     394:
     395:             /* merge by-list set into qualification set */
     396:             for (i = 0; i < 8; i++)
     397:             {
     398:                 if (byset != NULL)
     399:                     byset[i] |= rset[i];
     400:                 qset[i] |= rset[i];
     401:                 rset[i] = 0;
     402:             }
     403:
     404:             /* make aggregate list set */
     405:             makedset(vn, t->left->right->right, NULL, rset, aset, qset);
     406:         }
     407:         else
     408:         {
     409:             /* simple aggregate */
     410: #			ifdef xQTR3
     411:             if (t->left->sym.type != AOP)
     412:                 syserr("dopro: AGHEAD->left %d", t->left->sym.type);
     413: #			endif
     414:
     415:             /* check for qualification */
     416:             if (t->right->sym.type == QLEND)
     417:             {
     418:                 /* simple, unqualified aggregate */
     419:                 makedset(vn, t->left->right, NULL, aset, aset, qset);
     420:             }
     421:             else
     422:             {
     423: #				ifdef xQTR3
     424:                 if (t->right->sym.type != AND)
     425:                     syserr("dopro: AND=%d", t->right->sym.type);
     426: #				endif
     427:                 makedset(vn, t->left->right, NULL, rset, aset, qset);
     428:             }
     429:         }
     430:         break;
     431:
     432:       case ROOT:
     433:         makedset(vn, t->left, uset, rset, aset, qset);
     434:         break;
     435:     }
     436:
     437:     /* scan qualifcation */
     438:     makedset(vn, t->right, NULL, &qset, &aset, &qset);
     439:
     440:     /* if retrieval, drop the 'update' set */
     441:     if (qmode == mdRETTERM)
     442:     {
     443:         for (i = 0; i < 8; i++)
     444:         {
     445:             uset[i] = 0;
     446:         }
     447:     }
     448:
     449: #	ifdef xQTR1
     450:     if (tTf(51, 2))
     451:     {
     452:         printf("qmode %d\n", qmode);
     453:         pr_set(uset, "uset");
     454:         pr_set(rset, "rset");
     455:         pr_set(aset, "aset");
     456:         pr_set(qset, "qset");
     457:     }
     458: #	endif
     459:
     460:     /* create a bit map of all referenced operations */
     461:     noperm = 0;
     462:     if (!bequal(uset, zeros, sizeof zeros))
     463:         noperm |= Proopmap[qmode];
     464:     if (!bequal(&rset, &zeros, sizeof zeros))
     465:         noperm |= PRO_RETR;
     466:     if (!bequal(&aset, &zeros, sizeof zeros))
     467:         noperm |= PRO_AGGR;
     468:     if (!bequal(&qset, &zeros, sizeof zeros))
     469:         noperm |= PRO_TEST;
     470:
     471:     /* if no oper, then the query was probably just aggr's */
     472:     if (noperm == 0)
     473:         return;
     474:
     475:     /* initialize qualification portion */
     476:     for (i = 0; i < 4; )
     477:         quals[i++].q_qual = NULL;
     478:     noqual = FALSE;
     479:
     480:     /* check the protection catalog */
     481:     opencatalog("protect", 0);
     482:     setkey(&Prodes, &prokey, Rangev[vn].relid, PRORELID);
     483:     setkey(&Prodes, &prokey, Rangev[vn].rowner, PRORELOWN);
     484:     find(&Prodes, EXACTKEY, &lotid, &hitid, &prokey);
     485:
     486:     while ((i = get(&Prodes, &lotid, &hitid, &protup, TRUE)) == 0)
     487:     {
     488:         if (kcompare(&Prodes, &prokey, &protup) != 0)
     489:             continue;
     490:
     491: #		ifdef xQTR2
     492:         if (tTf(51, 4))
     493:         {
     494:             printf("PROTECT: ");
     495:             printup(&Prodes, &protup);
     496:         }
     497: #		endif
     498:
     499:         /* check if this is the correct user, terminal, etc */
     500:         if (!proappl(&protup))
     501:             continue;
     502:
     503:         /* alright, let's check the operation */
     504:         i = 0;
     505:         if (qmode != mdRETTERM)
     506:             i = quals[0].q_mode = prochk(Proopmap[qmode], &uset, &protup);
     507:         i |= quals[1].q_mode = prochk(PRO_RETR, &rset, &protup);
     508:         i |= quals[2].q_mode = prochk(PRO_AGGR, &aset, &protup);
     509:         i |= quals[3].q_mode = prochk(PRO_TEST, &qset, &protup);
     510:
     511: #		ifdef xQTR2
     512:         if (tTf(51, 5))
     513:             printf("Satisfies operations %o\n", i);
     514: #		endif
     515:
     516:         /* see if this tuple is "interesting" */
     517:         if (i == 0)
     518:             continue;
     519:
     520:         /* it is!  get the qualification (if any) */
     521:         if (protup.protree >= 0)
     522:         {
     523:             p = gettree(Rangev[vn].relid, Rangev[vn].rowner, mdPROT, protup.protree, FALSE);
     524: #			ifdef xQTR2
     525:             if (tTf(51, 6))
     526:                 treepr(p, "Protection Clause");
     527: #			endif
     528:             p = trimqlend(p->right);
     529: #			ifdef xQTR3
     530:             /* check for a non-null qualification */
     531:             if (p == NULL)
     532:                 syserr("protect: null tree");
     533: #			endif
     534:
     535:             /* translate to the interesting variable */
     536:             j = protup.proresvar;
     537:             if (Remap[j] >= 0)
     538:                 j = Remap[j];
     539:             mergevar(j, varno, p);
     540:
     541:             /* disjoin the protection qual to real qual */
     542:             for (j = 0; j < 4; j++)
     543:             {
     544:                 if (quals[j].q_mode == 0)
     545:                     continue;
     546:                 if (quals[j].q_qual == NULL)
     547:                     quals[j].q_qual = p;
     548:                 else
     549:                     quals[j].q_qual = tree(quals[j].q_qual, p, OR, 0);
     550:             }
     551:         }
     552:         else
     553:             noqual = TRUE;
     554:
     555:         /* mark this operation as having been handled */
     556:         noperm &= ~i;
     557:     }
     558:
     559:     /* test 'get' return code */
     560:     if (i < 0)
     561:         syserr("protect: get");
     562:
     563: #	ifdef xQTR1
     564:     if (tTf(51, 12))
     565:         printf("No perm on %o\n", noperm);
     566: #	endif
     567:
     568:     /* see if no tuples applied for some operation */
     569:     if (noperm != 0)
     570:         ferror(3500, Qmode, vn, 0);
     571:
     572:     /* see if we want to modify the query at all */
     573:     if (!noqual)
     574:     {
     575:         /* conjoin the qualification */
     576:         pqual = NULL;
     577:         for (i = 0; i < 4; i++)
     578:             if (quals[i].q_qual != NULL)
     579:                 if (pqual == NULL)
     580:                     pqual = quals[i].q_qual;
     581:                 else
     582:                     pqual = tree(pqual, quals[i].q_qual, AND, 0);
     583:         pqual = tree(pqual, tree(NULL, NULL, QLEND, 0), AND, 0);
     584:         appqual(pqual, t);
     585:
     586:         /* normalize the tree */
     587:         t->right = norml(trimqlend(t->right));
     588:     }
     589: }
     590: /*
     591: **  MAKEDSET -- make domain reference sets
     592: **
     593: **	This routine creates some sets which reflect the usage of
     594: **	domains for a particular variable.
     595: **
     596: **	The interesting nodes are 'case' labels in the large
     597: **	switch statement which comprises most of the code.  To
     598: **	describe briefly:
     599: **
     600: **	VAR nodes are easy: if they are for the current variable,
     601: **		set the bit corresponding to the domain in the
     602: **		'retrieval' set.  They can have no descendents,
     603: **		so just return.
     604: **	RESDOM nodes are also easy: they can be handled the same,
     605: **		but the bit is set in the 'update' set instead.
     606: **	AGHEAD nodes signal the beginning of an aggregate or
     607: **		aggregate function.  In this case, we scan the
     608: **		qualification first (noting that RESDOM and VAR
     609: **		nodes are processed as 'qualification' sets
     610: **		instead of 'retrieval' or 'update' sets).  Then,
     611: **		if the aggregate has a WHERE clause or a BY list,
     612: **		we treat it as a retrieve; otherwise, we call our-
     613: **		selves recursively treating VAR nodes as 'aggregate'
     614: **		types rather than 'retrieve' types.
     615: **	BYHEAD nodes signal the beginning of a BY list.  The left
     616: **		subtree (the actual BY-list) is processed with
     617: **		RESDOM nodes ignored (since they are pseudo-domains
     618: **		anyhow) and VAR nodes mapped into the 'qualification'
     619: **		set.  Then we check the right subtree (which better
     620: **		begin with an AOP node!) and continue processing.
     621: **	AOP nodes must have a null left subtree, so we just drop
     622: **		to the right subtree and iterate.  Notice that we
     623: **		do NOT map VAR nodes into the 'aggregate' set for
     624: **		this node, since this has already been done by the
     625: **		AGHEAD node; also, this aggregate might be counted
     626: **		as a retrieve operation instead of an aggregate
     627: **		operation (as far as the protection system is con-
     628: **		cerned) -- this has been handled by the AGHEAD
     629: **		node.
     630: **	All other nodes are processed recursively along both edges.
     631: **
     632: **	Parameters:
     633: **		vn -- the variable number that we are currently
     634: **			interested in.
     635: **		tree -- the root of the tree to scan.  Notice that this
     636: **			will in general be only one half of the tree --
     637: **			makedset will be called once for the target
     638: **			list and once for the qualification, with
     639: **			different sets for the following parameters.
     640: **		uset -- adjusted to be the set of all domains
     641: **			updated.
     642: **		rset -- adjusted to be the set of all domains
     643: **			retrieved implicitly, that is, on the right-
     644: **			hand-side of an assignment operator.
     645: **		aset -- adjusted to be the set of all domains
     646: **			aggregated.  Notice that this set is not
     647: **			adjusted explicitly, but rather is passed
     648: **			to recursive incarnations of this routine
     649: **			as 'rset'.
     650: **		qset -- adjusted to be the set of domains retrieved
     651: **			implicitly in a qualification.  Like 'aset',
     652: **			this is passed as 'rset' to recursive
     653: **			incarnations.
     654: **
     655: **	Returns:
     656: **		none
     657: **
     658: **	Side Effects:
     659: **		none
     660: **
     661: **	Requires:
     662: **		lsetbit()
     663: **
     664: **	Called By:
     665: **		protect() -- in two places.
     666: **
     667: **	Trace Flags:
     668: **		53
     669: **
     670: **	Diagnostics:
     671: **		none
     672: **
     673: **	Syserrs:
     674: **		makedset: AOP->left
     675: **			A truly obscure error message, this means
     676: **			that the left subtree of an AOP node was
     677: **			not null.
     678: **		makedset: AOP %d
     679: **			Another goodie, this one means that the
     680: **			right branch of a BYHEAD node was not an
     681: **			AOP node as required; the %d is the type
     682: **			it actually was.
     683: */
     684:
     685: makedset(vn, tree, uset, rset, aset, qset)
     686: int vn;
     687: QTREE   *tree;
     688: int uset[8];
     689: int rset[8];
     690: int aset[8];
     691: int qset[8];
     692: {
     693:     register QTREE  *t;
     694:     register int    i;
     695:     int     byset[8];
     696:
     697:     t = tree;
     698:
     699: #	ifdef xQTR1
     700:     if (tTf(53, 0))
     701:     {
     702:         printf("->makedset\n");
     703:         pr_set(uset, "uset");
     704:         pr_set(rset, "rset");
     705:         pr_set(aset, "aset");
     706:         pr_set(qset, "qset");
     707:     }
     708: #	endif
     709:
     710:     while (t != NULL)
     711:     {
     712:         switch (t->sym.type)
     713:         {
     714:           case VAR:
     715:             if (((struct qt_var *)t)->varno == vn)
     716:                 lsetbit(((struct qt_var *)t)->attno, rset);
     717:             break;
     718:
     719:           case AGHEAD:
     720:             /* do protection on qualification */
     721:             dopro(vn, t, -1, byset);
     722:
     723:             /* merge by-list set into qualification set */
     724:             for (i = 0; i < 8; i++)
     725:                 qset[i] |= byset[i];
     726:
     727:             break;
     728:
     729:           case BYHEAD:
     730:           case AOP:
     731:             syserr("makedset: node %d", t->sym.type);
     732:
     733:           case RESDOM:
     734:             if (((struct qt_res *)t)->resno == 0)
     735:             {
     736:                 /* tid -- ignore right subtree (and this node) */
     737:                 t = t->left;
     738:                 continue;
     739:             }
     740:             if (uset != NULL)
     741:                 lsetbit(((struct qt_res *)t)->resno, uset);
     742:             /* explicit fall-through to "default" case */
     743:
     744:           default:
     745:             /* handle left subtree (recursively) */
     746:             makedset(vn, t->left, uset, rset, aset, qset);
     747:
     748:             /* handle right subtree (iteratively) */
     749:             t = t->right;
     750:             continue;
     751:         }
     752:         break;
     753:     }
     754:
     755: #	ifdef xQTR1
     756:     if (tTf(53, 15))
     757:     {
     758:         printf("makedset->\n");
     759:         pr_set(uset, "uset");
     760:         pr_set(rset, "rset");
     761:         pr_set(aset, "aset");
     762:         pr_set(qset, "qset");
     763:     }
     764: #	endif
     765:
     766:     return;
     767: }
     768: /*
     769: **  PROAPPL -- check for protection tuple applicable
     770: **
     771: **	A given protection catalog tuple is checked in a query-
     772: **	independent way for applicability.
     773: **
     774: **	This routine checks such environmental constraints as the
     775: **	user, the terminal, and the time of day.  The code is
     776: **	fairly straightforward, just take a look.
     777: **
     778: **	One note: the user and terminal codes contained in the
     779: **	protection catalog are blank to mean 'any value' of the
     780: **	corresponding field.
     781: **
     782: **	Parameters:
     783: **		protup -- the protection tuple to compare against.
     784: **
     785: **	Returns:
     786: **		TRUE -- this tuple applies to the current environment.
     787: **		FALSE -- this tuple does not apply.
     788: **
     789: **	Side Effects:
     790: **		none (unless you include trashing the static vector
     791: **			returned by localtime).
     792: **
     793: **	Requires:
     794: **		localtime()
     795: **		Usercode -- the code for the current user.
     796: **		Terminal -- the result of a 'ttyn()' call, that is,
     797: **			the current terminal id.  This should be
     798: **			blank if running in background.
     799: **
     800: **	Called By:
     801: **		protect()
     802: **
     803: **	Trace Flags:
     804: **		54
     805: **
     806: **	Diagnostics:
     807: **		none
     808: **
     809: **	Syserrs:
     810: **		none
     811: **
     812: **	History:
     813: **		8/21/78 (eric) -- written.
     814: */
     815:
     816: proappl(protup)
     817: struct protect  *protup;
     818: {
     819:     register struct protect *p;
     820:     int         tvect[2];
     821:     register int        *tt;
     822:     extern int      *localtime();
     823:     register int        mtime;
     824:
     825:     p = protup;
     826:
     827:     /* check for correct user [insert clique code here] */
     828:     if (!bequal("  ", p->prouser, 2))
     829:     {
     830:         if (!bequal(p->prouser, Usercode, 2))
     831:             return (FALSE);
     832:     }
     833:
     834:     /* check for correct terminal */
     835: #	ifndef xV7_UNIX
     836:     if (p->proterm != ' ')
     837:     {
     838:         if (p->proterm != Terminal)
     839:             return (FALSE);
     840:     }
     841: #	endif
     842: #	ifdef xV7_UNIX
     843:     if (p->proterm[0] != ' ')
     844:     {
     845:         if (!bequal(p->proterm, Terminal, 2))
     846:             return (FALSE);
     847:     }
     848: #	endif
     849:
     850:     /* check for correct time of day & week */
     851:     time(tvect);
     852:     tt = localtime(tvect);
     853:     mtime = tt[2] * 60 + tt[1];
     854:
     855:     if (p->protodbgn > mtime || p->protodend < mtime)
     856:         return (FALSE);
     857:     if (p->prodowbgn > tt[6] || p->prodowend < tt[6])
     858:         return (FALSE);
     859:
     860:     /* hasn't failed yet -- I guess it's ok */
     861:     return (TRUE);
     862: }
     863: /*
     864: **  PROCHK -- query-dependent protection tuple check
     865: **
     866: **	This routine does the query-dependent part of checking
     867: **	the validity of a protection tuple.  Unlike proappl,
     868: **	which looked at aspects of the environment but not the
     869: **	query being run, this routine assumes that the environ-
     870: **	ment is ok, and checks that if it applies to this tuple.
     871: **
     872: **	Two things are checked.  The first is if this tuple applies
     873: **	to the operation in question (passed as 'inbit').  The
     874: **	second is if the set of domains in the tuple contains the
     875: **	set of domains in the query.  If either of these fail,
     876: **	the return is zero.  Otherwise the return is the operation
     877: **	bit.  In otherwise, the return is the operation to which
     878: **	this tuple applies (if any).
     879: **
     880: **	As a special check, the domain set is checked for all
     881: **	zero.  If so, no domains have been referenced for this
     882: **	operation at all, and we return zero.  In other words, this
     883: **	tuple might apply to this operation, but since we don't
     884: **	use the operation anyhow we will ignore it.  It is important
     885: **	to handle things in this way so that the qualification for
     886: **	this tuple doesn't get appended if the variable is not
     887: **	used in a particular context.
     888: **
     889: **	Parameters:
     890: **		inbit -- the bit describing the operation to be
     891: **			checked.  Note that only one bit should
     892: **			be set in this word, although this is
     893: **			not checked.
     894: **		domset -- the set of domains actually referenced
     895: **			in this query for the operation described
     896: **			by 'inbit'.
     897: **		protup -- the tuple in question.
     898: **
     899: **	Returns:
     900: **		The operation (if any) to which this tuple applies.
     901: **
     902: **	Side Effects:
     903: **		none
     904: **
     905: **	Called By:
     906: **		protect() -- in four places.
     907: **
     908: **	Trace Flags:
     909: **		55
     910: **
     911: **	Diagnostics:
     912: **		none
     913: **
     914: **	Syserrs:
     915: **		none
     916: **
     917: **	History:
     918: **		8/21/78 (eric) -- written.
     919: */
     920:
     921: prochk(inbit, domset, protup)
     922: int     inbit;
     923: int     domset[8];
     924: struct protect  *protup;
     925: {
     926:     register struct protect *p;
     927:     register int        *d;
     928:     register int        i;
     929:
     930:     p = protup;
     931:     d = domset;
     932:
     933: #	ifdef xQTR1
     934:     if (tTf(55, 0))
     935:     {
     936:         printf("->prochk, inbit=%o, proopset=%o\n", inbit, p->proopset);
     937:         pr_set(d, "domset");
     938:         pr_set(p->prodomset, "prodomset");
     939:     }
     940: #	endif
     941:
     942:     /* check for null domain set, if so return zero */
     943:     for (i = 0; i < 8; i++)
     944:         if (d[i] != 0)
     945:             break;
     946:     if (i >= 8)
     947:     {
     948: #		ifdef xQTR2
     949:         tTfp(55, 15, "prochk-> null set\n");
     950: #		endif
     951:         return (0);
     952:     }
     953:
     954:     /* see if this tuple applies to this operation */
     955:     if ((inbit & p->proopset) == 0)
     956:     {
     957: #		ifdef xQTR2
     958:         tTfp(55, 15, "prochk-> no op\n");
     959: #		endif
     960:         return (0);
     961:     }
     962:
     963:     /* check if domains are a subset */
     964:     for (i = 0; i < 8; i++)
     965:     {
     966:         if ((d[i] & ~p->prodomset[i]) != 0)
     967:         {
     968:             /* failure */
     969: #			ifdef xQTR2
     970:             tTfp(55, 15, "prochk-> not subset\n");
     971: #			endif
     972:             return (0);
     973:         }
     974:     }
     975:
     976:     /* this is hereby an "interesting" tuple */
     977: #	ifdef xQTR2
     978:     if (tTf(55, 15))
     979:         printf("prochk-> %d\n", inbit);
     980: #	endif
     981:     return (inbit);
     982: }
     983:
     984: # ifdef xQTR1
     985:
     986: /*
     987: **  PR_SET -- print set for debugging
     988: **
     989: **	This routine prints a 128-bit set for debugging.
     990: **
     991: **	Parameters:
     992: **		xset -- the set to convert.
     993: **		labl -- a label to print before the set.
     994: **
     995: **	Returns:
     996: **		a pointer to the converted string.
     997: **
     998: **	Side Effects:
     999: **		none
    1000: **
    1001: **	History:
    1002: **		8/22/78 (eric) -- written.
    1003: */
    1004:
    1005: pr_set(xset, labl)
    1006: int xset[8];
    1007: char    *labl;
    1008: {
    1009:     register int    *x;
    1010:     register int    i;
    1011:     register long   *y;
    1012:
    1013:     printf("\t%s: ", labl);
    1014:     y = (long *) (x = xset);
    1015:     if (x == NULL)
    1016:     {
    1017:         printf("<NULL>\n");
    1018:         return;
    1019:     }
    1020:     for (i = 7; i >= 0; i--)
    1021:         printf("%o/", x[i]);
    1022:     printf(" <> ");
    1023:     for (i = 0; i < 4; i++)
    1024:         printf("/%s", locv(y[i]));
    1025:     printf("\n");
    1026: }
    1027:
    1028: # endif

#### Defined functions

dopro defined in line 333; used 2 times

- in line 280, 721

makedset defined in line 685; used 7 times

- in line 393, 405, 419, 427, 433-438(2), 746

pr_set defined in line 1005; used 15 times

- in line 453-456(4), 703-706(4), 759-762(4), 937-938(2)
- in /usr/ingres/source/qrymod/integrity.c line 116

proappl defined in line 816; used 1 times

- in line 500

prochk defined in line 921; used 4 times

- in line 506-509(4)

protect defined in line 207; used 2 times

- in /usr/ingres/source/qrymod/qrymod.c line 43, 59

#### Defined variables

Proopmap defined in line 188; used 2 times

- in line 463, 506

#### Defined struct's

qvect defined in line 353; used 2 times

- in line 358(2)

Last modified: 1995-02-19 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2099 |