uint32_t sapgss_context_time( uint32_t *minor_status, gss_ctx_id_t context_handle, uint32_t *time_rec) { return gss_context_time(minor_status, context_handle, time_rec); }
OM_uint32 ntlm_gss_context_time( OM_uint32 *minor_status, const gss_ctx_id_t context_handle, OM_uint32 *time_rec) { OM_uint32 ret; ret = gss_context_time(minor_status, context_handle, time_rec); return (ret); }
int Condor_Auth_X509 :: endTime() const { OM_uint32 major_status; OM_uint32 minor_status; OM_uint32 time_rec; major_status = gss_context_time(&minor_status , context_handle , &time_rec); if (!(major_status == GSS_S_COMPLETE)) { return -1; } return time_rec; }
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 GSSAPI_CALLCONV _gss_spnego_context_time (OM_uint32 *minor_status, gss_const_ctx_id_t context_handle, OM_uint32 *time_rec ) { gssspnego_ctx ctx; *minor_status = 0; if (context_handle == GSS_C_NO_CONTEXT) { return GSS_S_NO_CONTEXT; } ctx = (gssspnego_ctx)context_handle; if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { return GSS_S_NO_CONTEXT; } return gss_context_time(minor_status, ctx->negotiated_ctx_id, time_rec); }
static isc_result_t process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout, dns_tsig_keyring_t *ring) { isc_result_t result = ISC_R_SUCCESS; dst_key_t *dstkey = NULL; dns_tsigkey_t *tsigkey = NULL; dns_fixedname_t principal; isc_stdtime_t now; isc_region_t intoken; isc_buffer_t *outtoken = NULL; gss_ctx_id_t gss_ctx = NULL; /* * You have to define either a gss credential (principal) to * accept with tkey-gssapi-credential, or you have to * configure a specific keytab (with tkey-gssapi-keytab) in * order to use gsstkey */ if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) { tkey_log("process_gsstkey(): no tkey-gssapi-credential " "or tkey-gssapi-keytab configured"); return (ISC_R_NOPERM); } if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) && !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) { tkeyout->error = dns_tsigerror_badalg; tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */ return (ISC_R_SUCCESS); } /* * XXXDCL need to check for key expiry per 4.1.1 * XXXDCL need a way to check fully established, perhaps w/key_flags */ intoken.base = tkeyin->key; intoken.length = tkeyin->keylen; result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring); if (result == ISC_R_SUCCESS) gss_ctx = dst_key_getgssctx(tsigkey->key); dns_fixedname_init(&principal); /* * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set */ result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab, &intoken, &outtoken, &gss_ctx, dns_fixedname_name(&principal), tctx->mctx); if (result == DNS_R_INVALIDTKEY) { if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); tkeyout->error = dns_tsigerror_badkey; tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */ return (ISC_R_SUCCESS); } if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) goto failure; /* * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times. */ isc_stdtime_get(&now); if (tsigkey == NULL) { #ifdef GSSAPI OM_uint32 gret, minor, lifetime; #endif isc_uint32_t expire; RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx, &dstkey, &intoken)); /* * Limit keys to 1 hour or the context's lifetime whichever * is smaller. */ expire = now + 3600; #ifdef GSSAPI gret = gss_context_time(&minor, gss_ctx, &lifetime); if (gret == GSS_S_COMPLETE && now + lifetime < expire) expire = now + lifetime; #endif RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm, dstkey, ISC_TRUE, dns_fixedname_name(&principal), now, expire, ring->mctx, ring, NULL)); dst_key_free(&dstkey); tkeyout->inception = now; tkeyout->expire = expire; } else { tkeyout->inception = tsigkey->inception; tkeyout->expire = tsigkey->expire; dns_tsigkey_detach(&tsigkey); } if (outtoken) { tkeyout->key = isc_mem_get(tkeyout->mctx, isc_buffer_usedlength(outtoken)); if (tkeyout->key == NULL) { result = ISC_R_NOMEMORY; goto failure; } tkeyout->keylen = isc_buffer_usedlength(outtoken); memmove(tkeyout->key, isc_buffer_base(outtoken), isc_buffer_usedlength(outtoken)); isc_buffer_free(&outtoken); } else { tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen); if (tkeyout->key == NULL) { result = ISC_R_NOMEMORY; goto failure; } tkeyout->keylen = tkeyin->keylen; memmove(tkeyout->key, tkeyin->key, tkeyin->keylen); } tkeyout->error = dns_rcode_noerror; tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */ return (ISC_R_SUCCESS); failure: if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); if (dstkey != NULL) dst_key_free(&dstkey); if (outtoken != NULL) isc_buffer_free(&outtoken); tkey_log("process_gsstkey(): %s", isc_result_totext(result)); /* XXXSRA */ return (result); }
/* perform a LDAP/SASL/SPNEGO/GSSKRB5 bind */ static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name) { ADS_STATUS status; bool ok; uint32 minor_status; int gss_rc, rc; gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL; gss_OID_desc krb5_mech_type = {9, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }; gss_OID mech_type = &krb5_mech_type; gss_OID actual_mech_type = GSS_C_NULL_OID; const char *spnego_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL}; gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT; gss_buffer_desc input_token, output_token; uint32 req_flags, ret_flags; uint32 req_tmp, ret_tmp; DATA_BLOB unwrapped; DATA_BLOB wrapped; struct berval cred, *scred = NULL; uint32_t context_validity = 0; time_t context_endtime = 0; status = ads_init_gssapi_cred(ads, &gss_cred); if (!ADS_ERR_OK(status)) { goto failed; } input_token.value = NULL; input_token.length = 0; req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG; switch (ads->ldap.wrap_type) { case ADS_SASLWRAP_TYPE_SEAL: req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG; break; case ADS_SASLWRAP_TYPE_SIGN: req_flags |= GSS_C_INTEG_FLAG; break; case ADS_SASLWRAP_TYPE_PLAIN: break; } /* Note: here we explicit ask for the krb5 mech_type */ gss_rc = gss_init_sec_context(&minor_status, gss_cred, &context_handle, serv_name, mech_type, req_flags, 0, NULL, &input_token, &actual_mech_type, &output_token, &ret_flags, NULL); if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) { status = ADS_ERROR_GSS(gss_rc, minor_status); goto failed; } /* * As some gssapi krb5 mech implementations * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG * to req_flags internaly, it's not possible to * use plain or signing only connection via * the gssapi interface. * * Because of this we need to check it the ret_flags * has more flags as req_flags and correct the value * of ads->ldap.wrap_type. * * I ads->auth.flags has ADS_AUTH_SASL_FORCE * we need to give an error. */ req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); if (req_tmp == ret_tmp) { /* everythings fine... */ } else if (req_flags & GSS_C_CONF_FLAG) { /* * here we wanted sealing but didn't got it * from the gssapi library */ status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED); goto failed; } else if ((req_flags & GSS_C_INTEG_FLAG) && !(ret_flags & GSS_C_INTEG_FLAG)) { /* * here we wanted siging but didn't got it * from the gssapi library */ status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED); goto failed; } else if (ret_flags & GSS_C_CONF_FLAG) { /* * here we didn't want sealing * but the gssapi library forces it * so correct the needed wrap_type if * the caller didn't forced siging only */ if (ads->auth.flags & ADS_AUTH_SASL_FORCE) { status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED); goto failed; } ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL; req_flags = ret_flags; } else if (ret_flags & GSS_C_INTEG_FLAG) { /* * here we didn't want signing * but the gssapi library forces it * so correct the needed wrap_type if * the caller didn't forced plain */ if (ads->auth.flags & ADS_AUTH_SASL_FORCE) { status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED); goto failed; } ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN; req_flags = ret_flags; } else { /* * This could (should?) not happen */ status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR); goto failed; } /* and wrap that in a shiny SPNEGO wrapper */ unwrapped = data_blob_const(output_token.value, output_token.length); wrapped = spnego_gen_negTokenInit(talloc_tos(), spnego_mechs, &unwrapped, NULL); gss_release_buffer(&minor_status, &output_token); if (unwrapped.length > wrapped.length) { status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); goto failed; } cred.bv_val = (char *)wrapped.data; cred.bv_len = wrapped.length; rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); data_blob_free(&wrapped); if (rc != LDAP_SUCCESS) { status = ADS_ERROR(rc); goto failed; } if (scred) { wrapped = data_blob_const(scred->bv_val, scred->bv_len); } else { wrapped = data_blob_null; } ok = spnego_parse_auth_response(talloc_tos(), wrapped, NT_STATUS_OK, OID_KERBEROS5_OLD, &unwrapped); if (scred) ber_bvfree(scred); if (!ok) { status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE); goto failed; } input_token.value = unwrapped.data; input_token.length = unwrapped.length; /* * As we asked for mutal authentication * we need to pass the servers response * to gssapi */ gss_rc = gss_init_sec_context(&minor_status, gss_cred, &context_handle, serv_name, mech_type, req_flags, 0, NULL, &input_token, &actual_mech_type, &output_token, &ret_flags, NULL); data_blob_free(&unwrapped); if (gss_rc) { status = ADS_ERROR_GSS(gss_rc, minor_status); goto failed; } gss_release_buffer(&minor_status, &output_token); /* * If we the sign and seal options * doesn't match after getting the response * from the server, we don't want to use the connection */ req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); if (req_tmp != ret_tmp) { /* everythings fine... */ status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE); goto failed; } gss_rc = gss_context_time(&minor_status, context_handle, &context_validity); if (gss_rc == GSS_S_COMPLETE) { if (context_validity != 0) { context_endtime = time(NULL) + context_validity; DEBUG(10, ("context (service ticket) valid for " "%u seconds\n", context_validity)); } else { DEBUG(10, ("context (service ticket) expired\n")); } } else { DEBUG(1, ("gss_context_time failed (%d,%u) -" " this will be a one-time context\n", gss_rc, minor_status)); if (gss_rc == GSS_S_CONTEXT_EXPIRED) { DEBUG(10, ("context (service ticket) expired\n")); } } if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) { uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED; gss_rc = gss_wrap_size_limit(&minor_status, context_handle, (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL), GSS_C_QOP_DEFAULT, max_msg_size, &ads->ldap.out.max_unwrapped); if (gss_rc) { status = ADS_ERROR_GSS(gss_rc, minor_status); goto failed; } ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped; ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */ ads->ldap.in.max_wrapped = max_msg_size; status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle); if (!ADS_ERR_OK(status)) { DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n", ads_errstr(status))); goto failed; } /* make sure we don't free context_handle */ context_handle = GSS_C_NO_CONTEXT; } ads->auth.tgs_expire = context_endtime; status = ADS_SUCCESS; failed: if (gss_cred != GSS_C_NO_CREDENTIAL) gss_release_cred(&minor_status, &gss_cred); if (context_handle != GSS_C_NO_CONTEXT) gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER); return status; }