//o====o====o====o====o====o====o====o====o====o====o====o====o====o //| CGITrace : CGI専用アクセス逆探知ライブラリ version 1.0.2 | //| Copyright (C) by 渡辺尚貴 1998. | //o====o====o====o====o====o====o====o====o====o====o====o====o====o #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cgitrace.h" //---- エラーの識別コード enum { ENOERROR, ENOAGAIN, ENORADDR, ENOREFER, ENOAGENT, ENOHANDLE, ENOHNAME, ENORPORT, ENOLPORT, ECBROKEN, ENOIDENT, EITIMEOUT, ENOUSER, ENOFINGER, EFTIMEOUT }; //---- エラーの解説文字列 const char* ct_errlist[15] = { "No error.", "Do not call this function again.", "Environment variable REMOTE_ADDR is not set by httpd.", "Environment variable HTTP_REFERER is not set by browser.", "Environment variable HTTP_USER_AGENT is not set by browser.", "No authorizations are required in htaccess.", "DNS has failed to look up the IP address.", "Environment variable REMOTE_PORT is not set by httpd.", "Environment variable SERVER_PORT is not set by httpd.", "Connection has broken.", "Ident daemon is not running in the remote host.", "Ident daemon did not answer.", "Ident daemon could not find the user.", "Finger daemon is not running in the remote host.", "Finger daemon did not answer." }; static int t_errno = ENOERROR; //==== ライブラリ関数が使用する補助関数の定義 //---- 環境変数の値を指定バッファに格納する関数 static int copyenv( const char* env, char* str, size_t size ) { char* ptr; return ((ptr=getenv(env))==NULL) ? -1 : (strncpy(str,ptr,size), 0); } //---- 環境変数の値を指定バッファに追加する関数 static int catenv( const char* env, char* str ) { char* ptr; return ((ptr=getenv(env))==NULL) ? -1 : sprintf( str, "%s.(%s)", str, ptr ), 0; } //---- 環境変数の値を指定関数で整数値に変換する関数 static int getnumenv( char* env, int (*convertor)(const char*) ) { char* ptr; return ((ptr=getenv(env))==NULL) ? 0 : (*convertor)(ptr); } //---- 環境変数を設定する関数 static int setenv( char* env, char* val ) { static char str[256]; sprintf( str, "%s=%s", env, val ); char* newenv = new char [strlen(str)+1]; strcpy( newenv, str ); return putenv(newenv); } //==== ソケットを管理するクラスの宣言と定義 class Socket { int soc; FILE* pipe; public: inline Socket( void ); inline ~Socket(); int Connect( u_long IP, u_short port ); int Printf( const char* format, ... ); int Scanf( const char* format, char* argv1 ); char* Gets( char* buffer, int size ); }; inline Socket::Socket( void ) { soc = socket( AF_INET, SOCK_STREAM, 0 ); pipe = NULL; } inline Socket::~Socket() { if( pipe != NULL ) fclose(pipe); close(soc); } int Socket::Connect( u_long IP, u_short port ) { struct sockaddr_in inaddr; inaddr.sin_addr.s_addr = IP; inaddr.sin_family = AF_INET; inaddr.sin_port = htons(port); return connect( soc, (sockaddr*)&inaddr, sizeof(sockaddr) ); } int Socket::Printf( const char* format, ... ) { static char buffer[256]; va_list argptr; va_start( argptr, format ); int size = vsprintf( buffer, format, argptr ); if( size != write( soc, buffer, size ) ) return(-1); return( size ); } int Socket::Scanf( const char* format, char* argv1 ) { static char buffer[256]; if( read( soc, buffer, sizeof(buffer) ) < 0 ) return(-1); return sscanf( buffer, format, argv1 ); } char* Socket::Gets( char* buffer, int size ) { if( pipe == NULL ) pipe = fdopen( soc, "r" ); return fgets( buffer, size, pipe ); } //==== Timerを管理するクラスの宣言と定義 class Timer { static jmp_buf stack; public: static void timeout( const int ){ longjmp( stack, 1 ); } inline int Set( const int sec ){ alarm(sec); signal( SIGALRM, timeout ); return setjmp(stack); } inline ~Timer(){ alarm(0); } }; jmp_buf Timer::stack; //==== ライブラリ関数の定義 //---- 逆探知していることを通知する関数 extern "C" void twarning( void ) { puts( "

This CGI has traced your access by CGITrace 1.0.

" ); } //---- エラーの理由を出力する関数 extern "C" void terror( const char* str ) { printf("

\n%s : %s\n

