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
makedset defined in line 685; used 7 times
pr_set defined in line 1005; used 15 times
proappl defined in line 816; used 1 times
prochk defined in line 921; used 4 times
protect defined in line 207; used 2 times

Defined variables

Proopmap defined in line 188; used 2 times

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: 4853
Valid CSS Valid XHTML 1.0 Strict