krb5-admin/1140: Patch for reproducible kadmind crash

mrl@isc.upenn.edu mrl at isc.upenn.edu
Thu Jul 25 16:27:42 EDT 2002


>Number:         1140
>Category:       krb5-admin
>Synopsis:       kadmind dumps core when it receives bad data from client
>Confidential:   yes
>Severity:       serious
>Priority:       high
>Responsible:    krb5-unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   unknown
>Arrival-Date:   Thu Jul 25 16:28:00 EDT 2002
>Last-Modified:
>Originator:     Mark R. Levinson
>Organization:
	University of Pennsylvania
>Release:        krb5-1.2.5
>Environment:
System: SunOS gnaghi.isc-net.upenn.edu 5.8 Generic_108528-12 sun4u sparc SUNW,Ultra-5_10
Architecture: sun4

>Description:
Bad data in client requests can reliably cause kadmind to crash in
krb5_unparse_name_ext(), where it tries to dereference a NULL pointer.

The patch below prevents these crashes by checking for a NULL principal
argument in krb5_unparse_name_ext(), and checking the return values from
several calls to krb5_unparse_name() in kadmin/server/server_stubs.c.

Notes on the patch:

 - I've reproduced this crash only in create_principal_1(), but the
   patch also fixes the other calls to krb5_unparse_name() in
   server_stubs.c that don't check its return value.

 - I chose KADM5_BAD_PRINCIPAL as the error code to return from the
   kadmin server functions when krb5_unparse_name() fails, although
   doc/kadm5/api-funcspec.tex doesn't document this as an expected return
   code for those functions.

 - Currently any bad attempts that fail due to krb5_unparse_name() errors
   aren't logged. It might be desirable to log them.

>How-To-Repeat:
I found this bug when someone made a mistake while experimenting with the
Authen::Krb5::Admin module for Perl, available from
http://www.cpan.org/modules/by-module/Authen/Authen-Krb5-Admin-0.03.tar.gz

I haven't developed C code to exercise the bug, but here's a minimal Perl
script that reliably crashes kadmind due to incorrect usage of the
Authen::Krb5::Admin module:

#!/usr/local/bin/perl

use Authen::Krb5;
Authen::Krb5::init_context();
Authen::Krb5::init_ets();

print "Principal: ";
chomp($principal = scalar(<STDIN>));
print "Password: ";
chomp($password = scalar(<STDIN>));

use Authen::Krb5::Admin;
$kadm5 = Authen::Krb5::Admin->init_with_password($principal, $password)
        or die Authen::Krb5::Admin::error;

$x = Authen::Krb5::Admin::Principal::new('') or die Authen::Krb5::Admin::error;
$rc = $kadm5->create_principal($x, '') or die Authen::Krb5::Admin::error;

>Fix:
*** src/lib/krb5/krb/unparse.c	Thu Jul 25 13:54:34 2002
--- src/lib/krb5/krb/unparse.c	Thu Jul 25 09:41:34 2002
***************
*** 70,75 ****
--- 70,78 ----
  	krb5_int32 nelem;
  	register int totalsize = 0;
  
+ 	if (!principal)
+ 		return KRB5_PARSE_MALFORMED;
+ 
  	cp = krb5_princ_realm(context, principal)->data;
  	length = krb5_princ_realm(context, principal)->length;
  	totalsize += length;
