* svr_principal.c (add_to_history): If the policy a principal uses has
authorMitchell Berger <mitchb@mit.edu>
Tue, 16 Oct 2001 10:12:31 +0000 (10:12 +0000)
committerMitchell Berger <mitchb@mit.edu>
Tue, 16 Oct 2001 10:12:31 +0000 (10:12 +0000)
been changed to hold a lesser number of history entries than it did
before, extract the correct number and value of old keys from the
history array into a newly allocated array of the proper size.  Failing
to do this made kadmind vulnerable to a crash upon changing such a
principal's password.  Original patch written by Matt Crawford, with
a few changes.

[Fixes krb5-admin/929]

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13813 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/kadm5/srv/ChangeLog
src/lib/kadm5/srv/svr_principal.c

index 57b9b10eecdef8bc3dfeec3a657e303190f3d65c..df297ffdf07b5d602c2f8d4d2b5e588f877872ec 100644 (file)
@@ -1,3 +1,14 @@
+2001-10-16  Mitchell Berger  <mitchb@mit.edu>
+           Matt Crawford  <crawdad@fnal.gov>
+
+       * svr_principal.c (add_to_history): If the policy a principal uses has
+       been changed to hold a lesser number of history entries than it did
+       before, extract the correct number and value of old keys from the
+       history array into a newly allocated array of the proper size.  Failing
+       to do this made kadmind vulnerable to a crash upon changing such a
+       principal's password.  Original patch written by Matt Crawford, with
+       a few changes.
+
 2001-10-09  Ken Raeburn  <raeburn@mit.edu>
 
        * server_acl.h: Make prototypes unconditional.
index c0899aa38c013fd481a516303ee72a620e94a10d..933d3c1f7745e2802439674383a082c5c3113e0b 100644 (file)
@@ -986,6 +986,7 @@ void free_history_entry(krb5_context context, osa_pw_hist_ent *hist)
  * array where the next element should be written, and must be [0,
  * adb->old_key_len).
  */
+#define KADM_MOD(x) (x + adb->old_key_next) % adb->old_key_len
 static kadm5_ret_t add_to_history(krb5_context context,
                                  osa_princ_ent_t adb,
                                  kadm5_policy_ent_t pol,
@@ -1013,6 +1014,39 @@ static kadm5_ret_t add_to_history(krb5_context context,
          
          memset(&adb->old_keys[adb->old_key_len],0,sizeof(osa_pw_hist_ent)); 
          adb->old_key_len++;
+     } else if (adb->old_key_len > pol->pw_history_num-1) {
+        /*
+         * The policy must have changed!  Shrink the array.
+         * Can't simply realloc() down, since it might be wrapped.
+         * To understand the arithmetic below, note that we are
+         * copying into new positions 0 .. N-1 from old positions
+         * old_key_next-N .. old_key_next-1, modulo old_key_len,
+         * where N = pw_history_num - 1 is the length of the
+         * shortened list.        Matt Crawford, FNAL
+         */
+        int j;
+        histp = (osa_pw_hist_ent *)
+            malloc((pol->pw_history_num - 1) * sizeof (osa_pw_hist_ent));
+        if (histp) {
+            for (i = 0; i < pol->pw_history_num - 1; i++) {
+                /* We need the number we use the modulus operator on to be
+                   positive, so after subtracting pol->pw_history_num-1, we
+                   add back adb->old_key_len. */
+                j = KADM_MOD(i - (pol->pw_history_num - 1) + adb->old_key_len);
+                histp[i] = adb->old_keys[j];
+            }
+            /* Now free the ones we don't keep (the oldest ones) */
+            for (i = 0; i < adb->old_key_len - (pol->pw_history_num - 1); i++)
+                for (j = 0; j < adb->old_keys[KADM_MOD(i)].n_key_data; j++)
+                    krb5_free_key_data_contents(context,
+                               &adb->old_keys[KADM_MOD(i)].key_data[j]);
+            free((void *)adb->old_keys);
+            adb->old_keys = histp;
+            adb->old_key_len = pol->pw_history_num - 1;
+            adb->old_key_next = 0;
+        } else {
+            return(ENOMEM);
+        }
      }
 
      /* free the old pw history entry if it contains data */
@@ -1029,6 +1063,7 @@ static kadm5_ret_t add_to_history(krb5_context context,
 
      return(0);
 }
+#undef KADM_MOD
 
 kadm5_ret_t
 kadm5_chpass_principal(void *server_handle,