Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
    }
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
/* 
   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;
}