OM_uint32 _gssiakerb_accept_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle, const gss_cred_id_t acceptor_cred_handle, const gss_buffer_t input_token_buffer, const gss_channel_bindings_t input_chan_bindings, gss_name_t * src_name, gss_OID * mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags, OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle) { return accept_sec_context(minor_status, context_handle, acceptor_cred_handle, input_token_buffer, input_chan_bindings, src_name, mech_type, output_token, ret_flags, time_rec, delegated_cred_handle, GSS_IAKERB_MECHANISM, iakerb_acceptor_start); }
static int do_gss_auth(void *obj, char *ibuf, size_t ibuflen, char *rbuf, int *rbuflen, char *username, size_t ulen, struct session_info *sinfo ) { OM_uint32 status = 0; gss_name_t client_name; gss_ctx_id_t context = GSS_C_NO_CONTEXT; gss_buffer_desc ticket_buffer, authenticator_buff; int ret = 0; /* * Try to accept the secondary context, using the ticket/token the * client sent us. Ticket is stored at current ibuf position. * Don't try to release ticket_buffer later, it points into ibuf! */ ticket_buffer.length = ibuflen; ticket_buffer.value = ibuf; if ((ret = accept_sec_context(&context, &ticket_buffer, &client_name, &authenticator_buff))) return ret; log_service_name(context); /* We succesfully acquired the secondary context, now get the username for afpd and gss_wrap the sessionkey */ if ((ret = get_client_username(username, ulen, &client_name))) goto cleanup_client_name; if ((ret = wrap_sessionkey(context, sinfo))) goto cleanup_client_name; /* Authenticated, construct the reply using: * authenticator length (uint16_t) * authenticator */ /* copy the authenticator length into the reply buffer */ uint16_t auth_len = htons(authenticator_buff.length); memcpy(rbuf, &auth_len, sizeof(auth_len)); *rbuflen += sizeof(auth_len); rbuf += sizeof(auth_len); /* copy the authenticator value into the reply buffer */ memcpy(rbuf, authenticator_buff.value, authenticator_buff.length); *rbuflen += authenticator_buff.length; cleanup_client_name: gss_release_name(&status, &client_name); cleanup_context: gss_release_buffer(&status, &authenticator_buff); gss_delete_sec_context(&status, &context, NULL); return ret; }
static int build_context(struct client *ipeer, struct client *apeer, int32_t flags, int32_t hCred, int32_t *iContext, int32_t *aContext, int32_t *hDelegCred) { int32_t val = GSMERR_ERROR, ic = 0, ac = 0, deleg = 0; krb5_data itoken, otoken; int iDone = 0, aDone = 0; int step = 0; int first_call = 0x80; if (apeer->target_name == NULL) errx(1, "apeer %s have no target name", apeer->name); krb5_data_zero(&itoken); while (!iDone || !aDone) { if (iDone) { warnx("iPeer already done, aPeer want extra rtt"); val = GSMERR_ERROR; goto out; } val = init_sec_context(ipeer, &ic, &hCred, flags|first_call, apeer->target_name, &itoken, &otoken); step++; switch(val) { case GSMERR_OK: iDone = 1; if (aDone) continue; break; case GSMERR_CONTINUE_NEEDED: break; default: warnx("iPeer %s failed with %d (step %d)", ipeer->name, (int)val, step); goto out; } if (aDone) { warnx("aPeer already done, iPeer want extra rtt"); val = GSMERR_ERROR; goto out; } val = accept_sec_context(apeer, &ac, flags|first_call, &otoken, &itoken, &deleg); step++; switch(val) { case GSMERR_OK: aDone = 1; if (iDone) continue; break; case GSMERR_CONTINUE_NEEDED: break; default: warnx("aPeer %s failed with %d (step %d)", apeer->name, (int)val, step); val = GSMERR_ERROR; goto out; } first_call = 0; val = GSMERR_OK; } if (iContext == NULL || val != GSMERR_OK) { if (ic) toast_resource(ipeer, ic); if (iContext) *iContext = 0; } else *iContext = ic; if (aContext == NULL || val != GSMERR_OK) { if (ac) toast_resource(apeer, ac); if (aContext) *aContext = 0; } else *aContext = ac; if (hDelegCred == NULL || val != GSMERR_OK) { if (deleg) toast_resource(apeer, deleg); if (hDelegCred) *hDelegCred = 0; } else *hDelegCred = deleg; out: return val; }
/* return 0 on success */ static int do_gss_auth(void *obj, char *ibuf, int ticket_len, char *rbuf, int *rbuflen, char *username, int ulen, struct session_info *sinfo ) { OM_uint32 status = 0; gss_name_t server_name, client_name; gss_cred_id_t server_creds; gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT; gss_buffer_desc ticket_buffer, authenticator_buff; int ret = 0; /* import our principal name from afpd */ if (get_afpd_principal(obj, &server_name) != 0) { return 1; } log_principal(server_name); /* Now we have to acquire our credentials */ if ((ret = acquire_credentials (&server_name, &server_creds))) goto cleanup_vars; /* * Try to accept the secondary context, using the ticket/token the * client sent us. Ticket is stored at current ibuf position. * Don't try to release ticket_buffer later, it points into ibuf! */ ticket_buffer.length = ticket_len; ticket_buffer.value = ibuf; ret = accept_sec_context (&context_handle, server_creds, &ticket_buffer, &client_name, &authenticator_buff); if (!ret) { /* We succesfully acquired the secondary context, now get the username for afpd and gss_wrap the sessionkey */ if ( 0 == (ret = get_client_username(username, ulen, &client_name)) ) { ret = wrap_sessionkey(context_handle, sinfo); } if (!ret) { /* FIXME: Is copying the authenticator really necessary? Where is this documented? */ u_int16_t auth_len = htons( authenticator_buff.length ); /* copy the authenticator length into the reply buffer */ memcpy( rbuf, &auth_len, sizeof(auth_len) ); *rbuflen += sizeof(auth_len); rbuf += sizeof(auth_len); /* copy the authenticator value into the reply buffer */ memcpy( rbuf, authenticator_buff.value, authenticator_buff.length ); *rbuflen += authenticator_buff.length; } /* Clean up after ourselves */ gss_release_name( &status, &client_name ); if ( authenticator_buff.value) gss_release_buffer( &status, &authenticator_buff ); gss_delete_sec_context( &status, &context_handle, NULL ); } gss_release_cred( &status, &server_creds ); cleanup_vars: gss_release_name( &status, &server_name ); return ret; }