/* Copyright (C) 2012 the GSS-PROXY contributors, see COPYING for license */ #include "gss_plugin.h" #include OM_uint32 gssi_export_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_buffer_t interprocess_token) { struct gpp_context_handle *ctx; gss_buffer_desc output_token; OM_uint32 maj, min; GSSI_TRACE(); ctx = (struct gpp_context_handle *)context_handle; if (!ctx) { return GSS_S_CALL_INACCESSIBLE_READ; } /* for now we have support only for some specific known * mechanisms for which we can export/import the context */ if (ctx->remote && !ctx->local) { maj = gpp_remote_to_local_ctx(&min, &ctx->remote, &ctx->local); if (maj != GSS_S_COMPLETE) { *minor_status = gpp_map_error(min); return maj; } } maj = gss_export_sec_context(minor_status, &ctx->local, interprocess_token); if (maj == GSS_S_COMPLETE && ctx->remote) { (void)gpm_delete_sec_context(&min, &ctx->remote, &output_token); } return maj; } OM_uint32 gssi_import_sec_context(OM_uint32 *minor_status, gss_buffer_t interprocess_token, gss_ctx_id_t *context_handle) { GSSI_TRACE(); return GSS_S_UNAVAILABLE; } OM_uint32 gssi_import_sec_context_by_mech(OM_uint32 *minor_status, gss_OID mech_type, gss_buffer_t interprocess_token, gss_ctx_id_t *context_handle) { struct gpp_context_handle *ctx; gss_buffer_desc wrap_token = {0}; OM_uint32 maj, min = 0; GSSI_TRACE(); ctx = calloc(1, sizeof(struct gpp_context_handle)); if (!ctx) { *minor_status = 0; return GSS_S_FAILURE; } /* NOTE: it makes no sense to import a context remotely atm, * so we only handle the local case for now. */ maj = gpp_wrap_sec_ctx_token(&min, mech_type, interprocess_token, &wrap_token); if (maj != GSS_S_COMPLETE) { goto done; } maj = gss_import_sec_context(&min, &wrap_token, &ctx->local); done: *minor_status = gpp_map_error(min); if (maj == GSS_S_COMPLETE) { *context_handle = (gss_ctx_id_t)ctx; } else { free(ctx); } (void)gss_release_buffer(&min, &wrap_token); return maj; } OM_uint32 gssi_process_context_token(OM_uint32 *minor_status, gss_ctx_id_t context_handle, gss_buffer_t token_buffer) { struct gpp_context_handle *ctx; OM_uint32 maj, min; GSSI_TRACE(); ctx = (struct gpp_context_handle *)context_handle; if (!ctx) { return GSS_S_CALL_INACCESSIBLE_READ; } /* for now we have support only for some specific known * mechanisms for which we can export/import the context */ if (ctx->remote && !ctx->local) { maj = gpp_remote_to_local_ctx(&min, &ctx->remote, &ctx->local); if (maj != GSS_S_COMPLETE) { *minor_status = gpp_map_error(min); return maj; } } return gss_process_context_token(minor_status, ctx->local, token_buffer); } OM_uint32 gssi_context_time(OM_uint32 *minor_status, gss_ctx_id_t context_handle, OM_uint32 *time_rec) { struct gpp_context_handle *ctx; OM_uint32 maj, min; GSSI_TRACE(); *minor_status = 0; ctx = (struct gpp_context_handle *)context_handle; if (!ctx) { return GSS_S_CALL_INACCESSIBLE_READ; } /* for now we have support only for some specific known * mechanisms for which we can export/import the context */ if (ctx->remote) { OM_uint32 lifetime; maj = gpm_inquire_context(&min, ctx->remote, NULL, NULL, &lifetime, NULL, NULL, NULL, NULL); if (maj != GSS_S_COMPLETE) { *minor_status = gpp_map_error(min); return maj; } if (lifetime > 0) { *time_rec = lifetime; return GSS_S_COMPLETE; } else { *time_rec = 0; return GSS_S_CONTEXT_EXPIRED; } } else if (ctx->local) { return gss_context_time(minor_status, ctx->local, time_rec); } else { return GSS_S_NO_CONTEXT; } } OM_uint32 gssi_inquire_context(OM_uint32 *minor_status, gss_ctx_id_t context_handle, gss_name_t *src_name, gss_name_t *targ_name, OM_uint32 *lifetime_rec, gss_OID *mech_type, OM_uint32 *ctx_flags, int *locally_initiated, int *open) { struct gpp_context_handle *ctx_handle; struct gpp_name_handle *s_name = NULL; struct gpp_name_handle *t_name = NULL; gss_OID mech_oid; OM_uint32 maj, min; GSSI_TRACE(); if (!context_handle) { return GSS_S_CALL_INACCESSIBLE_READ; } ctx_handle = (struct gpp_context_handle *)context_handle; if (!ctx_handle->local && !ctx_handle->remote) { return GSS_S_CALL_INACCESSIBLE_READ; } if (src_name) { s_name = calloc(1, sizeof(struct gpp_name_handle)); if (!s_name) { min = ENOMEM; maj = GSS_S_FAILURE; goto done; } } if (targ_name) { t_name = calloc(1, sizeof(struct gpp_name_handle)); if (!t_name) { min = ENOMEM; maj = GSS_S_FAILURE; goto done; } } if (ctx_handle->local) { maj = gss_inquire_context(&min, ctx_handle->local, s_name ? &s_name->local : NULL, t_name ? &t_name->local : NULL, lifetime_rec, &mech_oid, ctx_flags, locally_initiated, open); } else { maj = gpm_inquire_context(&min, ctx_handle->remote, s_name ? &s_name->remote : NULL, t_name ? &t_name->remote : NULL, lifetime_rec, &mech_oid, ctx_flags, locally_initiated, open); } if (maj != GSS_S_COMPLETE) { goto done; } if (s_name) { maj = gpp_copy_oid(&min, mech_oid, &s_name->mech_type); if (maj != GSS_S_COMPLETE) { goto done; } } if (t_name) { maj = gpp_copy_oid(&min, mech_oid, &t_name->mech_type); if (maj != GSS_S_COMPLETE) { goto done; } } done: *minor_status = gpp_map_error(min); if (maj == GSS_S_COMPLETE) { if (mech_type) { *mech_type = mech_oid; } else { (void)gss_release_oid(&min, &mech_oid); } if (src_name) { *src_name = (gss_name_t)s_name; } if (targ_name) { *targ_name = (gss_name_t)t_name; } } else { (void)gss_release_oid(&min, &mech_oid); (void)gssi_release_name(&min, (gss_name_t *)&s_name); (void)gssi_release_name(&min, (gss_name_t *)&t_name); } return maj; } OM_uint32 gssi_inquire_sec_context_by_oid(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, const gss_OID desired_object, gss_buffer_set_t *data_set) { struct gpp_context_handle *ctx; OM_uint32 maj, min; GSSI_TRACE(); ctx = (struct gpp_context_handle *)context_handle; if (!ctx) { return GSS_S_CALL_INACCESSIBLE_READ; } /* for now we have support only for some specific known * mechanisms for which we can export/import the context */ if (ctx->remote && !ctx->local) { maj = gpp_remote_to_local_ctx(&min, &ctx->remote, &ctx->local); if (maj != GSS_S_COMPLETE) { *minor_status = gpp_map_error(min); return maj; } } return gss_inquire_sec_context_by_oid(minor_status, ctx->local, desired_object, data_set); } OM_uint32 gssi_set_sec_context_option(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, const gss_OID desired_object, const gss_buffer_t value) { struct gpp_context_handle *ctx; OM_uint32 maj, min; GSSI_TRACE(); if (*context_handle) { ctx = (struct gpp_context_handle *)(*context_handle); } else { ctx = calloc(1, sizeof(struct gpp_context_handle)); if (!ctx) { *minor_status = 0; return GSS_S_FAILURE; } } /* for now we have support only for some specific known * mechanisms for which we can export/import the context */ if (ctx->remote && !ctx->local) { maj = gpp_remote_to_local_ctx(&min, &ctx->remote, &ctx->local); if (maj != GSS_S_COMPLETE) { *minor_status = gpp_map_error(min); goto done; } } maj = gss_set_sec_context_option(minor_status, &ctx->local, desired_object, value); done: *context_handle = (gss_ctx_id_t)ctx; if (maj != GSS_S_COMPLETE) { (void)gssi_delete_sec_context(&min, context_handle, NULL); } return maj; } OM_uint32 gssi_delete_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_buffer_t output_token) { struct gpp_context_handle *ctx; OM_uint32 maj, min; OM_uint32 rmaj = GSS_S_COMPLETE; GSSI_TRACE(); ctx = (struct gpp_context_handle *)*context_handle; *context_handle = GSS_C_NO_CONTEXT; if (ctx == NULL) { *minor_status = 0; return GSS_S_COMPLETE; } if (ctx->local) { maj = gss_delete_sec_context(&min, &ctx->local, output_token); if (maj != GSS_S_COMPLETE) { rmaj = maj; *minor_status = gpp_map_error(min); } } if (ctx->remote) { maj = gpm_delete_sec_context(&min, &ctx->remote, output_token); if (maj && rmaj == GSS_S_COMPLETE) { rmaj = maj; *minor_status = gpp_map_error(min); } } return rmaj; } OM_uint32 gssi_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle, int prf_key, const gss_buffer_t prf_in, ssize_t desired_output_len, gss_buffer_t prf_out) { struct gpp_context_handle *ctx; OM_uint32 maj, min; GSSI_TRACE(); ctx = (struct gpp_context_handle *)context_handle; if (!ctx) { return GSS_S_CALL_INACCESSIBLE_READ; } /* for now we have support only for some specific known * mechanisms for which we can export/import the context */ if (ctx->remote && !ctx->local) { maj = gpp_remote_to_local_ctx(&min, &ctx->remote, &ctx->local); if (maj != GSS_S_COMPLETE) { *minor_status = gpp_map_error(min); return maj; } } return gss_pseudo_random(minor_status, ctx->local, prf_key, prf_in, desired_output_len, prf_out); }