From e6e6e54e89bc9644144436c3f267796ed790f70c Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Thu, 8 Jan 2015 15:56:37 -0500 Subject: Add indicator support to OTP Read an "indicator" profile variable for OTP token types and assert its values as indicators when that token type is used to authenticate. Add a test case in t_otp.py for this feature. ticket: 8157 --- src/plugins/preauth/otp/main.c | 13 ++++++++++++- src/plugins/preauth/otp/otp_state.c | 29 ++++++++++++++++++++++++----- src/plugins/preauth/otp/otp_state.h | 3 ++- 3 files changed, 38 insertions(+), 7 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/preauth/otp/main.c b/src/plugins/preauth/otp/main.c index 7941b4a..2649e9a 100644 --- a/src/plugins/preauth/otp/main.c +++ b/src/plugins/preauth/otp/main.c @@ -40,9 +40,12 @@ static krb5_preauthtype otp_pa_type_list[] = { KRB5_PADATA_OTP_REQUEST, 0 }; struct request_state { + krb5_context context; krb5_kdcpreauth_verify_respond_fn respond; void *arg; krb5_enc_tkt_part *enc_tkt_reply; + krb5_kdcpreauth_callbacks preauth_cb; + krb5_kdcpreauth_rock rock; }; static krb5_error_code @@ -151,9 +154,11 @@ nonce_generate(krb5_context ctx, unsigned int length, krb5_data *nonce_out) } static void -on_response(void *data, krb5_error_code retval, otp_response response) +on_response(void *data, krb5_error_code retval, otp_response response, + char *const *indicators) { struct request_state rs = *(struct request_state *)data; + char *const *ind; free(data); @@ -163,6 +168,9 @@ on_response(void *data, krb5_error_code retval, otp_response response) if (retval == 0) rs.enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; + for (ind = indicators; ind != NULL && *ind != NULL && retval == 0; ind++) + retval = rs.preauth_cb->add_auth_indicator(rs.context, rs.rock, *ind); + rs.respond(rs.arg, retval, NULL, NULL, NULL); } @@ -305,9 +313,12 @@ otp_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, rs = k5alloc(sizeof(struct request_state), &retval); if (rs == NULL) goto error; + rs->context = context; rs->arg = arg; rs->respond = respond; rs->enc_tkt_reply = enc_tkt_reply; + rs->preauth_cb = cb; + rs->rock = rock; /* Get the principal's OTP configuration string. */ retval = cb->get_string(context, rock, "otp", &config); diff --git a/src/plugins/preauth/otp/otp_state.c b/src/plugins/preauth/otp/otp_state.c index 7deb462..79fbc4d 100644 --- a/src/plugins/preauth/otp/otp_state.c +++ b/src/plugins/preauth/otp/otp_state.c @@ -52,6 +52,7 @@ typedef struct token_type_st { int timeout; size_t retries; krb5_boolean strip_realm; + char **indicators; } token_type; typedef struct token_st { @@ -133,6 +134,7 @@ token_type_free(token_type *type) free(type->name); free(type->server); free(type->secret); + profile_free_list(type->indicators); } /* Construct the internal default token type. */ @@ -172,6 +174,8 @@ static krb5_error_code token_type_decode(profile_t profile, const char *name, token_type *out) { char *server = NULL, *name_copy = NULL, *secret = NULL, *pstr = NULL; + char **indicators = NULL; + const char *keys[4]; int strip_realm, timeout, retries; krb5_error_code retval; @@ -241,18 +245,32 @@ token_type_decode(profile_t profile, const char *name, token_type *out) if (retval != 0) goto cleanup; + /* Get the authentication indicators to assert if this token is used. */ + keys[0] = "otp"; + keys[1] = name; + keys[2] = "indicator"; + keys[3] = NULL; + retval = profile_get_values(profile, keys, &indicators); + if (retval == PROF_NO_RELATION) + retval = 0; + if (retval != 0) + goto cleanup; + out->name = name_copy; out->server = server; out->secret = secret; out->timeout = timeout; out->retries = retries; out->strip_realm = strip_realm; + out->indicators = indicators; name_copy = server = secret = NULL; + indicators = NULL; cleanup: free(name_copy); free(server); free(secret); + profile_free_list(indicators); return retval; } @@ -545,6 +563,7 @@ callback(krb5_error_code retval, const krad_packet *rqst, const krad_packet *resp, void *data) { request *req = data; + char *const *indicators = req->tokens[req->index].type->indicators; req->index++; @@ -554,7 +573,7 @@ callback(krb5_error_code retval, const krad_packet *rqst, /* If we received an accept packet, success! */ if (krad_packet_get_code(resp) == krad_code_name2num("Access-Accept")) { - req->cb(req->data, retval, otp_response_success); + req->cb(req->data, retval, otp_response_success, indicators); request_free(req); return; } @@ -567,7 +586,7 @@ callback(krb5_error_code retval, const krad_packet *rqst, request_send(req); error: - req->cb(req->data, retval, otp_response_fail); + req->cb(req->data, retval, otp_response_fail, NULL); request_free(req); } @@ -594,7 +613,7 @@ request_send(request *req) return; error: - req->cb(req->data, retval, otp_response_fail); + req->cb(req->data, retval, otp_response_fail, NULL); request_free(req); } @@ -615,7 +634,7 @@ otp_state_verify(otp_state *state, verto_ctx *ctx, krb5_const_principal princ, rqst = calloc(1, sizeof(request)); if (rqst == NULL) { - (*cb)(data, ENOMEM, otp_response_fail); + (*cb)(data, ENOMEM, otp_response_fail, NULL); return; } rqst->state = state; @@ -646,6 +665,6 @@ otp_state_verify(otp_state *state, verto_ctx *ctx, krb5_const_principal princ, return; error: - (*cb)(data, retval, otp_response_fail); + (*cb)(data, retval, otp_response_fail, NULL); request_free(rqst); } diff --git a/src/plugins/preauth/otp/otp_state.h b/src/plugins/preauth/otp/otp_state.h index 4247d0b..da57ad9 100644 --- a/src/plugins/preauth/otp/otp_state.h +++ b/src/plugins/preauth/otp/otp_state.h @@ -43,7 +43,8 @@ typedef enum otp_response { typedef struct otp_state_st otp_state; typedef void -(*otp_cb)(void *data, krb5_error_code retval, otp_response response); +(*otp_cb)(void *data, krb5_error_code retval, otp_response response, + char *const *indicators); krb5_error_code otp_state_new(krb5_context ctx, otp_state **self); -- cgit v1.1