/* * Try to find tokeninfos which match configuration data recorded in the input * ccache, and if exactly one is found, drop the rest. */ static krb5_error_code filter_config_tokeninfos(krb5_context context, krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, krb5_otp_tokeninfo **tis) { krb5_otp_tokeninfo *match = NULL; size_t i, j; const char *vendor, *alg_id, *token_id; /* Pull up what we know about the token we want to use. */ vendor = cb->get_cc_config(context, rock, "vendor"); alg_id = cb->get_cc_config(context, rock, "algID"); token_id = cb->get_cc_config(context, rock, "tokenID"); /* Look for a single matching entry. */ for (i = 0; tis[i] != NULL; i++) { if (vendor != NULL && tis[i]->vendor.length > 0 && !data_eq_string(tis[i]->vendor, vendor)) continue; if (alg_id != NULL && tis[i]->alg_id.length > 0 && !data_eq_string(tis[i]->alg_id, alg_id)) continue; if (token_id != NULL && tis[i]->token_id.length > 0 && !data_eq_string(tis[i]->token_id, token_id)) continue; /* Oh, we already had a matching entry. More than one -> no change. */ if (match != NULL) return 0; match = tis[i]; } /* No matching entry -> no change. */ if (match == NULL) return 0; /* Prune out everything except the best match. */ for (i = 0, j = 0; tis[i] != NULL; i++) { if (tis[i] != match) k5_free_otp_tokeninfo(context, tis[i]); else tis[j++] = tis[i]; } tis[j] = NULL; return 0; }