/** * gnutls_alpn_set_protocols: * @session: is a #gnutls_session_t type. * @protocols: is the protocol names to add. * @protocols_size: the number of protocols to add. * @flags: zero or a sequence of %gnutls_alpn_flags_t * * This function is to be used by both clients and servers, to declare * the supported ALPN protocols, which are used during negotiation with peer. * * See %gnutls_alpn_flags_t description for the documentation of available * flags. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since 3.2.0 **/ int gnutls_alpn_set_protocols(gnutls_session_t session, const gnutls_datum_t * protocols, unsigned protocols_size, unsigned int flags) { int ret; alpn_ext_st *priv; extension_priv_data_t epriv; unsigned i; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_ALPN, &epriv); if (ret < 0) { priv = gnutls_calloc(1, sizeof(*priv)); if (priv == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } epriv = priv; _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_ALPN, epriv); } else priv = epriv; if (protocols_size > MAX_ALPN_PROTOCOLS) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); for (i = 0; i < protocols_size; i++) { if (protocols[i].size >= MAX_ALPN_PROTOCOL_NAME) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); memcpy(priv->protocols[i], protocols[i].data, protocols[i].size); priv->protocol_size[i] = protocols[i].size; priv->size++; } priv->flags = flags; return 0; }
/* Parses the Signature Algorithm structure and stores data into * session->security_parameters.extensions. */ int _gnutls_sign_algorithm_parse_data (gnutls_session_t session, const uint8_t * data, size_t data_size) { unsigned int sig, i; sig_ext_st *priv; extension_priv_data_t epriv; priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } for (i = 0; i < data_size; i += 2) { sign_algorithm_st aid; aid.hash_algorithm = data[i]; aid.sign_algorithm = data[i + 1]; sig = _gnutls_tls_aid_to_sign (&aid); _gnutls_handshake_log ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session, aid.hash_algorithm, aid.sign_algorithm, gnutls_sign_get_name(sig)); if (sig != GNUTLS_SIGN_UNKNOWN) { priv->sign_algorithms[priv->sign_algorithms_size++] = sig; if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS) break; } } epriv.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv); return 0; }
void _gnutls_ext_restore_resumed_session(gnutls_session_t session) { int i; /* clear everything except MANDATORY extensions */ for (i = 0; i < MAX_EXT_TYPES; i++) { if (session->internals.extension_int_data[i].set != 0 && _gnutls_ext_parse_type(session-> internals.extension_int_data[i]. type) != GNUTLS_EXT_MANDATORY) { _gnutls_ext_unset_session_data(session, session->internals. extension_int_data [i].type); } } /* copy resumed to main */ for (i = 0; i < MAX_EXT_TYPES; i++) { if (session->internals.resumed_extension_int_data[i].set != 0 && _gnutls_ext_parse_type(session->internals. resumed_extension_int_data [i].type) != GNUTLS_EXT_MANDATORY) { _gnutls_ext_set_session_data(session, session->internals. resumed_extension_int_data [i].type, session->internals. resumed_extension_int_data [i].priv); session->internals.resumed_extension_int_data[i]. set = 0; } } }
int _gnutls_ext_sr_send_cs (gnutls_session_t session) { int ret, set = 0; sr_ext_st *priv; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); if (ret < 0) { set = 1; } else if (ret < 0) { gnutls_assert (); return ret; } if (set != 0) { priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } epriv.ptr = priv; } if (set != 0) _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv); return 0; }
/* Parses the Signature Algorithm structure and stores data into * session->security_parameters.extensions. */ int _gnutls_sign_algorithm_parse_data (gnutls_session_t session, const opaque * data, size_t data_size) { int sig, i; sig_ext_st *priv; extension_priv_data_t epriv; priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } for (i = 0; i < data_size; i += 2) { sign_algorithm_st aid; aid.hash_algorithm = data[i]; aid.sign_algorithm = data[i + 1]; sig = _gnutls_tls_aid_to_sign (&aid); if (sig != GNUTLS_SIGN_UNKNOWN) { priv->sign_algorithms[priv->sign_algorithms_size++] = sig; if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS) break; } } epriv.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv); return 0; }
/** * gnutls_record_set_max_size: * @session: is a #gnutls_session_t type. * @size: is the new size * * This function sets the maximum record packet size in this * connection. This property can only be set to clients. The server * may choose not to accept the requested size. * * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and * 4096(=2^12). The requested record size does get in effect * immediately only while sending data. The receive part will take * effect after a successful handshake. * * This function uses a TLS extension called 'max record size'. Not * all TLS implementations use or even understand this extension. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ ssize_t gnutls_record_set_max_size(gnutls_session_t session, size_t size) { ssize_t new_size; extension_priv_data_t epriv; if (session->security_parameters.entity == GNUTLS_SERVER) return GNUTLS_E_INVALID_REQUEST; new_size = _gnutls_mre_record2num(size); if (new_size < 0) { gnutls_assert(); return new_size; } session->security_parameters.max_record_send_size = size; epriv = (void *)(intptr_t)size; _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_MAX_RECORD_SIZE, epriv); return 0; }
/** * gnutls_session_ticket_enable_client: * @session: is a #gnutls_session_t type. * * Request that the client should attempt session resumption using * SessionTicket. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an * error code. * * Since: 2.10.0 **/ int gnutls_session_ticket_enable_client(gnutls_session_t session) { session_ticket_ext_st *priv = NULL; extension_priv_data_t epriv; if (!session) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } priv = gnutls_calloc(1, sizeof(*priv)); if (priv == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } priv->session_ticket_enable = 1; epriv = priv; _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SESSION_TICKET, epriv); return 0; }
/* * In case of a server: if a NAME_DNS extension type is received then * it stores into the session the value of NAME_DNS. The server may * use gnutls_ext_get_server_name(), in order to access it. * * In case of a client: If a proper NAME_DNS extension type is found * in the session then it sends the extension to the peer. * */ static int _gnutls_server_name_recv_params(gnutls_session_t session, const uint8_t * data, size_t _data_size) { int i; const unsigned char *p; uint16_t len, type; ssize_t data_size = _data_size; int server_names = 0; server_name_ext_st *priv; extension_priv_data_t epriv; if (session->security_parameters.entity == GNUTLS_SERVER) { DECR_LENGTH_RET(data_size, 2, 0); len = _gnutls_read_uint16(data); if (len != data_size) { /* This is unexpected packet length, but * just ignore it, for now. */ gnutls_assert(); return 0; } p = data + 2; /* Count all server_names in the packet. */ while (data_size > 0) { DECR_LENGTH_RET(data_size, 1, 0); p++; DECR_LEN(data_size, 2); len = _gnutls_read_uint16(p); p += 2; if (len > 0) { DECR_LENGTH_RET(data_size, len, 0); server_names++; p += len; } else _gnutls_handshake_log ("HSK[%p]: Received (0) size server name (under attack?)\n", session); } /* we cannot accept more server names. */ if (server_names > MAX_SERVER_NAME_EXTENSIONS) { _gnutls_handshake_log ("HSK[%p]: Too many server names received (under attack?)\n", session); server_names = MAX_SERVER_NAME_EXTENSIONS; } if (server_names == 0) return 0; /* no names found */ priv = gnutls_calloc(1, sizeof(*priv)); if (priv == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } priv->server_names_size = server_names; p = data + 2; for (i = 0; i < server_names; i++) { type = *p; p++; len = _gnutls_read_uint16(p); p += 2; switch (type) { case 0: /* NAME_DNS */ if (len < MAX_SERVER_NAME_SIZE) { memcpy(priv->server_names[i].name, p, len); priv->server_names[i].name[len] = 0; priv->server_names[i].name_length = len; priv->server_names[i].type = GNUTLS_NAME_DNS; break; } } /* move to next record */ p += len; } epriv = priv; _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, epriv); } return 0; }
/** * gnutls_server_name_set: * @session: is a #gnutls_session_t type. * @type: specifies the indicator type * @name: is a string that contains the server name. * @name_length: holds the length of name * * This function is to be used by clients that want to inform (via a * TLS extension mechanism) the server of the name they connected to. * This should be used by clients that connect to servers that do * virtual hosting. * * The value of @name depends on the @type type. In case of * %GNUTLS_NAME_DNS, a UTF-8 null-terminated domain name string, * without the trailing dot, is expected. * * IPv4 or IPv6 addresses are not permitted. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_server_name_set(gnutls_session_t session, gnutls_server_name_type_t type, const void *name, size_t name_length) { int server_names, ret; server_name_ext_st *priv; extension_priv_data_t epriv; char *idn_name = NULL; int set = 0, rc; if (session->security_parameters.entity == GNUTLS_SERVER) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (name_length == 0) { /* unset extension */ _gnutls_ext_unset_session_data(session, GNUTLS_EXTENSION_SERVER_NAME); return 0; } #ifdef HAVE_LIBIDN rc = idna_to_ascii_8z (name, &idn_name, IDNA_ALLOW_UNASSIGNED); if (rc != IDNA_SUCCESS) { _gnutls_debug_log("unable to convert name %s to IDNA format: %s\n", (char*)name, idna_strerror(rc)); return GNUTLS_E_IDNA_ERROR; } name = idn_name; name_length = strlen(idn_name); #endif if (name_length > MAX_SERVER_NAME_SIZE) { ret = GNUTLS_E_SHORT_MEMORY_BUFFER; goto cleanup; } ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, &epriv); if (ret < 0) { set = 1; } if (set != 0) { priv = gnutls_calloc(1, sizeof(*priv)); if (priv == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } epriv = priv; } else priv = epriv; server_names = priv->server_names_size + 1; if (server_names > MAX_SERVER_NAME_EXTENSIONS) server_names = MAX_SERVER_NAME_EXTENSIONS; priv->server_names[server_names - 1].type = type; memcpy(priv->server_names[server_names - 1].name, name, name_length); priv->server_names[server_names - 1].name_length = name_length; priv->server_names_size = server_names; if (set != 0) _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, epriv); ret = 0; cleanup: #ifdef HAVE_LIBIDN idn_free(idn_name); #endif return ret; }
static int _proxyinfo_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) { //printf("Recv params\n"); int i; const unsigned char *p; uint16_t len, type; ssize_t data_size = _data_size; int server_names = 0; ProxyInfo_ext_st *priv; extension_priv_data_t epriv; if (session->security_parameters.entity == GNUTLS_SERVER) { DECR_LENGTH_RET (data_size, 2, 0); len = _gnutls_read_uint16 (data); if (len != data_size) { /* This is unexpected packet length, but * just ignore it, for now. */ gnutls_assert (); return 0; } p = data + 2; DECR_LEN (data_size, 2); unsigned count = _gnutls_read_uint16 (p); p+=2; printf("Received Proxy_Info for %d intermediate proxies\n",count+1); priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } priv->proxy_cnt=count; for (int proxy_id=0;proxy_id<count+1;proxy_id++){ DECR_LEN (data_size, 2); unsigned cipher_algo = _gnutls_read_uint16 (p); p+=2; DECR_LEN (data_size, 2); unsigned kx_algo = _gnutls_read_uint16 (p); p+=2; DECR_LEN (data_size, 2); unsigned mac_algo = _gnutls_read_uint16 (p); p+=2; DECR_LEN (data_size, 2); unsigned ip_addr = _gnutls_read_uint16 (p); p+=2; DECR_LEN (data_size, 2); unsigned mac_addr = _gnutls_read_uint16 (p); p+=2; //printf("%d %d %d %d %d\n",cipher_algo,kx_algo,mac_algo,ip_addr,mac_addr); priv->proxy_info[proxy_id].cipher_algo=cipher_algo; priv->proxy_info[proxy_id].kx_algo=kx_algo; priv->proxy_info[proxy_id].mac_algo=mac_algo; priv->proxy_info[proxy_id].ip_addr=ip_addr; priv->proxy_info[proxy_id].mac_addr=mac_addr; } printf("Stored the proxy_info to local instance of extension...\n"); /* Count all server_names in the packet. */ while (data_size > 0) { DECR_LENGTH_RET (data_size, 1, 0); p++; DECR_LEN (data_size, 2); len = _gnutls_read_uint16 (p); p += 2; if (len > 0) { DECR_LENGTH_RET (data_size, len, 0); server_names++; p += len; } else _gnutls_handshake_log ("HSK[%p]: Received (0) size server name (under attack?)\n", session); } /* we cannot accept more server names. */ if (server_names > MAX_SERVER_NAME_EXTENSIONS) { _gnutls_handshake_log ("HSK[%p]: Too many server names received (under attack?)\n", session); server_names = MAX_SERVER_NAME_EXTENSIONS; } if (server_names == 0) return 0; /* no names found */ priv->server_names_size = server_names; p = data + 4; p+=10*(count+1); for (i = 0; i < server_names; i++) { type = *p; p++; len = _gnutls_read_uint16 (p); p += 2; switch (type) { case 0: /* NAME_DNS */ if (len <= MAX_SERVER_NAME_SIZE) { memcpy (priv->server_names[i].name, p, len); priv->server_names[i].name_length = len; priv->server_names[i].type = GNUTLS_NAME_DNS; break; } } /* move to next record */ p += len; } epriv.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_PROXYINFO, epriv); } return 0; }
int gnutls_proxyinfo_set (gnutls_session_t session, gnutls_server_name_type_t type, const void *name, size_t name_length, void *data,int data_length, int proxy_id) { printf("Set Data locally in the extension...\n"); int server_names, ret; ProxyInfo_ext_st *priv; extension_priv_data_t epriv; int set = 0; /* Fill the contents of foobar_info * in foobar_ext_st structure viz. priv * Temporarily it is filled only for GNUTLS_CLIENT */ if (session->security_parameters.entity == GNUTLS_SERVER) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if(data_length/sizeof(gnutls_ProxyInfo_ext) > MAX_PROXIES - 1 ) return GNUTLS_E_SHORT_MEMORY_BUFFER; if (name_length > MAX_SERVER_NAME_SIZE) return GNUTLS_E_SHORT_MEMORY_BUFFER; ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_PROXYINFO, &epriv); if (ret < 0) { set = 1; } if (set != 0) { priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } epriv.ptr = priv; } else priv = epriv.ptr; server_names = priv->server_names_size + 1; if (server_names > MAX_SERVER_NAME_EXTENSIONS) server_names = MAX_SERVER_NAME_EXTENSIONS; priv->server_names[server_names - 1].type = type; memcpy (priv->server_names[server_names - 1].name, name, name_length); priv->server_names[server_names - 1].name_length = name_length; priv->server_names_size++; int proxy_index=(data_length/sizeof(gnutls_ProxyInfo_ext)); priv->proxy_cnt=proxy_index;//proxy_id; for(int i=0;i<proxy_index;i++){ priv->proxy_info[i].cipher_algo=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))); priv->proxy_info[i].kx_algo=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))+4); priv->proxy_info[i].mac_algo=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))+8); priv->proxy_info[i].ip_addr=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))+12); priv->proxy_info[i].mac_addr=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))+16); } if(proxy_index>0) printf("Past data parsed from data packet and set in Extension...\n"); priv->proxy_info[proxy_index]=get_proxy_info(session); proxy_id=proxy_index; printf("Current Proxy Info:\nProxy Index: %d\n%d, %d, %d, %d, %d\n",priv->proxy_cnt,priv->proxy_info[proxy_id].cipher_algo,priv->proxy_info[proxy_id].kx_algo,priv->proxy_info[proxy_id].mac_algo,priv->proxy_info[proxy_id].ip_addr,priv->proxy_info[proxy_id].mac_addr); if (set != 0) _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_PROXYINFO, epriv); ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_PROXYINFO, &epriv); return 0; }
static int _gnutls_sr_send_params (gnutls_session_t session, gnutls_buffer_st* extdata) { /* The format of this extension is a one-byte length of verify data followed * by the verify data itself. Note that the length byte does not include * itself; IOW, empty verify data is represented as a length of 0. That means * the minimum extension is one byte: 0x00. */ sr_ext_st *priv; int ret, set = 0, len; extension_priv_data_t epriv; size_t init_length = extdata->length; if (session->internals.priorities.sr == SR_DISABLED) { gnutls_assert (); return 0; } ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); if (ret < 0) { set = 1; } if (set != 0) { priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } epriv.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv); } else priv = epriv.ptr; /* Always offer the extension if we're a client */ if (priv->connection_using_safe_renegotiation || session->security_parameters.entity == GNUTLS_CLIENT) { len = priv->client_verify_data_len; if (session->security_parameters.entity == GNUTLS_SERVER) len += priv->server_verify_data_len; ret = _gnutls_buffer_append_prefix(extdata, 8, len); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_append_data(extdata, priv->client_verify_data, priv->client_verify_data_len); if (ret < 0) return gnutls_assert_val(ret); if (session->security_parameters.entity == GNUTLS_SERVER) { ret = _gnutls_buffer_append_data(extdata, priv->server_verify_data, priv->server_verify_data_len); if (ret < 0) return gnutls_assert_val(ret); } } else return 0; return extdata->length - init_length; }
static int _gnutls_sr_recv_params (gnutls_session_t session, const uint8_t * data, size_t _data_size) { unsigned int len = data[0]; ssize_t data_size = _data_size; sr_ext_st *priv; extension_priv_data_t epriv; int set = 0, ret; DECR_LEN (data_size, len + 1 /* count the first byte and payload */ ); if (session->internals.priorities.sr == SR_DISABLED) { gnutls_assert (); return 0; } ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); if (ret < 0 && session->security_parameters.entity == GNUTLS_SERVER) { set = 1; } else if (ret < 0) { gnutls_assert (); return ret; } if (set != 0) { priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } epriv.ptr = priv; } else priv = epriv.ptr; /* It is not legal to receive this extension on a renegotiation and * not receive it on the initial negotiation. */ if (session->internals.initial_negotiation_completed != 0 && priv->connection_using_safe_renegotiation == 0) { gnutls_assert (); return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; } if (len > sizeof (priv->ri_extension_data)) { gnutls_assert (); return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; } if (len > 0) memcpy (priv->ri_extension_data, &data[1], len); priv->ri_extension_data_len = len; /* "safe renegotiation received" means on *this* handshake; "connection using * safe renegotiation" means that the initial hello received on the connection * indicated safe renegotiation. */ priv->safe_renegotiation_received = 1; priv->connection_using_safe_renegotiation = 1; if (set != 0) _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv); return 0; }
/* returns data_size or a negative number on failure */ static int _gnutls_inner_application_send_params (gnutls_session_t session, opaque * data, size_t data_size) { extension_priv_data_t epriv; ia_ext_st *priv = NULL; int ret; ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); if (ret < 0) { priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } epriv.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_INNER_APPLICATION, epriv); } else priv = epriv.ptr; /* 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) priv->flags |= IA_ENABLE; } else /* SERVER */ { gnutls_ia_server_credentials_t cred; cred = (gnutls_ia_server_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); if (cred) priv->flags |= IA_PEER_ENABLE; } /* 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 (!(priv->flags & IA_ENABLE)) return 0; if (session->security_parameters.entity == GNUTLS_SERVER && !(priv->flags & 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 (priv->flags & IA_ALLOW_SKIP) *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 ((priv->flags & IA_ALLOW_SKIP) && (priv->flags & IA_PEER_ALLOW_SKIP) && session->internals.resumed == RESUME_TRUE) *data = NO; } return 1; }
/** * gnutls_ext_set_data: * @session: a #gnutls_session_t opaque pointer * @type: the numeric id of the extension * @data: the private data to set * * This function allows an extension handler to store data in the current session * and retrieve them later on. The set data will be deallocated using * the gnutls_ext_deinit_data_func. * * Since: 3.4.0 **/ void gnutls_ext_set_data(gnutls_session_t session, unsigned type, gnutls_ext_priv_data_t data) { _gnutls_ext_set_session_data(session, type, data); }