Annotation of 43BSD/ingres/source/qrymod/protect.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.