From: Luke Howard Date: Wed, 26 Aug 2009 05:55:41 +0000 (+0000) Subject: add support for importing composite names, and bounds checking to krb5_gss_import_name X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aad4b07621668f82532f470d6bc8023014927478;p=thirdparty%2Fkrb5.git add support for importing composite names, and bounds checking to krb5_gss_import_name git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/authdata@22611 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c index 0716f35353..4c615505ab 100644 --- a/src/lib/gssapi/krb5/import_name.c +++ b/src/lib/gssapi/krb5/import_name.c @@ -45,6 +45,46 @@ * GSS_S_FAILURE if memory allocation fails */ +static krb5_error_code +import_name_composite(krb5_context context, + unsigned char *enc_data, size_t enc_length, + krb5_authdata_context *pad_context) +{ + krb5_authdata_context ad_context; + krb5_error_code code; + krb5_data data; + krb5_authdata **authdata; + + data.data = (char *)enc_data; + data.length = enc_length; + + code = decode_krb5_authdata(&data, &authdata); + if (code != 0) + return code; + + code = krb5_authdata_context_init(context, &ad_context); + if (code != 0) { + krb5_free_authdata(context, authdata); + return code; + } + + code = krb5_authdata_import_attributes(context, + ad_context, + AD_USAGE_AP_REQ, + authdata); + if (code != 0) { + krb5_free_authdata(context, authdata); + krb5_authdata_context_free(context, ad_context); + return code; + } + + krb5_free_authdata(context, authdata); + + *pad_context = ad_context; + + return 0; +} + OM_uint32 krb5_gss_import_name(minor_status, input_name_buffer, input_name_type, output_name) @@ -56,11 +96,14 @@ krb5_gss_import_name(minor_status, input_name_buffer, krb5_context context; krb5_principal princ = NULL; krb5_error_code code; - char *stringrep, *tmp, *tmp2, *cp; - OM_uint32 length; + unsigned char *cp, *end; + char *tmp, *stringrep, *tmp2; + ssize_t length; #ifndef NO_PASSWORD struct passwd *pw; #endif + int has_ad = 0; + krb5_authdata_context ad_context = NULL; code = krb5_gss_init_context(&context); if (code) { @@ -81,7 +124,7 @@ krb5_gss_import_name(minor_status, input_name_buffer, char *service, *host; if ((tmp = - (char *) xmalloc(input_name_buffer->length + 1)) == NULL) { + xmalloc(input_name_buffer->length + 1)) == NULL) { *minor_status = ENOMEM; krb5_free_context(context); return(GSS_S_FAILURE); @@ -155,28 +198,49 @@ krb5_gss_import_name(minor_status, input_name_buffer, goto do_getpwuid; #endif } else if (g_OID_equal(input_name_type, gss_nt_exported_name)) { - cp = tmp; +#define BOUNDS_CHECK(cp, end, n) do { if (cp + n > end) goto fail_name; } while (0) + cp = (unsigned char *)tmp; + end = cp + input_name_buffer->length; + + BOUNDS_CHECK(cp, end, 2); if (*cp++ != 0x04) goto fail_name; - if (*cp++ != 0x01) + switch (*cp++) { + case 0x01: + break; + case 0x02: + has_ad++; + break; + default: goto fail_name; + } + + BOUNDS_CHECK(cp, end, 2); if (*cp++ != 0x00) goto fail_name; length = *cp++; - if (length != gss_mech_krb5->length+2) + if (length != (ssize_t)gss_mech_krb5->length+2) goto fail_name; + + BOUNDS_CHECK(cp, end, 2); if (*cp++ != 0x06) goto fail_name; length = *cp++; - if (length != gss_mech_krb5->length) + if (length != (ssize_t)gss_mech_krb5->length) goto fail_name; + + BOUNDS_CHECK(cp, end, length); if (memcmp(cp, gss_mech_krb5->elements, length) != 0) goto fail_name; cp += length; + + BOUNDS_CHECK(cp, end, 4); length = *cp++; length = (length << 8) | *cp++; length = (length << 8) | *cp++; length = (length << 8) | *cp++; + + BOUNDS_CHECK(cp, end, length); tmp2 = malloc(length+1); if (tmp2 == NULL) { xfree(tmp); @@ -184,10 +248,27 @@ krb5_gss_import_name(minor_status, input_name_buffer, krb5_free_context(context); return GSS_S_FAILURE; } - strncpy(tmp2, cp, length); + strncpy(tmp2, (char *)cp, length); tmp2[length] = 0; - stringrep = tmp2; + cp += length; + + if (has_ad) { + BOUNDS_CHECK(cp, end, 4); + length = *cp++; + length = (length << 8) | *cp++; + length = (length << 8) | *cp++; + length = (length << 8) | *cp++; + + BOUNDS_CHECK(cp, end, length); + code = import_name_composite(context, + cp, length, + &ad_context); + if (code != 0) + goto fail_name; + cp += length; + } + assert(cp == end); } else { xfree(tmp); krb5_free_context(context); @@ -218,18 +299,20 @@ krb5_gss_import_name(minor_status, input_name_buffer, if (code) { *minor_status = (OM_uint32) code; save_error_info(*minor_status, context); + krb5_authdata_context_free(context, ad_context); krb5_free_context(context); return(GSS_S_BAD_NAME); } /* save the name in the validation database */ - code = kg_init_name(context, princ, NULL, + code = kg_init_name(context, princ, ad_context, KG_INIT_NAME_INTERN | KG_INIT_NAME_NO_COPY, (krb5_gss_name_t *)output_name); if (code != 0) { *minor_status = (OM_uint32) code; - krb5_free_principal(context, princ); save_error_info(*minor_status, context); + krb5_free_principal(context, princ); + krb5_authdata_context_free(context, ad_context); krb5_free_context(context); return(GSS_S_FAILURE); } diff --git a/src/lib/gssapi/mechglue/g_imp_name.c b/src/lib/gssapi/mechglue/g_imp_name.c index c4767bf3e9..534e078381 100644 --- a/src/lib/gssapi/mechglue/g_imp_name.c +++ b/src/lib/gssapi/mechglue/g_imp_name.c @@ -177,6 +177,7 @@ allocation_failure: * GSS export name constants */ static const char *expNameTokId = "\x04\x01"; +static const char *expNameCompositeTokId = "\x04\x02"; static const unsigned int expNameTokIdLen = 2; static const unsigned int mechOidLenLen = 2; static const unsigned int nameTypeLenLen = 2; @@ -201,7 +202,8 @@ importExportName(minor, unionName) return (GSS_S_DEFECTIVE_TOKEN); buf = (unsigned char *)expName.value; - if (memcmp(expNameTokId, buf, expNameTokIdLen) != 0) + if (memcmp(expNameTokId, buf, expNameTokIdLen) != 0 && + memcmp(expNameCompositeTokId, buf, expNameTokIdLen) != 0) return (GSS_S_DEFECTIVE_TOKEN); buf += expNameTokIdLen;