static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end) { unsigned int name_len, val_len; while (p < end) { name_len = *p++; if (UNEXPECTED(name_len >= 128)) { if (UNEXPECTED(p + 3 >= end)) return 0; name_len = ((name_len & 0x7f) << 24); name_len |= (*p++ << 16); name_len |= (*p++ << 8); name_len |= *p++; } if (UNEXPECTED(p >= end)) return 0; val_len = *p++; if (UNEXPECTED(val_len >= 128)) { if (UNEXPECTED(p + 3 >= end)) return 0; val_len = ((val_len & 0x7f) << 24); val_len |= (*p++ << 16); val_len |= (*p++ << 8); val_len |= *p++; } if (UNEXPECTED(name_len + val_len > (unsigned int) (end - p))) { /* Malformated request */ return 0; } fcgi_hash_set(&req->env, FCGI_HASH_FUNC(p, name_len), (char*)p, name_len, (char*)p + name_len, val_len); p += name_len + val_len; } return 1; }
static int fcgi_read_request(fcgi_request *req) { fcgi_header hdr; int len, padding; unsigned char buf[FCGI_MAX_LENGTH+8]; req->keep = 0; req->closed = 0; req->in_len = 0; req->out_hdr = NULL; req->out_pos = req->out_buf; req->has_env = 1; if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; while (hdr.type == FCGI_STDIN && len == 0) { if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; } if (len + padding > FCGI_MAX_LENGTH) { return 0; } req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { if (safe_read(req, buf, len+padding) != len+padding) { return 0; } req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); #ifdef TCP_NODELAY if (req->keep && req->tcp && !req->nodelay) { # ifdef _WIN32 BOOL on = 1; # else int on = 1; # endif setsockopt(req->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)); req->nodelay = 1; } #endif switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { case FCGI_RESPONDER: fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1); break; case FCGI_AUTHORIZER: fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "AUTHORIZER", sizeof("AUTHORIZER")-1); break; case FCGI_FILTER: fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "FILTER", sizeof("FILTER")-1); break; default: return 0; } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; while (hdr.type == FCGI_PARAMS && len > 0) { if (len + padding > FCGI_MAX_LENGTH) { return 0; } if (safe_read(req, buf, len+padding) != len+padding) { req->keep = 0; return 0; } if (!fcgi_get_params(req, buf, buf+len)) { req->keep = 0; return 0; } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { req->keep = 0; return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; } } else if (hdr.type == FCGI_GET_VALUES) { unsigned char *p = buf + sizeof(fcgi_header); zval *value; unsigned int zlen; fcgi_hash_bucket *q; if (safe_read(req, buf, len+padding) != len+padding) { req->keep = 0; return 0; } if (!fcgi_get_params(req, buf, buf+len)) { req->keep = 0; return 0; } q = req->env.list; while (q != NULL) { if ((value = zend_hash_str_find(&fcgi_mgmt_vars, q->var, q->var_len)) == NULL) { continue; } zlen = Z_STRLEN_P(value); if ((p + 4 + 4 + q->var_len + zlen) >= (buf + sizeof(buf))) { break; } if (q->var_len < 0x80) { *p++ = q->var_len; } else { *p++ = ((q->var_len >> 24) & 0xff) | 0x80; *p++ = (q->var_len >> 16) & 0xff; *p++ = (q->var_len >> 8) & 0xff; *p++ = q->var_len & 0xff; } if (zlen < 0x80) { *p++ = zlen; } else { *p++ = ((zlen >> 24) & 0xff) | 0x80; *p++ = (zlen >> 16) & 0xff; *p++ = (zlen >> 8) & 0xff; *p++ = zlen & 0xff; } memcpy(p, q->var, q->var_len); p += q->var_len; memcpy(p, Z_STRVAL_P(value), zlen); p += zlen; } len = p - buf - sizeof(fcgi_header); len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { req->keep = 0; return 0; } return 0; } else {