Permit NULL context to krb5_get_error_message()
Application developers have a tendency to use krb5_get_error_message() as a drop in replacement for error_message() and under various circumstances they pass in a NULL context. This method works fine for MIT's implementation which ignores the context but in Heimdal passing in a NULL context would dump core. This patch set modifies krb5_get_error_message() in order to permit the passing of a NULL context. First, if the context is NULL, an attempt will be made to allocate one locally for the purpose of evaluating the error code. Second, if a local context cannot be allocated, fall back on calling error_message(). If error_message() fails to return a string, then generate an "unknown error" response. Only if all of the above fails is NULL returned. Change-Id: If4baf7d6c428cf0baf11c044b8dfd5c2b3cdf7e4
This commit is contained in:
		| @@ -206,29 +206,53 @@ krb5_vprepend_error_message(krb5_context context, krb5_error_code ret, | |||||||
| KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL | KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL | ||||||
| krb5_get_error_message(krb5_context context, krb5_error_code code) | krb5_get_error_message(krb5_context context, krb5_error_code code) | ||||||
| { | { | ||||||
|     char *str; |     char *str = NULL; | ||||||
|  |     const char *cstr = NULL; | ||||||
|  |     char buf[128]; | ||||||
|  |     int free_context = 0; | ||||||
|  |  | ||||||
|  |     if (code == 0) | ||||||
|  | 	return strdup("Success"); | ||||||
|  |  | ||||||
|  |     /* | ||||||
|  |      * The MIT version of this function ignores the krb5_context | ||||||
|  |      * and several widely deployed applications call krb5_get_error_message() | ||||||
|  |      * with a NULL context in order to translate an error code as a | ||||||
|  |      * replacement for error_message().  Another reason a NULL context | ||||||
|  |      * might be provided is if the krb5_init_context() call itself | ||||||
|  |      * failed. | ||||||
|  |      */ | ||||||
|  |     if (context) | ||||||
|  |     { | ||||||
|         HEIMDAL_MUTEX_lock(context->mutex); |         HEIMDAL_MUTEX_lock(context->mutex); | ||||||
|         if (context->error_string && |         if (context->error_string && | ||||||
|             (code == context->error_code || context->error_code == 0)) |             (code == context->error_code || context->error_code == 0)) | ||||||
|         { |         { | ||||||
|             str = strdup(context->error_string); |             str = strdup(context->error_string); | ||||||
| 	if (str) { |  | ||||||
| 	    HEIMDAL_MUTEX_unlock(context->mutex); |  | ||||||
| 	    return str; |  | ||||||
| 	} |  | ||||||
|         } |         } | ||||||
|         HEIMDAL_MUTEX_unlock(context->mutex); |         HEIMDAL_MUTEX_unlock(context->mutex); | ||||||
|  |  | ||||||
|     if (code == 0) |         if (str) | ||||||
| 	return strdup("Success"); |             return str; | ||||||
|     { |  | ||||||
| 	const char *msg; |  | ||||||
| 	char buf[128]; |  | ||||||
| 	msg = com_right_r(context->et_list, code, buf, sizeof(buf)); |  | ||||||
| 	if (msg) |  | ||||||
| 	    return strdup(msg); |  | ||||||
|     } |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         if (krb5_init_context(&context) == 0) | ||||||
|  |             free_context = 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (context) | ||||||
|  |         cstr = com_right_r(context->et_list, code, buf, sizeof(buf)); | ||||||
|  |  | ||||||
|  |     if (free_context) | ||||||
|  |         krb5_free_context(context); | ||||||
|  |  | ||||||
|  |     if (cstr) | ||||||
|  |         return strdup(cstr); | ||||||
|  |  | ||||||
|  |     cstr = error_message(code); | ||||||
|  |     if (cstr) | ||||||
|  |         return strdup(cstr); | ||||||
|  |  | ||||||
|     if (asprintf(&str, "<unknown error: %d>", (int)code) == -1 || str == NULL) |     if (asprintf(&str, "<unknown error: %d>", (int)code) == -1 || str == NULL) | ||||||
| 	return NULL; | 	return NULL; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jeffrey Altman
					Jeffrey Altman