\n", str, ct_errlist[t_errno] ); } //---- アクセス主のホストアドレスとport番号を捜査する関数 extern "C" int GetAddr( char* addr ) { if( copyenv( "REMOTE_ADDR", addr, ADDR_SIZE-8 ) ){ strcpy( addr, "-noraddr" ); return t_errno = ENORADDR, -1; } catenv( "REMOTE_PORT", addr ); return(0); } //---- アクセス主の履歴を捜査する関数 extern "C" int GetReferer( char* referer ) { if( copyenv( "HTTP_REFERER", referer, REFERER_SIZE ) ){ strcpy( referer, "-noreferer" ); return t_errno = ENOREFER, -1; } return(0); } //---- アクセス主のbrowser種別を捜査する関数 extern "C" int GetAgent( char* agent ) { if( copyenv( "HTTP_USER_AGENT", agent, AGENT_SIZE ) ){ strcpy( agent, "-noagent" ); return t_errno = ENOAGENT, -1; } return(0); } //---- .htaccessに定められたアクセス主のハンドル名を捜査する関数 extern "C" int GetHandle( char* handle ) { if( copyenv( "REMOTE_USER", handle, HANDLE_SIZE ) ){ strcpy( handle, "-nohandle" ); return t_errno = ENOHANDLE, -1; } return(0); } //---- アクセス主のホスト名とport番号を捜査する関数 extern "C" int GetHost( char* host ) { static int haveever = 0; if( haveever++ ){ strcpy( host, "-noagain" ); return t_errno = ENOAGAIN, -1; } u_long IP = getnumenv( "REMOTE_ADDR", (int(*)(char*))inet_addr ); if( IP == 0 ){ strcpy( host, "-noraddr" ); return t_errno = ENORADDR, -1; } struct hostent* hptr = gethostbyaddr( (char*)&IP, 4, AF_INET ); if( hptr == NULL ){ strcpy( host, "-nohname" ); return t_errno = ENOHNAME, -1; } strncpy( host, hptr->h_name, HOST_SIZE-8 ); catenv( "REMOTE_PORT", host ); setenv( "REMOTE_HOST", host ); return(0); } //---- アクセス主のユーザー名を捜査する関数 extern "C" int GetUser( char* user ) { static int haveever = 0; if( haveever++ ){ strcpy( user, "-noagain" ); return t_errno = ENOAGAIN, -1; } if( !copyenv( "REMOTE_IDENT", user, USER_SIZE ) ){ return(0); } u_long IP = getnumenv( "REMOTE_ADDR", (int(*)(char*))inet_addr ); if( IP == 0 ){ strcpy( user, "-noraddr" ); return t_errno = ENORADDR, -1; } u_short fport = getnumenv("REMOTE_PORT", atoi ); if( fport == 0 ){ strcpy( user, "-norport" ); return t_errno = ENORPORT, -1; } u_short lport = getnumenv("SERVER_PORT", atoi ); if( lport == 0 ){ strcpy( user, "-nolport" ); return t_errno = ENOLPORT, -1; } Timer T; if( T.Set(4) ){ strcpy( user, "-timeout" ); return t_errno = EITIMEOUT, -1; } Socket S; if( S.Connect( IP, 113 ) ){ strcpy( user, "-noident" ); return t_errno = ENOIDENT, -1; } if( S.Printf( " %u , %u\n", fport, lport ) < 0 ){ strcpy( user, "-cbroken" ); return t_errno = ECBROKEN, -1; } if( S.Scanf( "%*u , %*u : USERID :%*[^:]:%16s", user ) != 1 ){ strcpy( user, "-nouser" ); return t_errno = ENOUSER, -1; } setenv( "REMOTE_IDENT", user ); return(0); } //---- アクセス元のログイン状況を捜査する関数 extern "C" int GetFinger( char lines[][FINGER_SIZE] ) { static int haveever = 0; if( haveever++ ){ return t_errno = ENOAGAIN, -1; } u_long IP = getnumenv( "REMOTE_ADDR", (int(*)(char*))inet_addr ); if( IP == 0 ){ return t_errno = ENORADDR, -1; } Timer T; if( T.Set(12) ){ return t_errno = EFTIMEOUT, -1; } Socket S; if( S.Connect( IP, 79 ) ){ return t_errno = ENOFINGER, -1; } if( S.Printf( "-h\n" ) < 0 ){ return t_errno = ECBROKEN, -1; } int no; for( no=0 ; no < FINGER_LINES ; no++ ){ if( S.Gets( lines[no], FINGER_SIZE ) == NULL ) break; } return( no ); } //---- 現在時刻を捜査する関数 extern "C" int GetTime( char* timestr ) { time_t tt = time(NULL); strftime( timestr, TIME_SIZE, "%d/%b/%Y:%H:%M:%S", localtime(&tt) ); return(0); }