diff options
-rw-r--r-- | CHANGELOG | 59 | ||||
-rw-r--r-- | INSTALL | 88 | ||||
-rw-r--r-- | Makefile | 40 | ||||
-rw-r--r-- | README | 23 | ||||
-rw-r--r-- | access_log.sql | 24 | ||||
-rwxr-xr-x | make_combined_log.pl | 12 | ||||
-rw-r--r-- | mod_log_sql.c | 258 |
7 files changed, 385 insertions, 119 deletions
@@ -1,16 +1,69 @@ | |||
1 | $Id: CHANGELOG,v 1.2 2001/11/30 08:29:04 helios Stab $ | 1 | $Id: CHANGELOG,v 1.3 2001/12/03 19:54:02 helios Exp $ |
2 | 2 | ||
3 | 3 | ||
4 | TODO: | 4 | TODO: |
5 | * Full commenting of the code. | 5 | * Full commenting of the code. |
6 | * Bounds checking on all data prior to INSERT | 6 | * Rethink documentation flow and rewrite? |
7 | 7 | ||
8 | 8 | ||
9 | CHANGES: | 9 | CHANGES: |
10 | 10 | ||
11 | 1.11: | ||
12 | |||
13 | * Completely re-worked the cookie code. Now the user can instruct | ||
14 | mod_log_mysql which cookie (out of many available) to log. (See | ||
15 | the online directives documentation and FAQ.) | ||
16 | * New config capability: 'H' to log the request protocol | ||
17 | (e.g. HTTP/1.1) | ||
18 | * New config capability: 'm' to log the request method | ||
19 | (e.g. GET, PUT, etc.) | ||
20 | * New config capabilities: 'z' 'q' & 'Q' to log SSL_CIPHER, | ||
21 | SSL_CIPHER_USEKEYSIZE and SSL_CIPHER_ALGKEYSIZE. These require | ||
22 | openssl and glibc-devel to be installed. (See the online | ||
23 | directives documentation and FAQ.) | ||
24 | * Fixed a bug in make_combined_log.pl that caused it to generate | ||
25 | incorrect output on single-digit days. | ||
26 | * Fixed make_combined_log.pl to use the data logged by 'H' and 'm'. | ||
27 | * Migrated all log_error calls to the newer ap_log_error call. | ||
28 | * Added a DEBUG define to activate certain debugging/informational | ||
29 | error-log messages (for devel purposes). | ||
30 | * I apologize for the inconvenience this may cause: I decided to | ||
31 | rename the runtime configuration directives so that they would | ||
32 | make more sense and group together with a "MySQL" prefix. They | ||
33 | are now: | ||
34 | MySQLRefererLogTable | ||
35 | The MySQL table that holds the referer log | ||
36 | MySQLAgentLogTable | ||
37 | The MySQL table that holds the agent log | ||
38 | MySQLTransferLogTable | ||
39 | The MySQL table that holds the transfer log | ||
40 | MySQLTransferLogFormat | ||
41 | Instruct the module what information to log to the MySQL transfer log | ||
42 | MySQLRefererIgnore | ||
43 | List of referers to ignore, accesses that match will not be logged to MySQL | ||
44 | MySQLRequestIgnore | ||
45 | List of URIs to ignore, accesses that match will not be logged to MySQL | ||
46 | MySQLRemhostIgnore | ||
47 | List of remote hosts to ignore, accesses that match will not be logged to MySQL | ||
48 | MySQLDatabase | ||
49 | The name of the MySQL database for logging | ||
50 | MySQLWhichCookie | ||
51 | The CookieName that you want logged when using the 'c' config directive | ||
52 | MySQLLoginInfo | ||
53 | The MySQL host, user-id and password for logging | ||
54 | You'll need to just do a search-and-replace in your httpd.conf... | ||
55 | Again, I'm sorry, but it really is better this way. | ||
56 | * Cleaned up the summaries that get output on "httpd -L" | ||
57 | * Expanded the enclosed access_log.sql file to support every column type | ||
58 | that mod_log_mysql provides -- delete the ones that you don't need. | ||
59 | * Some cleanup of the Makefile - pay attention to the settings | ||
60 | * Made the MySQLTransferLogFormat default "AbHhmRSsTUuv" to incorporate the | ||
61 | new column types and sort the characters alphabetically for reading ease. | ||
62 | |||
63 | |||
11 | 1.10: | 64 | 1.10: |
12 | 65 | ||
13 | * New capability: log mod_usertrack cookies. | 66 | * New config directive/capability: 'c' to log mod_usertrack cookies. |
14 | * Some code cleanup and commenting. | 67 | * Some code cleanup and commenting. |
15 | * Referer and User-Agent now set to want_orig=1 ( a very minor detail ) | 68 | * Referer and User-Agent now set to want_orig=1 ( a very minor detail ) |
16 | * Corrected mysql_escape_log to properly check for and escape strings | 69 | * Corrected mysql_escape_log to properly check for and escape strings |
@@ -1,30 +1,68 @@ | |||
1 | $Id: INSTALL,v 1.1 2001/11/28 05:26:54 helios Exp $ | 1 | $Id: INSTALL,v 1.2 2001/12/03 19:54:02 helios Exp $ |
2 | 2 | ||
3 | 3 | ||
4 | Requirements | 4 | Requirements |
5 | ============ | 5 | ============ |
6 | 6 | ||
7 | 0) I run a Red Hat 6.2 system, but these instructions should easily | 7 | * I run a Red Hat 6.2 system, but these instructions should easily |
8 | adapt to any modern distro. | 8 | adapt to any modern distro. |
9 | 9 | ||
10 | 1) Apache 1.2.x or higher installed. (I run 1.3.22 and it works fine). | 10 | * Apache 1.2.x or higher installed. (I run 1.3.22 and it works fine). |
11 | You should have already successfully compiled Apache and know what | 11 | You should have already successfully compiled Apache and know what |
12 | you're doing there. In fact, you should already have any other | 12 | you're doing there. In fact, you should already have any other |
13 | modules and add-ons like mod_ssl or PHP configured and installed | 13 | modules and add-ons like mod_ssl or PHP configured and installed |
14 | before you start this process. | 14 | before you start this process. |
15 | 15 | ||
16 | 2) The MySQL development headers. (I run MySQL-devel-3.23.44-1.i386.rpm). | 16 | * The MySQL development headers. (I run MySQL-devel-3.23.44-1.i386.rpm). |
17 | 17 | ||
18 | 3) MySQL configured, installed and running on either localhost or an | 18 | * MySQL configured, installed and running on either localhost or an |
19 | accessible networked machine. You should already have a basic | 19 | accessible networked machine. You should already have a basic |
20 | understanding of MySQL and how it functions. | 20 | understanding of MySQL and how it functions. |
21 | 21 | ||
22 | 4) Again, basic administrative skills with Apache and MySQL. I try to | 22 | * Again, basic administrative skills with Apache and MySQL. I try to |
23 | make things as easy as possible in this README, but its purpose is | 23 | make things as easy as possible in this README, but its purpose is |
24 | not to be an administrative tutorial. | 24 | not to be an administrative tutorial. |
25 | 25 | ||
26 | Installation | 26 | * Additionally, if you want to be able to log SSL information such as |
27 | ============ | 27 | keysize or cipher, you need OpenSSL and glibc-devel installed. Both |
28 | are available as RPMs. | ||
29 | |||
30 | |||
31 | Installation (as an Apache DSO) | ||
32 | =============================== | ||
33 | |||
34 | For folks interested in using this module as an Apache DSO, these | ||
35 | instructions are currently UNTESTED but should work. (I would be | ||
36 | grateful to hear back from a DSO user as to my accuracy with these | ||
37 | instructions.) | ||
38 | |||
39 | 0) Perform all the following steps as root so that you have install | ||
40 | privs, etc. | ||
41 | |||
42 | 1) Unpack the archive into a working directory. | ||
43 | |||
44 | # tar zxf mod_log_mysql.tar.gz -C /usr/local/src | ||
45 | # cd /usr/local/src/mod_log_mysql | ||
46 | |||
47 | 2) Instruct apxs to compile and install the module as a DSO. (My apxs is | ||
48 | in /usr/local/Apache/bin, perform a "locate" to find yours...) | ||
49 | |||
50 | # <path>/apxs -i -a -c mod_log_mysql.c | ||
51 | |||
52 | You should see something like this: | ||
53 | |||
54 | gcc -fpic -DSHARED_MODULE -I/usr/local/Apache/include -c mod_log_mysql.c | ||
55 | ld -Bshareable -o mod_log_mysql.so mod_log_mysql.o | ||
56 | cp mod_log_mysql.so <your path to Apache libexec>/mod_log_mysql.so | ||
57 | chmod 755 <your path to Apache libexec>/mod_log_mysql.so | ||
58 | [activating module foo' in /path/to/apache/etc/httpd.conf] | ||
59 | |||
60 | 3) Now go to step (9) in the instructions below to configure httpd.conf... | ||
61 | |||
62 | |||
63 | Installation (as a static module compiled into httpd) | ||
64 | ===================================================== | ||
65 | [This is what I do, FYI.] | ||
28 | 66 | ||
29 | 0) Perform all the following steps as root so that you have install | 67 | 0) Perform all the following steps as root so that you have install |
30 | privs, etc. | 68 | privs, etc. |
@@ -117,6 +155,15 @@ Installation | |||
117 | </VirtualHost> | 155 | </VirtualHost> |
118 | 156 | ||
119 | 157 | ||
158 | 9a) For users who have a DSO-enabled httpd: | ||
159 | |||
160 | If you you are building mod_log_mysql as a static module BUT | ||
161 | your httpd is enabled for DSOs, add the following line to your | ||
162 | httpd.conf: | ||
163 | |||
164 | AddModule mod_log_mysql.c | ||
165 | |||
166 | |||
120 | 10) Create a database and table to hold the new log data. I log the | 167 | 10) Create a database and table to hold the new log data. I log the |
121 | same data as the regular "combined log" plus a little extra information | 168 | same data as the regular "combined log" plus a little extra information |
122 | that can be useful. | 169 | that can be useful. |
@@ -128,8 +175,11 @@ Installation | |||
128 | # mysql -uadmin -pmypassword | 175 | # mysql -uadmin -pmypassword |
129 | mysql> create database apache; | 176 | mysql> create database apache; |
130 | 177 | ||
131 | Then I created the table called "access_log". You should use the | 178 | Then create the table called "access_log". I enclosed an SQL file |
132 | enclosed SQL file to do this for you. | 179 | that will create every column type that mod_log_mysql supports. |
180 | Unless you're just testing or playing around, this is probably NOT | ||
181 | what you want, so edit the file first and delete the lines that | ||
182 | don't pertain to you. Then: | ||
133 | 183 | ||
134 | mysql> source access_log.sql | 184 | mysql> source access_log.sql |
135 | 185 | ||
@@ -1,25 +1,49 @@ | |||
1 | # $Id: Makefile,v 1.1 2001/11/28 05:26:54 helios Exp $ | 1 | # $Id: Makefile,v 1.2 2001/12/03 19:54:02 helios Exp $ |
2 | 2 | ||
3 | # Verify that this points to the right place... | 3 | # Verify that this points to the right place... |
4 | APACHEDIR = /usr/local/src/apache_1.3.22/src | 4 | APACHEDIR = /usr/local/src/apache_1.3.22 |
5 | |||
6 | # Use the first one if you want mod_log_mysql to be able to log | ||
7 | # SSL variables like keysize or cipher. Use the second one if | ||
8 | # you don't use SSL or don't care to log it. | ||
9 | DEFS = -DWANT_SSL_LOGGING | ||
10 | #DEFS = | ||
11 | |||
12 | # Use this one if you do WANT_SSL_LOGGING, and confirm the last two paths. | ||
13 | # Make "/usr/local/ssl/include" point to where your openssl/*.h files are, | ||
14 | # and make "/usr/include/db1" point to where ndbm.h can be found. | ||
15 | # | ||
16 | # How to find your directories: | ||
17 | # | ||
18 | # $ locate http_core.h | ||
19 | # /usr/local/Apache/include/http_core.h | ||
20 | # | ||
21 | # $ locate x509.h | ||
22 | # /usr/local/ssl/include/openssl/x509.h | ||
23 | # | ||
24 | # $ locate ndbm.h | ||
25 | # /usr/include/db1/ndbm.h | ||
26 | |||
27 | CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include -I/usr/local/ssl/include -I/usr/include/db1 | ||
28 | |||
29 | # Use this one if you don't WANT_SSL_LOGGING: | ||
30 | |||
31 | #CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include | ||
5 | 32 | ||
6 | # Verify that this include directory is correct for you... | ||
7 | CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include | ||
8 | 33 | ||
9 | # --------------------------------------------------------- | 34 | # --------------------------------------------------------- |
10 | # You shouldn't have to touch below here! | 35 | # You shouldn't have to touch below here. |
11 | 36 | ||
12 | CC = gcc | 37 | CC = gcc |
13 | DEFS = -DSHARED_MODULE | ||
14 | INSTALL = /usr/bin/install -m 664 | 38 | INSTALL = /usr/bin/install -m 664 |
15 | 39 | ||
16 | all: mod_log_mysql.o | 40 | all: mod_log_mysql.o |
17 | 41 | ||
18 | mod_log_mysql.o: mod_log_mysql.c | 42 | mod_log_mysql.o: mod_log_mysql.c Makefile |
19 | $(CC) ${CFLAGS} ${DEFS} -c mod_log_mysql.c | 43 | $(CC) ${CFLAGS} ${DEFS} -c mod_log_mysql.c |
20 | 44 | ||
21 | install: all | 45 | install: all |
22 | $(INSTALL) mod_log_mysql.o ${APACHEDIR}/mod_log_mysql.o | 46 | $(INSTALL) mod_log_mysql.o ${APACHEDIR}/src/mod_log_mysql.o |
23 | 47 | ||
24 | distro: all | 48 | distro: all |
25 | cd ..; tar zcf mod_log_mysql.tar.gz mod_log_mysql/; $(INSTALL) mod_log_mysql.tar.gz /usr/local/Apache/html/mod_log_mysql/; rm -f mod_log_mysql.tar.gz | 49 | cd ..; tar zcf mod_log_mysql.tar.gz mod_log_mysql/; $(INSTALL) mod_log_mysql.tar.gz /usr/local/Apache/html/mod_log_mysql/; rm -f mod_log_mysql.tar.gz |
@@ -1,4 +1,4 @@ | |||
1 | $Id: README,v 1.1 2001/11/28 05:26:54 helios Exp $ | 1 | $Id: README,v 1.2 2001/12/03 19:54:02 helios Exp $ |
2 | 2 | ||
3 | 3 | ||
4 | Homepage | 4 | Homepage |
@@ -51,8 +51,11 @@ Supported directives | |||
51 | Please see the web-based documentation for full explanation of all | 51 | Please see the web-based documentation for full explanation of all |
52 | supported run-time directives. | 52 | supported run-time directives. |
53 | 53 | ||
54 | http://www.grubbybaby.com/mod_log_mysql/directives.html | 54 | http://www.grubbybaby.com/mod_log_mysql/directives.html |
55 | 55 | ||
56 | See the FAQ for some handy examples: | ||
57 | |||
58 | http://www.grubbybaby.com/mod_log_mysql/faq.html | ||
56 | 59 | ||
57 | 60 | ||
58 | What gets logged by default? | 61 | What gets logged by default? |
@@ -64,7 +67,8 @@ accept this default and employ the enclosed access_log.sql to | |||
64 | format your table. Customize your logging format after you've | 67 | format your table. Customize your logging format after you've |
65 | had a chance to experiment with the default first. | 68 | had a chance to experiment with the default first. |
66 | 69 | ||
67 | The MySQL table looks like this if you use the enclosed access_log.sql: | 70 | If you just want to log enough data to be able to reconstruct |
71 | a Combined Log Format log, log these: | ||
68 | 72 | ||
69 | +------------------+------------------+ | 73 | +------------------+------------------+ |
70 | | Field | Type | | 74 | | Field | Type | |
@@ -72,13 +76,14 @@ The MySQL table looks like this if you use the enclosed access_log.sql: | |||
72 | | remote_host | varchar(50) | | 76 | | remote_host | varchar(50) | |
73 | | remote_user | varchar(50) | | 77 | | remote_user | varchar(50) | |
74 | | request_uri | varchar(50) | | 78 | | request_uri | varchar(50) | |
75 | | request_duration | smallint(6) | | ||
76 | | virtual_host | varchar(50) | | 79 | | virtual_host | varchar(50) | |
77 | | time_stamp | int(10) unsigned | | 80 | | time_stamp | int(10) unsigned | |
78 | | status | smallint(6) | | 81 | | status | smallint(6) | |
79 | | bytes_sent | int(11) | | 82 | | bytes_sent | int(11) | |
80 | | referer | varchar(255) | | 83 | | referer | varchar(255) | |
81 | | agent | varchar(255) | | 84 | | agent | varchar(255) | |
85 | | request_method | varchar(6) | | ||
86 | | request_protocol | varchar(10) | | ||
82 | +------------------+------------------+ | 87 | +------------------+------------------+ |
83 | 88 | ||
84 | remote_host: corresponds to the Apache %h directive. Contains the remote | 89 | remote_host: corresponds to the Apache %h directive. Contains the remote |
@@ -129,7 +134,15 @@ agent: corresponds to the Apache "%{User-Agent}" directive. Contains the | |||
129 | broswer type (user agent) of the software that made the request. | 134 | broswer type (user agent) of the software that made the request. |
130 | Example: Mozilla/3.0 (Slurp/si; slurp@inktomi.com; http://www.inktomi.com/slurp.html) | 135 | Example: Mozilla/3.0 (Slurp/si; slurp@inktomi.com; http://www.inktomi.com/slurp.html) |
131 | 136 | ||
132 | 137 | request_method: corresponds to the Apache %m directive. Contains the type | |
138 | of request sent: GET, PUT, etc. | ||
139 | Example: GET | ||
140 | |||
141 | request_protocol: corresponds to the Apache %H directive. Contains the HTTP | ||
142 | protocol that was used. | ||
143 | Example: HTTP/1.1 | ||
144 | |||
145 | |||
133 | Notes | 146 | Notes |
134 | ----- | 147 | ----- |
135 | 148 | ||
diff --git a/access_log.sql b/access_log.sql index c38cb50..46d5a6e 100644 --- a/access_log.sql +++ b/access_log.sql | |||
@@ -1,13 +1,25 @@ | |||
1 | create table access_log ( | 1 | create table access_log ( |
2 | agent varchar(255) not null, | ||
3 | bytes_sent int not null, | ||
4 | child_pid smallint unsigned, | ||
5 | cookie varchar(255), | ||
6 | request_file varchar(255), | ||
7 | referer varchar(255) not null, | ||
2 | remote_host varchar(50) not null, | 8 | remote_host varchar(50) not null, |
9 | remote_logname varchar(50) not null, | ||
3 | remote_user varchar(50) not null, | 10 | remote_user varchar(50) not null, |
4 | request_uri varchar(50) not null, | ||
5 | request_duration smallint not null, | 11 | request_duration smallint not null, |
6 | virtual_host varchar(50) not null, | 12 | request_line varchar(255), |
7 | time_stamp int unsigned not null, | 13 | request_method not null, |
14 | request_protocol not null, | ||
15 | request_time char(28), | ||
16 | request_uri varchar(50) not null, | ||
17 | server_port smallint unsigned, | ||
18 | ssl_cipher varchar(25), | ||
19 | ssl_keysize smallint | ||
20 | ssl_maxkeysize smallint, | ||
8 | status smallint not null, | 21 | status smallint not null, |
9 | bytes_sent int not null, | 22 | time_stamp int unsigned not null, |
10 | referer varchar(255) not null, | 23 | virtual_host varchar(50) not null, |
11 | agent varchar(255) not null | ||
12 | ) | 24 | ) |
13 | 25 | ||
diff --git a/make_combined_log.pl b/make_combined_log.pl index d375f3a..009db42 100755 --- a/make_combined_log.pl +++ b/make_combined_log.pl | |||
@@ -1,6 +1,6 @@ | |||
1 | #!/usr/bin/perl | 1 | #!/usr/bin/perl |
2 | 2 | ||
3 | # $Id: make_combined_log.pl,v 1.1 2001/11/28 05:26:54 helios Exp $ | 3 | # $Id: make_combined_log.pl,v 1.2 2001/12/03 19:54:02 helios Exp $ |
4 | # | 4 | # |
5 | # make_combined_log.pl | 5 | # make_combined_log.pl |
6 | # | 6 | # |
@@ -45,7 +45,7 @@ $virthost = $ARGV[1]; | |||
45 | # | 45 | # |
46 | # Set up the proper variables to permit database access | 46 | # Set up the proper variables to permit database access |
47 | # | 47 | # |
48 | $serverName = "your.dbmachine.com"; | 48 | $serverName = "your.dbhost.com"; |
49 | $serverPort = "3306"; | 49 | $serverPort = "3306"; |
50 | $serverUser = "someuser"; | 50 | $serverUser = "someuser"; |
51 | $serverPass = "somepass"; | 51 | $serverPass = "somepass"; |
@@ -57,8 +57,6 @@ $serverDb = "apache"; | |||
57 | # | 57 | # |
58 | $st_tz = "-0800"; | 58 | $st_tz = "-0800"; |
59 | $dt_tz = "-0700"; | 59 | $dt_tz = "-0700"; |
60 | $type = "GET"; | ||
61 | $http = "HTTP/1.1"; | ||
62 | 60 | ||
63 | $now = time(); | 61 | $now = time(); |
64 | $start = $now - (86400 * $days); | 62 | $start = $now - (86400 * $days); |
@@ -71,7 +69,7 @@ if (not $dbh) { | |||
71 | die "Unable to connect to the database. Please check your connection variables. (Bad password? Incorrect perms?)"; | 69 | die "Unable to connect to the database. Please check your connection variables. (Bad password? Incorrect perms?)"; |
72 | } | 70 | } |
73 | 71 | ||
74 | $records = $dbh->prepare("select remote_host,remote_user,request_uri,request_duration,time_stamp,status,bytes_sent,referer,agent from $serverTbl where virtual_host='$virthost' and time_stamp >= $start"); | 72 | $records = $dbh->prepare("select remote_host,remote_user,request_uri,time_stamp,status,bytes_sent,referer,agent,request_method,request_protocol from $serverTbl where virtual_host='$virthost' and time_stamp >= $start"); |
75 | $records->execute; | 73 | $records->execute; |
76 | if (not $records) { | 74 | if (not $records) { |
77 | die "No such table or the select returned no records." | 75 | die "No such table or the select returned no records." |
@@ -94,7 +92,7 @@ while (@data = $records->fetchrow_array) { | |||
94 | $year=$year+1900; | 92 | $year=$year+1900; |
95 | 93 | ||
96 | # Create format for leading-zero formatting | 94 | # Create format for leading-zero formatting |
97 | if ($day < 10) { $day = "0$day"; } | 95 | if ($mday < 10) { $mday = "0$mday"; } |
98 | if ($month < 10) { $month = "0$month"; } | 96 | if ($month < 10) { $month = "0$month"; } |
99 | if ($hour < 10) { $hour = "0$hour"; } | 97 | if ($hour < 10) { $hour = "0$hour"; } |
100 | if ($min < 10) { $min = "0$min"; } | 98 | if ($min < 10) { $min = "0$min"; } |
@@ -123,7 +121,7 @@ while (@data = $records->fetchrow_array) { | |||
123 | } else { | 121 | } else { |
124 | print "$st_tz\] "; | 122 | print "$st_tz\] "; |
125 | } | 123 | } |
126 | print "\"$type $data[2] $http\" $data[5] $data[6] \"$data[7]\" \"$data[8]\"\n"; | 124 | print "\"$data[9] $data[2] $data[10]\" $data[5] $data[6] \"$data[7]\" \"$data[8]\"\n"; |
127 | } | 125 | } |
128 | 126 | ||
129 | # | 127 | # |
diff --git a/mod_log_sql.c b/mod_log_sql.c index 0739372..5bb992b 100644 --- a/mod_log_sql.c +++ b/mod_log_sql.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: mod_log_sql.c,v 1.2 2001/11/30 08:29:04 helios Stab $ | 1 | /* $Id: mod_log_sql.c,v 1.3 2001/12/03 19:54:02 helios Exp $ |
2 | * | 2 | * |
3 | * mod_log_mysql.c | 3 | * mod_log_mysql.c |
4 | * Release v 1.10 | 4 | * Release v 1.10 |
@@ -71,22 +71,41 @@ | |||
71 | */ | 71 | */ |
72 | 72 | ||
73 | 73 | ||
74 | /* DEFINES */ | ||
75 | #define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") | ||
76 | |||
77 | #define ERRLEVEL APLOG_ERR|APLOG_NOERRNO | ||
78 | |||
79 | #undef DEBUG | ||
80 | #ifdef DEBUG | ||
81 | #define DEBUGLEVEL APLOG_INFO|APLOG_NOERRNO | ||
82 | #endif | ||
83 | |||
84 | |||
85 | |||
86 | /* INCLUDES */ | ||
74 | #include <time.h> | 87 | #include <time.h> |
75 | #include <mysql/mysql.h> | 88 | #include <mysql/mysql.h> |
89 | #include <stdio.h> | ||
76 | 90 | ||
77 | #include "httpd.h" | 91 | #include "httpd.h" |
78 | #include "http_config.h" | 92 | #include "http_config.h" |
79 | #include "http_log.h" | 93 | #include "http_log.h" |
80 | #include "http_core.h" | 94 | #include "http_core.h" |
81 | #if MODULE_MAGIC_NUMBER >= 19980324 | 95 | #if MODULE_MAGIC_NUMBER >= 19980324 |
82 | #include "ap_compat.h" | 96 | #include "ap_compat.h" |
83 | #endif | 97 | #endif |
84 | 98 | ||
99 | #ifdef WANT_SSL_LOGGING | ||
100 | #include "/usr/local/src/apache_1.3.22/src/modules/ssl/mod_ssl.h" | ||
101 | #endif | ||
102 | |||
103 | |||
104 | |||
105 | /* DECLARATIONS */ | ||
85 | module mysql_log_module; | 106 | module mysql_log_module; |
86 | MYSQL log_sql_server, *mysql_log = NULL; | 107 | MYSQL log_sql_server, *mysql_log = NULL; |
87 | char *log_db_name = NULL, *db_host = NULL, *db_user = NULL, *db_pwd = NULL; | 108 | char *log_db_name = NULL, *db_host = NULL, *db_user = NULL, *db_pwd = NULL, *cookie_name = NULL; |
88 | |||
89 | #define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") | ||
90 | 109 | ||
91 | typedef const char *(*item_key_func) (request_rec *, char *); | 110 | typedef const char *(*item_key_func) (request_rec *, char *); |
92 | typedef struct { | 111 | typedef struct { |
@@ -97,8 +116,11 @@ typedef struct { | |||
97 | char *transfer_log_format; | 116 | char *transfer_log_format; |
98 | } log_mysql_state; | 117 | } log_mysql_state; |
99 | 118 | ||
100 | /* Defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ | 119 | |
101 | #if MODULE_MAGIC_NUMBER < 19970103 | 120 | |
121 | #if MODULE_MAGIC_NUMBER < 19970103 /* Defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ | ||
122 | extern const char *log_request_protocol(request_rec *r, char *a); | ||
123 | extern const char *log_request_method(request_rec *r, char *a); | ||
102 | extern const char *log_remote_host(request_rec *r, char *a); | 124 | extern const char *log_remote_host(request_rec *r, char *a); |
103 | extern const char *log_remote_logname(request_rec *r, char *a); | 125 | extern const char *log_remote_logname(request_rec *r, char *a); |
104 | extern const char *log_remote_user(request_rec *r, char *a); | 126 | extern const char *log_remote_user(request_rec *r, char *a); |
@@ -118,6 +140,7 @@ extern const char *log_virtual_host(request_rec *r, char *a); | |||
118 | extern const char *log_server_port(request_rec *r, char *a); | 140 | extern const char *log_server_port(request_rec *r, char *a); |
119 | extern const char *log_child_pid(request_rec *r, char *a); | 141 | extern const char *log_child_pid(request_rec *r, char *a); |
120 | #else | 142 | #else |
143 | |||
121 | static char *format_integer(pool *p, int i) | 144 | static char *format_integer(pool *p, int i) |
122 | { | 145 | { |
123 | char dummy[40]; | 146 | char dummy[40]; |
@@ -161,6 +184,69 @@ static const char *log_remote_user(request_rec *r, char *a) | |||
161 | return rvalue; | 184 | return rvalue; |
162 | } | 185 | } |
163 | 186 | ||
187 | #ifdef WANT_SSL_LOGGING | ||
188 | static const char *log_ssl_keysize(request_rec *r, char *a) | ||
189 | { | ||
190 | char *result = NULL; | ||
191 | |||
192 | if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) { | ||
193 | result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_USEKEYSIZE"); | ||
194 | #ifdef DEBUG | ||
195 | ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_mysql: SSL_KEYSIZE: %s", result); | ||
196 | #endif | ||
197 | if (result != NULL && result[0] == '\0') | ||
198 | result = NULL; | ||
199 | return result; | ||
200 | } else { | ||
201 | return "0"; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static const char *log_ssl_maxkeysize(request_rec *r, char *a) | ||
206 | { | ||
207 | char *result = NULL; | ||
208 | |||
209 | if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) { | ||
210 | result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_ALGKEYSIZE"); | ||
211 | #ifdef DEBUG | ||
212 | ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_mysql: SSL_ALGKEYSIZE: %s", result); | ||
213 | #endif | ||
214 | if (result != NULL && result[0] == '\0') | ||
215 | result = NULL; | ||
216 | return result; | ||
217 | } else { | ||
218 | return "0"; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | static const char *log_ssl_cipher(request_rec *r, char *a) | ||
223 | { | ||
224 | char *result = NULL; | ||
225 | |||
226 | if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) { | ||
227 | result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER"); | ||
228 | #ifdef DEBUG | ||
229 | ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_mysql: SSL_CIPHER: %s", result); | ||
230 | #endif | ||
231 | if (result != NULL && result[0] == '\0') | ||
232 | result = NULL; | ||
233 | return result; | ||
234 | } else { | ||
235 | return "0"; | ||
236 | } | ||
237 | } | ||
238 | #endif /* WANT_SSL_LOGGING */ | ||
239 | |||
240 | static const char *log_request_method(request_rec *r, char *a) | ||
241 | { | ||
242 | return r->method; | ||
243 | } | ||
244 | |||
245 | static const char *log_request_protocol(request_rec *r, char *a) | ||
246 | { | ||
247 | return r->protocol; | ||
248 | } | ||
249 | |||
164 | static const char *log_request_line(request_rec *r, char *a) | 250 | static const char *log_request_line(request_rec *r, char *a) |
165 | { | 251 | { |
166 | return r->the_request; | 252 | return r->the_request; |
@@ -292,49 +378,63 @@ static const char *log_cookie(request_rec *r, char *a) | |||
292 | { | 378 | { |
293 | const char *cookiestr; | 379 | const char *cookiestr; |
294 | char *cookieend; | 380 | char *cookieend; |
381 | char *isvalid; | ||
382 | char *cookiebuf; | ||
295 | 383 | ||
296 | cookiestr = table_get(r->headers_in, "cookie"); | 384 | cookiestr = (char *)table_get(r->headers_in, "cookie2"); |
297 | 385 | if (cookiestr != NULL) { | |
298 | /* First look for Cookie2: header */ | 386 | #ifdef DEBUG |
299 | if ( (cookiestr = table_get(r->headers_in, "cookie2")) ) { | 387 | ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_mysql: Cookie2: [%s]", cookiestr); |
300 | cookieend = strchr(cookiestr, ';'); | 388 | #endif |
301 | if (cookieend) | 389 | isvalid = strstr(cookiestr, cookie_name); |
302 | *cookieend = '\0'; /* Ignore anything after a ; */ | 390 | if (isvalid != NULL) { |
303 | return cookiestr; | 391 | isvalid += strlen(cookie_name) + 1; |
392 | cookiebuf = ap_pstrdup(r->pool, isvalid); | ||
393 | cookieend = strchr(cookiebuf, ';'); | ||
394 | if (cookieend != NULL) | ||
395 | *cookieend = '\0'; | ||
396 | return cookiebuf; | ||
397 | } | ||
304 | } | 398 | } |
305 | 399 | ||
306 | /* Then try a Cookie: header */ | 400 | |
307 | else if ( (cookiestr = table_get(r->headers_in, "cookie")) ) { | 401 | cookiestr = (char *)table_get(r->headers_in, "cookie"); |
308 | cookieend = strchr(cookiestr, ';'); | 402 | if (cookiestr != NULL) { |
309 | if (cookieend) | 403 | #ifdef DEBUG |
310 | *cookieend = '\0'; | 404 | ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_mysql: Cookie: [%s]", cookiestr); |
311 | return cookiestr; | 405 | #endif |
406 | isvalid = strstr(cookiestr, cookie_name); | ||
407 | if (isvalid != NULL) { | ||
408 | isvalid += strlen(cookie_name) + 1; | ||
409 | cookiebuf = ap_pstrdup(r->pool, isvalid); | ||
410 | cookieend = strchr(cookiebuf, ';'); | ||
411 | if (cookieend != NULL) | ||
412 | *cookieend = '\0'; | ||
413 | return cookiebuf; | ||
414 | } | ||
312 | } | 415 | } |
313 | 416 | ||
314 | /* Still none? Use the Set-Cookie: header. I feel a little | ||
315 | * guilty about this, because some clients refuse cookies. The | ||
316 | * log will in their cases log a ton of different Set-Cookie requests | ||
317 | * that aren't being honored. However, it's necessary to insert this | ||
318 | * check so that the first request of a series doesn't log a - ... | ||
319 | */ | ||
320 | else if ( (cookiestr = table_get(r->headers_out, "set-cookie")) ) { | ||
321 | cookieend = strchr(cookiestr, ';'); | ||
322 | if (cookieend) | ||
323 | *cookieend = '\0'; | ||
324 | return cookiestr; | ||
325 | } | ||
326 | 417 | ||
327 | /* Okay, fine, no eligible headers. Return a - instead. | 418 | cookiestr = table_get(r->headers_out, "set-cookie"); |
328 | * I /could/ insert a look for the Set-Cookie2: header here, but I think | 419 | if (cookiestr != NULL) { |
329 | * it would be imprudent. It's apparent that the current browsers don't | 420 | #ifdef DEBUG |
330 | * support Cookie2 cookies, so why bother logging a bunch of Set-Cookie2: | 421 | ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_mysql: Set-Cookie: [%s]", cookiestr); |
331 | * requests that aren't even going to be honored? | 422 | #endif |
332 | */ | 423 | isvalid = strstr(cookiestr, cookie_name); |
333 | else { | 424 | if (isvalid != NULL) { |
334 | return "-"; | 425 | isvalid += strlen(cookie_name) + 1; |
335 | } | 426 | cookiebuf = ap_pstrdup(r->pool, isvalid); |
427 | cookieend = strchr(cookiebuf, ';'); | ||
428 | if (cookieend != NULL) | ||
429 | *cookieend = '\0'; | ||
430 | return cookiebuf; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | return "-"; | ||
336 | } | 435 | } |
337 | 436 | ||
437 | |||
338 | const char *log_request_timestamp(request_rec *r, char *a) | 438 | const char *log_request_timestamp(request_rec *r, char *a) |
339 | { | 439 | { |
340 | char tstr[32]; | 440 | char tstr[32]; |
@@ -352,7 +452,7 @@ static const char *log_env_var(request_rec *r, char *a) | |||
352 | { | 452 | { |
353 | return table_get(r->subprocess_env, a); | 453 | return table_get(r->subprocess_env, a); |
354 | } | 454 | } |
355 | #endif | 455 | #endif /* MODULE_MAGIC_NUMBER */ |
356 | 456 | ||
357 | 457 | ||
358 | /* End declarations of various log_ functions */ | 458 | /* End declarations of various log_ functions */ |
@@ -371,10 +471,12 @@ struct log_mysql_item_list { | |||
371 | { 'c', log_cookie, "cookie", 0, 1 }, | 471 | { 'c', log_cookie, "cookie", 0, 1 }, |
372 | { 'e', log_env_var, "env_var", 0, 1 }, | 472 | { 'e', log_env_var, "env_var", 0, 1 }, |
373 | { 'f', log_request_file, "request_file", 0, 1 }, | 473 | { 'f', log_request_file, "request_file", 0, 1 }, |
374 | { 'h', log_remote_host, "remote_host", 0, 1 }, | 474 | { 'H', log_request_protocol, "request_protocol", 0, 1 }, |
475 | { 'h', log_remote_host, "remote_host", 0, 1 }, | ||
375 | { 'i', log_header_in, "header_in", 0, 1 }, | 476 | { 'i', log_header_in, "header_in", 0, 1 }, |
376 | { 'l', log_remote_logname, "remote_logname", 0, 1 }, | 477 | { 'l', log_remote_logname, "remote_logname", 0, 1 }, |
377 | { 'n', log_note, "note", 0, 1 }, | 478 | { 'm', log_request_method, "request_method", 0, 1 }, |
479 | { 'n', log_note, "note", 0, 1 }, | ||
378 | { 'o', log_header_out, "header_out", 0, 1 }, | 480 | { 'o', log_header_out, "header_out", 0, 1 }, |
379 | { 'P', log_child_pid, "child_pid", 0, 0 }, | 481 | { 'P', log_child_pid, "child_pid", 0, 0 }, |
380 | { 'p', log_server_port, "server_port", 0, 0 }, | 482 | { 'p', log_server_port, "server_port", 0, 0 }, |
@@ -387,6 +489,11 @@ struct log_mysql_item_list { | |||
387 | { 'u', log_remote_user, "remote_user", 0, 1 }, | 489 | { 'u', log_remote_user, "remote_user", 0, 1 }, |
388 | { 'U', log_request_uri, "request_uri", 1, 1 }, | 490 | { 'U', log_request_uri, "request_uri", 1, 1 }, |
389 | { 'v', log_virtual_host, "virtual_host", 0, 1 }, | 491 | { 'v', log_virtual_host, "virtual_host", 0, 1 }, |
492 | #ifdef WANT_SSL_LOGGING | ||
493 | { 'q', log_ssl_keysize, "ssl_keysize", 0, 1 }, | ||
494 | { 'Q', log_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 }, | ||
495 | { 'z', log_ssl_cipher, "ssl_cipher", 0, 1 }, | ||
496 | #endif | ||
390 | {'\0'} | 497 | {'\0'} |
391 | }; | 498 | }; |
392 | 499 | ||
@@ -521,6 +628,12 @@ const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg) | |||
521 | return NULL; | 628 | return NULL; |
522 | } | 629 | } |
523 | 630 | ||
631 | const char *set_log_mysql_cookie(cmd_parms *parms, void *dummy, char *arg) | ||
632 | { | ||
633 | cookie_name = arg; | ||
634 | return NULL; | ||
635 | } | ||
636 | |||
524 | const char *set_log_mysql_info(cmd_parms *parms, void *dummy, char *host, char *user, char *pwd) | 637 | const char *set_log_mysql_info(cmd_parms *parms, void *dummy, char *host, char *user, char *pwd) |
525 | { | 638 | { |
526 | if (*host != '.') { | 639 | if (*host != '.') { |
@@ -570,32 +683,35 @@ const char *add_remhost_mysql_ignore(cmd_parms *parms, void *dummy, char *arg) | |||
570 | } | 683 | } |
571 | 684 | ||
572 | command_rec log_mysql_cmds[] = { | 685 | command_rec log_mysql_cmds[] = { |
573 | {"RefererLogMySQLTable", set_referer_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 686 | {"MySQLRefererLogTable", set_referer_log_mysql_table, NULL, RSRC_CONF, TAKE1, |
574 | "the table of the referer log"} | 687 | "The MySQL table that holds the referer log"} |
688 | , | ||
689 | {"MySQLAgentLogTable", set_agent_log_mysql_table, NULL, RSRC_CONF, TAKE1, | ||
690 | "The MySQL table that holds the agent log"} | ||
575 | , | 691 | , |
576 | {"AgentLogMySQLTable", set_agent_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 692 | {"MySQLTransferLogTable", set_transfer_log_mysql_table, NULL, RSRC_CONF, TAKE1, |
577 | "the table of the agent log"} | 693 | "The MySQL table that holds the transfer log"} |
578 | , | 694 | , |
579 | {"TransferLogMySQLTable", set_transfer_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 695 | {"MySQLTransferLogFormat", set_transfer_log_format, NULL, RSRC_CONF, TAKE1, |
580 | "the table of the transfer log"} | 696 | "Instruct the module what information to log to the MySQL transfer log"} |
581 | , | 697 | , |
582 | {"TransferLogMySQLFormat", set_transfer_log_format, NULL, RSRC_CONF, TAKE1, | 698 | {"MySQLRefererIgnore", add_referer_mysql_ignore, NULL, RSRC_CONF, ITERATE, |
583 | "specific format for the MySQL transfer log"} | 699 | "List of referers to ignore, accesses that match will not be logged to MySQL"} |
584 | , | 700 | , |
585 | {"RefererIgnore", add_referer_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 701 | {"MySQLRequestIgnore", add_transfer_mysql_ignore, NULL, RSRC_CONF, ITERATE, |
586 | "referer hostnames to ignore"} | 702 | "List of URIs to ignore, accesses that match will not be logged to MySQL"} |
587 | , | 703 | , |
588 | {"RequestIgnore", add_transfer_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 704 | {"MySQLRemhostIgnore", add_remhost_mysql_ignore, NULL, RSRC_CONF, ITERATE, |
589 | "transfer log URIs to ignore"} | 705 | "List of remote hosts to ignore, accesses that match will not be logged to MySQL"} |
590 | , | 706 | , |
591 | {"RemhostIgnore", add_remhost_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 707 | {"MySQLDatabase", set_log_mysql_db, NULL, RSRC_CONF, TAKE1, |
592 | "transfer log remote hosts to ignore"} | 708 | "The name of the MySQL database for logging"} |
593 | , | 709 | , |
594 | {"LogMySQLDB", set_log_mysql_db, NULL, RSRC_CONF, TAKE1, | 710 | {"MySQLWhichCookie", set_log_mysql_cookie, NULL, RSRC_CONF, TAKE1, |
595 | "the database of the referer log"} | 711 | "The CookieName that you want logged when using the 'c' config directive"} |
596 | , | 712 | , |
597 | {"LogMySQLInfo", set_log_mysql_info, NULL, RSRC_CONF, TAKE3, | 713 | {"MySQLLoginInfo", set_log_mysql_info, NULL, RSRC_CONF, TAKE3, |
598 | "host, user and password for MySQL link"} | 714 | "The MySQL host, user-id and password for logging"} |
599 | , | 715 | , |
600 | {NULL} | 716 | {NULL} |
601 | }; | 717 | }; |
@@ -622,17 +738,17 @@ int safe_mysql_query(request_rec *r, const char *query) | |||
622 | 738 | ||
623 | { /* We need to restart the server link */ | 739 | { /* We need to restart the server link */ |
624 | mysql_log = NULL; | 740 | mysql_log = NULL; |
625 | log_error("MySQL: connection lost, attempting reconnect", r->server); | 741 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: connection lost, attempting reconnect"); |
626 | 742 | ||
627 | open_log_dblink(); | 743 | open_log_dblink(); |
628 | 744 | ||
629 | if (mysql_log == NULL) { /* still unable to link */ | 745 | if (mysql_log == NULL) { /* still unable to link */ |
630 | signal(SIGPIPE, handler); | 746 | signal(SIGPIPE, handler); |
631 | log_error("MySQL: reconnect failed.", r->server); | 747 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect failed."); |
632 | return error; | 748 | return error; |
633 | } | 749 | } |
634 | 750 | ||
635 | log_error("MySQL: reconnect successful.", r->server); | 751 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect successful."); |
636 | error = mysql_query(mysql_log, query); | 752 | error = mysql_query(mysql_log, query); |
637 | } | 753 | } |
638 | 754 | ||
@@ -652,11 +768,11 @@ int safe_mysql_query(request_rec *r, const char *query) | |||
652 | 768 | ||
653 | if (error) { | 769 | if (error) { |
654 | str = pstrcat(r->pool, "MySQL query failed: ", query, NULL); | 770 | str = pstrcat(r->pool, "MySQL query failed: ", query, NULL); |
655 | log_error(str, r->server); | 771 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str); |
656 | str = pstrcat(r->pool, "MySQL failure reason: ", MYSQL_ERROR(mysql_log), NULL); | 772 | str = pstrcat(r->pool, "MySQL failure reason: ", MYSQL_ERROR(mysql_log), NULL); |
657 | log_error(str, r->server); | 773 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str); |
658 | } else { | 774 | } else { |
659 | log_error("MySQL: INSERT successful after a delayed retry.", r->server); | 775 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: insert successful after a delayed retry."); |
660 | } | 776 | } |
661 | } | 777 | } |
662 | return error; | 778 | return error; |
@@ -775,7 +891,7 @@ int log_mysql_transaction(request_rec *orig) | |||
775 | 891 | ||
776 | /* If not specified by the user, use the default format */ | 892 | /* If not specified by the user, use the default format */ |
777 | if (cls->transfer_log_format[0] == '\0') { | 893 | if (cls->transfer_log_format[0] == '\0') { |
778 | cls->transfer_log_format = "huSUsbTvRA"; | 894 | cls->transfer_log_format = "AbHhmRSsTUuv"; |
779 | } | 895 | } |
780 | length = strlen(cls->transfer_log_format); | 896 | length = strlen(cls->transfer_log_format); |
781 | 897 | ||