static apr_status_t socket_bucket_read(apr_bucket *a, const char **str, apr_size_t *len, apr_read_type_e block) { apr_socket_t *p = a->data; char *buf; apr_status_t rv; apr_interval_time_t timeout; if (block == APR_NONBLOCK_READ) { apr_socket_timeout_get(p, &timeout); apr_socket_timeout_set(p, 0); } *str = NULL; *len = APR_BUCKET_BUFF_SIZE; buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */ rv = apr_socket_recv(p, buf, len); if (block == APR_NONBLOCK_READ) { apr_socket_timeout_set(p, timeout); } if (rv != APR_SUCCESS && rv != APR_EOF) { apr_bucket_free(buf); return rv; } /* * If there's more to read we have to keep the rest of the socket * for later. XXX: Note that more complicated bucket types that * refer to data not in memory and must therefore have a read() * function similar to this one should be wary of copying this * code because if they have a destroy function they probably * want to migrate the bucket's subordinate structure from the * old bucket to a raw new one and adjust it as appropriate, * rather than destroying the old one and creating a completely * new bucket. * * Even if there is nothing more to read, don't close the socket here * as we have to use it to send any response :) We could shut it * down for reading, but there is no benefit to doing so. */ if (*len > 0) { apr_bucket_heap *h; /* Change the current bucket to refer to what we read */ a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free); h = a->data; h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */ *str = buf; APR_BUCKET_INSERT_AFTER(a, apr_bucket_socket_create(p, a->list)); } else { apr_bucket_free(buf); a = apr_bucket_immortal_make(a, "", 0); *str = a->data; } return APR_SUCCESS; }
apr_status_t winnt_insert_network_bucket(conn_rec *c, apr_bucket_brigade *bb, apr_socket_t *socket) { apr_bucket *e; winnt_conn_ctx_t *context = ap_get_module_config(c->conn_config, &mpm_winnt_module); if (context == NULL || (e = context->overlapped.Pointer) == NULL) return AP_DECLINED; /* seed the brigade with AcceptEx read heap bucket */ APR_BRIGADE_INSERT_HEAD(bb, e); /* also seed the brigade with the client socket. */ e = apr_bucket_socket_create(socket, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); return APR_SUCCESS; }
/* Read the OCSP response from the socket 'sd', using temporary memory * BIO 'bio', and return the decoded OCSP response object, or NULL on * error. */ static OCSP_RESPONSE *read_response(apr_socket_t *sd, BIO *bio, conn_rec *c, apr_pool_t *p) { apr_bucket_brigade *bb, *tmpbb; OCSP_RESPONSE *response; char *line; apr_size_t count; apr_int64_t code; /* Using brigades for response parsing is much simpler than using * apr_socket_* directly. */ bb = apr_brigade_create(p, c->bucket_alloc); tmpbb = apr_brigade_create(p, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_socket_create(sd, c->bucket_alloc)); line = get_line(tmpbb, bb, c, p); if (!line || strncmp(line, "HTTP/", 5) || (line = ap_strchr(line, ' ')) == NULL || (code = apr_atoi64(++line)) < 200 || code > 299) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01980) "bad response from OCSP server: %s", line ? line : "(none)"); return NULL; } /* Read till end of headers; don't have to even bother parsing the * Content-Length since the server is obliged to close the * connection after the response anyway for HTTP/1.0. */ count = 0; while ((line = get_line(tmpbb, bb, c, p)) != NULL && line[0] && ++count < MAX_HEADERS) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01981) "OCSP response header: %s", line); } if (count == MAX_HEADERS) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01982) "could not read response headers from OCSP server, " "exceeded maximum count (%u)", MAX_HEADERS); return NULL; } else if (!line) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01983) "could not read response header from OCSP server"); return NULL; } /* Read the response body into the memory BIO. */ count = 0; while (!APR_BRIGADE_EMPTY(bb)) { const char *data; apr_size_t len; apr_status_t rv; apr_bucket *e = APR_BRIGADE_FIRST(bb); rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ); if (rv == APR_EOF) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01984) "OCSP response: got EOF"); break; } if (rv != APR_SUCCESS) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01985) "error reading response from OCSP server"); return NULL; } if (len == 0) { /* Ignore zero-length buckets (possible side-effect of * line splitting). */ apr_bucket_delete(e); continue; } count += len; if (count > MAX_CONTENT) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01986) "OCSP response size exceeds %u byte limit", MAX_CONTENT); return NULL; } ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01987) "OCSP response: got %" APR_SIZE_T_FMT " bytes, %" APR_SIZE_T_FMT " total", len, count); BIO_write(bio, data, (int)len); apr_bucket_delete(e); } apr_brigade_destroy(bb); apr_brigade_destroy(tmpbb); /* Finally decode the OCSP response from what's stored in the * bio. */ response = d2i_OCSP_RESPONSE_bio(bio, NULL); if (response == NULL) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01988) "failed to decode OCSP response data"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, mySrvFromConn(c)); } return response; }
int ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes) { apr_bucket *e; apr_status_t rv; core_net_rec *net = f->ctx; core_ctx_t *ctx = net->in_ctx; const char *str; apr_size_t len; if (mode == AP_MODE_INIT) { /* * this mode is for filters that might need to 'initialize' * a connection before reading request data from a client. * NNTP over SSL for example needs to handshake before the * server sends the welcome message. * such filters would have changed the mode before this point * is reached. however, protocol modules such as NNTP should * not need to know anything about SSL. given the example, if * SSL is not in the filter chain, AP_MODE_INIT is a noop. */ return APR_SUCCESS; } if (!ctx) { ctx = apr_pcalloc(f->c->pool, sizeof(*ctx)); ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc); ctx->tmpbb = apr_brigade_create(ctx->b->p, ctx->b->bucket_alloc); /* seed the brigade with the client socket. */ e = apr_bucket_socket_create(net->client_socket, f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->b, e); net->in_ctx = ctx; } else if (APR_BRIGADE_EMPTY(ctx->b)) { return APR_EOF; } /* ### This is bad. */ BRIGADE_NORMALIZE(ctx->b); /* check for empty brigade again *AFTER* BRIGADE_NORMALIZE() * If we have lost our socket bucket (see above), we are EOF. * * Ideally, this should be returning SUCCESS with EOS bucket, but * some higher-up APIs (spec. read_request_line via ap_rgetline) * want an error code. */ if (APR_BRIGADE_EMPTY(ctx->b)) { return APR_EOF; } if (mode == AP_MODE_GETLINE) { /* we are reading a single LF line, e.g. the HTTP headers */ rv = apr_brigade_split_line(b, ctx->b, block, HUGE_STRING_LEN); /* We should treat EAGAIN here the same as we do for EOF (brigade is * empty). We do this by returning whatever we have read. This may * or may not be bogus, but is consistent (for now) with EOF logic. */ if (APR_STATUS_IS_EAGAIN(rv)) { rv = APR_SUCCESS; } return rv; } /* ### AP_MODE_PEEK is a horrific name for this mode because we also * eat any CRLFs that we see. That's not the obvious intention of * this mode. Determine whether anyone actually uses this or not. */ if (mode == AP_MODE_EATCRLF) { apr_bucket *e; const char *c; /* The purpose of this loop is to ignore any CRLF (or LF) at the end * of a request. Many browsers send extra lines at the end of POST * requests. We use the PEEK method to determine if there is more * data on the socket, so that we know if we should delay sending the * end of one request until we have served the second request in a * pipelined situation. We don't want to actually delay sending a * response if the server finds a CRLF (or LF), becuause that doesn't * mean that there is another request, just a blank line. */ while (1) { if (APR_BRIGADE_EMPTY(ctx->b)) return APR_EOF; e = APR_BRIGADE_FIRST(ctx->b); rv = apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ); if (rv != APR_SUCCESS) return rv; c = str; while (c < str + len) { if (*c == APR_ASCII_LF) c++; else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF) c += 2; else return APR_SUCCESS; } /* If we reach here, we were a bucket just full of CRLFs, so * just toss the bucket. */ /* FIXME: Is this the right thing to do in the core? */ apr_bucket_delete(e); } return APR_SUCCESS; } /* If mode is EXHAUSTIVE, we want to just read everything until the end * of the brigade, which in this case means the end of the socket. * To do this, we attach the brigade that has currently been setaside to * the brigade that was passed down, and send that brigade back. * * NOTE: This is VERY dangerous to use, and should only be done with * extreme caution. However, the Perchild MPM needs this feature * if it is ever going to work correctly again. With this, the Perchild * MPM can easily request the socket and all data that has been read, * which means that it can pass it to the correct child process. */ if (mode == AP_MODE_EXHAUSTIVE) { apr_bucket *e; /* Tack on any buckets that were set aside. */ APR_BRIGADE_CONCAT(b, ctx->b); /* Since we've just added all potential buckets (which will most * likely simply be the socket bucket) we know this is the end, * so tack on an EOS too. */ /* We have read until the brigade was empty, so we know that we * must be EOS. */ e = apr_bucket_eos_create(f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); return APR_SUCCESS; } /* read up to the amount they specified. */ if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE) { apr_bucket *e; AP_DEBUG_ASSERT(readbytes > 0); e = APR_BRIGADE_FIRST(ctx->b); rv = apr_bucket_read(e, &str, &len, block); if (APR_STATUS_IS_EAGAIN(rv)) { return APR_SUCCESS; } else if (rv != APR_SUCCESS) { return rv; } else if (block == APR_BLOCK_READ && len == 0) { /* We wanted to read some bytes in blocking mode. We read * 0 bytes. Hence, we now assume we are EOS. * * When we are in normal mode, return an EOS bucket to the * caller. * When we are in speculative mode, leave ctx->b empty, so * that the next call returns an EOS bucket. */ apr_bucket_delete(e); if (mode == AP_MODE_READBYTES) { e = apr_bucket_eos_create(f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); } return APR_SUCCESS; } /* We can only return at most what we read. */ if (len < readbytes) { readbytes = len; } rv = apr_brigade_partition(ctx->b, readbytes, &e); if (rv != APR_SUCCESS) { return rv; } /* Must do move before CONCAT */ brigade_move(ctx->b, ctx->tmpbb, e); if (mode == AP_MODE_READBYTES) { APR_BRIGADE_CONCAT(b, ctx->b); } else if (mode == AP_MODE_SPECULATIVE) { apr_bucket *copy_bucket; for (e = APR_BRIGADE_FIRST(ctx->b); e != APR_BRIGADE_SENTINEL(ctx->b); e = APR_BUCKET_NEXT(e)) { rv = apr_bucket_copy(e, ©_bucket); if (rv != APR_SUCCESS) { return rv; } APR_BRIGADE_INSERT_TAIL(b, copy_bucket); } } /* Take what was originally there and place it back on ctx->b */ APR_BRIGADE_CONCAT(ctx->b, ctx->tmpbb); } return APR_SUCCESS; }