/** * gnutls_srtp_get_selected_profile: * @session: is a #gnutls_session_t type. * @profile: will hold the profile * * This function allows you to get the negotiated SRTP profile. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since 3.1.4 **/ int gnutls_srtp_get_selected_profile(gnutls_session_t session, gnutls_srtp_profile_t * profile) { srtp_ext_st *priv; int ret; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP, &epriv); if (ret < 0) { gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } priv = epriv; if (priv->selected_profile == 0) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } *profile = priv->selected_profile; return 0; }
/** * gnutls_srtp_set_mki: * @session: is a #gnutls_session_t type. * @mki: holds the MKI * * This function sets the Master Key Identifier, to be * used by this session (if any). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since 3.1.4 **/ int gnutls_srtp_set_mki(gnutls_session_t session, const gnutls_datum_t * mki) { int ret; srtp_ext_st *priv; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP, &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_SRTP, epriv); } else priv = epriv; if (mki->size > 0 && mki->size <= sizeof(priv->mki)) { priv->mki_size = mki->size; memcpy(priv->mki, mki->data, mki->size); } else return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); return 0; }
/** * gnutls_srtp_get_mki: * @session: is a #gnutls_session_t type. * @mki: will hold the MKI * * This function exports the negotiated Master Key Identifier, * received by the peer if any. The returned value in @mki should be * treated as constant and valid only during the session's lifetime. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since 3.1.4 **/ int gnutls_srtp_get_mki(gnutls_session_t session, gnutls_datum_t * mki) { srtp_ext_st *priv; int ret; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP, &epriv); if (ret < 0) return gnutls_assert_val (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); priv = epriv; if (priv->mki_received == 0) return gnutls_assert_val (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); mki->data = priv->mki; mki->size = priv->mki_size; return 0; }
/** * gnutls_ocsp_status_request_get: * @session: is a #gnutls_session_t structure. * @response: a #gnutls_datum_t with DER encoded OCSP response * * This function returns the OCSP status response received * from the TLS server. The @response should be treated as * constant. If no OCSP response is available then * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since: 3.1.3 **/ int gnutls_ocsp_status_request_get(gnutls_session_t session, gnutls_datum_t * response) { status_request_ext_st *priv; extension_priv_data_t epriv; int ret; if (session->security_parameters.entity == GNUTLS_SERVER) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_STATUS_REQUEST, &epriv); if (ret < 0) return gnutls_assert_val(ret); priv = epriv.ptr; if (priv == NULL || priv->response.data == NULL) return gnutls_assert_val (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); response->data = priv->response.data; response->size = priv->response.size; return 0; }
static int _gnutls_status_request_send_params(gnutls_session_t session, gnutls_buffer_st * extdata) { extension_priv_data_t epriv; status_request_ext_st *priv; int ret; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_STATUS_REQUEST, &epriv); if (session->security_parameters.entity == GNUTLS_CLIENT) { if (ret < 0 || epriv.ptr == NULL) /* it is ok not to have it */ return 0; priv = epriv.ptr; return client_send(session, extdata, priv); } else { epriv.ptr = priv = gnutls_calloc(1, sizeof(*priv)); if (priv == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_STATUS_REQUEST, epriv); return server_send(session, extdata, priv); } }
/** * gnutls_srtp_set_profile: * @session: is a #gnutls_session_t type. * @profile: is the profile id to add. * * This function is to be used by both clients and servers, to declare * what SRTP profiles they support, to negotiate with the peer. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since 3.1.4 **/ int gnutls_srtp_set_profile(gnutls_session_t session, gnutls_srtp_profile_t profile) { int ret; srtp_ext_st *priv; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP, &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_SRTP, epriv); } else priv = epriv; if (priv->profiles_size < MAX_SRTP_PROFILES) priv->profiles_size++; priv->profiles[priv->profiles_size - 1] = profile; return 0; }
/** * gnutls_sign_algorithm_get_requested: * @session: is a #gnutls_session_t type. * @indx: is an index of the signature algorithm to return * @algo: the returned certificate type will be stored there * * Returns the signature algorithm specified by index that was * requested by the peer. If the specified index has no data available * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If * the negotiated TLS version does not support signature algorithms * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even * for the first index. The first index is 0. * * This function is useful in the certificate callback functions * to assist in selecting the correct certificate. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. * * Since: 2.10.0 **/ int gnutls_sign_algorithm_get_requested(gnutls_session_t session, size_t indx, gnutls_sign_algorithm_t * algo) { const version_entry_st *ver = get_version(session); sig_ext_st *priv; extension_priv_data_t epriv; int ret; if (unlikely(ver == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, &epriv); if (ret < 0) { gnutls_assert(); return ret; } priv = epriv; if (!_gnutls_version_has_selectable_sighash(ver) || priv->sign_algorithms_size == 0) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } if (indx < priv->sign_algorithms_size) { *algo = priv->sign_algorithms[indx]; return 0; } else return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; }
/* returns data_size or a negative number on failure */ static int _gnutls_ext_etm_send_params(gnutls_session_t session, gnutls_buffer_st * extdata) { if (session->internals.priorities.no_etm != 0) return 0; /* this function sends the client extension data */ if (session->security_parameters.entity == GNUTLS_CLIENT) { if (session->internals.priorities.have_cbc != 0) return GNUTLS_E_INT_RET_0; else return 0; } else { /* server side */ const cipher_entry_st *c; int ret; extension_priv_data_t epriv; c = _gnutls_cipher_suite_get_cipher_algo(session->security_parameters.cipher_suite); if (c == NULL || (c->type == CIPHER_AEAD || c->type == CIPHER_STREAM)) return 0; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_ETM, &epriv); if (ret < 0 || ((intptr_t)epriv) == 0) return 0; session->security_parameters.etm = 1; return GNUTLS_E_INT_RET_0; } return 0; }
/** * gnutls_sign_algorithm_get_requested: * @session: is a #gnutls_session_t structure. * @indx: is an index of the signature algorithm to return * @algo: the returned certificate type will be stored there * * Returns the signature algorithm specified by index that was * requested by the peer. If the specified index has no data available * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If * the negotiated TLS version does not support signature algorithms * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even * for the first index. The first index is 0. * * This function is useful in the certificate callback functions * to assist in selecting the correct certificate. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. * * Since: 2.10.0 **/ int gnutls_sign_algorithm_get_requested (gnutls_session_t session, size_t indx, gnutls_sign_algorithm_t * algo) { gnutls_protocol_t ver = gnutls_protocol_get_version (session); sig_ext_st *priv; extension_priv_data_t epriv; int ret; ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, &epriv); if (ret < 0) { gnutls_assert (); return ret; } priv = epriv.ptr; if (!_gnutls_version_has_selectable_sighash (ver) || priv->sign_algorithms_size == 0) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } if (indx < priv->sign_algorithms_size) { *algo = priv->sign_algorithms[indx]; return 0; } else return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; }
static int _gnutls_heartbeat_recv_params(gnutls_session_t session, const uint8_t * data, size_t _data_size) { unsigned policy; extension_priv_data_t epriv; if (_gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0) { if (session->security_parameters.entity == GNUTLS_CLIENT) return gnutls_assert_val (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); return 0; /* Not enabled */ } if (_data_size == 0) return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; policy = epriv.num; if (data[0] == 1) policy |= LOCAL_ALLOWED_TO_SEND; else if (data[0] == 2) policy |= LOCAL_NOT_ALLOWED_TO_SEND; else return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); epriv.num = policy; _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_HEARTBEAT, epriv); return 0; }
/** * gnutls_alpn_get_selected_protocol: * @session: is a #gnutls_session_t structure. * @protocol: will hold the protocol name * * This function allows you to get the negotiated protocol name. The * returned protocol should be treated as opaque, constant value and * only valid during the session life. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since 3.1.11 **/ int gnutls_alpn_get_selected_protocol (gnutls_session_t session, gnutls_datum_t * protocol) { alpn_ext_st *priv; int ret; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_ALPN, &epriv); if (ret < 0) { gnutls_assert (); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } priv = epriv.ptr; if (priv->selected_protocol_size == 0) return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); protocol->data = priv->selected_protocol; protocol->size = priv->selected_protocol_size; return 0; }
static int _gnutls_max_record_recv_params(gnutls_session_t session, const uint8_t * data, size_t _data_size) { ssize_t new_size; ssize_t data_size = _data_size; extension_priv_data_t epriv; int ret; if (session->security_parameters.entity == GNUTLS_SERVER) { if (data_size > 0) { DECR_LEN(data_size, 1); new_size = _gnutls_mre_num2record(data[0]); if (new_size < 0) { gnutls_assert(); return new_size; } session->security_parameters.max_record_send_size = new_size; session->security_parameters.max_record_recv_size = new_size; } } else { /* CLIENT SIDE - we must check if the sent record size is the right one */ if (data_size > 0) { ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_MAX_RECORD_SIZE, &epriv); if (ret < 0) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } if (data_size != 1) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } new_size = _gnutls_mre_num2record(data[0]); if (new_size < 0 || new_size != (intptr_t) epriv) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } else { session->security_parameters. max_record_recv_size = (intptr_t)epriv; } } } return 0; }
/** * gnutls_server_name_get: * @session: is a #gnutls_session_t type. * @data: will hold the data * @data_length: will hold the data length. Must hold the maximum size of data. * @type: will hold the server name indicator type * @indx: is the index of the server_name * * This function will allow you to get the name indication (if any), a * client has sent. The name indication may be any of the enumeration * gnutls_server_name_type_t. * * If @type is GNUTLS_NAME_DNS, then this function is to be used by * servers that support virtual hosting, and the data will be a null * terminated IDNA ACE string (prior to GnuTLS 3.4.0 it was a UTF-8 string). * * If @data has not enough size to hold the server name * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will * hold the required size. * * @index is used to retrieve more than one server names (if sent by * the client). The first server name has an index of 0, the second 1 * and so on. If no name with the given index exists * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, on UTF-8 * decoding error %GNUTLS_E_IDNA_ERROR is returned, otherwise a negative * error code is returned. **/ int gnutls_server_name_get(gnutls_session_t session, void *data, size_t * data_length, unsigned int *type, unsigned int indx) { char *_data = data; server_name_ext_st *priv; int ret; gnutls_datum_t idn_name = {NULL,0}; extension_priv_data_t epriv; if (session->security_parameters.entity == GNUTLS_CLIENT) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, &epriv); if (ret < 0) { gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } priv = epriv; if (indx + 1 > priv->server_names_size) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } *type = priv->server_names[indx].type; ret = gnutls_idna_map((char*)priv->server_names[indx].name, priv->server_names[indx].name_length, &idn_name, 0); if (ret < 0) { _gnutls_debug_log("unable to convert name %s to IDNA2003 format\n", (char*)priv->server_names[indx].name); return GNUTLS_E_IDNA_ERROR; } if (*data_length > /* greater since we need one extra byte for the null */ idn_name.size) { *data_length = idn_name.size; memcpy(data, idn_name.data, *data_length); if (*type == GNUTLS_NAME_DNS) /* null terminate */ _data[(*data_length)] = 0; } else { *data_length = idn_name.size + 1; ret = GNUTLS_E_SHORT_MEMORY_BUFFER; goto cleanup; } ret = 0; cleanup: gnutls_free(idn_name.data); return ret; }
/** * gnutls_server_name_set: * @session: is a #gnutls_session_t structure. * @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, an ASCII (0)-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; int set = 0; if (session->security_parameters.entity == GNUTLS_SERVER) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (name_length > MAX_SERVER_NAME_SIZE) return GNUTLS_E_SHORT_MEMORY_BUFFER; 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.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++; if (set != 0) _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SERVER_NAME, epriv); return 0; }
/* This does not do any conversion not perform any check */ int _gnutls_server_name_set_raw(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; int set = 0; if (name_length > MAX_SERVER_NAME_SIZE) { return GNUTLS_E_SHORT_MEMORY_BUFFER; } 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; if (name_length > 0) { memcpy(priv->server_names[server_names - 1].name, name, name_length); priv->server_names[server_names - 1].name[name_length] = 0; } 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); return 0; }
static int _gnutls_inner_application_recv_params (gnutls_session_t session, const opaque * data, size_t data_size) { extension_priv_data_t epriv; ia_ext_st *priv; int ret; if (data_size != 1) { gnutls_assert (); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } 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; priv->flags |= IA_PEER_ENABLE; priv->flags &= ~IA_PEER_ALLOW_SKIP; switch ((unsigned char) *data) { case NO: /* Peer's ia_on_resume == no */ priv->flags |= IA_PEER_ALLOW_SKIP; break; case YES: break; default: gnutls_assert (); } return 0; }
/* returns a positive number if we send the extension data, (0) if we do not want to send it, and a negative number on failure. */ static int session_ticket_send_params(gnutls_session_t session, gnutls_buffer_st * extdata) { session_ticket_ext_st *priv = NULL; extension_priv_data_t epriv; int ret; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); if (ret >= 0) priv = epriv; if (priv == NULL || !priv->session_ticket_enable) return 0; if (session->security_parameters.entity == GNUTLS_SERVER) { if (priv && priv->session_ticket_renew) { return GNUTLS_E_INT_RET_0; } } else { ret = _gnutls_ext_get_resumed_session_data(session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); if (ret >= 0) priv = epriv; /* no previous data. Just advertize it */ if (ret < 0) return GNUTLS_E_INT_RET_0; /* previous data had session tickets disabled. Don't advertize. Ignore. */ if (!priv->session_ticket_enable) return 0; if (priv->session_ticket_len > 0) { ret = _gnutls_buffer_append_data(extdata, priv-> session_ticket, priv-> session_ticket_len); if (ret < 0) return gnutls_assert_val(ret); return priv->session_ticket_len; } } return 0; }
/** * gnutls_server_name_get: * @session: is a #gnutls_session_t structure. * @data: will hold the data * @data_length: will hold the data length. Must hold the maximum size of data. * @type: will hold the server name indicator type * @indx: is the index of the server_name * * This function will allow you to get the name indication (if any), a * client has sent. The name indication may be any of the enumeration * gnutls_server_name_type_t. * * If @type is GNUTLS_NAME_DNS, then this function is to be used by * servers that support virtual hosting, and the data will be a null * terminated UTF-8 string. * * If @data has not enough size to hold the server name * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will * hold the required size. * * @index is used to retrieve more than one server names (if sent by * the client). The first server name has an index of 0, the second 1 * and so on. If no name with the given index exists * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_server_name_get (gnutls_session_t session, void *data, size_t * data_length, unsigned int *type, unsigned int indx) { char *_data = data; server_name_ext_st *priv; int ret; extension_priv_data_t epriv; if (session->security_parameters.entity == GNUTLS_CLIENT) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME, &epriv); if (ret < 0) { gnutls_assert (); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } priv = epriv.ptr; if (indx + 1 > priv->server_names_size) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } *type = priv->server_names[indx].type; if (*data_length > /* greater since we need one extra byte for the null */ priv->server_names[indx].name_length) { *data_length = priv->server_names[indx].name_length; memcpy (data, priv->server_names[indx].name, *data_length); if (*type == GNUTLS_NAME_DNS) /* null terminate */ _data[(*data_length)] = 0; } else { *data_length = priv->server_names[indx].name_length; return GNUTLS_E_SHORT_MEMORY_BUFFER; } return 0; }
/* returns data_size or a negative number on failure */ static int _gnutls_max_record_send_params (gnutls_session_t session, gnutls_buffer_st* extdata) { uint8_t p; int ret; /* this function sends the client extension data (dnsname) */ if (session->security_parameters.entity == GNUTLS_CLIENT) { extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_MAX_RECORD_SIZE, &epriv); if (ret < 0) /* it is ok not to have it */ { return 0; } if (epriv.num != DEFAULT_MAX_RECORD_SIZE) { p = (uint8_t) _gnutls_mre_record2num (epriv.num); ret = _gnutls_buffer_append_data( extdata, &p, 1); if (ret < 0) return gnutls_assert_val(ret); return 1; } } else { /* server side */ if (session->security_parameters.max_record_recv_size != DEFAULT_MAX_RECORD_SIZE) { p = (uint8_t) _gnutls_mre_record2num (session->security_parameters.max_record_recv_size); ret = _gnutls_buffer_append_data( extdata, &p, 1); if (ret < 0) return gnutls_assert_val(ret); return 1; } } return 0; }
/* Returns a requested by the peer signature algorithm that * matches the given certificate's public key algorithm. */ gnutls_sign_algorithm_t _gnutls_session_get_sign_algo(gnutls_session_t session, gnutls_pcert_st * cert) { unsigned i; int ret; const version_entry_st *ver = get_version(session); sig_ext_st *priv; extension_priv_data_t epriv; unsigned int cert_algo; if (unlikely(ver == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL); ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, &epriv); priv = epriv; if (ret < 0 || !_gnutls_version_has_selectable_sighash(ver) || priv->sign_algorithms_size == 0) /* none set, allow SHA-1 only */ { ret = gnutls_pk_to_sign(cert_algo, GNUTLS_DIG_SHA1); if (_gnutls_session_sign_algo_enabled(session, ret) < 0) goto fail; return ret; } for (i = 0; i < priv->sign_algorithms_size; i++) { if (gnutls_sign_get_pk_algorithm(priv->sign_algorithms[i]) == cert_algo) { if (_gnutls_pubkey_compatible_with_sig (session, cert->pubkey, ver, priv->sign_algorithms[i]) < 0) continue; if (_gnutls_session_sign_algo_enabled (session, priv->sign_algorithms[i]) < 0) continue; return priv->sign_algorithms[i]; } } fail: return GNUTLS_SIGN_UNKNOWN; }
/** * gnutls_srtp_set_profile_direct: * @session: is a #gnutls_session_t type. * @profiles: is a string that contains the supported SRTP profiles, * separated by colons. * @err_pos: In case of an error this will have the position in the string the error occurred, may be NULL. * * This function is to be used by both clients and servers, to declare * what SRTP profiles they support, to negotiate with the peer. * * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned, * %GNUTLS_E_SUCCESS on success, or an error code. * * Since 3.1.4 **/ int gnutls_srtp_set_profile_direct(gnutls_session_t session, const char *profiles, const char **err_pos) { int ret; srtp_ext_st *priv; extension_priv_data_t epriv; int set = 0; const char *col; gnutls_srtp_profile_t id; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP, &epriv); if (ret < 0) { set = 1; priv = gnutls_calloc(1, sizeof(*priv)); if (priv == NULL) { if (err_pos != NULL) *err_pos = profiles; gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } epriv = priv; } else priv = epriv; do { col = strchr(profiles, ':'); id = find_profile(profiles, col); if (id == 0) { if (set != 0) gnutls_free(priv); if (err_pos != NULL) *err_pos = profiles; return GNUTLS_E_INVALID_REQUEST; } if (priv->profiles_size < MAX_SRTP_PROFILES) { priv->profiles_size++; } priv->profiles[priv->profiles_size - 1] = id; profiles = col + 1; } while (col != NULL); if (set != 0) _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SRTP, epriv); return 0; }
/** * gnutls_heartbeat_allowed: * @session: is a #gnutls_session_t structure. * @type: one of %GNUTLS_HB_LOCAL_ALLOWED_TO_SEND and %GNUTLS_HB_PEER_ALLOWED_TO_SEND * * This function will check whether heartbeats are allowed * to be sent or received in this session. * * Returns: Non zero if heartbeats are allowed. * * Since: 3.1.2 **/ int gnutls_heartbeat_allowed(gnutls_session_t session, unsigned int type) { extension_priv_data_t epriv; if (_gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0) return 0; /* Not enabled */ if (type == GNUTLS_HB_LOCAL_ALLOWED_TO_SEND) { if (epriv.num & LOCAL_ALLOWED_TO_SEND) return 1; } else if (epriv.num & GNUTLS_HB_PEER_ALLOWED_TO_SEND) return 1; return 0; }
static int new_record_padding_before_epoch_change(gnutls_session_t session) { extension_priv_data_t epriv; int ret; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_NEW_RECORD_PADDING, &epriv); if (ret < 0) return 0; /* fine */ if (epriv.num != 0) session->security_parameters.new_record_padding = 1; return 0; }
/* Check if the given signature algorithm is accepted by * the peer. Returns 0 on success or a negative value * on error. */ int _gnutls_session_sign_algo_requested (gnutls_session_t session, gnutls_sign_algorithm_t sig) { unsigned i; int ret, hash; gnutls_protocol_t ver = gnutls_protocol_get_version (session); sig_ext_st *priv; extension_priv_data_t epriv; if (!_gnutls_version_has_selectable_sighash (ver)) { return 0; } ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, &epriv); if (ret < 0) { gnutls_assert (); /* extension not received allow SHA1 and SHA256 */ hash = _gnutls_sign_get_hash_algorithm (sig); if (hash == GNUTLS_DIG_SHA1 || hash == GNUTLS_DIG_SHA256) return 0; else return ret; } priv = epriv.ptr; if (priv->sign_algorithms_size == 0) /* none set, allow all */ { return 0; } for (i = 0; i < priv->sign_algorithms_size; i++) { if (priv->sign_algorithms[i] == sig) { return 0; /* ok */ } } return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; }
int _gnutls_ext_sr_finished (gnutls_session_t session, void *vdata, size_t vdata_size, int dir) { int ret; sr_ext_st *priv; extension_priv_data_t epriv; if (session->internals.priorities.sr == SR_DISABLED) { return 0; } ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); if (ret < 0) { gnutls_assert (); return ret; } priv = epriv.ptr; /* Save data for safe renegotiation. */ if (vdata_size > MAX_VERIFY_DATA_SIZE) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if ((session->security_parameters.entity == GNUTLS_CLIENT && dir == 0) || (session->security_parameters.entity == GNUTLS_SERVER && dir == 1)) { priv->client_verify_data_len = vdata_size; memcpy (priv->client_verify_data, vdata, vdata_size); } else { priv->server_verify_data_len = vdata_size; memcpy (priv->server_verify_data, vdata, vdata_size); } return 0; }
/** * gnutls_alpn_set_protocols: * @session: is a #gnutls_session_t structure. * @protocols: is the protocol names to add. * @protocols_size: the number of protocols to add. * @flags: zero or %GNUTLS_ALPN_* * * This function is to be used by both clients and servers, to declare * the supported ALPN protocols, which are used during peer negotiation. * * If %GNUTLS_ALPN_MAND is specified the connection will be aborted * if no matching ALPN protocol is found. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since 3.1.11 **/ 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.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_ALPN, epriv); } else priv = epriv.ptr; 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; }
/** * gnutls_safe_renegotiation_status: * @session: is a #gnutls_session_t structure. * * Can be used to check whether safe renegotiation is being used * in the current session. * * Returns: 0 when safe renegotiation is not used and non (0) when * safe renegotiation is used. * * Since: 2.10.0 **/ int gnutls_safe_renegotiation_status (gnutls_session_t session) { int ret; sr_ext_st *priv; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); if (ret < 0) { gnutls_assert (); return 0; } priv = epriv.ptr; return priv->connection_using_safe_renegotiation; }
int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed) { unsigned int i; int ret; extension_priv_data_t data; int cur_size; int size_offset; int total_exts_pos; int exts = 0; total_exts_pos = packed->length; BUFFER_APPEND_NUM(packed, 0); for (i = 0; i < extfunc_size; i++) { ret = _gnutls_ext_get_session_data(session, extfunc[i].type, &data); if (ret >= 0 && extfunc[i].pack_func != NULL) { BUFFER_APPEND_NUM(packed, extfunc[i].type); size_offset = packed->length; BUFFER_APPEND_NUM(packed, 0); cur_size = packed->length; ret = extfunc[i].pack_func(data, packed); if (ret < 0) { gnutls_assert(); return ret; } exts++; /* write the actual size */ _gnutls_write_uint32(packed->length - cur_size, packed->data + size_offset); } } _gnutls_write_uint32(exts, packed->data + total_exts_pos); return 0; }
/* if a server received the special ciphersuite. */ int _gnutls_ext_sr_recv_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; } else priv = epriv.ptr; 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; }
static int _gnutls_status_request_recv_params(gnutls_session_t session, const uint8_t * data, size_t size) { extension_priv_data_t epriv; status_request_ext_st *priv; int ret; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_STATUS_REQUEST, &epriv); if (ret < 0 || epriv.ptr == NULL) /* it is ok not to have it */ return 0; priv = epriv.ptr; if (session->security_parameters.entity == GNUTLS_CLIENT) return client_recv(session, priv, data, size); return server_recv(session, priv, data, size); }