int HttpCgiTool::buildCommonEnv( IEnv * pEnv, HttpConnection * pConn ) { int count = 0; HttpReq * pReq = pConn->getReq(); const char * pTemp; int n; int i; char buf[128]; pTemp = pReq->getAuthUser(); if ( *pTemp ) { //FIXME: only Basic is support now pEnv->add( "AUTH_TYPE", 9, "Basic", 5 ); pEnv->add( "REMOTE_USER", 11, pTemp, strlen( pTemp ) ); count += 2; } //ADD_ENV("REMOTE_IDENT", "" ) //FIXME: not supported yet //extensions of CGI/1.1 const AutoStr2 * pDocRoot = pReq->getDocRoot(); pEnv->add( "DOCUMENT_ROOT", 13, pDocRoot->c_str(), pDocRoot->len()-1 ); pEnv->add( "REMOTE_ADDR", 11, pConn->getPeerAddrString(), pConn->getPeerAddrStrLen() ); n = safe_snprintf( buf, 10, "%hu", pConn->getRemotePort() ); pEnv->add( "REMOTE_PORT", 11, buf, n ); n = pConn->getServerAddrStr( buf, 128 ); pEnv->add( "SERVER_ADDR", 11, buf, n ); pEnv->add( "SERVER_NAME", 11, pReq->getHostStr(), pReq->getHostStrLen() ); const AutoStr2 &sPort = pReq->getPortStr(); pEnv->add( "SERVER_PORT", 11, sPort.c_str(), sPort.len() ); pEnv->add( "REQUEST_URI", 11, pReq->getOrgReqURL(), pReq->getOrgReqURLLen() ); count += 7; n = pReq->getPathInfoLen(); if ( n > 0) { int m; char achTranslated[10240]; m = pReq->translatePath( pReq->getPathInfo(), n, achTranslated, sizeof( achTranslated ) ); if ( m != -1 ); { pEnv->add( "PATH_TRANSLATED", 15, achTranslated, m ); ++count; } pEnv->add( "PATH_INFO", 9, pReq->getPathInfo(), n); ++count; } //add geo IP env here if ( pReq->isGeoIpOn() ) { GeoInfo * pInfo = pConn->getClientInfo()->getGeoInfo(); if ( pInfo ) { pEnv->add( "GEOIP_ADDR", 10, pConn->getPeerAddrString(), pConn->getPeerAddrStrLen() ); count += pInfo->addGeoEnv( pEnv )+1; } } n = pReq->getEnvCount(); count += n; for( i = 0; i < n; ++i ) { const char * pKey; const char * pVal; int keyLen; int valLen; pKey = pReq->getEnvByIndex( i, keyLen, pVal, valLen ); if ( pKey ) pEnv->add( pKey, keyLen, pVal, valLen ); } if ( pConn->isSSL() ) { SSLConnection * pSSL = pConn->getSSL(); pEnv->add( "HTTPS", 5, "on", 2 ); const char * pVersion = pSSL->getVersion(); n = strlen( pVersion ); pEnv->add( "SSL_VERSION", 11, pVersion, n ); count += 2; SSL_SESSION * pSession = pSSL->getSession(); if ( pSession ) { int idLen = SSLConnection::getSessionIdLen( pSession ); n = idLen * 2; assert( n < (int)sizeof( buf ) ); StringTool::hexEncode( (char *)SSLConnection::getSessionId( pSession ), idLen, buf ); pEnv->add( "SSL_SESSION_ID", 14, buf, n ); ++count; } const SSL_CIPHER * pCipher = pSSL->getCurrentCipher(); if ( pCipher ) { const char * pName = pSSL->getCipherName(); n = strlen( pName ); pEnv->add( "SSL_CIPHER", 10, pName, n ); int algkeysize; int keysize = SSLConnection::getCipherBits( pCipher, &algkeysize ); n = safe_snprintf( buf, 20, "%d", keysize ); pEnv->add( "SSL_CIPHER_USEKEYSIZE", 21, buf, n ); n = safe_snprintf( buf, 20, "%d", algkeysize ); pEnv->add( "SSL_CIPHER_ALGKEYSIZE", 21, buf, n ); count += 3; } X509 * pClientCert = pSSL->getPeerCertificate(); if ( pClientCert ) { //IMPROVE: too many deep copy here. char achBuf[4096]; n = SSLCert::PEMWriteCert( pClientCert, achBuf, 4096 ); if ((n>0)&&( n <= 4096 )) { pEnv->add( "SSL_CLIENT_CERT", 15, achBuf, n ); ++count; } } } return count; }
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; }
//Only for types from LSI_REQ_SSL_VERSION to LSI_REQ_PATH_TRANSLATED which are defined in ls.h int RequestVars::getReqVar2( HttpSession *pSession, int type, char * &pValue, int bufLen) { HttpReq * pReq = pSession->getReq(); int ret = 0; if (type >= LSI_REQ_SSL_VERSION && type <= LSI_REQ_SSL_CLIENT_CERT) { if( !pSession->isSSL() ) return 0; SSLConnection *pSSL = pSession->getSSL(); if( type == LSI_REQ_SSL_VERSION) { pValue = (char *)pSSL->getVersion(); ret = strlen( pValue ); return ret; } else if( type == LSI_REQ_SSL_SESSION_ID ) { SSL_SESSION *pSession = pSSL->getSession(); if ( pSession ) { int idLen = SSLConnection::getSessionIdLen( pSession ); ret = idLen * 2; if ( ret > bufLen ) ret = bufLen; StringTool::hexEncode((char *)SSLConnection::getSessionId( pSession ), ret / 2, pValue ); } return ret; } else if( type == LSI_REQ_SSL_CLIENT_CERT ) { X509 * pClientCert = pSSL->getPeerCertificate(); if ( pClientCert ) ret = SSLCert::PEMWriteCert( pClientCert, pValue, bufLen ); return ret; } else { const SSL_CIPHER * pCipher = pSSL->getCurrentCipher(); if ( pCipher ) { if( type == LSI_REQ_SSL_CIPHER ) { pValue = (char *)pSSL->getCipherName(); ret = strlen( pValue ); } else { int algkeysize; int keysize = SSLConnection::getCipherBits( pCipher, &algkeysize ); if( type == LSI_REQ_SSL_CIPHER_USEKEYSIZE ) ret = safe_snprintf( pValue, 20, "%d", keysize ); else //LSI_REQ_SSL_CIPHER_ALGKEYSIZE ret = safe_snprintf( pValue, 20, "%d", algkeysize ); } } return ret; } } else if( type == LSI_REQ_GEOIP_ADDR) { ret = pSession->getPeerAddrStrLen(); pValue = (char *)pSession->getPeerAddrString(); return ret; } else if( type == LSI_REQ_PATH_TRANSLATED) { int n = pReq->getPathInfoLen(); if ( n > 0) ret = pReq->translatePath( pReq->getPathInfo(), n, pValue, bufLen); return ret; } else return 0; }
int HttpCgiTool::buildCommonEnv(IEnv *pEnv, HttpSession *pSession) { int count = 0; HttpReq *pReq = pSession->getReq(); const char *pTemp; int n; char buf[128]; RadixNode *pNode; pTemp = pReq->getAuthUser(); if (pTemp) { //NOTE: only Basic is support now pEnv->add("AUTH_TYPE", 9, "Basic", 5); pEnv->add("REMOTE_USER", 11, pTemp, strlen(pTemp)); count += 2; } //ADD_ENV("REMOTE_IDENT", "" ) //TODO: not supported yet //extensions of CGI/1.1 const AutoStr2 *pDocRoot = pReq->getDocRoot(); pEnv->add("DOCUMENT_ROOT", 13, pDocRoot->c_str(), pDocRoot->len() - 1); pEnv->add("REMOTE_ADDR", 11, pSession->getPeerAddrString(), pSession->getPeerAddrStrLen()); n = ls_snprintf(buf, 10, "%hu", pSession->getRemotePort()); pEnv->add("REMOTE_PORT", 11, buf, n); n = pSession->getServerAddrStr(buf, 128); pEnv->add("SERVER_ADDR", 11, buf, n); pEnv->add("SERVER_NAME", 11, pReq->getHostStr(), pReq->getHostStrLen()); const AutoStr2 &sPort = pReq->getPortStr(); pEnv->add("SERVER_PORT", 11, sPort.c_str(), sPort.len()); pEnv->add("REQUEST_URI", 11, pReq->getOrgReqURL(), pReq->getOrgReqURLLen()); count += 7; n = pReq->getPathInfoLen(); if (n > 0) { int m; char achTranslated[10240]; m = pReq->translatePath(pReq->getPathInfo(), n, achTranslated, sizeof(achTranslated)); if (m != -1) { pEnv->add("PATH_TRANSLATED", 15, achTranslated, m); ++count; } pEnv->add("PATH_INFO", 9, pReq->getPathInfo(), n); ++count; } //add geo IP env here if (pReq->isGeoIpOn()) { GeoInfo *pInfo = pSession->getClientInfo()->getGeoInfo(); if (pInfo) { pEnv->add("GEOIP_ADDR", 10, pSession->getPeerAddrString(), pSession->getPeerAddrStrLen()); count += pInfo->addGeoEnv(pEnv) + 1; } } n = pReq->getEnvCount(); count += n; if ((pNode = (RadixNode *)pReq->getEnvNode()) != NULL) pNode->for_each2(addEnv, pEnv); if (pSession->getStream()->isSpdy()) { const char *pProto = HioStream::getProtocolName((HiosProtocol) pSession->getStream()->getProtocol()); pEnv->add("X_SPDY", 6, pProto, strlen(pProto)); ++count; } if (pSession->isSSL()) { SslConnection *pSSL = pSession->getSSL(); pEnv->add("HTTPS", 5, "on", 2); const char *pVersion = pSSL->getVersion(); n = strlen(pVersion); pEnv->add("SSL_VERSION", 11, pVersion, n); count += 2; SSL_SESSION *pSession = pSSL->getSession(); if (pSession) { int idLen = SslConnection::getSessionIdLen(pSession); n = idLen * 2; assert(n < (int)sizeof(buf)); StringTool::hexEncode( (char *)SslConnection::getSessionId(pSession), idLen, buf); pEnv->add("SSL_SESSION_ID", 14, buf, n); ++count; } const SSL_CIPHER *pCipher = pSSL->getCurrentCipher(); if (pCipher) { const char *pName = pSSL->getCipherName(); n = strlen(pName); pEnv->add("SSL_CIPHER", 10, pName, n); int algkeysize; int keysize = SslConnection::getCipherBits(pCipher, &algkeysize); n = ls_snprintf(buf, 20, "%d", keysize); pEnv->add("SSL_CIPHER_USEKEYSIZE", 21, buf, n); n = ls_snprintf(buf, 20, "%d", algkeysize); pEnv->add("SSL_CIPHER_ALGKEYSIZE", 21, buf, n); count += 3; } int i = pSSL->getVerifyMode(); if (i != 0) { char achBuf[4096]; X509 *pClientCert = pSSL->getPeerCertificate(); if (pSSL->isVerifyOk()) { if (pClientCert) { //IMPROVE: too many deep copy here. //n = SslCert::PEMWriteCert( pClientCert, achBuf, 4096 ); //if ((n>0)&&( n <= 4096 )) //{ // pEnv->add( "SSL_CLIENT_CERT", 15, achBuf, n ); // ++count; //} n = snprintf(achBuf, sizeof(achBuf), "%lu", X509_get_version(pClientCert) + 1); pEnv->add("SSL_CLIENT_M_VERSION", 20, achBuf, n); ++count; n = lookup_ssl_cert_serial(pClientCert, achBuf, 4096); if (n != -1) { pEnv->add("SSL_CLIENT_M_SERIAL", 19, achBuf, n); ++count; } X509_NAME_oneline(X509_get_subject_name(pClientCert), achBuf, 4096); pEnv->add("SSL_CLIENT_S_DN", 15, achBuf, strlen(achBuf)); ++count; X509_NAME_oneline(X509_get_issuer_name(pClientCert), achBuf, 4096); pEnv->add("SSL_CLIENT_I_DN", 15, achBuf, strlen(achBuf)); ++count; if (SslConnection::isClientVerifyOptional(i)) { strcpy(achBuf, "GENEROUS"); n = 8; } else { strcpy(achBuf, "SUCCESS"); n = 7; } } else { strcpy(achBuf, "NONE"); n = 4; } } else n = pSSL->buildVerifyErrorString(achBuf, sizeof(achBuf)); pEnv->add("SSL_CLIENT_VERIFY", 17, achBuf, n); ++count; } } return count; }