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