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

unix.superglobalmegacorp.com

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