int ssl3_dispatch_alert(SSL *s) { int i, j; void (*cb)(const SSL *ssl, int type, int val) = NULL; s->s3->alert_dispatch = 0; i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2); if (i <= 0) { s->s3->alert_dispatch = 1; } else { /* Alert sent to BIO. If it is important, flush it now. If the message * does not get sent due to non-blocking IO, we will not worry too much. */ if (s->s3->send_alert[0] == SSL3_AL_FATAL) { BIO_flush(s->wbio); } if (s->msg_callback) { s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 2, s, s->msg_callback_arg); } if (s->info_callback != NULL) { cb = s->info_callback; } else if (s->ctx->info_callback != NULL) { cb = s->ctx->info_callback; } if (cb != NULL) { j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1]; cb(s, SSL_CB_WRITE_ALERT, j); } } return i; }
int ssl3_dispatch_alert(SSL *ssl) { ssl->s3->alert_dispatch = 0; int ret = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2); if (ret <= 0) { ssl->s3->alert_dispatch = 1; return ret; } /* If the alert is fatal, flush the BIO now. */ if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) { BIO_flush(ssl->wbio); } if (ssl->msg_callback != NULL) { ssl->msg_callback(1 /* write */, ssl->version, SSL3_RT_ALERT, ssl->s3->send_alert, 2, ssl, ssl->msg_callback_arg); } void (*cb)(const SSL *ssl, int type, int value) = NULL; if (ssl->info_callback != NULL) { cb = ssl->info_callback; } else if (ssl->ctx->info_callback != NULL) { cb = ssl->ctx->info_callback; } if (cb != NULL) { int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1]; cb(ssl, SSL_CB_WRITE_ALERT, alert); } return 1; }
/* Call this to write data in records of type |type|. It will return <= 0 if * not all data has been sent or non-blocking IO. */ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) { const uint8_t *buf = buf_; unsigned int tot, n, nw; int i; s->rwstate = SSL_NOTHING; assert(s->s3->wnum <= INT_MAX); tot = s->s3->wnum; s->s3->wnum = 0; if (!s->in_handshake && SSL_in_init(s) && !SSL_in_false_start(s)) { i = s->handshake_func(s); if (i < 0) { return i; } if (i == 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE); return -1; } } /* Ensure that if we end up with a smaller value of data to write out than * the the original len from a write which didn't complete for non-blocking * I/O and also somehow ended up avoiding the check for this in * ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be possible to * end up with (len-tot) as a large number that will then promptly send * beyond the end of the users buffer ... so we trap and report the error in * a way the user will notice. */ if (len < 0 || (size_t)len < tot) { OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH); return -1; } n = (len - tot); for (;;) { /* max contains the maximum number of bytes that we can put into a * record. */ unsigned max = s->max_send_fragment; if (n > max) { nw = max; } else { nw = n; } i = do_ssl3_write(s, type, &buf[tot], nw); if (i <= 0) { s->s3->wnum = tot; return i; } if (i == (int)n || (type == SSL3_RT_APPLICATION_DATA && (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) { return tot + i; } n -= i; tot += i; } }
int ssl3_dispatch_alert(SSL *ssl) { ssl->s3->alert_dispatch = 0; int ret = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2); if (ret <= 0) { ssl->s3->alert_dispatch = 1; return ret; } /* If the alert is fatal, flush the BIO now. */ if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) { BIO_flush(ssl->wbio); } ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_ALERT, ssl->s3->send_alert, 2); int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1]; ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert); return 1; }