set_refresh_time(context, cred->ccache, refresh);
}
+struct verify_params {
+ krb5_principal princ;
+ krb5_keytab keytab;
+};
+
+static krb5_error_code
+verify_initial_cred(krb5_context context, krb5_creds *creds,
+ const struct verify_params *verify)
+{
+ krb5_verify_init_creds_opt vopts;
+
+ krb5_verify_init_creds_opt_init(&vopts);
+ krb5_verify_init_creds_opt_set_ap_req_nofail(&vopts, TRUE);
+ return krb5_verify_init_creds(context, creds, verify->princ,
+ verify->keytab, NULL, &vopts);
+}
+
/* Get initial credentials using the supplied password or client keytab. */
static krb5_error_code
-get_initial_cred(krb5_context context, krb5_gss_cred_id_rec *cred)
+get_initial_cred(krb5_context context, const struct verify_params *verify,
+ krb5_gss_cred_id_rec *cred)
{
krb5_error_code code;
krb5_get_init_creds_opt *opt = NULL;
}
if (code)
goto cleanup;
+ if (cred->password != NULL && verify != NULL) {
+ code = verify_initial_cred(context, &creds, verify);
+ if (code)
+ goto cleanup;
+ }
kg_cred_set_initial_refresh(context, cred, &creds.times);
cred->have_tgt = TRUE;
cred->expire = creds.times.endtime;
/* Get initial credentials if we ought to and are able to. */
static krb5_error_code
-maybe_get_initial_cred(krb5_context context, krb5_gss_cred_id_rec *cred)
+maybe_get_initial_cred(krb5_context context,
+ const struct verify_params *verify,
+ krb5_gss_cred_id_rec *cred)
{
krb5_error_code code;
/* Get creds if we have none or if it's time to refresh. */
if (cred->expire == 0 || kg_cred_time_to_refresh(context, cred)) {
- code = get_initial_cred(context, cred);
+ code = get_initial_cred(context, verify, cred);
/* If we were trying to refresh and failed, we can keep going. */
if (code && cred->expire == 0)
return code;
}
static OM_uint32
-acquire_init_cred(krb5_context context,
- OM_uint32 *minor_status,
- krb5_ccache req_ccache,
- gss_buffer_t password,
+acquire_init_cred(krb5_context context, OM_uint32 *minor_status,
+ krb5_ccache req_ccache, gss_buffer_t password,
krb5_keytab client_keytab,
+ const struct verify_params *verify,
krb5_gss_cred_id_rec *cred)
{
krb5_error_code code;
}
#endif
- code = maybe_get_initial_cred(context, cred);
+ code = maybe_get_initial_cred(context, verify, cred);
if (code)
goto error;
OM_uint32 time_req, gss_cred_usage_t cred_usage,
krb5_ccache ccache, krb5_keytab client_keytab,
krb5_keytab keytab, const char *rcname,
+ const struct verify_params *verify,
krb5_boolean iakerb, gss_cred_id_t *output_cred_handle,
OM_uint32 *time_rec)
{
*/
if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) {
ret = acquire_init_cred(context, minor_status, ccache, password,
- client_keytab, cred);
+ client_keytab, verify, cred);
if (ret != GSS_S_COMPLETE)
goto error_out;
}
ret = acquire_cred_context(context, minor_status, desired_name, password,
time_req, cred_usage, ccache, NULL, keytab,
- NULL, iakerb, output_cred_handle, time_rec);
+ NULL, NULL, iakerb, output_cred_handle,
+ time_rec);
out:
krb5_free_context(context);
}
/* Resolve name to ccache and possibly get initial credentials. */
- code = maybe_get_initial_cred(context, cred);
+ code = maybe_get_initial_cred(context, NULL, cred);
if (code)
goto kerr;
krb5_keytab client_keytab = NULL;
krb5_keytab keytab = NULL;
krb5_ccache ccache = NULL;
+ krb5_principal verify_princ = NULL;
const char *rcname, *value;
+ struct verify_params vparams = { NULL };
+ const struct verify_params *verify = NULL;
gss_buffer_desc pwbuf;
gss_buffer_t password = NULL;
OM_uint32 ret;
password = &pwbuf;
}
+ ret = kg_value_from_cred_store(cred_store, KRB5_CS_VERIFY_URN, &value);
+ if (GSS_ERROR(ret))
+ goto out;
+ if (value != NULL) {
+ if (iakerb || password == NULL) {
+ /* Only valid if acquiring cred with password, and not supported
+ * with IAKERB. */
+ *minor_status = G_BAD_USAGE;
+ ret = GSS_S_FAILURE;
+ goto out;
+ }
+ if (*value != '\0') {
+ code = krb5_parse_name(context, value, &verify_princ);
+ if (code != 0) {
+ *minor_status = code;
+ ret = GSS_S_FAILURE;
+ goto out;
+ }
+ }
+ vparams.princ = verify_princ;
+ vparams.keytab = keytab;
+ verify = &vparams;
+ }
ret = acquire_cred_context(context, minor_status, desired_name, password,
time_req, cred_usage, ccache, client_keytab,
- keytab, rcname, iakerb, output_cred_handle,
- time_rec);
+ keytab, rcname, verify, iakerb,
+ output_cred_handle, time_rec);
out:
if (ccache != NULL)
krb5_kt_close(context, client_keytab);
if (keytab != NULL)
krb5_kt_close(context, keytab);
+ krb5_free_principal(context, verify_princ);
krb5_free_context(context);
return ret;
}
realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, 'password',
password('user')], expected_trace=msgs)
+mark('verify')
+msgs = ('Getting initial credentials for %s' % realm.user_princ,
+ 'Storing %s -> %s in MEMORY:' % (realm.user_princ, realm.krbtgt_princ),
+ 'Getting credentials %s -> %s' % (realm.user_princ, service_cs),
+ 'Storing %s -> %s in MEMORY:' % (realm.user_princ, service_cs))
+realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, 'password',
+ password('user'), 'keytab', servicekeytab, 'verify',
+ service_cs], expected_trace=msgs)
+# Try again with verification failing due to key mismatch.
+realm.run([kadminl, 'cpw', '-randkey', service_cs])
+realm.run([kadminl, 'modprinc', '-kvno', '1', service_cs])
+errmsg = 'Cannot decrypt ticket for %s' % service_cs
+realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, 'password',
+ password('user'), 'keytab', servicekeytab, 'verify',
+ service_cs], expected_code=1, expected_msg=errmsg)
+
success('Credential store tests')