/* alias_chk.c - checks aliases from position provided downwards. */ /* A management tool - probably best to run this as a manager. */ #ifndef lint static char *rcsid = "$Header: /f/osi/others/quipu/uips/manage/RCS/alias_chk.c,v 7.1 91/02/22 09:32:02 mrose Interim $"; #endif /* * $Header: /f/osi/others/quipu/uips/manage/RCS/alias_chk.c,v 7.1 90/07/27 08:4 * * * $Log: alias_chk.c,v $ * Revision 7.1 91/02/22 09:32:02 mrose * Interim 6.8 * * Revision 7.0 91/01/24 14:43:41 mrose * *** empty log message *** * * Revision 7.1 90/07/27 08:47:16 mrose * update * * Revision 7.0 90/06/26 14:52:31 mrose * *** empty log message *** * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ #include "quipu/entry.h" #include "quipu/util.h" #include "quipu/compare.h" #include "quipu/ds_search.h" #include "quipu/read.h" #define ORG_PERSON "thornPerson & quipuObject" /* this should probably go elsewhere !!! */ extern DN dn; #define OPT (!frompipe || rps -> ps_byteno == 0 ? opt : rps) #define RPS (!frompipe || opt -> ps_byteno == 0 ? rps : opt) extern char frompipe; extern PS opt; extern PS rps; extern Entry current_entry; extern DN sequence_dn(); extern DN str2dn_aux(); extern Filter get_filter(); char **NULLARGV = (char **) 0; call_alias_chk(argc, argv) int argc ; char **argv ; { struct ds_search_arg search_arg; struct DSError search_error; struct ds_search_result search_result; DN save_dn, tmp_dn = NULLDN; char alias = FALSE ; char verify_alias() ; EntryInfo *ptr ; if (argc > 2) { ps_print(OPT, "Error, too many arguments..\n") ; return(NOTOK) ; } if (argc == 2) { /* Convert arg 2 to a DN for future use. */ /* Turn a sequence number back into a DN */ if (*argv[1] >= '0' && *argv[1] <= '9') { /* First convert the number into a dn */ tmp_dn = dn_cpy(sequence_dn(atoi(argv[1]))) ; } else { if (*argv[1] == '.') { ps_print(OPT, "..@ gives me a headache. Ambiguous. Aborting.\n") ; return(NOTOK) ; } if (*argv[1] == '@') { tmp_dn = dn_cpy(str2dn(argv[1] + 1)) ; } else { save_dn = dn_cpy(str2dn_aux(argv[1], &alias)) ; if (save_dn != NULLDN) { if (alias) { tmp_dn = dn_cpy(save_dn); } else { if (dn == NULLDN) { tmp_dn = dn_cpy(save_dn) ; } else { tmp_dn = dn_cpy(dn) ; dn_append(tmp_dn, dn_cpy(save_dn)); } } dn_free(save_dn) ; } } } } /* We now have the start location in tmp_dn */ if (tmp_dn != NULLDN) { save_dn = dn_cpy(dn) ; /* save start location for later restore */ dn_free(dn) ; dn = dn_cpy(tmp_dn) ; dn_free(tmp_dn) ; } /* dn should be set to a: either current location, or b: 2nd arg if specified. */ /* Is dn a leaf or a non_leaf? */ { struct ds_compare_arg compare_arg; struct DSError compare_error; struct ds_compare_result compare_result; if ((argc = service_control (OPT, argc, argv, &compare_arg.cma_common)) == -1) return(NOTOK) ; compare_arg.cma_common.ca_servicecontrol.svc_options |= SVC_OPT_DONTDEREFERENCEALIAS ; compare_arg.cma_object = dn; if (get_ava (&compare_arg.cma_purported, "objectClass", "quipuNonLeafObject") != OK) { ps_print(OPT, "Oops, 'objectClass=quipuNonLeafObject' is a bad attribute!\n") ; ps_print(OPT, "This is very bad...\n") ; return(NOTOK) ; } if (compare_arg.cma_common.ca_security != (struct security_parms *) 0) { struct signature *sign_operation(); int encode_DAS_CompareArgumentData(); compare_arg.cma_common.ca_sig = sign_operation((caddr_t)&compare_arg, encode_DAS_CompareArgumentData) ; } if (rebind () != OK) return(NOTOK) ; while (ds_compare (&compare_arg, &compare_error, &compare_result) != DS_OK) { if (dish_error (OPT, &compare_error) == 0) { return(NOTOK) ; } compare_arg.cma_object = compare_error.ERR_REFERRAL.DSE_ref_candidates->cr_name; } /* If the object is a leaf then check it out and exit... */ if ( compare_result.cmr_matched == FALSE ) { struct DSError read_error; struct ds_read_result read_result; struct ds_read_arg read_arg; read_arg.rda_eis.eis_allattributes = TRUE ; read_arg.rda_eis.eis_select = NULLATTR ; read_arg.rda_eis.eis_infotypes = TRUE ; if (service_control (OPT, argc, argv, &read_arg.rda_common) == -1) { return(-1) ; } read_arg.rda_common.ca_servicecontrol.svc_options |= SVC_OPT_DONTDEREFERENCEALIAS ; read_arg.rda_object = dn; /* Strong authentication */ if (read_arg.rda_common.ca_security != (struct security_parms *) 0) { struct signature *sign_operation(); int encode_DAS_ReadArgumentData(); read_arg.rda_common.ca_sig = sign_operation((caddr_t)&read_arg, encode_DAS_ReadArgumentData); } while (ds_read (&read_arg, &read_error, &read_result) != DS_OK) { if (dish_error (OPT, &read_error) == 0) return (-2); read_arg.rda_object = read_error.ERR_REFERRAL.DSE_ref_candidates->cr_name; } if ( verify_alias(&read_result.rdr_entry) != OK ) { ps_print(OPT, "Bad Alias.\n") ; } return(OK) ; } } /* Else search the subtree below this current * position for ALL aliases, and check each one. */ /* Sort out the search filter for this. */ search_arg.sra_baseobject = dn ; search_arg.sra_subset = SRA_WHOLESUBTREE ; search_arg.sra_common.ca_servicecontrol.svc_sizelimit = SVC_NOSIZELIMIT ; search_arg.sra_searchaliases = FALSE ; search_arg.sra_filter = NULLFILTER ; if ((argc = service_control (OPT, argc, argv, &search_arg.sra_common)) == -1) return(NOTOK); if ((search_arg.sra_filter = get_filter("objectClass=alias")) == NULLFILTER) { ps_printf (OPT,"Very bad... Filter wrong. Aborting...\n"); return(NOTOK) ; } ps_print(OPT, "Searching... please wait...\n") ; if (rebind () != OK) return(NOTOK); /* Strong authentication */ if (search_arg.sra_common.ca_security != (struct security_parms *) 0) { struct signature *sign_operation(); int encode_DAS_SearchArgumentData(); search_arg.sra_common.ca_sig = sign_operation((caddr_t)&search_arg, encode_DAS_SearchArgumentData); } while (ds_search (&search_arg, &search_error, &search_result) != DS_OK) { if (dish_error (OPT, &search_error) == 0) return(NOTOK); search_arg.sra_baseobject = search_error.ERR_REFERRAL.DSE_ref_candidates->cr_name ; } correlate_search_results (&search_result); if (search_result.CSR_entries == NULLENTRYINFO) { ps_printf(OPT, "No aliases found...\n"); return(OK) ; } for (ptr = search_result.CSR_entries; ptr != NULLENTRYINFO; ptr = ptr->ent_next) { /* decode it immediately so we only have to do it once. */ cache_entry (ptr, TRUE, TRUE) ; if ( verify_alias(ptr) != OK ) { ps_print(OPT, "Bad Alias.\n") ; } } handle_problems (RPS, search_result.CSR_cr,search_result.CSR_limitproblem, TRUE); filter_free (search_arg.sra_filter); dn_free(dn) ; dn = dn_cpy(save_dn) ; dn_free(save_dn) ; return(OK) ; } char verify_alias(alias_entry) EntryInfo *alias_entry ; { static char *nvec[2] = {"search"}; struct DSError read_error; struct ds_read_result read_result; struct ds_read_arg read_arg; struct attrcomp *tmp_ent_attr ; AttributeType at_ojc ; AttributeType at_aoj ; AttributeType at_acl ; AttributeType at_sa ; AttributeType at_lmt ; AttributeType at_lmb ; AttributeType at_trs ; AttributeType at_c ; AttributeType at_o ; AttributeType at_ou ; AttributeType at_cn ; AV_Sequence object_class_of_object ; AV_Sequence tree_strAVS = NULLAV ; DN dn_above_alias, trail, dnptr ; char Name=FALSE, Acl=FALSE, ObjClass=FALSE, AlObjNam=FALSE ; char BackReference=FALSE ; char GoodAlias = OK ; at_ojc = AttrT_new("objectClass") ; /* objectClass */ at_aoj = AttrT_new("aliasedObjectName") ; at_acl = AttrT_new("acl") ; at_sa = AttrT_new("seeAlso") ; at_lmt = AttrT_new("lastModifiedTime") ; at_lmb = AttrT_new("lastModifiedBy") ; at_trs = AttrT_new("treeStructure") ; at_c = AttrT_new("countryName") ; at_o = AttrT_new("organizationName") ; at_ou = AttrT_new("organizationalUnitName") ; at_cn = AttrT_new("commonName") ; nvec[1] = "-compact"; read_arg.rda_object = NULLDN ; ps_print(OPT, "\nFound alias:") ; dn_print(OPT, alias_entry->ent_dn, EDBOUT) ; ps_print(OPT, "\n") ; /* We now have ourselves an entrystruct which is an alias, and we * have to check various features!! * 1: only the allowed objects. * 2: the seeAlso attribute is correct (ie points to a real entry). * 3: The objectClass of the real entry fits under where the alias * lives. */ /* Does the alias have the allowed objects and only the allowed? */ for (tmp_ent_attr = alias_entry->ent_attr; tmp_ent_attr != NULL; tmp_ent_attr = tmp_ent_attr->attr_link) { if (AttrT_cmp(tmp_ent_attr->attr_type, at_ojc) == 0) { ObjClass = TRUE ; } else if (AttrT_cmp(tmp_ent_attr->attr_type, at_aoj) == 0) { read_arg.rda_object = dn_cpy ((DN) tmp_ent_attr->attr_value->avseq_av.av_struct); AlObjNam = TRUE ; } else if (AttrT_cmp(tmp_ent_attr->attr_type, at_acl) == 0) { Acl = TRUE ; } else if (AttrT_cmp(tmp_ent_attr->attr_type, at_lmt) == 0) { ; } else if (AttrT_cmp(tmp_ent_attr->attr_type, at_lmb) == 0) { ; } else if (AttrT_cmp(tmp_ent_attr->attr_type, at_c) == 0 || AttrT_cmp(tmp_ent_attr->attr_type, at_o) == 0 || AttrT_cmp(tmp_ent_attr->attr_type, at_ou) == 0 || AttrT_cmp(tmp_ent_attr->attr_type, at_cn) == 0) { Name = TRUE ; } else { ps_print(OPT, "Illegal attribute type: ") ; AttrT_print (OPT, tmp_ent_attr->attr_type, EDBOUT) ; ps_print(OPT, "\n") ; GoodAlias = NOTOK; } } if (read_arg.rda_object == NULLDN ) { ps_print(OPT, "Malformed alias. No alias object name present!\n" ) ; return (NOTOK) ; } if (ObjClass == FALSE) { ps_print(OPT, "Object Class missing.\n") ; } if (AlObjNam == FALSE) { ps_print(OPT, "Alias Object name missing.\n") ; } if (Acl == FALSE) { ps_print(OPT, "ACL missing.\n") ; } if (Name == FALSE) { ps_print(OPT, "Name of alias is missing.\n") ; } GoodAlias = ((ObjClass && AlObjNam && Acl && Name) ? OK : NOTOK) ; /* Read the entry that the alias points to.... */ read_arg.rda_eis.eis_allattributes = TRUE ; read_arg.rda_eis.eis_select = NULLATTR ; read_arg.rda_eis.eis_infotypes = TRUE ; if (service_control (OPT, 0, NULLARGV, &read_arg.rda_common) == -1) { return(-1) ; } read_arg.rda_common.ca_servicecontrol.svc_options |= SVC_OPT_DONTDEREFERENCEALIAS ; /* Strong authentication */ if (read_arg.rda_common.ca_security != (struct security_parms *) 0) { struct signature *sign_operation(); int encode_DAS_ReadArgumentData(); read_arg.rda_common.ca_sig = sign_operation((caddr_t)&read_arg, encode_DAS_ReadArgumentData); } while (ds_read (&read_arg, &read_error, &read_result) != DS_OK) { if (dish_error (OPT, &read_error) == 0) { ps_print(OPT, "Can't read ") ; dn_print(OPT, read_arg.rda_object, EDBOUT) ; ps_print(OPT, "\n") ; return (GoodAlias); } read_arg.rda_object = read_error.ERR_REFERRAL.DSE_ref_candidates->cr_name; } /* and see if it points back to this alias. * It should do, but doesn't have to. While we are at it, * collect the objectClass of this entry. */ for (tmp_ent_attr = read_result.rdr_entry.ent_attr; tmp_ent_attr != NULL; tmp_ent_attr = tmp_ent_attr->attr_link) { if (AttrT_cmp(tmp_ent_attr->attr_type, at_sa) == 0) { AV_Sequence tmp_avs = tmp_ent_attr->attr_value; for (; tmp_avs != NULL; tmp_avs = tmp_avs->avseq_next) { if (dn_cmp((DN) tmp_avs->avseq_av.av_struct, alias_entry->ent_dn)) { ps_print(OPT, "Alias object correctly points back to alias itself.\n") ; BackReference = TRUE ; } } } else if (AttrT_cmp(tmp_ent_attr->attr_type, at_ojc) == 0) { object_class_of_object = avs_cpy(tmp_ent_attr->attr_value) ; } } if (BackReference == FALSE) { ps_print(OPT, "Alias object should point back to alias.\n") ; } if (object_class_of_object == NULLAV) { ps_print(OPT, "Can't find object class of aliased object\n. Assuming OK\n") ; return(GoodAlias) ; } /* Move above the alias in order to find the treeStructure. */ dn_above_alias = dn_cpy(alias_entry->ent_dn) ; for (dnptr = dn_above_alias; dnptr->dn_parent != NULLDN; dnptr = dnptr->dn_parent) trail = dnptr; dn_comp_free (dnptr); trail->dn_parent = NULLDN; /* Now read it... */ read_arg.rda_object = dn_cpy(dn_above_alias) ; /* Strong authentication */ if (read_arg.rda_common.ca_security != (struct security_parms *) 0) { struct signature *sign_operation(); int encode_DAS_ReadArgumentData(); read_arg.rda_common.ca_sig = sign_operation((caddr_t)&read_arg, encode_DAS_ReadArgumentData); } while (ds_read (&read_arg, &read_error, &read_result) != DS_OK) { if (dish_error (OPT, &read_error) == 0) return (-2); read_arg.rda_object = read_error.ERR_REFERRAL.DSE_ref_candidates->cr_name; } for (tmp_ent_attr = read_result.rdr_entry.ent_attr; tmp_ent_attr != NULL; tmp_ent_attr = tmp_ent_attr->attr_link) { if (AttrT_cmp(tmp_ent_attr->attr_type, at_trs) == 0) { tree_strAVS = avs_cpy(tmp_ent_attr->attr_value) ; } } if (tree_strAVS == NULLAV) { ps_print(OPT, "Tree structure missing - assuming validity.\n") ; } else if (test_schema(tree_strAVS, object_class_of_object) != OK) { ps_print(OPT, "Tree structure bad...\n") ; GoodAlias = NOTOK ; } return (GoodAlias) ; } shadow_entry() { ; }