diff options
-rw-r--r-- | src/gss_names.c | 9 | ||||
-rw-r--r-- | src/gss_ntlmssp.h | 14 | ||||
-rw-r--r-- | src/gss_sec_ctx.c | 110 | ||||
-rw-r--r-- | src/gss_spi.c | 21 |
4 files changed, 154 insertions, 0 deletions
diff --git a/src/gss_names.c b/src/gss_names.c index fe95aeb..7ccc3a0 100644 --- a/src/gss_names.c +++ b/src/gss_names.c @@ -244,6 +244,7 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst) int ret; dst->type = src->type; switch (src->type) { + case GSSNTLM_NAME_NULL: case GSSNTLM_NAME_ANON: break; case GSSNTLM_NAME_USER: @@ -302,6 +303,11 @@ uint32_t gssntlm_duplicate_name(uint32_t *minor_status, in = (struct gssntlm_name *)input_name; + if (in->type == GSSNTLM_NAME_NULL) { + *dest_name = GSS_C_NO_NAME; + return GSS_S_COMPLETE; + } + out = calloc(1, sizeof(struct gssntlm_name)); if (!out) { *minor_status = ENOMEM; @@ -322,6 +328,8 @@ void gssntlm_int_release_name(struct gssntlm_name *name) if (!name) return; switch (name->type) { + case GSSNTLM_NAME_NULL: + return; case GSSNTLM_NAME_ANON: break; case GSSNTLM_NAME_USER: @@ -332,6 +340,7 @@ void gssntlm_int_release_name(struct gssntlm_name *name) safefree(name->data.server.name); break; } + name->type = GSSNTLM_NAME_NULL; } uint32_t gssntlm_release_name(uint32_t *minor_status, diff --git a/src/gss_ntlmssp.h b/src/gss_ntlmssp.h index 308ecfd..de56bad 100644 --- a/src/gss_ntlmssp.h +++ b/src/gss_ntlmssp.h @@ -62,6 +62,7 @@ struct gssntlm_name { enum ntlm_name_type { + GSSNTLM_NAME_NULL, GSSNTLM_NAME_ANON, GSSNTLM_NAME_USER, GSSNTLM_NAME_SERVER @@ -132,6 +133,9 @@ struct gssntlm_ctx { struct ntlm_buffer chal_msg; struct ntlm_buffer auth_msg; + struct gssntlm_name source_name; + struct gssntlm_name target_name; + uint8_t server_chal[8]; /* requested gss fags */ @@ -269,4 +273,14 @@ uint32_t gssntlm_unwrap(uint32_t *minor_status, gss_buffer_t output_message_buffer, int *conf_state, gss_qop_t *qop_state); + +uint32_t gssntlm_inquire_context(uint32_t *minor_status, + gss_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + uint32_t *lifetime_rec, + gss_OID *mech_type, + uint32_t *ctx_flags, + int *locally_initiated, + int *open); #endif /* _GSS_NTLMSSP_H_ */ diff --git a/src/gss_sec_ctx.c b/src/gss_sec_ctx.c index fb574f4..7736244 100644 --- a/src/gss_sec_ctx.c +++ b/src/gss_sec_ctx.c @@ -114,6 +114,12 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status, } } else { cred = (struct gssntlm_cred *)claimant_cred_handle; + if ((cred->type != GSSNTLM_CRED_ANON) + && (cred->type != GSSNTLM_CRED_USER)) { + retmin = EINVAL; + retmaj = GSS_S_BAD_NAMETYPE; + goto done; + } } retmin = gssntlm_copy_creds(cred, &ctx->cred); @@ -122,6 +128,21 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status, goto done; } + retmin = gssntlm_copy_name(&ctx->cred.cred.user.user, + &ctx->source_name); + if (retmin) { + retmaj = GSS_S_FAILURE; + goto done; + } + + if (server) { + retmin = gssntlm_copy_name(server, &ctx->target_name); + if (retmin) { + retmaj = GSS_S_FAILURE; + goto done; + } + } + ctx->gss_flags = req_flags; ctx->role = GSSNTLM_CLIENT; @@ -572,6 +593,9 @@ uint32_t gssntlm_delete_sec_context(uint32_t *minor_status, ctx->chal_msg.length = 0; ctx->auth_msg.length = 0; + gssntlm_int_release_name(&ctx->source_name); + gssntlm_int_release_name(&ctx->target_name); + safefree(*context_handle); if (ret) { @@ -800,6 +824,12 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status, if (retmaj) goto done; } + retmin = gssntlm_copy_name(server_name, &ctx->target_name); + if (retmin) { + retmaj = GSS_S_FAILURE; + goto done; + } + computer_name = strdup(server_name->data.server.name); if (!computer_name) { retmin = ENOMEM; @@ -941,6 +971,12 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status, NULL, NULL); if (retmaj) goto done; + retmin = gssntlm_copy_name(gss_usrname, &ctx->source_name); + if (retmin) { + retmaj = GSS_S_FAILURE; + goto done; + } + /* NTLMv2 Key */ retmin = NTOWFv2(ctx->ntlm, &usr_cred->cred.user.nt_hash, usr_cred->cred.user.user.data.user.name, @@ -1042,3 +1078,77 @@ done: ntlm_free_buffer_data(&target_info); return retmaj; } + +uint32_t gssntlm_inquire_context(uint32_t *minor_status, + gss_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + uint32_t *lifetime_rec, + gss_OID *mech_type, + uint32_t *ctx_flags, + int *locally_initiated, + int *open) +{ + struct gssntlm_ctx *ctx; + uint32_t retmaj; + uint32_t retmin; + time_t now; + + *minor_status = 0; + + ctx = (struct gssntlm_ctx *)context_handle; + if (!ctx) return GSS_S_NO_CONTEXT; + + if (src_name) { + retmaj = gssntlm_duplicate_name(&retmin, + (gss_name_t)&ctx->source_name, + src_name); + if (retmaj) return retmaj; + } + + if (targ_name) { + retmaj = gssntlm_duplicate_name(&retmin, + (gss_name_t)&ctx->target_name, + targ_name); + if (retmaj) return retmaj; + } + + if (mech_type) { + *mech_type = discard_const(&gssntlm_oid); + } + + if (ctx_flags) { + *ctx_flags = ctx->gss_flags; + } + + if (locally_initiated) { + if (ctx->role == GSSNTLM_CLIENT) { + *locally_initiated = 1; + } else { + *locally_initiated = 0; + } + } + + if (ctx->established) { + if (lifetime_rec) { + now = time(NULL); + if (ctx->expiration_time > now) { + *lifetime_rec = 0; + } else { + *lifetime_rec = ctx->expiration_time - now; + } + } + if (open) { + *open = 1; + } + } else { + if (lifetime_rec) { + *lifetime_rec = 0; + } + if (open) { + *open = 0; + } + } + + return GSS_S_COMPLETE; +} diff --git a/src/gss_spi.c b/src/gss_spi.c index 8139d3c..d456f14 100644 --- a/src/gss_spi.c +++ b/src/gss_spi.c @@ -232,3 +232,24 @@ OM_uint32 gss_unwrap(OM_uint32 *minor_status, conf_state, qop_state); } + +OM_uint32 gss_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) +{ + return gssntlm_inquire_context(minor_status, + context_handle, + src_name, + targ_name, + lifetime_rec, + mech_type, + ctx_flags, + locally_initiated, + open); +} |