diff options
Diffstat (limited to 'ssl/s3_srvr.c')
-rw-r--r-- | ssl/s3_srvr.c | 116 |
1 files changed, 114 insertions, 2 deletions
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 632b924ef2..ba324848c1 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -403,9 +403,30 @@ int ssl3_accept(SSL *s) s->state=SSL3_ST_SW_CHANGE_A; #endif else - s->state=SSL3_ST_SW_CERT_A; - s->init_num=0; +#ifndef OPENSSL_NO_TLSEXT + s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_A; +#else + s->state = SSL3_ST_SW_CERT_A; +#endif + s->init_num = 0; + break; + +#ifndef OPENSSL_NO_TLSEXT + case SSL3_ST_SW_SUPPLEMENTAL_DATA_A: + case SSL3_ST_SW_SUPPLEMENTAL_DATA_B: + /* We promised to send an audit proof in the hello. */ + if (s->s3->tlsext_authz_promised_to_client) + { + ret = tls1_send_server_supplemental_data(s); + if (ret <= 0) goto end; + } + else + skip = 1; + + s->state = SSL3_ST_SW_CERT_A; + s->init_num = 0; break; +#endif case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: @@ -3629,4 +3650,95 @@ int ssl3_get_next_proto(SSL *s) return 1; } # endif + +int tls1_send_server_supplemental_data(SSL *s) + { + size_t length = 0; + const unsigned char *authz, *orig_authz; + unsigned char *p; + size_t authz_length, i; + + if (s->state != SSL3_ST_SW_SUPPLEMENTAL_DATA_A) + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + + orig_authz = authz = ssl_get_authz_data(s, &authz_length); + if (authz == NULL) + { + /* This should never occur. */ + return 0; + } + + /* First we walk over the authz data to see how long the handshake + * message will be. */ + for (i = 0; i < authz_length; i++) + { + unsigned short len; + unsigned char type; + + type = *(authz++); + n2s(authz, len); + + if (memchr(s->s3->tlsext_authz_client_types, + type, + s->s3->tlsext_authz_client_types_len) != NULL) + length += 1 /* authz type */ + 2 /* length */ + len; + + authz += len; + i += len; + } + + length += 1 /* handshake type */ + + 3 /* handshake length */ + + 3 /* supplemental data length */ + + 2 /* supplemental entry type */ + + 2 /* supplemental entry length */; + + if (!BUF_MEM_grow_clean(s->init_buf, length)) + { + SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); + return 0; + } + + p = (unsigned char *)s->init_buf->data; + *(p++) = SSL3_MT_SUPPLEMENTAL_DATA; + /* Handshake length */ + l2n3(length - 4, p); + /* Length of supplemental data */ + l2n3(length - 7, p); + /* Supplemental data type */ + s2n(TLSEXT_SUPPLEMENTALDATATYPE_authz_data, p); + /* Its length */ + s2n(length - 11, p); + + authz = orig_authz; + + /* Walk over the authz again and append the selected elements. */ + for (i = 0; i < authz_length; i++) + { + unsigned short len; + unsigned char type; + + type = *(authz++); + n2s(authz, len); + + if (memchr(s->s3->tlsext_authz_client_types, + type, + s->s3->tlsext_authz_client_types_len) != NULL) + { + *(p++) = type; + s2n(len, p); + memcpy(p, authz, len); + p += len; + } + + authz += len; + i += len; + } + + s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B; + s->init_num = length; + s->init_off = 0; + + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + } #endif |