/* returns error if no retry_after hdr field is present */ static int blst_add_retry_after_f(struct sip_msg* msg, char* min, char* max) { #ifdef USE_DST_BLACKLIST int t_min, t_max, t; struct dest_info src; struct hdr_field* hf; if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){ if (unlikely(get_int_fparam(&t_min, msg, (fparam_t*)min)<0)) return -1; if (likely(max)){ if (unlikely(get_int_fparam(&t_max, msg, (fparam_t*)max)<0)) return -1; }else{ t_max=0; } init_dest_info(&src); src.send_sock=0; src.to=msg->rcv.src_su; src.id=msg->rcv.proto_reserved1; src.proto=msg->rcv.proto; t=-1; if ((parse_headers(msg, HDR_RETRY_AFTER_F, 0)==0) && (msg->parsed_flag & HDR_RETRY_AFTER_F)){ for (hf=msg->headers; hf; hf=hf->next) if (hf->type==HDR_RETRY_AFTER_T){ /* found */ t=(unsigned)(unsigned long)hf->parsed; break; } } if (t<0) return -1; t=MAX_unsigned(t, t_min); t=MIN_unsigned(t, t_max); if (likely(t)) dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg, S_TO_TICKS(t)); return 1; }else{ LOG(L_WARN, "WARNING: blst: blst_add_retry_after:" " blacklist support disabled\n"); } #else /* USE_DST_BLACKLIST */ LOG(L_WARN, "WARNING: blst: blst_add_retry_after:" " blacklist support not compiled-in - no effect -\n"); #endif /* USE_DST_BLACKLIST */ return 1; }
/** tls read. * Each modification of ssl data structures has to be protected, another process * might ask for the same connection and attempt write to it which would * result in updating the ssl structures. * WARNING: must be called whic c->write_lock _unlocked_. * @param c - tcp connection pointer. The following flags might be set: * @param flags - value/result: * input: RD_CONN_FORCE_EOF - force EOF after the first * successful read (bytes_read >=0 ) * output: RD_CONN_SHORT_READ if the read exhausted * all the bytes in the socket read buffer. * RD_CONN_EOF if EOF detected (0 bytes read) * or forced via RD_CONN_FORCE_EOF. * RD_CONN_REPEAT_READ if this function should * be called again (e.g. has some data * buffered internally that didn't fit in * tcp_req). * Note: RD_CONN_SHORT_READ & RD_CONN_EOF should be cleared * before calling this function when there is new * data (e.g. POLLIN), but not if the called is * retried because of RD_CONN_REPEAT_READ and there * is no information about the socket having more * read data available. * @return bytes decrypted on success, -1 on error (it also sets some * tcp connection flags and might set c->state and r->error on * EOF or error). */ int tls_read_f(struct tcp_connection* c, int* flags) { struct tcp_req* r; int bytes_free, bytes_read, read_size, ssl_error, ssl_read; SSL* ssl; unsigned char rd_buf[TLS_RD_MBUF_SZ]; unsigned char wr_buf[TLS_WR_MBUF_SZ]; struct tls_mbuf rd, wr; struct tls_extra_data* tls_c; struct tls_rd_buf* enc_rd_buf; int n, flush_flags; char* err_src; int x; int tls_dbg; TLS_RD_TRACE("(%p, %p (%d)) start (%s -> %s:%d*)\n", c, flags, *flags, su2a(&c->rcv.src_su, sizeof(c->rcv.src_su)), ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); ssl_read = 0; r = &c->req; enc_rd_buf = 0; *flags &= ~RD_CONN_REPEAT_READ; if (unlikely(tls_fix_connection(c) < 0)) { TLS_RD_TRACE("(%p, %p) end: tls_fix_connection failed =>" " immediate error exit\n", c, flags); return -1; } /* here it's safe to use c->extra_data in read-only mode. If it's != 0 is changed only on destroy. It's not possible to have parallel reads.*/ tls_c = c->extra_data; bytes_free = c->req.b_size - (int)(r->pos - r->buf); if (unlikely(bytes_free == 0)) { ERR("Buffer overrun, dropping\n"); r->error = TCP_REQ_OVERRUN; return -1; } redo_read: /* if data queued from a previous read(), use it (don't perform * a real read()). */ if (unlikely(tls_c->enc_rd_buf)) { /* use queued data */ /* safe to use without locks, because only read changes it and there can't be parallel reads on the same connection */ enc_rd_buf = tls_c->enc_rd_buf; tls_c->enc_rd_buf = 0; TLS_RD_TRACE("(%p, %p) using queued data (%p: %p %d bytes)\n", c, flags, enc_rd_buf, enc_rd_buf->buf + enc_rd_buf->pos, enc_rd_buf->size - enc_rd_buf->pos); tls_mbuf_init(&rd, enc_rd_buf->buf + enc_rd_buf->pos, enc_rd_buf->size - enc_rd_buf->pos); rd.used = enc_rd_buf->size - enc_rd_buf->pos; } else { /* if we were using using queued data before, free & reset the the queued read data before performing the real read() */ if (unlikely(enc_rd_buf)) { TLS_RD_TRACE("(%p, %p) reset prev. used enc_rd_buf (%p)\n", c, flags, enc_rd_buf); shm_free(enc_rd_buf); enc_rd_buf = 0; } /* real read() */ tls_mbuf_init(&rd, rd_buf, sizeof(rd_buf)); /* read() only if no previously detected EOF, or previous short read (which means the socket buffer was emptied) */ if (likely(!(*flags & (RD_CONN_EOF|RD_CONN_SHORT_READ)))) { /* don't read more then the free bytes in the tcp req buffer */ read_size = MIN_unsigned(rd.size, bytes_free); bytes_read = tcp_read_data(c->fd, c, (char*)rd.buf, read_size, flags); TLS_RD_TRACE("(%p, %p) tcp_read_data(..., %d, *%d) => %d bytes\n", c, flags, read_size, *flags, bytes_read); /* try SSL_read even on 0 bytes read, it might have internally buffered data */ if (unlikely(bytes_read < 0)) { goto error; } rd.used = bytes_read; } } continue_ssl_read: tls_mbuf_init(&wr, wr_buf, sizeof(wr_buf)); ssl_error = SSL_ERROR_NONE; err_src = "TLS read:"; /* we have to avoid to run in the same time * with a tls_write because of the * update bio stuff (we don't want a write * stealing the wbio or rbio under us or vice versa) * => lock on con->write_lock (ugly hack) */ lock_get(&c->write_lock); tls_set_mbufs(c, &rd, &wr); ssl = tls_c->ssl; n = 0; if (unlikely(tls_write_wants_read(tls_c) && !(*flags & RD_CONN_EOF))) { n = tls_ct_wq_flush(c, &tls_c->ct_wq, &flush_flags, &ssl_error); TLS_RD_TRACE("(%p, %p) tls write on read (WRITE_WANTS_READ):" " ct_wq_flush()=> %d (ff=%d ssl_error=%d))\n", c, flags, n, flush_flags, ssl_error); if (unlikely(n < 0 )) { tls_set_mbufs(c, 0, 0); lock_release(&c->write_lock); ERR("write flush error (%d)\n", n); goto error; } if (likely(flush_flags & F_BUFQ_EMPTY)) tls_c->flags &= ~F_TLS_CON_WR_WANTS_RD; if (unlikely(flush_flags & F_BUFQ_ERROR_FLUSH)) err_src = "TLS write:"; } if (likely(ssl_error == SSL_ERROR_NONE)) { if (unlikely(tls_c->state == S_TLS_CONNECTING)) { n = tls_connect(c, &ssl_error); TLS_RD_TRACE("(%p, %p) tls_connect() => %d (err=%d)\n", c, flags, n, ssl_error); if (unlikely(n>=1)) { n = SSL_read(ssl, r->pos, bytes_free); } else { /* tls_connect failed/needs more IO */ if (unlikely(n < 0 && ssl_error == SSL_ERROR_NONE)) { lock_release(&c->write_lock); goto error; } err_src = "TLS connect:"; goto ssl_read_skipped; } } else if (unlikely(tls_c->state == S_TLS_ACCEPTING)) { n = tls_accept(c, &ssl_error); TLS_RD_TRACE("(%p, %p) tls_accept() => %d (err=%d)\n", c, flags, n, ssl_error); if (unlikely(n>=1)) { n = SSL_read(ssl, r->pos, bytes_free); } else { /* tls_accept failed/needs more IO */ if (unlikely(n < 0 && ssl_error == SSL_ERROR_NONE)) { lock_release(&c->write_lock); goto error; } err_src = "TLS accept:"; goto ssl_read_skipped; } } else { /* if bytes in then decrypt read buffer into tcpconn req. buffer */ n = SSL_read(ssl, r->pos, bytes_free); } /** handle SSL_read() return. * There are 3 main cases, each with several sub-cases, depending * on whether or not the output buffer was filled, if there * is still unconsumed input data in the input buffer (rd) * and if there is "cached" data in the internal openssl * buffers. * 0. error (n<=0): * SSL_ERROR_WANT_READ - input data fully * consumed, no more returnable cached data inside openssl * => exit. * SSL_ERROR_WANT_WRITE - should never happen (the write * buffer is big enough to handle any re-negociation). * SSL_ERROR_ZERO_RETURN - ssl level shutdown => exit. * other errors are unexpected. * 1. output buffer filled (n == bytes_free): * 1i. - still unconsumed input, nothing buffered by openssl * 1ip. - unconsumed input + buffered data by openssl (pending on the next SSL_read). * 1p. - completely consumed input, buffered data internally * by openssl (pending). * Likely to happen, about the only case when * SSL_pending() could be used (but only if readahead=0). * 1f. - consumed input, no buffered data. * 2. output buffer not fully filled (n < bytes_free): * 2i. - still unconsumed input, nothing buffered by openssl. * This can appear if SSL readahead is 0 (SSL_read() * tries to get only 1 record from the input). * 2ip. - unconsumed input and buffered data by openssl. * Unlikely to happen (e.g. readahead is 1, more * records are buffered internally by openssl, but * there was not enough space for buffering the whole * input). * 2p - consumed input, but buffered data by openssl. * It happens especially when readahead is 1. * 2f. - consumed input, no buffered data. * * One should repeat SSL_read() until and error is detected * (0*) or the input and internal ssl buffers are fully consumed * (1f or 2f). However in general is not possible to see if * SSL_read() could return more data. SSL_pending() has very * limited usability (basically it would return !=0 only if there * was no enough space in the output buffer and only if this did * not happen at a record boundary). * The solution is to repeat SSL_read() until error or until * the output buffer is filled (0* or 1*). * In the later case, this whole function should be called again * once there is more output space (set RD_CONN_REPEAT_READ). */ if (unlikely(tls_c->flags & F_TLS_CON_RENEGOTIATION)) { /* Fix CVE-2009-3555 - disable renegotiation if started by client * - simulate SSL EOF to force close connection*/ tls_dbg = cfg_get(tls, tls_cfg, debug); LOG(tls_dbg, "Reading on a renegotiation of connection (n:%d) (%d)\n", n, SSL_get_error(ssl, n)); err_src = "TLS R-N read:"; ssl_error = SSL_ERROR_ZERO_RETURN; } else { if (unlikely(n <= 0)) { ssl_error = SSL_get_error(ssl, n); err_src = "TLS read:"; /* errors handled below, outside the lock */ } else { ssl_error = SSL_ERROR_NONE; r->pos += n; ssl_read += n; bytes_free -=n; } } TLS_RD_TRACE("(%p, %p) SSL_read() => %d (err=%d) ssl_read=%d" " *flags=%d tls_c->flags=%d\n", c, flags, n, ssl_error, ssl_read, *flags, tls_c->flags); ssl_read_skipped: ; } if (unlikely(wr.used != 0 && ssl_error != SSL_ERROR_ZERO_RETURN)) { TLS_RD_TRACE("(%p, %p) tcpconn_send_unsafe %d bytes\n", c, flags, wr.used); /* something was written and it's not ssl EOF*/ if (unlikely(tcpconn_send_unsafe(c->fd, c, (char*)wr.buf, wr.used, c->send_flags) < 0)) { tls_set_mbufs(c, 0, 0); lock_release(&c->write_lock); TLS_RD_TRACE("(%p, %p) tcpconn_send_unsafe error\n", c, flags); goto error_send; } } /* quickly catch bugs: segfault if accessed and not set */ tls_set_mbufs(c, 0, 0); lock_release(&c->write_lock); switch(ssl_error) { case SSL_ERROR_NONE: if (unlikely(n < 0)) { BUG("unexpected SSL_ERROR_NONE for n=%d\n", n); goto error; } break; case SSL_ERROR_ZERO_RETURN: /* SSL EOF */ TLS_RD_TRACE("(%p, %p) SSL EOF (fd=%d)\n", c, flags, c->fd); goto ssl_eof; case SSL_ERROR_WANT_READ: TLS_RD_TRACE("(%p, %p) SSL_ERROR_WANT_READ *flags=%d\n", c, flags, *flags); /* needs to read more data */ if (unlikely(rd.pos != rd.used)) { /* data still in the read buffer */ BUG("SSL_ERROR_WANT_READ but data still in" " the rbio (%p, %d bytes at %d)\n", rd.buf, rd.used - rd.pos, rd.pos); goto bug; } if (unlikely((*flags & (RD_CONN_EOF | RD_CONN_SHORT_READ)) == 0) && bytes_free){ /* there might still be data to read and there is space to decrypt it in tcp_req (no byte has been written into tcp_req in this case) */ TLS_RD_TRACE("(%p, %p) redo read *flags=%d bytes_free=%d\n", c, flags, *flags, bytes_free); goto redo_read; } goto end; /* no more data to read */ case SSL_ERROR_WANT_WRITE: if (wr.used) { /* something was written => buffer not big enough to hold everything => reset buffer & retry (the tcp_write already happened if we are here) */ TLS_RD_TRACE("(%p) SSL_ERROR_WANT_WRITE partial write" " (written %d), retrying\n", c, wr.used); goto continue_ssl_read; } /* else write buffer too small, nothing written */ BUG("write buffer too small (%d/%d bytes)\n", wr.used, wr.size); goto bug; case SSL_ERROR_SSL: /* protocol level error */ TLS_ERR(err_src); goto error; #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*0.9.7*/ case SSL_ERROR_WANT_CONNECT: /* only if the underlying BIO is not yet connected and the call would block in connect(). (not possible in our case) */ BUG("unexpected SSL_ERROR_WANT_CONNECT\n"); goto bug; case SSL_ERROR_WANT_ACCEPT: /* only if the underlying BIO is not yet connected and call would block in accept() (not possible in our case) */ BUG("unexpected SSL_ERROR_WANT_ACCEPT\n"); goto bug; #endif case SSL_ERROR_WANT_X509_LOOKUP: /* can only appear on client application and it indicates that an installed client cert. callback should be called again (it returned < 0 indicated that it wants to be called later). Not possible in our case */ BUG("unsupported SSL_ERROR_WANT_X509_LOOKUP"); goto bug; case SSL_ERROR_SYSCALL: TLS_ERR_RET(x, err_src); if (!x) { if (n == 0) { WARN("Unexpected EOF\n"); } else /* should never happen */ BUG("IO error (%d) %s\n", errno, strerror(errno)); } goto error; default: TLS_ERR(err_src); BUG("unexpected SSL error %d\n", ssl_error); goto bug; } if (unlikely(n < 0)) { /* here n should always be >= 0 */ BUG("unexpected value (n = %d)\n", n); goto bug; } if (unlikely(rd.pos != rd.used)) { /* encrypted data still in the read buffer (SSL_read() did not consume all of it) */ if (unlikely(n < 0)) /* here n should always be >= 0 */ BUG("unexpected value (n = %d)\n", n); else { if (unlikely(bytes_free != 0)) { /* 2i or 2ip: unconsumed input and output buffer not filled => retry ssl read (SSL_read() will read will stop at record boundaries, unless readahead==1). No tcp_read() is attempted, since that would reset the current no-yet-consumed input data. */ TLS_RD_TRACE("(%p, %p) input not fully consumed =>" " retry SSL_read" " (pos: %d, remaining %d, output free %d)\n", c, flags, rd.pos, rd.used-rd.pos, bytes_free); goto continue_ssl_read; } /* 1i or 1ip: bytes_free == 0 (unconsumed input, but filled output buffer) => queue read data, and exit asking for repeating the call once there is some space in the output buffer. */ if (likely(!enc_rd_buf)) { TLS_RD_TRACE("(%p, %p) creating enc_rd_buf (for %d bytes)\n", c, flags, rd.used - rd.pos); enc_rd_buf = shm_malloc(sizeof(*enc_rd_buf) - sizeof(enc_rd_buf->buf) + rd.used - rd.pos); if (unlikely(enc_rd_buf == 0)) { ERR("memory allocation error (%d bytes requested)\n", (int)(sizeof(*enc_rd_buf) + sizeof(enc_rd_buf->buf) + rd.used - rd.pos)); goto error; } enc_rd_buf->pos = 0; enc_rd_buf->size = rd.used - rd.pos; memcpy(enc_rd_buf->buf, rd.buf + rd.pos, enc_rd_buf->size); } else if ((enc_rd_buf->buf + enc_rd_buf->pos) == rd.buf) { TLS_RD_TRACE("(%p, %p) enc_rd_buf already in use," " updating pos %d\n", c, flags, enc_rd_buf->pos); enc_rd_buf->pos += rd.pos; } else { BUG("enc_rd_buf->buf = %p, pos = %d, rd_buf.buf = %p\n", enc_rd_buf->buf, enc_rd_buf->pos, rd.buf); goto bug; } if (unlikely(tls_c->enc_rd_buf)) BUG("tls_c->enc_rd_buf!=0 (%p)\n", tls_c->enc_rd_buf); /* there can't be 2 reads in parallel, so no locking is needed here */ tls_c->enc_rd_buf = enc_rd_buf; enc_rd_buf = 0; *flags |= RD_CONN_REPEAT_READ; } } else if (bytes_free != 0) { /* 2f or 2p: input fully consumed (rd.pos == rd.used), output buffer not filled, still possible to have pending data buffered by openssl */ if (unlikely((*flags & (RD_CONN_EOF|RD_CONN_SHORT_READ)) == 0)) { /* still space in the tcp unenc. req. buffer, no SSL_read error, not a short read and not an EOF (possible more data in the socket buffer) => try a new tcp read too */ TLS_RD_TRACE("(%p, %p) retry read (still space and no short" " tcp read: %d)\n", c, flags, *flags); goto redo_read; } else { /* don't tcp_read() anymore, but there might still be data buffered internally by openssl (e.g. if readahead==1) => retry SSL_read() with the current full input buffer (if no more internally SSL buffered data => WANT_READ => exit). */ TLS_RD_TRACE("(%p, %p) retry SSL_read only (*flags =%d)\n", c, flags, *flags); goto continue_ssl_read; } } else { /* 1p or 1f: rd.pos == rd.used && bytes_free == 0 (input fully consumed && output buffer filled) */ /* ask for a repeat when there is more buffer space (there is no definitive way to know if ssl doesn't still have some internal buffered data until we get WANT_READ, see SSL_read() comment above) */ *flags |= RD_CONN_REPEAT_READ; TLS_RD_TRACE("(%p, %p) output filled, exit asking to be called again" " (*flags =%d)\n", c, flags, *flags); } end: if (enc_rd_buf) shm_free(enc_rd_buf); TLS_RD_TRACE("(%p, %p) end => %d (*flags=%d)\n", c, flags, ssl_read, *flags); return ssl_read; ssl_eof: /* behave as an EOF would have been received at the tcp level */ if (enc_rd_buf) shm_free(enc_rd_buf); c->state = S_CONN_EOF; *flags |= RD_CONN_EOF; TLS_RD_TRACE("(%p, %p) end EOF => %d (*flags=%d)\n", c, flags, ssl_read, *flags); return ssl_read; error_send: error: bug: if (enc_rd_buf) shm_free(enc_rd_buf); r->error=TCP_READ_ERROR; TLS_RD_TRACE("(%p, %p) end error => %d (*flags=%d)\n", c, flags, ssl_read, *flags); return -1; }