+/* Set salt in rock based on pw-salt or afs3-salt elements in padata. */
+static krb5_error_code
+get_salt(krb5_context context, krb5_pa_data **padata,
+ krb5_kdc_req *request, krb5_clpreauth_rock rock)
+{
+ krb5_error_code ret;
+ krb5_pa_data *pa;
+ krb5_data d;
+ const char *p;
+
+ /* Look for a pw-salt or afs3-salt element. */
+ pa = krb5int_find_pa_data(context, padata, KRB5_PADATA_PW_SALT);
+ if (pa == NULL)
+ pa = krb5int_find_pa_data(context, padata, KRB5_PADATA_AFS3_SALT);
+ if (pa == NULL)
+ return 0;
+
+ /* Set rock->salt based on the element we found. */
+ krb5_free_data_contents(context, rock->salt);
+ d = padata2data(*pa);
+ ret = krb5int_copy_data_contents(context, &d, rock->salt);
+ if (ret)
+ return ret;
+
+ /* Adjust the salt if we got it from an afs3-salt element. */
+ if (pa->pa_type == KRB5_PADATA_AFS3_SALT) {
+ /* Work around a (possible) old Heimdal KDC foible. */
+ p = memchr(rock->salt->data, '@', rock->salt->length);
+ if (p != NULL)
+ rock->salt->length = p - rock->salt->data;
+ /* Tolerate extra null in MIT KDC afs3-salt value. */
+ if (rock->salt->length > 0 &&
+ rock->salt->data[rock->salt->length - 1] == '\0')
+ rock->salt->length--;
+ /* Set an s2kparams value to indicate AFS string-to-key. */
+ krb5_free_data_contents(context, rock->s2kparams);
+ ret = alloc_data(rock->s2kparams, 1);
+ if (ret)
+ return ret;
+ rock->s2kparams->data[0] = '\1';
+ }
+
+ *rock->default_salt = FALSE;
+ TRACE_PREAUTH_SALT(context, rock->salt, pa->pa_type);
+ return 0;
+}
+