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