int ProxyConn::connectSSL() { if (!m_ssl.getSSL()) { m_ssl.setSSL(getSslConn()); if (!m_ssl.getSSL()) return LS_FAIL; m_ssl.setfd(getfd()); HttpReq *pReq = getConnector()->getHttpSession()->getReq(); char *pHostName; int hostLen = pReq->getNewHostLen(); if (hostLen > 0) pHostName = (char *)pReq->getNewHost(); else { pHostName = (char *)pReq->getHeader(HttpHeader::H_HOST); hostLen = pReq->getHeaderLen(HttpHeader::H_HOST); } if (pHostName) { char ch = *(pHostName + hostLen); *(pHostName + hostLen) = 0; m_ssl.setTlsExtHostName(pHostName); *(pHostName + hostLen) = ch; } } int ret = m_ssl.connect(); switch (ret) { case 0: setSSLAgain(); break; case 1: LS_DBG_L(this, "[SSL] connected!"); break; default: if (errno == EIO) LS_DBG_L(this, "SSL_connect() failed!: %s ", SslError().what()); break; } return ret; }
int RequestVars::getSubstValue( const SubstItem * pItem, HttpSession *pSession, char * &pValue, int bufLen ) { HttpReq * pReq = pSession->getReq(); int type = pItem->getType(); int i; if ( type < REF_STRING ) { pValue = (char *)pReq->getHeader( type ); if ( *pValue ) return pReq->getHeaderLen( type ); else return 0; } switch( type ) { case REF_STRING: pValue = (char *)pItem->getStr()->c_str(); return pItem->getStr()->len(); case REF_ENV: pValue = (char *)RequestVars::getEnv( pSession, pItem->getStr()->c_str(), pItem->getStr()->len(), i ); if ( !pValue ) { i = 0; } return i; case REF_HTTP_HEADER: pValue = (char *)pReq->getHeader( pItem->getStr()->c_str(), pItem->getStr()->len(), i ); if ( !pValue ) i = 0; return i; default: return RequestVars::getReqVar( pSession, type, pValue, bufLen ); } return 0; }
int RewriteEngine::getSubstValue( const RewriteSubstItem * pItem, HttpConnection *pConn, char * &pValue, int bufLen ) { HttpReq * pReq = pConn->getReq(); int type = pItem->getType(); int i; if ( type < REF_STRING ) { pValue = (char *)pReq->getHeader( type ); if ( *pValue ) return pReq->getHeaderLen( type ); else return 0; } /* if ( type >= REF_TIME ) { time_t t = time(NULL); struct tm *tm = localtime(&t); switch( type ) { case REF_TIME: i = snprintf( pValue, bufLen, "%04d%02d%02d%02d%02d%02d", tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); break; case REF_TIME_YEAR: i = snprintf( pValue, bufLen, "%04d", tm->tm_year + 1900); break; case REF_TIME_MON: i = snprintf( pValue, bufLen, "%02d", tm->tm_mon+1 ); break; case REF_TIME_DAY: i = snprintf( pValue, bufLen, "%02d", tm->tm_mday); break; case REF_TIME_HOUR: i = snprintf( pValue, bufLen, "%02d", tm->tm_hour); break; case REF_TIME_MIN: i = snprintf( pValue, bufLen, "%02d", tm->tm_min); break; case REF_TIME_SEC: i = snprintf( pValue, bufLen, "%02d", tm->tm_sec); break; case REF_TIME_WDAY: i = snprintf( pValue, bufLen, "%d", tm->tm_wday); break; default: return 0; } return i; } */ switch( type ) { case REF_STRING: pValue = (char *)pItem->getStr()->c_str(); return pItem->getStr()->len(); case REF_MAP: { MapRefItem * pRef = pItem->getMapRef(); int len = 1024; char achBuf[1024]; if ( buildString( pRef->getKeyFormat(), pConn, achBuf, len ) == NULL ) return 0; if ( (len = pRef->getMap()->lookup( achBuf, len, pValue, bufLen )) == -1 ) { if ( pRef->getDefaultFormat() ) { if ( buildString( pRef->getDefaultFormat(), pConn, pValue, bufLen ) == NULL ) return 0; len = bufLen; } else len = 0; } return len; } break; case REF_RULE_SUBSTR: return getSubstr( m_pSourceURL, m_ruleVec, m_ruleMatches, pItem->getIndex(), pValue, m_flag & RULE_FLAG_BR_ESCAPE ); case REF_COND_SUBSTR: return getSubstr( m_pCondBuf, m_condVec, m_condMatches, pItem->getIndex(), pValue, m_flag & RULE_FLAG_BR_ESCAPE ); case REF_ENV: pValue = (char *)RequestVars::getEnv( pConn, pItem->getStr()->c_str(), pItem->getStr()->len(), i ); if ( !pValue ) { i = 0; } return i; case REF_HTTP_HEADER: pValue = (char *)pReq->getHeader( pItem->getStr()->c_str(), pItem->getStr()->len(), i ); if ( !pValue ) i = 0; return i; case REF_REQUST_FN: case REF_SCRIPTFILENAME: if ( m_iScriptLen == -1 ) { pReq->checkPathInfo( m_pSourceURL, m_sourceURLLen, m_iFilePathLen, m_iScriptLen, m_iPathInfoLen, m_pContext ); } pValue = HttpGlobals::g_achBuf; //if ( m_pStrip ) // return m_iFilePathLen; //else // return m_iFilePathLen + m_iPathInfoLen; return m_iFilePathLen; case REF_PATH_INFO: if ( m_iScriptLen == -1 ) { pReq->checkPathInfo( m_pSourceURL, m_sourceURLLen, m_iFilePathLen, m_iScriptLen, m_iPathInfoLen, m_pContext ); } pValue = &HttpGlobals::g_achBuf[ m_iFilePathLen ]; return m_iPathInfoLen; case REF_SCRIPT_NAME: if ( m_iScriptLen == -1 ) { pReq->checkPathInfo( m_pSourceURL, m_sourceURLLen, m_iFilePathLen, m_iScriptLen, m_iPathInfoLen, m_pContext ); } pValue = (char *)pReq->getOrgReqURL(); return m_iScriptLen; case REF_REQ_URI: //in rewrite rule, this does not include Query String part if ( pReq->getRedirects() == 0 ) { pValue = (char *)pReq->getOrgReqURL(); return pReq->getOrgReqURILen(); } if ( m_pStrip ) { memmove( pValue, m_pStrip->c_str(), m_pStrip->len() ); memmove( pValue + m_pStrip->len(), m_pSourceURL, m_sourceURLLen ); return m_pStrip->len() + m_sourceURLLen; } //fall through case REF_CUR_URI: pValue = (char *)m_pSourceURL; return m_sourceURLLen; case REF_QUERY_STRING: pValue = (char *)m_pQS; return m_qsLen; default: return RequestVars::getReqVar( pConn, type, pValue, bufLen ); } return 0; }
int RequestVars::getReqVar( HttpSession *pSession, int type, char * &pValue, int bufLen) { HttpReq * pReq = pSession->getReq(); int i; char *p; if ( type < REF_STRING ) { pValue = (char *)pReq->getHeader( type ); if ( *pValue ) return pReq->getHeaderLen( type ); else return 0; } switch( type ) { case REF_REMOTE_HOST: //FIXME: use remote addr for now case REF_REMOTE_ADDR: pValue = (char *)pSession->getPeerAddrString(); return pSession->getPeerAddrStrLen(); case REF_REMOTE_PORT: return snprintf( pValue, bufLen, "%hu", pSession->getRemotePort() ); case REF_REMOTE_USER: pValue = (char *)pReq->getAuthUser(); return strlen( pValue ); case REF_REMOTE_IDENT: //do not support; return 0; case REF_REQ_METHOD: i = pReq->getMethod(); strcpy(pValue, HttpMethod::get( i ) ); return HttpMethod::getLen( i ); case REF_QUERY_STRING: pValue = (char *)pReq->getQueryString(); return pReq->getQueryStringLen(); case REF_AUTH_TYPE: //FIXME: hard code for now strncpy( pValue, "Basic", 6 ); return 5; case REF_REQUST_FN: case REF_SCRIPTFILENAME: case REF_SCRIPT_BASENAME: case REF_REQ_BASENAME: { const AutoStr2 * psTemp = pReq->getRealPath(); if ( psTemp ) { if (( type == REF_SCRIPT_BASENAME )|| ( type == REF_REQ_BASENAME )) { const char * pEnd = psTemp->c_str() + psTemp->len(); pValue = (char *)pEnd; while( pValue[-1] != '/' ) --pValue; return pEnd - pValue; } pValue = (char *)psTemp->c_str(); return psTemp->len(); } else return 0; } case REF_SCRIPT_UID: case REF_SCRIPT_GID: case REF_SCRIPT_USERNAME: case REF_SCRIPT_GRPNAME: case REF_SCRIPT_MODE: { const AutoStr2 * psTemp = pReq->getRealPath(); if ( psTemp ) { struct stat& st = pReq->getFileStat(); if ( type == REF_SCRIPT_UID ) { return snprintf( pValue, bufLen, "%d", st.st_uid ); } else if ( type == REF_SCRIPT_GID ) { return snprintf( pValue, bufLen, "%d", st.st_gid ); } else if ( type == REF_SCRIPT_MODE ) { return snprintf( pValue, bufLen, "%o", st.st_mode ); } else if ( type == REF_SCRIPT_USERNAME ) { struct passwd * pw = getpwuid( st.st_uid ); if ( pw ) return snprintf( pValue, bufLen, "%s", pw->pw_name ); } else { struct group * gr = getgrgid( st.st_gid ); if ( gr ) return snprintf( pValue, bufLen, "%s", gr->gr_name ); } } return 0; } case REF_PATH_INFO: pValue = (char *)pReq->getPathInfo(); return pReq->getPathInfoLen(); case REF_SCRIPT_NAME: pValue = (char *)pReq->getURI(); return pReq->getScriptNameLen(); case REF_SCRIPT_URI: p = pValue; if ( pSession->isSSL() ) { strcpy( p, "https://" ); p += 8; } else { strcpy( p, "http://" ); p += 7; } i = pReq->getHeaderLen( HttpHeader::H_HOST ); memmove( p, pReq->getHeader( HttpHeader::H_HOST ), i ); p += i; i = pReq->getOrgURILen(); memmove( p, pReq->getOrgURI(), i ); p += i; return p - pValue; case REF_ORG_REQ_URI: pValue = (char *)pReq->getOrgReqURL(); return pReq->getOrgReqURILen(); case REF_DOCUMENT_URI: return pReq->getDecodedOrgReqURI( pValue ); case REF_REQ_URI: pValue = (char *)pReq->getOrgReqURL(); return pReq->getOrgReqURLLen(); case REF_DOC_ROOT: pValue = (char *)pReq->getDocRoot()->c_str(); return pReq->getDocRoot()->len()-1; case REF_SERVER_ADMIN: if ( pReq->getVHost() ) { const AutoStr2 * pEmail = pReq->getVHost()->getAdminEmails(); pValue = (char *)pEmail->c_str(); return pEmail->len(); } return 0; case REF_VH_CNAME: if ( pReq->getVHost() ) { pValue = (char *)pReq->getVHost()->getVhName( i ); return i; } return 0; case REF_SERVER_NAME: pValue = (char *)pReq->getHostStr(); return pReq->getHostStrLen(); case REF_SERVER_ADDR: pValue = (char *)pReq->getLocalAddrStr()->c_str(); return pReq->getLocalAddrStr()->len(); case REF_SERVER_PORT: pValue = (char *)pReq->getPortStr().c_str(); return pReq->getPortStr().len(); case REF_SERVER_PROTO: i = pReq->getVersion(); pValue = (char *)HttpVer::getVersionString( i ); return HttpVer::getVersionStringLen( i ); case REF_SERVER_SOFT: pValue = (char *)HttpServerVersion::getVersion(); return HttpServerVersion::getVersionLen(); case REF_REQ_LINE: pValue = (char *)pReq->getOrgReqLine(); return pReq->getOrgReqLineLen(); case REF_IS_SUBREQ: strcpy( pValue, "false" ); return 5; case REF_RESP_BYTES: i = StringTool::str_off_t( pValue, bufLen, pSession->getResp()->getBodySent() ); return i; //case REF_COOKIE_VAL //case REF_STRFTIME 155 //case REF_CONN_STATE: case REF_REQ_TIME_MS: { struct timeval tv; gettimeofday( &tv, NULL ); DateTime::s_curTime = tv.tv_sec; DateTime::s_curTimeUs = tv.tv_usec; long lReqTime = (DateTime::s_curTime - pSession->getReqTime())*1000000 + (DateTime::s_curTimeUs - pSession->getReqTimeUs()); i = snprintf( pValue, bufLen, "%ld", lReqTime ); return i; } case REF_REQ_TIME_SEC: i = snprintf( pValue, bufLen, "%ld", (DateTime::s_curTime - pSession->getReqTime()) ); return i; case REF_DUMMY: return 0; case REF_PID: i = snprintf( pValue, bufLen, "%d", getpid() ); return i; case REF_STATUS_CODE: memmove( pValue, HttpStatusCode::getCodeString( pReq->getStatusCode() )+1, 3 ); pValue[3] = 0; return 3; case REF_CUR_URI: pValue = (char *)pReq->getURI(); i = pReq->getURILen(); return i; case REF_BYTES_IN: i = StringTool::str_off_t( pValue, bufLen, pSession->getBytesRecv() ); return i; case REF_BYTES_OUT: i = StringTool::str_off_t( pValue, bufLen, pSession->getBytesSent() ); return i; case REF_HTTPS: i = snprintf( pValue, bufLen, "%s", pSession->isSSL()?"on":"off" ); return i; case REF_DATE_GMT: case REF_DATE_LOCAL: case REF_LAST_MODIFIED: { time_t mtime = DateTime::s_curTime; struct tm * tm; if ( type == REF_LAST_MODIFIED ) { if ( pReq->getSSIRuntime() && pReq->getSSIRuntime()->getCurrentScript() ) { mtime = pReq->getSSIRuntime()->getCurrentScript()->getLastMod(); } else mtime = pReq->getFileStat().st_mtime; } if ( type == REF_DATE_GMT ) tm = gmtime( &mtime ); else tm = localtime( &mtime ); char fmt[101]; memccpy( fmt, pValue, 0, 100 ); fmt[100] = 0; i = strftime( pValue, bufLen, fmt, tm ); return i; } case REF_DOCUMENT_NAME: { const AutoStr2 * psTemp = pReq->getRealPath(); if ( psTemp ) { pValue = (char *)psTemp->c_str() + psTemp->len(); while( *(pValue -1) != '/' ) --pValue; return psTemp->c_str() + psTemp->len() - pValue; } else return 0; } case REF_QS_UNESCAPED: { int qsLen = pReq->getQueryStringLen(); const char * pQS = pReq->getQueryString(); if ( qsLen > 0 ) { qsLen = HttpUtil::unescape_n( pQS, qsLen, pValue, bufLen ); } return qsLen; } case REF_RESP_CONTENT_TYPE: i = 0; pValue = (char*)pSession->getResp()->getContentTypeHeader( i ); return i; case REF_RESP_CONTENT_LENGTH: { off_t l = pSession->getResp()->getContentLen(); if ( l <= 0 ) l = 0; i = StringTool::str_off_t( pValue, bufLen, l ); return i; } case REF_RESP_BODY: return 0; default: if ( type >= REF_TIME ) { time_t t = time(NULL); struct tm *tm = localtime(&t); switch( type ) { case REF_TIME: i = snprintf( pValue, bufLen, "%04d%02d%02d%02d%02d%02d", tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); break; case REF_TIME_YEAR: i = snprintf( pValue, bufLen, "%04d", tm->tm_year + 1900); break; case REF_TIME_MON: i = snprintf( pValue, bufLen, "%02d", tm->tm_mon+1 ); break; case REF_TIME_DAY: i = snprintf( pValue, bufLen, "%02d", tm->tm_mday); break; case REF_TIME_HOUR: i = snprintf( pValue, bufLen, "%02d", tm->tm_hour); break; case REF_TIME_MIN: i = snprintf( pValue, bufLen, "%02d", tm->tm_min); break; case REF_TIME_SEC: i = snprintf( pValue, bufLen, "%02d", tm->tm_sec); break; case REF_TIME_WDAY: i = snprintf( pValue, bufLen, "%d", tm->tm_wday); break; default: return 0; } return i; } return 0; } return 0; }
void AccessLog::log( HttpConnection* pConn ) { int n; HttpReq* pReq = pConn->getReq(); HttpResp* pResp = pConn->getResp(); const char * pUser = pReq->getAuthUser(); long contentWritten = pResp->getBodySent(); const ClientInfo * pInfo = pConn->getClientInfo(); const char * pAddr = pInfo->getHostName(); pResp->needLogAccess( 0 ); if ( m_iPipedLog ) { if ( !m_pManager ) return; m_pAppender = m_pManager->getAppender(); if ( !m_pAppender ) return; } if ( m_pCustomFormat ) return customLog( pConn ); if (( pAddr )&&( *pAddr )) { n = pInfo->getHostNameLen(); } else { pAddr = pInfo->getAddrString(); n = pInfo->getAddrStrLen(); } m_buf.appendNoCheck( pAddr, n ); if ( ! *pUser ) { m_buf.appendNoCheck( " - - ", 5 ); } else { n = safe_snprintf( m_buf.end(), 70, " - \"%s\" ", pUser ); m_buf.used( n ); } DateTime::getLogTime( pConn->getReqTime(), m_buf.end() ); m_buf.used( 30 ); n = pReq->getOrgReqLineLen(); char * pOrgReqLine = (char *)pReq->getOrgReqLine(); if ( pReq->getVersion() == HTTP_1_0 ) *(pOrgReqLine + n - 1) = '0'; if (( n > 4096 )||( m_buf.available() < 100 + n )) { flush(); m_pAppender->append( pOrgReqLine, n ); } else m_buf.appendNoCheck(pOrgReqLine, n ); m_buf.append( '"' ); m_buf.appendNoCheck( HttpStatusCode::getCodeString( pReq->getStatusCode() ), 5 ); if ( contentWritten == 0 ) { m_buf.append( '-' ); } else { n = safe_snprintf( m_buf.end(), 20, "%ld", contentWritten ); m_buf.used( n ); } if ( getAccessLogHeader() & LOG_REFERER ) { m_buf.append( ' ' ); appendStr( pReq->getHeader( HttpHeader::H_REFERER ), pReq->getHeaderLen( HttpHeader::H_REFERER )); } if ( getAccessLogHeader() & LOG_USERAGENT ) { m_buf.append( ' ' ); appendStr( pReq->getHeader( HttpHeader::H_USERAGENT), pReq->getHeaderLen( HttpHeader::H_USERAGENT) ); } if ( getAccessLogHeader() & LOG_VHOST ) { m_buf.append( ' ' ); appendStr( pReq->getHeader( HttpHeader::H_HOST ), pReq->getHeaderLen( HttpHeader::H_HOST ) ); } m_buf.append( '\n' ); if (( m_buf.available() < MAX_LOG_LINE_LEN ) ||!asyncAccessLog() ) { flush(); } }
int ProxyConn::sendReqHeader() { m_iovec.clear(); HttpSession *pSession = getConnector()->getHttpSession(); HttpReq *pReq = pSession->getReq(); //remove the trailing "\r\n" before adding our headers const char *pBegin = pReq->getOrgReqLine(); m_iTotalPending = pReq->getHttpHeaderLen(); int newReqLineLen = 0; int headerLen = 17; char *pExtraHeader = &m_extraHeader[23]; const char *pForward = pReq->getHeader(HttpHeader::H_X_FORWARDED_FOR); int len; if (*pForward != '\0') { len = pReq->getHeaderLen(HttpHeader::H_X_FORWARDED_FOR); if (len > 160) len = 160; memmove(&pExtraHeader[headerLen], pForward, len); headerLen += len; pExtraHeader[headerLen++] = ','; } //add "X-Forwarded-For" header memmove(&pExtraHeader[headerLen], pSession->getPeerAddrString(), pSession->getPeerAddrStrLen()); headerLen += pSession->getPeerAddrStrLen(); pExtraHeader[headerLen++] = '\r'; pExtraHeader[headerLen++] = '\n'; #if 1 //always set "Accept-Encoding" header to "gzip" char *pAE = (char *)pReq->getHeader(HttpHeader::H_ACC_ENCODING); if (*pAE) { int len = pReq->getHeaderLen(HttpHeader::H_ACC_ENCODING); if (len >= 4) { memmove(pAE, "gzip", 4); memset(pAE + 4, ' ', len - 4); } } else { pExtraHeader = m_extraHeader; headerLen += 23; } #endif if (*(pBegin + --m_iTotalPending - 1) == '\r') --m_iTotalPending; if (*pForward) { if ((pBegin + m_iTotalPending) - (pForward + pReq->getHeaderLen(HttpHeader::H_X_FORWARDED_FOR)) == 2) { const char *p = pForward -= 16; while (*(p - 1) != '\n') --p; m_iTotalPending = p - pBegin; } } //reconstruct request line if URL has been rewritten if (pReq->getRedirects() > 0) { const char *pReqLine = pReq->encodeReqLine(newReqLineLen); if (newReqLineLen > 0) { m_iovec.append(pReqLine, newReqLineLen); pBegin += pReq->getOrgReqLineLen() - 9; m_iTotalPending -= pReq->getOrgReqLineLen() - 9; } } int newHostLen = pReq->getNewHostLen(); char *pHost = (char *)pReq->getHeader(HttpHeader::H_HOST); int hostLen = pReq->getHeaderLen(HttpHeader::H_HOST); if (newHostLen > 0) { if (*pHost) { m_iovec.append(pBegin, pHost - pBegin); m_iovec.append(pReq->getNewHost(), newHostLen); m_iovec.append(pHost + hostLen, pBegin + m_iTotalPending - pHost - hostLen); m_iTotalPending += (newHostLen - hostLen); } else { m_iovec.append(pBegin, m_iTotalPending); m_iovec.append("Host: ", 6); m_iovec.append(pReq->getNewHost(), newHostLen); m_iovec.append("\r\n", 2); m_iTotalPending += newHostLen + 8; } } else m_iovec.append(pBegin, m_iTotalPending); m_iTotalPending += newReqLineLen; if (hostLen) { m_iovec.append(s_achForwardHost, sizeof(s_achForwardHost) - 1); m_iovec.append(pHost, hostLen); m_iovec.append("\r\n", 2); m_iTotalPending += hostLen + sizeof(s_achForwardHost) + 1 ; } if (pSession->isSSL()) { m_iovec.append(s_achForwardHttps, sizeof(s_achForwardHttps) - 1); m_iTotalPending += sizeof(s_achForwardHttps) - 1; } //if ( headerLen > 0 ) { pExtraHeader[headerLen++] = '\r'; pExtraHeader[headerLen++] = '\n'; m_iovec.append(pExtraHeader, headerLen); m_iTotalPending += headerLen; } m_iReqHeaderSize = m_iTotalPending; m_iReqBodySize = pReq->getContentFinished(); setInProcess(1); return 1; }