Ejemplo n.º 1
0
static krb5_error_code
tgs_check_authenticator(krb5_context context, 
			krb5_kdc_configuration *config,
	                krb5_auth_context ac,
			KDC_REQ_BODY *b, 
			const char **e_text,
			krb5_keyblock *key)
{
    krb5_authenticator auth;
    size_t len;
    unsigned char *buf;
    size_t buf_size;
    krb5_error_code ret;
    krb5_crypto crypto;
    
    krb5_auth_con_getauthenticator(context, ac, &auth);
    if(auth->cksum == NULL){
	kdc_log(context, config, 0, "No authenticator in request");
	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
	goto out;
    }
    /*
     * according to RFC1510 it doesn't need to be keyed,
     * but according to the latest draft it needs to.
     */
    if (
#if 0
!krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
	||
#endif
 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
	kdc_log(context, config, 0, "Bad checksum type in authenticator: %d", 
		auth->cksum->cksumtype);
	ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;
	goto out;
    }
		
    /* XXX should not re-encode this */
    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
    if(ret){
	kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", 
		krb5_get_err_text(context, ret));
	goto out;
    }
    if(buf_size != len) {
	free(buf);
	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
	*e_text = "KDC internal error";
	ret = KRB5KRB_ERR_GENERIC;
	goto out;
    }
    ret = krb5_crypto_init(context, key, 0, &crypto);
    if (ret) {
	free(buf);
	kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
		krb5_get_err_text(context, ret));
	goto out;
    }
    ret = krb5_verify_checksum(context,
			       crypto,
			       KRB5_KU_TGS_REQ_AUTH_CKSUM,
			       buf, 
			       len,
			       auth->cksum);
    free(buf);
    krb5_crypto_destroy(context, crypto);
    if(ret){
	kdc_log(context, config, 0,
		"Failed to verify authenticator checksum: %s", 
		krb5_get_err_text(context, ret));
    }
out:
    free_Authenticator(auth);
    free(auth);
    return ret;
}
Ejemplo n.º 2
0
KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype)
{
    return krb5_checksum_is_collision_proof(NULL, ctype);
}
Ejemplo n.º 3
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_safe(krb5_context context,
	     krb5_auth_context auth_context,
	     const krb5_data *inbuf,
	     krb5_data *outbuf,
	     krb5_replay_data *outdata)
{
    krb5_error_code ret;
    KRB_SAFE safe;
    size_t len;

    krb5_data_zero(outbuf);

    if ((auth_context->flags &
	 (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)))
    {
	if (outdata == NULL) {
	    krb5_set_error_message(context, KRB5_RC_REQUIRED,
				   N_("rd_safe: need outdata "
				      "to return data", ""));
	    return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
	}
	/* if these fields are not present in the safe-part, silently
           return zero */
	memset(outdata, 0, sizeof(*outdata));
    }

    ret = decode_KRB_SAFE (inbuf->data, inbuf->length, &safe, &len);
    if (ret)
	return ret;
    if (safe.pvno != 5) {
	ret = KRB5KRB_AP_ERR_BADVERSION;
	krb5_clear_error_message (context);
	goto failure;
    }
    if (safe.msg_type != krb_safe) {
	ret = KRB5KRB_AP_ERR_MSG_TYPE;
	krb5_clear_error_message (context);
	goto failure;
    }
    if (!krb5_checksum_is_keyed(context, safe.cksum.cksumtype)
	|| !krb5_checksum_is_collision_proof(context, safe.cksum.cksumtype)) {
	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
	krb5_clear_error_message (context);
	goto failure;
    }

    /* check sender address */

    if (safe.safe_body.s_address
	&& auth_context->remote_address
	&& !krb5_address_compare (context,
				  auth_context->remote_address,
				  safe.safe_body.s_address)) {
	ret = KRB5KRB_AP_ERR_BADADDR;
	krb5_clear_error_message (context);
	goto failure;
    }

    /* check receiver address */

    if (safe.safe_body.r_address
	&& auth_context->local_address
	&& !krb5_address_compare (context,
				  auth_context->local_address,
				  safe.safe_body.r_address)) {
	ret = KRB5KRB_AP_ERR_BADADDR;
	krb5_clear_error_message (context);
	goto failure;
    }

    /* check timestamp */
    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
	krb5_timestamp sec;

	krb5_timeofday (context, &sec);

	if (safe.safe_body.timestamp == NULL ||
	    safe.safe_body.usec      == NULL ||
	    abs(*safe.safe_body.timestamp - sec) > context->max_skew) {
	    ret = KRB5KRB_AP_ERR_SKEW;
	    krb5_clear_error_message (context);
	    goto failure;
	}
    }
    /* XXX - check replay cache */

    /* check sequence number. since MIT krb5 cannot generate a sequence
       number of zero but instead generates no sequence number, we accept that
    */

    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
	if ((safe.safe_body.seq_number == NULL
	     && auth_context->remote_seqnumber != 0)
	    || (safe.safe_body.seq_number != NULL
		&& *safe.safe_body.seq_number !=
		auth_context->remote_seqnumber)) {
	    ret = KRB5KRB_AP_ERR_BADORDER;
	    krb5_clear_error_message (context);
	    goto failure;
	}
	auth_context->remote_seqnumber++;
    }

    ret = verify_checksum (context, auth_context, &safe);
    if (ret)
	goto failure;

    outbuf->length = safe.safe_body.user_data.length;
    outbuf->data   = malloc(outbuf->length);
    if (outbuf->data == NULL && outbuf->length != 0) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	krb5_data_zero(outbuf);
	goto failure;
    }
    memcpy (outbuf->data, safe.safe_body.user_data.data, outbuf->length);

    if ((auth_context->flags &
	 (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) {

	if(safe.safe_body.timestamp)
	    outdata->timestamp = *safe.safe_body.timestamp;
	if(safe.safe_body.usec)
	    outdata->usec = *safe.safe_body.usec;
	if(safe.safe_body.seq_number)
	    outdata->seq = *safe.safe_body.seq_number;
    }

  failure:
    free_KRB_SAFE (&safe);
    return ret;
}