|
|
1.1 ! root 1: /* add_alias.c - a mutilated add.c*/ ! 2: ! 3: #ifndef lint ! 4: static char *rcsid = "$Header: /f/osi/others/quipu/uips/manage/RCS/add_alias.c,v 7.1 90/07/27 08:47:16 mrose Exp $"; ! 5: #endif ! 6: ! 7: /* ! 8: * $Header: /f/osi/others/quipu/uips/manage/RCS/add_alias.c,v 7.1 90/07/27 08:47:16 mrose Exp $ ! 9: * ! 10: * ! 11: * $Log: add_alias.c,v $ ! 12: * Revision 7.1 90/07/27 08:47:16 mrose ! 13: * update ! 14: * ! 15: * Revision 7.0 90/06/26 14:52:31 mrose ! 16: * *** empty log message *** ! 17: * ! 18: */ ! 19: ! 20: /* ! 21: * NOTICE ! 22: * ! 23: * Acquisition, use, and distribution of this module and related ! 24: * materials are subject to the restrictions of a license agreement. ! 25: * Consult the Preface in the User's Manual for the full terms of ! 26: * this agreement. ! 27: * ! 28: */ ! 29: ! 30: ! 31: #include "quipu/util.h" ! 32: #include "quipu/dua.h" ! 33: #include "quipu/add.h" ! 34: #include "quipu/entry.h" ! 35: #include "quipu/compare.h" ! 36: #include "quipu/modify.h" ! 37: ! 38: #define ORG_PERSON "thornPerson & quipuObject" ! 39: /* this should probably go elsewhere !!! */ ! 40: ! 41: extern DN dn; ! 42: #define OPT (!frompipe || rps -> ps_byteno == 0 ? opt : rps) ! 43: #define RPS (!frompipe || opt -> ps_byteno == 0 ? rps : opt) ! 44: extern char frompipe; ! 45: extern PS opt; ! 46: extern PS rps; ! 47: extern Entry current_entry; ! 48: static char new_draft; ! 49: ! 50: call_add_alias (argc, argv) ! 51: int argc; ! 52: char **argv; ! 53: { ! 54: DN oj_dn, aoj_dn ; ! 55: DN save_dn, dnptr, trail ; ! 56: DN moddn; ! 57: extern DN str2dn_aux() ; ! 58: extern DN sequence_dn() ; ! 59: Entry entry_ptr; ! 60: FILE *fd; ! 61: PS tmp ; ! 62: PS str_ps; ! 63: char str_buffer[1000]; ! 64: char fname[128]; ! 65: char alias = FALSE ; ! 66: ! 67: struct ds_addentry_arg add_arg; ! 68: struct DSError error; ! 69: struct DSError compare_error; ! 70: struct ds_compare_result compare_result; ! 71: struct ds_compare_arg compare_arg; ! 72: struct ds_modifyentry_arg mod_arg; ! 73: struct DSError mod_error; ! 74: struct entrymod *emnew ; ! 75: ! 76: AV_Sequence objClassAVS ; ! 77: AV_Sequence treeStrAVS ; ! 78: Attr_Sequence get_attributes(); ! 79: ! 80: extern int parse_status; ! 81: ! 82: int draft_flag = 0; ! 83: char *home; ! 84: char objectname[80] ; ! 85: char aliasobjectname[160] ; ! 86: char *contact_compare[6] ; ! 87: char *contact_showentry[6] ; ! 88: char *contact_modify[1] ; ! 89: ! 90: contact_compare[0] = "compare" ; ! 91: contact_compare[1] = ""; ! 92: contact_compare[2] = "-attribute"; ! 93: contact_compare[4] = "-noprint"; ! 94: contact_compare[5] = "-dontdereferencealias" ; ! 95: contact_showentry[0] = "showentry"; ! 96: contact_showentry[1] = "-noshow" ; ! 97: contact_showentry[2] = "-all" ; ! 98: contact_showentry[3] = "-nokey" ; ! 99: contact_showentry[4] = "-dontdereferencealias"; ! 100: contact_modify[0] = "modify" ; ! 101: ! 102: emnew = em_alloc() ; ! 103: contact_showentry[5] = (char *) malloc ((unsigned)strlen(argv[2])) ; ! 104: (void)strcpy(contact_showentry[5], argv[2]) ; ! 105: ! 106: contact_compare[3] = (char *) malloc ((unsigned)strlen("objectClass=alias.")) ; ! 107: (void)strcpy(contact_compare[3], "objectClass=alias") ; ! 108: ! 109: if (service_control (OPT, 6, contact_compare, &compare_arg.cma_common) == -1) ! 110: { ! 111: ps_print(OPT, "Problems with compare service control flags.\n") ; ! 112: return ; ! 113: } ! 114: ! 115: if (home = getenv ("HOME")) ! 116: (void) sprintf (fname, "%s/.dishdraft", home); ! 117: else ! 118: (void) strcpy (fname, "./.dishdraft"); ! 119: new_draft = FALSE; ! 120: ! 121: if ((argc = service_control (OPT, argc, argv, &add_arg.ada_common)) == -1) ! 122: return ; ! 123: if (argc < 3) ! 124: { ! 125: ps_printf(OPT, "Not enough arguments.\n") ; ! 126: Usage (argv[0]) ; ! 127: return ; ! 128: } ! 129: (void)strcpy(objectname, argv[1]) ; ! 130: (void)strcpy(aliasobjectname, argv[2]) ; ! 131: ! 132: /* Turn a sequence number back into a DN */ ! 133: if (*aliasobjectname >= '0' && *aliasobjectname <= '9') ! 134: { ! 135: /* First convert the number into a dn */ ! 136: aoj_dn = dn_cpy(sequence_dn(atoi(aliasobjectname))) ; ! 137: } ! 138: else ! 139: { ! 140: if (*aliasobjectname == '.') ! 141: { ! 142: ps_print(OPT, "..@ gives me a headache. Ambiguous. Abort... \n") ; ! 143: return ; ! 144: } ! 145: ! 146: if (*aliasobjectname == '@') ! 147: { ! 148: aoj_dn = dn_cpy(str2dn(aliasobjectname + 1)) ; ! 149: } ! 150: else ! 151: { ! 152: /*aoj_dn = dn_cpy(dn) ; ! 153: *dn_append(aoj_dn, dn_cpy(str2dn(aliasobjectname))) ; ! 154: */ ! 155: save_dn = str2dn_aux(aliasobjectname,&alias) ; ! 156: if (save_dn != NULLDN) ! 157: { ! 158: if (alias) ! 159: { ! 160: aoj_dn = dn_cpy(save_dn); ! 161: } ! 162: else ! 163: { ! 164: if (dn == NULLDN) ! 165: { ! 166: aoj_dn = dn_cpy(save_dn) ; ! 167: } ! 168: else ! 169: { ! 170: aoj_dn = dn_cpy(dn) ; ! 171: dn_append (aoj_dn,save_dn); ! 172: } ! 173: } ! 174: } ! 175: dn_free(save_dn) ; ! 176: } ! 177: } ! 178: ! 179: if (*objectname >= '0' && *objectname <= '9') ! 180: { ! 181: /* First convert the number into a dn */ ! 182: oj_dn = dn_cpy(sequence_dn(atoi(objectname))) ; ! 183: } ! 184: else ! 185: { ! 186: if (*objectname == '.') ! 187: { ! 188: ps_print(OPT, "..@ gives me a headache. Ambiguous. Abort... \n") ; ! 189: return ; ! 190: } ! 191: ! 192: if (*objectname == '@') ! 193: { ! 194: oj_dn = dn_cpy(str2dn(objectname + 1)) ; ! 195: } ! 196: else ! 197: { ! 198: oj_dn = dn_cpy(dn) ; ! 199: dn_append(oj_dn, dn_cpy(str2dn(objectname))) ; ! 200: } ! 201: } ! 202: ! 203: save_dn = dn_cpy(dn) ; ! 204: dn_free(dn) ; ! 205: dn = dn_cpy(aoj_dn) ; ! 206: if (!test_move_dn()) ! 207: { ! 208: ps_print(OPT, "Can't move to ") ; ! 209: dn_print(OPT, dn, EDBOUT) ; ! 210: ps_print(OPT, ".\nAborting.\n") ; ! 211: return ; ! 212: } ! 213: compare_arg.cma_object = aoj_dn; ! 214: if (get_ava (&compare_arg.cma_purported, "objectClass", "alias") != OK) ! 215: { ! 216: ps_print(OPT, "Oops, 'objectClass=alias' is a bad attribute!\n") ; ! 217: ps_print(OPT, "This is very bad...\n") ; ! 218: return ; ! 219: } ! 220: ! 221: if (rebind () != OK) ! 222: return ; ! 223: ! 224: while (ds_compare (&compare_arg, &compare_error, &compare_result) != DS_OK) ! 225: { ! 226: if (dish_error (OPT, &compare_error) == 0) ! 227: { ! 228: return ; ! 229: } ! 230: compare_arg.cma_object = compare_error.ERR_REFERRAL.DSE_ref_candidates->cr_name; ! 231: } ! 232: ! 233: if ( compare_result.cmr_matched == 1 ) /* if <AOJ> is an alias, abort. */ ! 234: { ! 235: ps_printf(OPT, "Sorry, %s is an alias.\nAliasing to aliases is illegal.\n", aliasobjectname) ; ! 236: return ; ! 237: } ! 238: ! 239: /* Now we want to discover the objectClass of our object, and make ! 240: * sure that this will be OK when we add in the alias. (ie fitting ! 241: * in with the treeStructure.) ! 242: */ ! 243: ! 244: /* stick the aliasobjectname into the cache so we can read ! 245: * bits of information from it. ! 246: */ ! 247: ! 248: call_showentry(6, contact_showentry) ; ! 249: contact_showentry[5] = (char *) malloc ((unsigned)strlen(argv[2])) ; ! 250: (void)strcpy(contact_showentry[5], argv[2]) ; ! 251: ! 252: if (current_entry == NULLENTRY) ! 253: { ! 254: ps_print(OPT, "Can't read ") ; ! 255: dn_print(OPT, dn, EDBOUT) ; ! 256: ps_print(OPT, " for objectClass attribute. Aborting.\n") ; ! 257: return ; ! 258: } ! 259: else ! 260: { ! 261: /* Find the objectClass attribute to compare with the tree ! 262: * structure of the node we are going to dangle the alias ! 263: * from. ! 264: * While we are at it, find out how many seeAlso attributes ! 265: * are present, so we can decide whether we need to add ! 266: * the entire attribute or just another value. ! 267: */ ! 268: ! 269: Attr_Sequence eptr ; ! 270: AttributeType a_t = AttrT_new("objectClass") ; ! 271: AttributeType a_t2 = AttrT_new("seeAlso") ; ! 272: ! 273: emnew->em_type = EM_ADDATTRIBUTE ; ! 274: for (eptr = current_entry->e_attributes; eptr != NULLATTR; eptr = eptr->attr_link) ! 275: { ! 276: if ( AttrT_cmp (eptr->attr_type, a_t) == 0 ) ! 277: { ! 278: objClassAVS = avs_cpy(eptr->attr_value); ! 279: } ! 280: if ( AttrT_cmp (eptr->attr_type, a_t2) == 0 ) ! 281: { ! 282: emnew->em_type = EM_ADDVALUES ; ! 283: } ! 284: } ! 285: } ! 286: if (objClassAVS == NULLAV) ! 287: { ! 288: ps_print(OPT, "We can't find Object Class.... Aborting.\n") ; ! 289: return ; ! 290: } ! 291: /* We should have got the ObjectClass now, so return to where we were ! 292: * and move up a level to grab the tree structure */ ! 293: ! 294: dn_free(dn) ; ! 295: dn = dn_cpy(oj_dn) ; ! 296: ! 297: for (dnptr = dn; dnptr->dn_parent != NULLDN; dnptr = dnptr->dn_parent) ! 298: trail = dnptr; ! 299: dn_comp_free (dnptr); ! 300: trail->dn_parent = NULLDN; ! 301: ! 302: contact_showentry[1] = ( char *) malloc ((unsigned)strlen("-noshow") + 1) ; ! 303: (void)strcpy(contact_showentry[1], "-noshow") ; ! 304: contact_showentry[2] = ( char *) malloc ((unsigned)strlen("-all") + 1) ; ! 305: (void)strcpy(contact_showentry[2], "-all") ; ! 306: contact_showentry[3] = ( char *) malloc ((unsigned)strlen("-nokey") + 1) ; ! 307: (void)strcpy(contact_showentry[3], "-nokey") ; ! 308: contact_showentry[4] = ( char *) malloc ((unsigned)strlen("-dontdereferencealias") + 1) ; ! 309: (void)strcpy(contact_showentry[4], "-dontdereferencealias") ; ! 310: ! 311: call_showentry(5, contact_showentry) ; ! 312: ! 313: if (current_entry == NULLENTRY) ! 314: { ! 315: ps_print(OPT, "Can't read ") ; ! 316: dn_print(OPT, dn, EDBOUT) ; ! 317: ps_print(OPT, " for the treeStructure. Aborting.\n") ; ! 318: return ; ! 319: } ! 320: else ! 321: { ! 322: Attr_Sequence eptr ; ! 323: AttributeType a_t = AttrT_new("treeStructure") ; ! 324: ! 325: for (eptr = current_entry->e_attributes; eptr != NULLATTR; eptr = eptr->attr_link) ! 326: { ! 327: if ( AttrT_cmp (eptr->attr_type, a_t) == 0 ) ! 328: { ! 329: treeStrAVS = avs_cpy (eptr->attr_value) ; ! 330: } ! 331: } ! 332: } ! 333: ! 334: if (treeStrAVS == NULLAV) ! 335: { ! 336: ps_print(OPT, "Tree Structure Missing in ") ; ! 337: dn_print(OPT, dn, EDBOUT) ; ! 338: ps_print(OPT, ".\nAssuming that the add will be valid.\n") ; ! 339: } ! 340: else ! 341: { ! 342: if (test_schema(treeStrAVS, objClassAVS) != OK) ! 343: { ! 344: ps_print(OPT, "Not allowed to add this alias here.\n") ; ! 345: ps_print(OPT, "It would break the directory schema to add this alias here.\n") ; ! 346: return ; ! 347: } ! 348: } ! 349: ! 350: /* This is where we have to start being rather careful, previously ! 351: * we have just being reading and checking, but now we start to add ! 352: * things in, changing in several places. Mistakes => inconsistencies ! 353: * ie BAD... ! 354: */ ! 355: ! 356: /* If we reach here, we should have the appropriate arguments, ! 357: * one is the new object, ! 358: * the other is an existing non-alias-entry object. ! 359: * We now write the information to a draft file, and 'whongo' ! 360: * the alias into the database. ! 361: */ ! 362: ! 363: /* open the draft file for writing... */ ! 364: ! 365: if ((fd = fopen (fname, "w")) == (FILE *) NULL) ! 366: { ! 367: ps_printf (OPT, "Can't open draft entry %s\n", fname); ! 368: return ; ! 369: } ! 370: ! 371: (void)fprintf(fd, "aliasedObjectName= ") ; ! 372: if ( ((tmp = ps_alloc (std_open)) != NULLPS) && ! 373: (std_setup (tmp, fd) != NOTOK) ) ! 374: { ! 375: dn_print(tmp, aoj_dn, EDBOUT) ; ! 376: } ! 377: else ! 378: { ! 379: ps_print(OPT, "Unable to open appropriate ps. Aborting..\n") ; ! 380: return ; ! 381: } ! 382: (void)fprintf(fd, "\nobjectClass= quipuObject & alias & top\n") ; ! 383: (void) fclose(fd) ; ! 384: ! 385: if (move (objectname) != OK) ! 386: { ! 387: ps_printf (OPT,"Unknown option %s\n",objectname); ! 388: return ; ! 389: } ! 390: ! 391: /* now parse the files */ ! 392: if ((fd = fopen (fname, "r")) == (FILE *) NULL) { ! 393: ps_printf (OPT, "Can't open draft entry %s\n", fname); ! 394: return ; ! 395: } ! 396: entry_ptr = get_default_entry (NULLENTRY); ! 397: entry_ptr->e_attributes = get_attributes (fd); ! 398: (void) fclose (fd); ! 399: if (parse_status != 0) ! 400: return ; ! 401: ! 402: add_arg.ada_object = dn; ! 403: for (moddn = dn ; moddn->dn_parent != NULLDN; moddn=moddn->dn_parent) ! 404: ; ! 405: entry_ptr->e_name = rdn_cpy (moddn->dn_rdn); ! 406: add_arg.ada_entry = entry_ptr->e_attributes; ! 407: ! 408: if (rebind () != OK) { ! 409: entry_free (entry_ptr); ! 410: return ; ! 411: } ! 412: ! 413: while (ds_addentry (&add_arg, &error) != DS_OK) { ! 414: if (dish_error (OPT, &error) == 0) { ! 415: entry_free (entry_ptr); ! 416: return ; ! 417: } ! 418: add_arg.ada_object = error.ERR_REFERRAL.DSE_ref_candidates->cr_name; ! 419: } ! 420: ps_print (RPS, "Added "); ! 421: dn_print (RPS, dn, EDBOUT); ! 422: ps_print (RPS, "\n"); ! 423: entry_free (entry_ptr); ! 424: make_old (fname,draft_flag); ! 425: ! 426: /* Now we have to add a "seeAlso=<DN>" attribute to the <AOJ> */ ! 427: ! 428: if (service_control(OPT, 1, contact_modify, &mod_arg.mea_common) == -1) ! 429: { ! 430: ps_printf(OPT, "Add_alias: Badly wrong. Service controls for modify in error...\n") ; ! 431: return ; ! 432: } ! 433: ! 434: dn_free(dn) ; ! 435: dn = dn_cpy(save_dn) ; ! 436: { ! 437: AV_Sequence new_avs = avs_comp_alloc() ; ! 438: AttributeValue new_AV = AttrV_alloc() ; ! 439: ! 440: if ((str_ps = ps_alloc(str_open)) == NULLPS) ! 441: { ! 442: ps_printf(OPT, "Ps alloc for your string failed.\n") ; ! 443: return ; ! 444: } ! 445: if (str_setup (str_ps, str_buffer, 998, 1) == NOTOK) ! 446: { ! 447: ps_printf (OPT, "str_setup: %s", ps_error (str_ps -> ps_errno)); ! 448: ps_free (str_ps); ! 449: return ; ! 450: } ! 451: dn_print(str_ps, oj_dn, EDBOUT) ; ! 452: *str_ps->ps_ptr = 0 ; ! 453: ps_free(str_ps) ; ! 454: ! 455: new_AV = AttrV_cpy(str2AttrV(str_buffer, str2syntax("DN"))) ; ! 456: new_avs = avs_comp_new(AttrV_cpy(new_AV)) ; ! 457: emnew->em_what = as_comp_new(AttrT_new("seeAlso"), new_avs, NULLACL_INFO) ; ! 458: } ! 459: emnew->em_next = NULLMOD ; ! 460: mod_arg.mea_object = aoj_dn; ! 461: mod_arg.mea_changes = emnew ; ! 462: ! 463: if (rebind () != OK) ! 464: return ; ! 465: ! 466: /* ! 467: * If this operation is time-stamped, it may have expired while the user ! 468: * was editing the entry. Re-calculate the time-stamp. Modify is the only ! 469: * dish command where this needs to be done. ! 470: */ ! 471: ! 472: if ((mod_arg.mea_common.ca_security != (struct security_parms *) 0) ! 473: && (mod_arg.mea_common.ca_security->sp_time != NULLCP)) ! 474: { ! 475: char *new_version(); ! 476: ! 477: free(mod_arg.mea_common.ca_security->sp_time); ! 478: mod_arg.mea_common.ca_security->sp_time = new_version(); ! 479: } ! 480: ! 481: /* If security parameters are present, take this to mean that strong ! 482: * authentication is required. This disallows 'parms + no signature' ! 483: * (pointless) and 'signature + no parms' (security risk). ! 484: */ ! 485: if (mod_arg.mea_common.ca_security != (struct security_parms *) 0) ! 486: { ! 487: int encode_DAS_ModifyEntryArgumentData(); ! 488: struct signature *sign_operation(); ! 489: mod_arg.mea_common.ca_sig = ! 490: sign_operation((caddr_t)&mod_arg, ! 491: encode_DAS_ModifyEntryArgumentData); ! 492: } ! 493: ! 494: while (ds_modifyentry (&mod_arg, &mod_error) != DS_OK) ! 495: { ! 496: if (dish_error (OPT, &mod_error) == 0) ! 497: { ! 498: ps_print(OPT, "Unable to modify ") ; ! 499: dn_print(OPT, aoj_dn, EDBOUT) ; ! 500: ps_print(OPT, "\n") ; ! 501: return ; ! 502: } ! 503: mod_arg.mea_object = mod_error.ERR_REFERRAL.DSE_ref_candidates->cr_name; ! 504: } ! 505: ps_print (RPS, "Modified "); ! 506: dn_print (RPS, aoj_dn, EDBOUT); ! 507: ps_print (RPS, "\n"); ! 508: delete_cache (aoj_dn); /* re-cache when next read */ ! 509: ! 510: dn_free(dn) ; ! 511: dn = dn_cpy(save_dn) ; ! 512: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.