2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2N/A/*
2N/A * lib/krb5/krb/princ_comp.c
2N/A *
2N/A * Copyright 1990,1991,2007 by the Massachusetts Institute of Technology.
2N/A * All Rights Reserved.
2N/A *
2N/A * Export of this software from the United States of America may
2N/A * require a specific license from the United States Government.
2N/A * It is the responsibility of any person or organization contemplating
2N/A * export to obtain such a license before exporting.
2N/A *
2N/A * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
2N/A * distribute this software and its documentation for any purpose and
2N/A * without fee is hereby granted, provided that the above copyright
2N/A * notice appear in all copies and that both that copyright notice and
2N/A * this permission notice appear in supporting documentation, and that
2N/A * the name of M.I.T. not be used in advertising or publicity pertaining
2N/A * to distribution of the software without specific, written prior
2N/A * permission. Furthermore if you modify this software you must label
2N/A * your software as modified software and not distribute it in such a
2N/A * fashion that it might be confused with the original M.I.T. software.
2N/A * M.I.T. makes no representations about the suitability of
2N/A * this software for any purpose. It is provided "as is" without express
2N/A * or implied warranty.
2N/A *
2N/A *
2N/A * compare two principals, returning a krb5_boolean true if equal, false if
2N/A * not.
2N/A */
2N/A
2N/A#include "k5-int.h"
2N/A#include "k5-unicode.h"
2N/A
2N/Astatic krb5_boolean
2N/Arealm_compare_flags(krb5_context context,
2N/A krb5_const_principal princ1,
2N/A krb5_const_principal princ2,
2N/A int flags)
2N/A{
2N/A const krb5_data *realm1 = krb5_princ_realm(context, princ1);
2N/A const krb5_data *realm2 = krb5_princ_realm(context, princ2);
2N/A
2N/A if (realm1->length != realm2->length)
2N/A return FALSE;
2N/A
2N/A return (flags & KRB5_PRINCIPAL_COMPARE_CASEFOLD) ?
2N/A (strncasecmp(realm1->data, realm2->data, realm2->length) == 0) :
2N/A (memcmp(realm1->data, realm2->data, realm2->length) == 0);
2N/A}
2N/A
2N/Akrb5_boolean KRB5_CALLCONV
2N/Akrb5_realm_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2)
2N/A{
2N/A return realm_compare_flags(context, princ1, princ2, 0);
2N/A}
2N/A
2N/Astatic krb5_error_code
2N/Aupn_to_principal(krb5_context context,
2N/A krb5_const_principal princ,
2N/A krb5_principal *upn)
2N/A{
2N/A char *unparsed_name;
2N/A krb5_error_code code;
2N/A
2N/A code = krb5_unparse_name_flags(context, princ,
2N/A KRB5_PRINCIPAL_UNPARSE_NO_REALM,
2N/A &unparsed_name);
2N/A if (code) {
2N/A *upn = NULL;
2N/A return code;
2N/A }
2N/A
2N/A code = krb5_parse_name(context, unparsed_name, upn);
2N/A
2N/A free(unparsed_name);
2N/A
2N/A return code;
2N/A}
2N/A
2N/Akrb5_boolean KRB5_CALLCONV
2N/Akrb5_principal_compare_flags(krb5_context context,
2N/A krb5_const_principal princ1,
2N/A krb5_const_principal princ2,
2N/A int flags)
2N/A{
2N/A register int i;
2N/A krb5_int32 nelem;
2N/A unsigned int utf8 = (flags & KRB5_PRINCIPAL_COMPARE_UTF8) != 0;
2N/A unsigned int casefold = (flags & KRB5_PRINCIPAL_COMPARE_CASEFOLD) != 0;
2N/A krb5_principal upn1 = NULL;
2N/A krb5_principal upn2 = NULL;
2N/A krb5_boolean ret = FALSE;
2N/A
2N/A if (flags & KRB5_PRINCIPAL_COMPARE_ENTERPRISE) {
2N/A /* Treat UPNs as if they were real principals */
2N/A if (krb5_princ_type(context, princ1) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
2N/A if (upn_to_principal(context, princ1, &upn1) == 0)
2N/A princ1 = upn1;
2N/A }
2N/A if (krb5_princ_type(context, princ2) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
2N/A if (upn_to_principal(context, princ2, &upn2) == 0)
2N/A princ2 = upn2;
2N/A }
2N/A }
2N/A
2N/A nelem = krb5_princ_size(context, princ1);
2N/A if (nelem != krb5_princ_size(context, princ2))
2N/A goto out;
2N/A
2N/A if ((flags & KRB5_PRINCIPAL_COMPARE_IGNORE_REALM) == 0 &&
2N/A !realm_compare_flags(context, princ1, princ2, flags))
2N/A goto out;
2N/A
2N/A for (i = 0; i < (int) nelem; i++) {
2N/A const krb5_data *p1 = krb5_princ_component(context, princ1, i);
2N/A const krb5_data *p2 = krb5_princ_component(context, princ2, i);
2N/A krb5_boolean eq;
2N/A
2N/A if (casefold) {
2N/A if (utf8)
2N/A eq = (krb5int_utf8_normcmp(p1, p2, KRB5_UTF8_CASEFOLD) == 0);
2N/A else
2N/A eq = (p1->length == p2->length
2N/A && strncasecmp(p1->data, p2->data, p2->length) == 0);
2N/A } else
2N/A eq = data_eq(*p1, *p2);
2N/A
2N/A if (!eq)
2N/A goto out;
2N/A }
2N/A
2N/A ret = TRUE;
2N/A
2N/Aout:
2N/A if (upn1 != NULL)
2N/A krb5_free_principal(context, upn1);
2N/A if (upn2 != NULL)
2N/A krb5_free_principal(context, upn2);
2N/A
2N/A return ret;
2N/A}
2N/A
2N/Akrb5_boolean KRB5_CALLCONV krb5_is_referral_realm(const krb5_data *r)
2N/A{
2N/A /*
2N/A * Check for a match with KRB5_REFERRAL_REALM. Currently this relies
2N/A * on that string constant being zero-length. (Unlike principal realm
2N/A * names, KRB5_REFERRAL_REALM is known to be a string.)
2N/A */
2N/A#ifdef DEBUG_REFERRALS
2N/A#if 0
2N/A printf("krb5_is_ref_realm: checking <%s> for referralness: %s\n",
2N/A r->data,(r->length==0)?"true":"false");
2N/A#endif
2N/A#endif
2N/A assert(strlen(KRB5_REFERRAL_REALM)==0);
2N/A if (r->length==0)
2N/A return TRUE;
2N/A else
2N/A return FALSE;
2N/A}
2N/A
2N/Akrb5_boolean KRB5_CALLCONV
2N/Akrb5_principal_compare(krb5_context context,
2N/A krb5_const_principal princ1,
2N/A krb5_const_principal princ2)
2N/A{
2N/A return krb5_principal_compare_flags(context, princ1, princ2, 0);
2N/A}
2N/A
2N/Akrb5_boolean KRB5_CALLCONV
2N/Akrb5_principal_compare_any_realm(krb5_context context,
2N/A krb5_const_principal princ1,
2N/A krb5_const_principal princ2)
2N/A{
2N/A return krb5_principal_compare_flags(context, princ1, princ2, KRB5_PRINCIPAL_COMPARE_IGNORE_REALM);
2N/A}