*** src/kadmin/server/server_stubs.c	Thu Jul 25 13:54:34 2002
--- src/kadmin/server/server_stubs.c	Thu Jul 25 13:28:07 2002
***************
*** 257,263 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg);
  
      if (CHANGEPW_SERVICE(rqstp)
  	|| !acl_check(handle->context, rqstp->rq_clntcred, ACL_ADD,
--- 257,266 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (CHANGEPW_SERVICE(rqstp)
  	|| !acl_check(handle->context, rqstp->rq_clntcred, ACL_ADD,
***************
*** 311,317 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg);
  
      if (CHANGEPW_SERVICE(rqstp)
  	|| !acl_check(handle->context, rqstp->rq_clntcred, ACL_ADD,
--- 314,323 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (CHANGEPW_SERVICE(rqstp)
  	|| !acl_check(handle->context, rqstp->rq_clntcred, ACL_ADD,
***************
*** 367,373 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
      
      if (CHANGEPW_SERVICE(rqstp)
  	|| !acl_check(handle->context, rqstp->rq_clntcred, ACL_DELETE,
--- 373,382 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
      
      if (CHANGEPW_SERVICE(rqstp)
  	|| !acl_check(handle->context, rqstp->rq_clntcred, ACL_DELETE,
***************
*** 415,421 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg);
  
      if (CHANGEPW_SERVICE(rqstp)
  	|| !acl_check(handle->context, rqstp->rq_clntcred, ACL_MODIFY,
--- 424,433 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (CHANGEPW_SERVICE(rqstp)
  	|| !acl_check(handle->context, rqstp->rq_clntcred, ACL_MODIFY,
***************
*** 469,476 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->src, &prime_arg1);
!     krb5_unparse_name(handle->context, arg->dest, &prime_arg2);
      sprintf(prime_arg, "%s to %s", prime_arg1, prime_arg2);
  
      ret.code = KADM5_OK;
--- 481,491 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->src, &prime_arg1) ||
!         krb5_unparse_name(handle->context, arg->dest, &prime_arg2)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
      sprintf(prime_arg, "%s to %s", prime_arg1, prime_arg2);
  
      ret.code = KADM5_OK;
***************
*** 539,545 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
  
      if (! cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ) &&
  	(CHANGEPW_SERVICE(rqstp) || !acl_check(handle->context,
--- 554,563 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (! cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ) &&
  	(CHANGEPW_SERVICE(rqstp) || !acl_check(handle->context,
***************
*** 659,665 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
  
      if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) {
  	 ret.code = chpass_principal_wrapper((void *)handle, arg->princ,
--- 677,686 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) {
  	 ret.code = chpass_principal_wrapper((void *)handle, arg->princ,
***************
*** 717,723 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
  
      if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) {
  	 ret.code = chpass_principal_wrapper((void *)handle, arg->princ,
--- 738,747 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) {
  	 ret.code = chpass_principal_wrapper((void *)handle, arg->princ,
***************
*** 778,784 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
  
      if (!(CHANGEPW_SERVICE(rqstp)) &&
  	       acl_check(handle->context, rqstp->rq_clntcred,
--- 802,811 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (!(CHANGEPW_SERVICE(rqstp)) &&
  	       acl_check(handle->context, rqstp->rq_clntcred,
***************
*** 833,839 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
  
      if (!(CHANGEPW_SERVICE(rqstp)) &&
  	       acl_check(handle->context, rqstp->rq_clntcred,
--- 860,869 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (!(CHANGEPW_SERVICE(rqstp)) &&
  	       acl_check(handle->context, rqstp->rq_clntcred,
***************
*** 888,894 ****
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
  
      if (!(CHANGEPW_SERVICE(rqstp)) &&
  	       acl_check(handle->context, rqstp->rq_clntcred,
--- 918,927 ----
  	 ret.code = KADM5_FAILURE;
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (!(CHANGEPW_SERVICE(rqstp)) &&
  	       acl_check(handle->context, rqstp->rq_clntcred,
***************
*** 952,958 ****
  	 free_server_handle(handle);
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
  
      if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) {
  	 ret.code = randkey_principal_wrapper((void *)handle,
--- 985,994 ----
  	 free_server_handle(handle);
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) {
  	 ret.code = randkey_principal_wrapper((void *)handle,
***************
*** 1025,1031 ****
  	 free_server_handle(handle);
  	 return &ret;
      }
!     krb5_unparse_name(handle->context, arg->princ, &prime_arg);
  
      if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) {
  	 ret.code = randkey_principal_wrapper((void *)handle,
--- 1061,1070 ----
  	 free_server_handle(handle);
  	 return &ret;
      }
!     if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
! 	 ret.code = KADM5_BAD_PRINCIPAL;
! 	 return &ret;
!     }
  
      if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) {
  	 ret.code = randkey_principal_wrapper((void *)handle,
>Audit-Trail:
>Unformatted:



More information about the krb5-bugs mailing list