diff options
Diffstat (limited to 'src/lib/krb5/krb/princ_comp.c')
| -rw-r--r-- | src/lib/krb5/krb/princ_comp.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/lib/krb5/krb/princ_comp.c b/src/lib/krb5/krb/princ_comp.c new file mode 100644 index 0000000000000..a6936107decb9 --- /dev/null +++ b/src/lib/krb5/krb/princ_comp.c @@ -0,0 +1,167 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/princ_comp.c - Compare two principals for equality */ +/* + * Copyright 1990,1991,2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "k5-unicode.h" + +static krb5_boolean +realm_compare_flags(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2, + int flags) +{ + const krb5_data *realm1 = &princ1->realm; + const krb5_data *realm2 = &princ2->realm; + + if (realm1->length != realm2->length) + return FALSE; + if (realm1->length == 0) + return TRUE; + + return (flags & KRB5_PRINCIPAL_COMPARE_CASEFOLD) ? + (strncasecmp(realm1->data, realm2->data, realm2->length) == 0) : + (memcmp(realm1->data, realm2->data, realm2->length) == 0); +} + +krb5_boolean KRB5_CALLCONV +krb5_realm_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2) +{ + return realm_compare_flags(context, princ1, princ2, 0); +} + +static krb5_error_code +upn_to_principal(krb5_context context, + krb5_const_principal princ, + krb5_principal *upn) +{ + char *unparsed_name; + krb5_error_code code; + + code = krb5_unparse_name_flags(context, princ, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &unparsed_name); + if (code) { + *upn = NULL; + return code; + } + + code = krb5_parse_name(context, unparsed_name, upn); + + free(unparsed_name); + + return code; +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare_flags(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2, + int flags) +{ + krb5_int32 i; + unsigned int utf8 = (flags & KRB5_PRINCIPAL_COMPARE_UTF8) != 0; + unsigned int casefold = (flags & KRB5_PRINCIPAL_COMPARE_CASEFOLD) != 0; + krb5_principal upn1 = NULL; + krb5_principal upn2 = NULL; + krb5_boolean ret = FALSE; + + if (flags & KRB5_PRINCIPAL_COMPARE_ENTERPRISE) { + /* Treat UPNs as if they were real principals */ + if (princ1->type == KRB5_NT_ENTERPRISE_PRINCIPAL) { + if (upn_to_principal(context, princ1, &upn1) == 0) + princ1 = upn1; + } + if (princ2->type == KRB5_NT_ENTERPRISE_PRINCIPAL) { + if (upn_to_principal(context, princ2, &upn2) == 0) + princ2 = upn2; + } + } + + if (princ1->length != princ2->length) + goto out; + + if ((flags & KRB5_PRINCIPAL_COMPARE_IGNORE_REALM) == 0 && + !realm_compare_flags(context, princ1, princ2, flags)) + goto out; + + for (i = 0; i < princ1->length; i++) { + const krb5_data *p1 = &princ1->data[i]; + const krb5_data *p2 = &princ2->data[i]; + krb5_boolean eq; + + if (casefold) { + if (utf8) + eq = (krb5int_utf8_normcmp(p1, p2, KRB5_UTF8_CASEFOLD) == 0); + else + eq = (p1->length == p2->length + && strncasecmp(p1->data, p2->data, p2->length) == 0); + } else + eq = data_eq(*p1, *p2); + + if (!eq) + goto out; + } + + ret = TRUE; + +out: + if (upn1 != NULL) + krb5_free_principal(context, upn1); + if (upn2 != NULL) + krb5_free_principal(context, upn2); + + return ret; +} + +krb5_boolean KRB5_CALLCONV krb5_is_referral_realm(const krb5_data *r) +{ + /* + * Check for a match with KRB5_REFERRAL_REALM. Currently this relies + * on that string constant being zero-length. (Unlike principal realm + * names, KRB5_REFERRAL_REALM is known to be a string.) + */ + assert(strlen(KRB5_REFERRAL_REALM)==0); + if (r->length==0) + return TRUE; + else + return FALSE; +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return krb5_principal_compare_flags(context, princ1, princ2, 0); +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare_any_realm(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return krb5_principal_compare_flags(context, princ1, princ2, KRB5_PRINCIPAL_COMPARE_IGNORE_REALM); +} |
