diff options
Diffstat (limited to 'lib/gssapi/krb5')
| -rw-r--r-- | lib/gssapi/krb5/accept_sec_context.c | 1 | ||||
| -rw-r--r-- | lib/gssapi/krb5/acquire_cred.c | 5 | ||||
| -rw-r--r-- | lib/gssapi/krb5/arcfour.c | 70 | ||||
| -rw-r--r-- | lib/gssapi/krb5/cfx.c | 52 | ||||
| -rw-r--r-- | lib/gssapi/krb5/decapsulate.c | 12 | ||||
| -rw-r--r-- | lib/gssapi/krb5/delete_sec_context.c | 2 | ||||
| -rw-r--r-- | lib/gssapi/krb5/display_status.c | 3 | ||||
| -rw-r--r-- | lib/gssapi/krb5/gsskrb5-private.h | 3 | ||||
| -rw-r--r-- | lib/gssapi/krb5/init_sec_context.c | 16 | ||||
| -rw-r--r-- | lib/gssapi/krb5/unwrap.c | 34 | 
10 files changed, 137 insertions, 61 deletions
| diff --git a/lib/gssapi/krb5/accept_sec_context.c b/lib/gssapi/krb5/accept_sec_context.c index d4680e9e8fb6..e35cc10e560c 100644 --- a/lib/gssapi/krb5/accept_sec_context.c +++ b/lib/gssapi/krb5/accept_sec_context.c @@ -443,6 +443,7 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,  	     * lets only send the error token on clock skew, that  	     * limit when send error token for non-MUTUAL.  	     */ +            free_Authenticator(ctx->auth_context->authenticator);  	    return send_error_token(minor_status, context, kret,  				    server, &indata, output_token);  	} else if (kret) { diff --git a/lib/gssapi/krb5/acquire_cred.c b/lib/gssapi/krb5/acquire_cred.c index 9c880b334fd6..431700070e53 100644 --- a/lib/gssapi/krb5/acquire_cred.c +++ b/lib/gssapi/krb5/acquire_cred.c @@ -100,6 +100,7 @@ acquire_cred_with_password(OM_uint32 *minor_status,      krb5_error_code kret;      time_t now;      OM_uint32 left; +    const char *realm;      if (cred_usage == GSS_C_ACCEPT) {          /* @@ -126,6 +127,10 @@ acquire_cred_with_password(OM_uint32 *minor_status,      if (kret)          goto end; +    realm = krb5_principal_get_realm(context, handle->principal); + +    krb5_get_init_creds_opt_set_default_flags(context, "gss_krb5", realm, opt); +      /*       * Get the current time before the AS exchange so we don't       * accidentally end up returning a value that puts advertised diff --git a/lib/gssapi/krb5/arcfour.c b/lib/gssapi/krb5/arcfour.c index d88ec4cddc53..aa03cbe41acb 100644 --- a/lib/gssapi/krb5/arcfour.c +++ b/lib/gssapi/krb5/arcfour.c @@ -177,7 +177,7 @@ arcfour_mic_cksum_iov(krb5_context context,  	memcpy(ptr + ofs,  	       padding->buffer.value,  	       padding->buffer.length); -	ofs += padding->buffer.length; +	/* ofs += padding->buffer.length; */      }      ret = krb5_crypto_init(context, key, 0, &crypto); @@ -365,7 +365,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,  	return GSS_S_FAILURE;      } -    cmp = ct_memcmp(cksum_data, p + 8, 8); +    cmp = (ct_memcmp(cksum_data, p + 8, 8) == 0);      if (cmp) {  	*minor_status = 0;  	return GSS_S_BAD_MIC; @@ -385,9 +385,9 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,      _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);      if (context_handle->more_flags & LOCAL) -	cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); +	cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);      else -	cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); +	cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);      memset_s(SND_SEQ, sizeof(SND_SEQ), 0, sizeof(SND_SEQ));      if (cmp != 0) { @@ -656,9 +656,9 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,      _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);      if (context_handle->more_flags & LOCAL) -	cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); +	cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);      else -	cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); +	cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);      if (cmp != 0) {  	*minor_status = 0; @@ -730,7 +730,7 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,  	return GSS_S_FAILURE;      } -    cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ +    cmp = (ct_memcmp(cksum_data, p0 + 16, 8) == 0); /* SGN_CKSUM */      if (cmp) {  	_gsskrb5_release_buffer(minor_status, output_message_buffer);  	*minor_status = 0; @@ -880,7 +880,13 @@ _gssapi_wrap_iov_length_arcfour(OM_uint32 *minor_status,  	}      } -    major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); +    if (header == NULL) { +        *minor_status = EINVAL; +        return GSS_S_FAILURE; +    } + +    major_status = _gk_verify_buffers(minor_status, ctx, header, +				      padding, trailer, FALSE);      if (major_status != GSS_S_COMPLETE) {  	    return major_status;      } @@ -937,7 +943,8 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,      padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);      trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); -    major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); +    major_status = _gk_verify_buffers(minor_status, ctx, header, +				      padding, trailer, FALSE);      if (major_status != GSS_S_COMPLETE) {  	return major_status;      } @@ -974,7 +981,7 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,  	header_len -= data_len;      } -    if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) { +    if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) {  	major_status = _gk_allocate_buffer(minor_status, header,  					   header_len);  	if (major_status != GSS_S_COMPLETE) @@ -988,7 +995,7 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,      }      if (padding) { -	if (GSS_IOV_BUFFER_FLAGS(padding->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) { +	if (GSS_IOV_BUFFER_FLAGS(padding->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) {  	    major_status = _gk_allocate_buffer(minor_status, padding, 1);  	    if (major_status != GSS_S_COMPLETE)  		goto failure; @@ -1181,10 +1188,11 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,      /* Check if the packet is correct */      major_status = _gk_verify_buffers(minor_status, -				  ctx, -				  header, -				  padding, -				  trailer); +				      ctx, +				      header, +				      padding, +				      trailer, +				      FALSE); /* behaves as stream cipher */      if (major_status != GSS_S_COMPLETE) {  	return major_status;      } @@ -1194,15 +1202,19 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,  	return GSS_S_FAILURE;      } -    if (IS_DCE_STYLE(context)) { -	verify_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + -		     GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE; -	if (header->buffer.length > verify_len) { -	    return GSS_S_BAD_MECH; +    verify_len = header->buffer.length; + +    if (!IS_DCE_STYLE(context)) { +	for (i = 0; i < iov_count; i++) { +	    /* length in header also includes data and padding */ +	    if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA) +		verify_len += iov[i].buffer.length;  	} -    } else { -	verify_len = header->buffer.length; + +	if (padding) +	    verify_len += padding->buffer.length;      } +      _p = header->buffer.value;      ret = _gssapi_verify_mech_header(&_p, @@ -1267,19 +1279,9 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,      _gsskrb5_decode_be_om_uint32(snd_seq, &seq_number);      if (ctx->more_flags & LOCAL) { -	cmp = memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4); -    } else { -	cmp = memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4); -    } -    if (cmp != 0) { -	*minor_status = 0; -	return GSS_S_BAD_MIC; -    } - -    if (ctx->more_flags & LOCAL) { -	cmp = memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4); +	cmp = (ct_memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4) != 0);      } else { -	cmp = memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4); +	cmp = (ct_memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4) != 0);      }      if (cmp != 0) {  	*minor_status = 0; diff --git a/lib/gssapi/krb5/cfx.c b/lib/gssapi/krb5/cfx.c index 29fecca861ce..8d806f9fbf1c 100644 --- a/lib/gssapi/krb5/cfx.c +++ b/lib/gssapi/krb5/cfx.c @@ -206,11 +206,36 @@ gss_iov_buffer_desc *  _gk_find_buffer(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type)  {      int i; +    gss_iov_buffer_t iovp = GSS_C_NO_IOV_BUFFER; -    for (i = 0; i < iov_count; i++) -	if (type == GSS_IOV_BUFFER_TYPE(iov[i].type)) -	    return &iov[i]; -    return NULL; +    if (iov == GSS_C_NO_IOV_BUFFER) +	return GSS_C_NO_IOV_BUFFER; + +    /* +     * This function is used to find header, padding or trailer buffers +     * which are singletons; return NULL if multiple instances are found. +     */ +    for (i = 0; i < iov_count; i++) { +	if (type == GSS_IOV_BUFFER_TYPE(iov[i].type)) { +	    if (iovp == GSS_C_NO_IOV_BUFFER) +		iovp = &iov[i]; +	    else +		return GSS_C_NO_IOV_BUFFER; +	} +    } + +    /* +     * For compatibility with SSPI, an empty padding buffer is treated +     * equivalent to an absent padding buffer (unless the caller is +     * requesting that a padding buffer be allocated). +     */ +    if (iovp && +	iovp->buffer.length == 0 && +	type == GSS_IOV_BUFFER_TYPE_PADDING && +	(GSS_IOV_BUFFER_FLAGS(iovp->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) == 0) +	iovp = NULL; + +    return iovp;  }  OM_uint32 @@ -239,7 +264,8 @@ _gk_verify_buffers(OM_uint32 *minor_status,  		   const gsskrb5_ctx ctx,  		   const gss_iov_buffer_desc *header,  		   const gss_iov_buffer_desc *padding, -		   const gss_iov_buffer_desc *trailer) +		   const gss_iov_buffer_desc *trailer, +		   int block_cipher)  {      if (header == NULL) {  	*minor_status = EINVAL; @@ -260,9 +286,12 @@ _gk_verify_buffers(OM_uint32 *minor_status,  	}      } else {  	/* -	 * In non-DCE style mode we require having a padding buffer +	 * In non-DCE style mode we require having a padding buffer for +	 * encryption types that do not behave as stream ciphers. This +	 * check is superfluous for now, as only RC4 and RFC4121 enctypes +	 * are presently implemented for the IOV APIs; be defensive.  	 */ -	if (padding == NULL) { +	if (block_cipher && padding == NULL) {  	    *minor_status = EINVAL;  	    return GSS_S_FAILURE;  	} @@ -306,7 +335,8 @@ _gssapi_wrap_cfx_iov(OM_uint32 *minor_status,      trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); -    major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); +    major_status = _gk_verify_buffers(minor_status, ctx, header, +				      padding, trailer, FALSE);      if (major_status != GSS_S_COMPLETE) {  	    return major_status;      } @@ -747,7 +777,8 @@ _gssapi_unwrap_cfx_iov(OM_uint32 *minor_status,      trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); -    major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); +    major_status = _gk_verify_buffers(minor_status, ctx, header, +				      padding, trailer, FALSE);      if (major_status != GSS_S_COMPLETE) {  	    return major_status;      } @@ -1069,7 +1100,8 @@ _gssapi_wrap_iov_length_cfx(OM_uint32 *minor_status,  	}      } -    major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); +    major_status = _gk_verify_buffers(minor_status, ctx, header, +				      padding, trailer, FALSE);      if (major_status != GSS_S_COMPLETE) {  	    return major_status;      } diff --git a/lib/gssapi/krb5/decapsulate.c b/lib/gssapi/krb5/decapsulate.c index 86085f569501..d7b75a642224 100644 --- a/lib/gssapi/krb5/decapsulate.c +++ b/lib/gssapi/krb5/decapsulate.c @@ -54,6 +54,8 @@ _gsskrb5_get_mech (const u_char *ptr,      e = der_get_length (p, total_len - 1, &len, &len_len);      if (e || 1 + len_len + len != total_len)  	return -1; +    if (total_len < 1 + len_len + 1) +	return -1;      p += len_len;      if (*p++ != 0x06)  	return -1; @@ -80,6 +82,10 @@ _gssapi_verify_mech_header(u_char **str,      if (mech_len != mech->length)  	return GSS_S_BAD_MECH; +    if (mech_len > total_len) +	return GSS_S_BAD_MECH; +    if (p - *str > total_len - mech_len) +	return GSS_S_BAD_MECH;      if (ct_memcmp(p,  		  mech->elements,  		  mech->length) != 0) @@ -193,13 +199,13 @@ _gssapi_verify_pad(gss_buffer_t wrapped_token,      if (wrapped_token->length < 1)  	return GSS_S_BAD_MECH; -    pad = (u_char *)wrapped_token->value + wrapped_token->length - 1; -    padlength = *pad; +    pad = (u_char *)wrapped_token->value + wrapped_token->length; +    padlength = pad[-1];      if (padlength > datalen)  	return GSS_S_BAD_MECH; -    for (i = padlength; i > 0 && *pad == padlength; i--, pad--) +    for (i = padlength; i > 0 && *--pad == padlength; i--)  	;      if (i != 0)  	return GSS_S_BAD_MIC; diff --git a/lib/gssapi/krb5/delete_sec_context.c b/lib/gssapi/krb5/delete_sec_context.c index 83a66cc0ca01..a4800791ec4e 100644 --- a/lib/gssapi/krb5/delete_sec_context.c +++ b/lib/gssapi/krb5/delete_sec_context.c @@ -75,6 +75,8 @@ _gsskrb5_delete_sec_context(OM_uint32 * minor_status,      krb5_data_free(&ctx->fwd_data);      if (ctx->crypto)      	krb5_crypto_destroy(context, ctx->crypto); +    if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE)) +	krb5_cc_close(context, ctx->ccache);      HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);      HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); diff --git a/lib/gssapi/krb5/display_status.c b/lib/gssapi/krb5/display_status.c index c50200672aaf..2587b966cfb8 100644 --- a/lib/gssapi/krb5/display_status.c +++ b/lib/gssapi/krb5/display_status.c @@ -64,8 +64,7 @@ routine_error(OM_uint32 v)  	"Incorrect channel bindings were supplied",  	"An invalid status code was supplied",  	"A token had an invalid MIC", -	"No credentials were supplied, " -	"or the credentials were unavailable or inaccessible.", +	"No credentials were supplied, or the credentials were unavailable or inaccessible.",  	"No context has been established",  	"A token was invalid",  	"A credential was invalid", diff --git a/lib/gssapi/krb5/gsskrb5-private.h b/lib/gssapi/krb5/gsskrb5-private.h index e05d4a6b6da6..29eea8adf0a8 100644 --- a/lib/gssapi/krb5/gsskrb5-private.h +++ b/lib/gssapi/krb5/gsskrb5-private.h @@ -42,7 +42,8 @@ _gk_verify_buffers (  	const gsskrb5_ctx /*ctx*/,  	const gss_iov_buffer_desc */*header*/,  	const gss_iov_buffer_desc */*padding*/, -	const gss_iov_buffer_desc */*trailer*/); +	const gss_iov_buffer_desc */*trailer*/, +	int /*block_cipher*/);  OM_uint32 GSSAPI_CALLCONV  _gk_wrap_iov ( diff --git a/lib/gssapi/krb5/init_sec_context.c b/lib/gssapi/krb5/init_sec_context.c index 4ef5c9c7123a..21ac554efd4f 100644 --- a/lib/gssapi/krb5/init_sec_context.c +++ b/lib/gssapi/krb5/init_sec_context.c @@ -600,7 +600,19 @@ init_auth_restart      if (ret == 0) {  	if (timedata.length == 4) {  	    const u_char *p = timedata.data; -	    offset = (p[0] <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0); +            if (p[0] < 128) { +                offset = (p[0] <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0); +            } else { +                /* +                 * (p[0] << 24), if p[0] > 127 -> offset is negative, but *p is +                 * positive, so this is overflow -- overflow we want, but UBSAN +                 * flags it. +                 * +                 * NOTE: We assume the platform is a twos-complement platform. +                 */ +                offset = INT32_MIN; +                offset |= ((p[0] & 0x7f) <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0); +            }  	}  	krb5_data_free(&timedata);      } @@ -921,7 +933,7 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context  			time_rec);  	if (ret != GSS_S_COMPLETE)  	    break; -	/* FALL THOUGH */ +	/* FALLTHROUGH */      case INITIATOR_RESTART:  	ret = init_auth_restart(minor_status,  				cred, diff --git a/lib/gssapi/krb5/unwrap.c b/lib/gssapi/krb5/unwrap.c index da939c052930..bab30f45016b 100644 --- a/lib/gssapi/krb5/unwrap.c +++ b/lib/gssapi/krb5/unwrap.c @@ -64,6 +64,8 @@ unwrap_des    if (IS_DCE_STYLE(context_handle)) {       token_len = 22 + 8 + 15; /* 45 */ +     if (input_message_buffer->length < token_len) +	  return GSS_S_BAD_MECH;    } else {       token_len = input_message_buffer->length;    } @@ -76,6 +78,11 @@ unwrap_des    if (ret)        return ret; +  len = (p - (u_char *)input_message_buffer->value) +      + 22 + 8; +  if (input_message_buffer->length < len) +      return GSS_S_BAD_MECH; +    if (memcmp (p, "\x00\x00", 2) != 0)      return GSS_S_BAD_SIG;    p += 2; @@ -117,7 +124,7 @@ unwrap_des    } else {      /* check pad */      ret = _gssapi_verify_pad(input_message_buffer, -			     input_message_buffer->length - len, +			     input_message_buffer->length - len - 8,  			     &padlength);      if (ret)          return ret; @@ -180,9 +187,10 @@ unwrap_des    output_message_buffer->value  = malloc(output_message_buffer->length);    if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)        return GSS_S_FAILURE; -  memcpy (output_message_buffer->value, -	  p + 24, -	  output_message_buffer->length); +  if (output_message_buffer->value != NULL) +      memcpy (output_message_buffer->value, +	      p + 24, +	      output_message_buffer->length);    return GSS_S_COMPLETE;  }  #endif @@ -215,6 +223,8 @@ unwrap_des3    if (IS_DCE_STYLE(context_handle)) {       token_len = 34 + 8 + 15; /* 57 */ +     if (input_message_buffer->length < token_len) +	  return GSS_S_BAD_MECH;    } else {       token_len = input_message_buffer->length;    } @@ -227,7 +237,12 @@ unwrap_des3    if (ret)        return ret; -  if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ +  len = (p - (u_char *)input_message_buffer->value) +      + 34 + 8; +  if (input_message_buffer->length < len) +      return GSS_S_BAD_MECH; + +  if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */      return GSS_S_BAD_SIG;    p += 2;    if (ct_memcmp (p, "\x02\x00", 2) == 0) { @@ -274,7 +289,7 @@ unwrap_des3    } else {      /* check pad */      ret = _gssapi_verify_pad(input_message_buffer, -			     input_message_buffer->length - len, +			     input_message_buffer->length - len - 8,  			     &padlength);      if (ret)          return ret; @@ -374,9 +389,10 @@ unwrap_des3    output_message_buffer->value  = malloc(output_message_buffer->length);    if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)        return GSS_S_FAILURE; -  memcpy (output_message_buffer->value, -	  p + 36, -	  output_message_buffer->length); +  if (output_message_buffer->value != NULL) +      memcpy (output_message_buffer->value, +	      p + 36, +	      output_message_buffer->length);    return GSS_S_COMPLETE;  } | 
