Code: create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp)
 {
     static generic_ret          ret;
     char                        *prime_arg;
    gss_buffer_desc             client_name, service_name;
     OM_uint32                   minor_stat;
     kadm5_server_handle_t       handle;
     restriction_t               *rp;
    const char                  *errmsg = NULL;

    xdr_free(xdr_generic_ret, &ret);

    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
        goto exit_func;

    if ((ret.code = check_handle((void *)handle)))
        goto exit_func;

    ret.api_version = handle->api_version;

    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
        ret.code = KADM5_FAILURE;
        goto exit_func;
    }
    if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) {
        ret.code = KADM5_BAD_PRINCIPAL;
        goto exit_func;
    }

    if (CHANGEPW_SERVICE(rqstp)
        || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_ADD,
                               arg->rec.principal, &rp)
        || kadm5int_acl_impose_restrictions(handle->context,
                                            &arg->rec, &arg->mask, rp)) {
        ret.code = KADM5_AUTH_ADD;
        log_unauth("kadm5_create_principal", prime_arg,
                   &client_name, &service_name, rqstp);
    } else {
        ret.code = kadm5_create_principal((void *)handle,
                                          &arg->rec, arg->mask,
                                          arg->passwd);

        if( ret.code != 0 )
            errmsg = krb5_get_error_message(handle->context, ret.code);

        log_done("kadm5_create_principal", prime_arg, errmsg,
                 &client_name, &service_name, rqstp);

        if (errmsg != NULL)
             krb5_free_error_message(handle->context, errmsg);
     }
     free(prime_arg);
    gss_release_buffer(&minor_stat, &client_name);
    gss_release_buffer(&minor_stat, &service_name);
 
 exit_func:
     free_server_handle(handle);
     return &ret;
 }

Commit Message: Fix leaks in kadmin server stubs [CVE-2015-8631]

In each kadmind server stub, initialize the client_name and
server_name variables, and release them in the cleanup handler.  Many
of the stubs will otherwise leak the client and server name if
krb5_unparse_name() fails.  Also make sure to free the prime_arg
variables in rename_principal_2_svc(), or we can leak the first one if
unparsing the second one fails.  Discovered by Simo Sorce.

CVE-2015-8631:

In all versions of MIT krb5, an authenticated attacker can cause
kadmind to leak memory by supplying a null principal name in a request
which uses one.  Repeating these requests will eventually cause
kadmind to exhaust all available memory.

    CVSSv2 Vector: AV:N/AC:L/Au:S/C:N/I:N/A:C/E:POC/RL:OF/RC:C

ticket: 8343 (new)
target_version: 1.14-next
target_version: 1.13-next
tags: pullup
CWE ID: CWE-119
create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp)
 {
     static generic_ret          ret;
     char                        *prime_arg;
    gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
     OM_uint32                   minor_stat;
     kadm5_server_handle_t       handle;
     restriction_t               *rp;
    const char                  *errmsg = NULL;

    xdr_free(xdr_generic_ret, &ret);

    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
        goto exit_func;

    if ((ret.code = check_handle((void *)handle)))
        goto exit_func;

    ret.api_version = handle->api_version;

    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
        ret.code = KADM5_FAILURE;
        goto exit_func;
    }
    if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) {
        ret.code = KADM5_BAD_PRINCIPAL;
        goto exit_func;
    }

    if (CHANGEPW_SERVICE(rqstp)
        || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_ADD,
                               arg->rec.principal, &rp)
        || kadm5int_acl_impose_restrictions(handle->context,
                                            &arg->rec, &arg->mask, rp)) {
        ret.code = KADM5_AUTH_ADD;
        log_unauth("kadm5_create_principal", prime_arg,
                   &client_name, &service_name, rqstp);
    } else {
        ret.code = kadm5_create_principal((void *)handle,
                                          &arg->rec, arg->mask,
                                          arg->passwd);

        if( ret.code != 0 )
            errmsg = krb5_get_error_message(handle->context, ret.code);

        log_done("kadm5_create_principal", prime_arg, errmsg,
                 &client_name, &service_name, rqstp);

        if (errmsg != NULL)
             krb5_free_error_message(handle->context, errmsg);
     }
     free(prime_arg);
 
 exit_func:
    gss_release_buffer(&minor_stat, &client_name);
    gss_release_buffer(&minor_stat, &service_name);
     free_server_handle(handle);
     return &ret;
 }
