summaryrefslogtreecommitdiff
path: root/libextra/ext_inner_application.c
blob: 487b02497c3b0ededdda61adb42c1b9cf59d9bd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * Copyright (C) 2005, 2006, 2008 Free Software Foundation
 *
 * Author: Simon Josefsson
 *
 * This file is part of GNUTLS-EXTRA.
 *
 * GNUTLS-EXTRA is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * GNUTLS-EXTRA is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 */

#include "gnutls_int.h"
#include "gnutls_auth.h"
#include "gnutls_errors.h"
#include "gnutls_num.h"
#include "ext_inner_application.h"
#include <gnutls/extra.h>

#define NO 0
#define YES 1

int
_gnutls_inner_application_recv_params (gnutls_session_t session,
				       const opaque * data, size_t data_size)
{
  tls_ext_st *ext = &session->security_parameters.extensions;

  if (data_size != 1)
    {
      gnutls_assert ();
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    }

  ext->gnutls_ia_peer_enable = 1;
  ext->gnutls_ia_peer_allowskip = 0;

  switch ((unsigned char) *data)
    {
    case NO:			/* Peer's ia_on_resume == no */
      ext->gnutls_ia_peer_allowskip = 1;
      break;

    case YES:
      break;

    default:
      gnutls_assert ();
    }

  return 0;
}


/* returns data_size or a negative number on failure
 */
int
_gnutls_inner_application_send_params (gnutls_session_t session,
				       opaque * data, size_t data_size)
{
  tls_ext_st *ext = &session->security_parameters.extensions;

  /* Set ext->gnutls_ia_enable depending on whether we have a TLS/IA
     credential in the session. */

  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {
      gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t)
	_gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

      if (cred)
	ext->gnutls_ia_enable = 1;
    }
  else
    {
      gnutls_ia_server_credentials_t cred = (gnutls_ia_server_credentials_t)
	_gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

      if (cred)
	ext->gnutls_ia_enable = 1;
    }

  /* If we don't want gnutls_ia locally, or we are a server and the
   * client doesn't want it, don't advertise TLS/IA support at all, as
   * required. */

  if (!ext->gnutls_ia_enable)
    return 0;

  if (session->security_parameters.entity == GNUTLS_SERVER &&
      !ext->gnutls_ia_peer_enable)
    return 0;

  /* We'll advertise. Check if there's room in the hello buffer. */

  if (data_size < 1)
    {
      gnutls_assert ();
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  /* default: require new application phase */

  *data = YES;

  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {

      /* Client: value follows local setting */

      if (ext->gnutls_ia_allowskip)
	*data = NO;
    }
  else
    {

      /* Server: value follows local setting and client's setting, but only
       * if we are resuming.
       *
       * XXX Can server test for resumption at this stage?
       *
       * Ai! It seems that read_client_hello only calls parse_extensions if
       * we're NOT resuming! That would make us automatically violate the IA
       * draft; if we're resuming, we must first learn what the client wants
       * -- IA or no IA -- and then prepare our response. Right now we'll
       * always skip IA on resumption, because recv_ext isn't even called
       * to record the peer's support for IA at all. Simon? */

      if (ext->gnutls_ia_allowskip &&
	  ext->gnutls_ia_peer_allowskip &&
	  session->internals.resumed == RESUME_TRUE)
	*data = NO;
    }

  return 1;
}