GNUmakefile.in 36.8 KB
Newer Older
Russ Fish's avatar
Russ Fish committed
1 2
#
# Copyright (c) 2000-2006 University of Utah and the Flux Group.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
Russ Fish's avatar
Russ Fish committed
22
#
23

Russ Fish's avatar
Russ Fish committed
24
# Top-level targets:
25 26
# "activate" isn't in "all" because it's a setup task that shouldn't be repeated.
all_tasks = src_forms spider forms_coverage input_coverage normal probe
Russ Fish's avatar
Russ Fish committed
27
# Stats from the top-level tasks:
28
msgs_tasks = src_msg site_msg forms_msg input_msg analyze probes_msg
29
.PHONY: activate all $(all_tasks) msgs $(msgs_tasks)
30 31

# See README-howto.txt for usage details.
32 33
all: $(all_tasks)
msgs: $(msgs_tasks)
Russ Fish's avatar
Russ Fish committed
34

35 36 37 38
# Notice that the output lists are put into the results subdir of the source dir.
# Spidered HTML pages go in (subdirs of) the obj dir.
#

Russ Fish's avatar
Russ Fish committed
39
SRCDIR		= @srcdir@
Russ Fish's avatar
Russ Fish committed
40 41
RESDIR		= $(SRCDIR)/results

Russ Fish's avatar
Russ Fish committed
42 43 44 45 46 47 48
TESTBED_SRCDIR	= @top_srcdir@

OBJDIR		= ../..
SUBDIR		= www/sec-check
SRCWWW		= $(TESTBED_SRCDIR)/www

OURDOMAIN       = @OURDOMAIN@
49

50 51
include $(TESTBED_SRCDIR)/GNUmakerules

52 53
# Delete a target file if the command fails in the middle of changing it.
.DELETE_ON_ERROR:
Russ Fish's avatar
Russ Fish committed
54 55

#================================================================
Russ Fish's avatar
Russ Fish committed
56
# src_forms: Grep the sources for <form and make up a list of php form files.
57
#
58
src_forms: src_list src_msg
Russ Fish's avatar
Russ Fish committed
59

Russ Fish's avatar
Russ Fish committed
60 61
SRC_FORMS	= $(RESDIR)/src_forms.list
SRC_FILES	= $(RESDIR)/src_files.list
62
src_list: $(SRC_FORMS) $(SRC_FILES)
63 64

# All of the forms lines.
65 66
$(SRC_FORMS):
	# Ignore any Emacs backup files with tilde's in the filenames.
Russ Fish's avatar
Russ Fish committed
67 68 69
	(cd $(SRCWWW); \
	  find . -maxdepth 1 -name '*.php*' -print0 | \
	    xargs -0 grep -n '<form' | fgrep -v /save/ | \
70
	    sed '/^[^:]*~/d' ) | sort > $(SRC_FORMS)
71 72

# Just the files list.
73 74 75 76
$(SRC_FILES): $(SRC_FORMS)
	# Just filenames; get rid of the "./" prefix and ":<lnum>: <form" suffix.
	sed -e 's|^[^:]*/||' -e 's|:.*||' $(SRC_FORMS) | uniq > $(SRC_FILES)

77
# Dump a stats message.
78
src_msg: src_list
79
	@echo "** Sources: `wc -l < $(SRC_FORMS)` separate forms" \
Russ Fish's avatar
Russ Fish committed
80
	     "are on `wc -l < $(SRC_FILES)` code pages. **" | tr -s " "
81 82
	@echo "** (See $(notdir $(SRC_FORMS)) and $(notdir $(SRC_FILES))"
	@echo "**  in $(RESDIR) .) **"
Russ Fish's avatar
Russ Fish committed
83
	@echo "**"
Russ Fish's avatar
Russ Fish committed
84 85

#================================================================
86
# Lots of common stuff for wget.
87
#
88
.PHONY: login admin logout
Russ Fish's avatar
Russ Fish committed
89

90 91 92 93 94
# Need an Emulab-in-Emulab experiment running, e.g. vulnElab.ns .
EinE_proj	= testbed
EinE_exp	= vulnElab
EinE_boss	= myboss
EinE_ops	= myops
Russ Fish's avatar
Russ Fish committed
95 96 97 98

# Login info for the inner Emulab.
uid		= $(USER)
### It's better to log in a browser and change your password in Edit Profile
99
### in the inner Elab to this string, than to put a real password here!
Russ Fish's avatar
Russ Fish committed
100
pswd		= EinE_tmp
101

102
# Real email address for confirmation messages.
Russ Fish's avatar
Russ Fish committed
103 104
email_dest	= flux.utah.edu
real_email	= $(uid)@$(email_dest)
105
# Another one, because they have to be unique in the inner Elab now.
106 107
email_dest2	= cs.utah.edu
real_email2	= $(uid)@$(email_dest2)
Russ Fish's avatar
Russ Fish committed
108

109
# Machine paths.
Russ Fish's avatar
Russ Fish committed
110
dom		= $(EinE_proj).$(OURDOMAIN)
111 112 113 114
boss		= $(EinE_boss).$(EinE_exp).$(dom)
ops		= $(EinE_ops).$(EinE_exp).$(dom)
root		= http://$(boss)
sroot		= https://$(boss)
Russ Fish's avatar
Russ Fish committed
115

116
# Cookie state stuff for wget.
Russ Fish's avatar
Russ Fish committed
117 118 119
COOKIES		= cookies.txt
sv_cookies	= --save-cookies $(COOKIES)
ld_cookies	= --load-cookies $(COOKIES)
120 121 122
ld_cookies_subdir = --load-cookies ../$(COOKIES)
cookie_args	= --keep-session-cookies --no-check-certificate
wget_args	= -S -k $(cookie_args) $(ld_cookies)
Russ Fish's avatar
Russ Fish committed
123
wget_args_subdir= -S -k $(cookie_args) $(ld_cookies_subdir)
124

125 126
# Patterns to categorize the HTML result.
analysis_patterns = $(SRCDIR)/success.txt $(SRCDIR)/failure.txt $(SRCDIR)/problem.txt
127 128 129
success_cmd = grep -f $(SRCDIR)/success.txt
FAIL_FILE = failure.txt
failure_cmd = grep -f $(SRCDIR)/$(FAIL_FILE)
Russ Fish's avatar
Russ Fish committed
130

131
# Log in and create a current cookies.txt file.
Russ Fish's avatar
Russ Fish committed
132 133
# Args are uid and password.  The password must match your login (see above.)
logindir = logins
134 135
login_user = @ echo ==== Logging in as $(1) ; \
	if [ ! -d $(logindir) ]; then mkdir $(logindir); fi; \
Russ Fish's avatar
Russ Fish committed
136 137
	wget -S -dv $(cookie_args) $(sv_cookies) \
	-o $(logindir)/login.log -O $(logindir)/login_$(1).html \
138
	--post-data "uid=$(1)&password=$(2)&login=Login" \
Russ Fish's avatar
Russ Fish committed
139 140 141 142
	$(sroot)/login.php3; \
	if $(failure_cmd) $(logindir)/login_$(1).html; then \
	      (echo "*** LOGIN FAILURE"; exit 1); \
	fi
143
login_sys := $(call login_user,$(uid),$(pswd))
Russ Fish's avatar
Russ Fish committed
144
login: logout
145 146 147
	$(login_sys)

# Log in above, then use this to toggle the admin bit on.
148 149
admin_cmd = @ echo ==== Turning on admin privs; \
	if [ ! -d $(logindir) ]; then mkdir $(logindir); fi; \
Russ Fish's avatar
Russ Fish committed
150 151 152 153 154 155
	wget -S -dv $(cookie_args) $(ld_cookies) \
	-o $(logindir)/admin.log -O $(logindir)/admin.html \
	"$(sroot)/toggle.php?target_uid=$(uid)&type=adminon&value=1"; \
	if $(failure_cmd) $(logindir)/admin.html; then \
	      (echo "*** ADMIN FAILURE"; exit 1); \
	fi 
156 157 158 159
admin: login
	$(admin_cmd)

# Must be logged out to see the public view.
160 161
logout_cmd = @ echo ==== Logging out; \
	if [ ! -d $(logindir) ]; then mkdir $(logindir); fi; \
Russ Fish's avatar
Russ Fish committed
162 163
	wget -S -dv $(cookie_args) $(ld_cookies)\
	-o $(logindir)/logout.log -O $(logindir)/logout.html \
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
	"$(sroot)/logout.php3?target_uid=$(uid)"
logout:
	$(logout_cmd)

#================================================================
# Factored-out commands for the "call" function.

# Format html args separated by a single space into an argument string with &'s.
# Putting them on separate lines with a backslash also results in a single space.
#
# The $(empty) var trick allows a subst arg of " " (a single space.)
# Found in the GNU make info node for Syntax of Functions.
empty :=
# Encode backslashed spaces in strings as %20, and double-quotes as %22.
fmt_html_args = $(subst $(empty) ,&,$(subst \ ,%20,$(subst \",%22,$(strip $(1)))))

# Post a form via wget and check the returned page.
181
# Args are [root],php_infile,[html_outfile],html_args,[run_time_args] .
182
# root defaults to $(sroot) .  html_outfile defaults to php_infile.html .
Russ Fish's avatar
Russ Fish committed
183
# The run_time_args are good for e.g. a repeatedly referenced db item.
Russ Fish's avatar
Russ Fish committed
184
outdir = activate.wget
185
define wget_post
Russ Fish's avatar
Russ Fish committed
186
	@ if [ ! -d $(outdir) ]; then mkdir $(outdir); fi
187 188
	@ root_dir=$(strip $(1)); \
	  php_infile=$(strip $(2)); \
Russ Fish's avatar
Russ Fish committed
189
	  html_outfile=$(strip $(3)); \
190
	  $(if $(5),$(5);) \
Russ Fish's avatar
Russ Fish committed
191
	  post_args="$(call fmt_html_args, $(4))"; \
Russ Fish's avatar
Russ Fish committed
192 193
	  echo "==== $(outdir) $${root_dir} $${php_infile}" \
		    "$${html_outfile:=$(2).html} ===="; \
Russ Fish's avatar
Russ Fish committed
194
	  echo "cd $(outdir); wget $(wget_args_subdir) \
Russ Fish's avatar
Russ Fish committed
195
	    -O $${html_outfile} \
Russ Fish's avatar
Russ Fish committed
196 197 198 199 200
	    -o $${html_outfile}.log \
	    --post-data '$${post_args}' \
	    $${root_dir:-$(sroot)}/$${php_infile}" \
	    > $(outdir)/$${html_outfile}.cmd; \
	  sh $(outdir)/$${html_outfile}.cmd; \
201
	  if $(failure_cmd) $(outdir)/$${html_outfile}; then \
Russ Fish's avatar
Russ Fish committed
202
	      (echo "*** FAILURE"; exit 1); \
203 204
	  elif $(success_cmd) $(outdir)/$${html_outfile}; then \
	      echo "* SUCCESS"; \
Russ Fish's avatar
Russ Fish committed
205 206
	  else echo "*** UNKNOWN RESULT"; \
	  fi
207 208
endef

Russ Fish's avatar
Russ Fish committed
209 210
# Send an SQL command to myboss.  The value is the last line if more than one.
# Commas separate "$(call" args.  Embed them into an arg with a variable $(comma).
211
comma := ,
212
boss_sql = echo "$(strip $(1))" | ssh $(boss) mysql tbdb | tail -1
213 214

#================================================================
Russ Fish's avatar
Russ Fish committed
215
# activate: Set up the newly swapped-in EinE site to turn on as many forms as we can.
216 217 218 219
#
### Don't forget to first log in a browser and change your password in Edit Profile
### in the inner Elab to match the string given above as $(pswd).
#
220
activate_tasks = fix_emails new_proj1 new_proj2 approve_proj new_group \
Russ Fish's avatar
Russ Fish committed
221 222
	  new_user1 confirm_user1 approve_user1 \
	  new_user2 confirm_user2 \
223
	  new_exp2 new_exp1 mod_exp2 \
224
	  new_nodetype new_osid new_imageid
225
.PHONY:   $(activate_tasks)
226
#
227 228 229 230 231 232
activate: activate.wget $(activate_tasks) analyze_activate

activate.wget:
	- rm -rf activate.wget.prev
	- mv -f activate.wget activate.wget.prev
	mkdir activate.wget
233 234 235 236 237 238 239 240 241 242 243

proj_common = $(call fmt_html_args,\
	    formfields[proj_URL]=$(root)\
	    formfields[proj_funders]=none\
	    formfields[proj_linked]=checked\
	    formfields[proj_members]=1\
	    formfields[proj_pcs]=3\
	    formfields[proj_public]=checked\
	    formfields[proj_why]=Test\ for\ injection.\
	    formfields[proj_whynotpublic]=\
	    submit=Submit)
244

245 246
# Also change all user e-mail addresses to me so I get the editgroup, etc. e-mail
# instead of bothering everybody else on testbed-ops.  This is *not* the primary
247
# e-mail address used as my login to Emulab $(real_email), which *has to be unique*!
248 249 250 251 252 253 254 255
fix_emails:
	@echo ==== Fixing email addresses ====
	echo "select uid, usr_email from users where usr_email not like '%@myops%'; \
	      update users set usr_email='$(real_email2)' \
	        where uid != '$(uid)' and usr_email not like '%@myops%'; \
	      select uid, usr_email from users where usr_email not like '%@myops%';" | \
	    ssh $(boss) mysql --table tbdb

256
# Start *two* test projects.
257
# Leave testproj2 unapproved so approveproject_form.php3 remains active.
258 259 260 261 262 263 264
proj1 = testproj
new_proj1: admin
	$(call wget_post,,newproject.php3,newproj1.html,\
	    formfields[pid]=$(proj1)\
	    formfields[proj_name]=$(proj1)\ description.\
	    $(proj_common))
# Assume we stay logged in and toggled to admin.
265
# Otherwise, each time looks like a separate browser login in the session DB.
266 267 268 269 270 271 272 273 274 275 276 277 278 279
proj2 = testproj2
new_proj2:
	$(call wget_post,,newproject.php3,newproj2.html,\
	    formfields[pid]=$(proj2)\
	    formfields[proj_name]=$(proj2)\ description.\
	    $(proj_common))

# Approve one test project.  (Takes a couple of minutes to run.)
approve_proj:
	$(call wget_post,,approveproject.php3,,\
	    pid=$(proj1) approval=approve OK=Submit\
	    head_uid= user_interface=emulab pcplab_okay=Yep ron_okay=Yep message=)

# Create a subgroup of the test project.  (Takes a few seconds to run.)
280
grp1 = testgroup
281 282
new_group:
	$(call wget_post,,newgroup.php3,,\
283 284 285 286 287
	    project=$(proj1)\
	    formfields[group_id]=$(grp1)\
	    formfields[group_leader]=$(uid)\
	    formfields[group_description]=$(proj1)\ subgroup.\
	    submit=Submit)
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304

user_common = $(call fmt_html_args,\
	    formfields[usr_title]=Tester\
	    formfields[usr_affil]=Emulab\ Scripts\
	    formfields[usr_URL]=http://www.emulab.net\
	    formfields[usr_addr]=Silly\
	    formfields[usr_addr2]=Address\
	    formfields[usr_city]=Salt\ Lake\ Silly\
	    formfields[usr_state]=UT\
	    formfields[usr_zip]=12345\
	    formfields[usr_country]=USA\
	    formfields[usr_phone]=(801)\ 123-4567\
	    formfields[password1]=user_pswd\
	    formfields[password2]=user_pswd\
	    formfields[pid]=$(proj1)\
	    formfields[gid]=\
	    submit=Submit)
305 306 307 308

# Make new users.  (Use http, not https; not logged in, join a project.)
# Do testuser and testusr2.
# Leave testusr2 unapproved (but confirmed) so approveuser_form.php3 is active.
309 310
usr1 = testuser
name1 = Test User 1
311 312
new_user1: ###logout
	$(logout_cmd)
313 314 315 316
	$(call wget_post,$(root),joinproject.php3,newuser1.html,\
	    formfields[joining_uid]=$(usr1)\
	    formfields[usr_name]=$(subst $(empty) ,\ ,$(name1))\
	    formfields[wikiname]=$(subst $(empty) ,,$(name1))\
Russ Fish's avatar
Russ Fish committed
317
	    formfields[usr_email]=$(subst $(empty) ,,$(name1))@$(email_dest)\
318
	    $(user_common))
319 320
	$(login_sys)
	$(admin_cmd)
Russ Fish's avatar
Russ Fish committed
321 322 323 324 325 326
# Pretend the user sent in his e-mail confirmation.
confirm_user1:
	$(call boss_sql,\
	    update users set status='unapproved' where uid='$(usr1)')
query_user1:
	$(call boss_sql,\
327
	    select uid$(comma) uid_idx$(comma) usr_name$(comma) status \
Russ Fish's avatar
Russ Fish committed
328
	      from users where uid='$(usr1)')
329 330
usr2 = testusr2
name2 = Test User 2
331 332
new_user2: ###logout
	$(logout_cmd)
333
	$(call wget_post,,joinproject.php3,newuser2.html,\
334 335 336 337
	    formfields[joining_uid]=$(usr2)\
	    formfields[usr_name]=$(subst $(empty) ,\ ,$(name2))\
	    formfields[wikiname]=$(subst $(empty) ,,$(name2))\
	    formfields[usr_email]=never.approve@nowhere.net\
338
	    $(user_common))
339 340
	$(login_sys)
	$(admin_cmd)
341
# Pretend the user sent in his e-mail confirmation.
Russ Fish's avatar
Russ Fish committed
342
confirm_user2:
343
	$(call boss_sql,\
Russ Fish's avatar
Russ Fish committed
344 345
	    update users set status='unapproved' where uid='$(usr2)')
query_user2:
346
	$(call boss_sql,\
347
	    select uid$(comma) uid_idx$(comma) usr_name$(comma) status \
Russ Fish's avatar
Russ Fish committed
348
	      from users where uid='$(usr2)')
349

350 351 352
# Approve a new user, Takes a couple of minutes to run.  %24 is "$", %2F is "/".
# Get the uid_idx for the user from the db on the inner boss at run time.
usr1_sql = $(call boss_sql, select uid_idx from users where uid='$(usr1)')
353
# Gotta log back in after being logged out above.
354
approve_user1:
355
	$(call wget_post,,approveuser.php3,appusr1.html,\
356 357
	    U$$usr1_idx%24%24approval-$(proj1)%2F$(proj1)=approve\
	    U$$usr1_idx%24%24trust-$(proj1)%2F$(proj1)=local_root\
358
	    OK=Submit,\
359
	    usr1_idx=`$(usr1_sql)`)
360 361 362 363 364 365 366 367 368

exp_common =  $(call fmt_html_args,\
	    beginexp=Submit\
	    formfields[exp_pid]=$(EinE_proj)\
	    formfields[exp_gid]=\
	    MAX_FILE_SIZE=512000\
	    formfields[exp_localnsfile]=/users/$(USER)/shaped-2-nodes.ns\
	    formfields[exp_swappable]=1\
	    formfields[exp_noswap_reason]=\
Russ Fish's avatar
Russ Fish committed
369
	    formfields[exp_idleswap]=0\
370
	    formfields[exp_idleswap_timeout]=4\
Russ Fish's avatar
Russ Fish committed
371 372
	    formfields[exp_noidleswap_reason]=Because\
	    formfields[exp_autoswap]=0\
373
	    formfields[exp_autoswap_timeout]=16\
374 375 376 377 378 379 380 381 382 383 384 385 386
	    formfields[exp_linktest]=0)

# Make an experiment via ssh and leave it not swapped in.
# (Do exp2 before exp1 so exp2 can finish creating before we do modifyexp on it.)
exp2 = testexp2
new_exp2:
	@echo ==== Creating $(exp2) ====
	scp -p $(SRCDIR)/shaped-2-nodes.ns $(ops):
	ssh $(ops) 'startexp -w -f -E "$(exp2) experiment." \
	    -p $(EinE_proj) -e $(exp2) shaped-2-nodes.ns'

# Make another new experiment.  Takes a few minutes to swap in.
# Must have at least one delay node for Traffic Shaping and Link Tracing pages.
387 388 389 390 391 392 393 394 395 396 397 398 399
exp1 = testexp1
new_exp1:
	scp -p $(SRCDIR)/shaped-2-nodes.ns $(ops):
	$(call wget_post,,beginexp_html.php3,newexp1.html,\
	    formfields[exp_id]=$(exp1)\
	    formfields[exp_description]=$(exp1)\ experiment.\
	    $(exp_common))

# Modify an experiment (first time creates an archive.)
mod_exp2:
	$(call wget_post,,modifyexp.php3,modexp2.html,\
	    pid=$(EinE_proj) eid=$(exp2) go=1\
	    MAX_FILE_SIZE=512000\
400
	    exp_localnsfile=/users/$(USER)/shaped-2-nodes.ns\
401 402 403
	    reboot=1\
	    eventrestart=1)

404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
# Create a nodetype to edit.
new_nodetype:
	-$(call boss_sql, \
	    delete from node_types where type like 'pc%test')
	-$(call boss_sql, \
	    delete from node_type_attributes where type like 'pc%test')
	-$(call boss_sql, \
	    delete from node_types_auxtypes where auxtype like 'pc%test')
	$(call wget_post,,editnodetype.php3,newnodetype.html,\
	    new_type=1\
	    node_type=pctest\
	    formfields[class]=pc\
	    formfields[isdynamic]=0\
	    formfields[issubnode]=0\
	    formfields[isplabdslice]=0\
	    formfields[isjailed]=0\
	    formfields[isremotenode]=0\
	    formfields[isvirtnode]=0\
	    formfields[issimnode]=0\
	    newattribute_name=testattr\
	    newattribute_type=integer\
	    newattribute_value=42\
	    submit=Submit)

# Create OS and image ID's to edit.
os1 = testosid
new_osid:
	$(call wget_post,,newosid.php3,newosid.html,\
432 433 434 435 436 437 438 439 440 441 442 443 444
	    formfields[pid]=$(proj1)\
	    formfields[osname]=$(os1)\
	    formfields[os_feature_isup]=checked\
	    formfields[magic]=\
	    formfields[path]=\
	    formfields[version]=666\
	    formfields[nextosid]=\
	    formfields[os_feature_veths]=checked\
	    formfields[os_feature_ping]=checked\
	    formfields[os_feature_ipod]=checked\
	    formfields[OS]=FreeBSD\
	    formfields[os_feature_linktest]=checked\
	    formfields[os_feature_mlinks]=checked\
445
	    formfields[mustclean]=1\
446 447 448
	    formfields[op_mode]=NORMALv2\
	    formfields[description]=Test OS description.\
	    formfields[reboot_waittime]=150\
449
	    formfields[shared]=1\
450 451 452
	    formfields[os_feature_linkdelays]=checked\
	    formfields[os_feature_ssh]=checked\
	    submit=Submit)
Russ Fish's avatar
Russ Fish committed
453 454 455 456
os1_osid_sql = $(call boss_sql, \
	select osid from os_info where pid='$(proj1)' and osname='$(os1)')
show_os1_osid:
	echo `$(os1_osid_sql)`
457 458 459 460 461 462 463 464
img1 = testimg
new_imageid:
	$(call wget_post,,newimageid.php3,newimageid.html,\
	    formfields[imagename]=$(img1)\
	    formfields[pid]=$(proj1)\
	    formfields[gid]=\
	    formfields[path]=/proj/testbed/images/$(img1).ndz\
	    formfields[loadlength]=1\
Russ Fish's avatar
Russ Fish committed
465 466 467
	    formfields[default_osid]=$$os1_osid\
	    formfields[part1_osid]=$$os1_osid\
	    formfields[mtype_pc600]=Yep\
468 469 470 471 472
	    formfields[mtype_pc850]=Yep\
	    formfields[makedefault]=Yep\
	    formfields[loadpart]=1\
	    formfields[node]=\
	    formfields[description]=Descriptive text.\
Russ Fish's avatar
Russ Fish committed
473 474
	    submit=Submit,\
	    os1_osid=`$(os1_osid_sql)`)
475

476 477 478 479 480 481
# Re-use the analysis action, running it in the activate.wget subdirectory.
analyze_activate: $(analysis_patterns)
	@cd activate.wget && $(MAKE) -f ../GNUmakefile --no-print-directory \
	    analysis_kind=Activation analyze_output=../$(ACTIVATE_ANALYSIS) \
	    SRCDIR=../$(SRCDIR) TESTBED_SRCDIR=../$(TESTBED_SRCDIR) \
	    analyze_msg
482 483
ACTIVATE_ANALYSIS = $(RESDIR)/analyze_activate.txt

484
#================================================================
Russ Fish's avatar
Russ Fish committed
485
# spider: Recursively a copy of the EinE site with wget and extract its forms list.
486 487
#
# Actually, spider it twice, once not logged in for the public view,
488 489 490
# and again, logged in and with administrative privileges, for the private view.
#
# The object here is to find and scan the forms, not execute them yet.
491 492 493
#
spider_tasks = clear_wget_dirs do_spider site_list site_msg
.PHONY: $(spider_tasks)
494
#
495
spider: $(spider_tasks)
Russ Fish's avatar
Russ Fish committed
496

Russ Fish's avatar
Russ Fish committed
497 498 499
# Login/admin mode changes are handled explicitly in the "activate:" target, and
# as "!actions" in the {setup,teardown}_forms.list specs controlling sep-urls.gawk .
#
500
# Don't follow page links that change the login/admin state here.
Russ Fish's avatar
Russ Fish committed
501
# Also reject other links to pages which don't have any input fields, and don't ask
502
# for confirmation before taking actions.  These must be tested specially.
503
top_links	= login.php3,logout.php3,toggle.php,pagenotworking.php
Russ Fish's avatar
Russ Fish committed
504 505 506
user_links	= suuser.php,sendtestmsg.php3
exp_links	= showlogfile.php3,request_idleinfo.php3,request_swapexp.php3
node_links	= nodetipacl.php3,showconlog.php3,nodessh.php3
507 508
linkmon_links	= spewevents.php,linkmon_mon.php3 
rej_links	= \
Russ Fish's avatar
Russ Fish committed
509
	.txt,$(top_links),$(user_links),$(exp_links),$(node_links),$(linkmon_links)
Russ Fish's avatar
Russ Fish committed
510

511
# Clear out wget subdirectories so we aren't confused by results of old runs.
512
wget_dirs	= public.wget admin.wget probes.wget
513
.PHONY: $(wget_dirs)
514
#
515
clear_wget_dirs: $(wget_dirs)
516

517 518 519 520 521 522 523 524
public.wget:
	- rm -rf public.wget.prev
	- mv -f public.wget public.wget.prev
	mkdir public.wget
admin.wget:
	- rm -rf admin.wget.prev
	- mv -f admin.wget admin.wget.prev
	mkdir admin.wget
525 526 527 528
probes.wget:
	- rm -rf probes.wget.prev
	- mv -f probes.wget probes.wget.prev
	mkdir -p probes.wget/undo
Russ Fish's avatar
Russ Fish committed
529

530 531 532
# Finally ready to grab the whole site.
.PHONY:    public_spider admin_spider
do_spider: public_spider admin_spider
Russ Fish's avatar
Russ Fish committed
533

534
public_spider: public.wget/public.log
535 536
public.wget/public.log: 
	$(logout_cmd)
Russ Fish's avatar
Russ Fish committed
537
	@ echo ==== Spidering the public interface.
538 539 540 541
	cd public.wget; \
	wget -r -S $(cookie_args) $(ld_cookies_subdir) -o public.log \
	     -k -D $(dom) -R $(rej_links) -X /downloads,/gallery $(sroot)
	du -s public.wget
Russ Fish's avatar
Russ Fish committed
542

543 544 545 546
admin_spider: admin.wget/admin.log
admin.wget/admin.log:
	$(login_sys)
	$(admin_cmd)
Russ Fish's avatar
Russ Fish committed
547 548
	@ echo ==== Spidering the private "(logged in, admin)" interface.
	@echo "** Be patient, spidering will take at least 10 minutes. **"
549 550
	cd admin.wget; \
	wget -r -S $(cookie_args) $(ld_cookies_subdir) -o admin.log \
Russ Fish's avatar
Russ Fish committed
551
	     -k -D $(dom) -R $(rej_links) -X /downloads,/gallery $(sroot)
552
	du -s admin.wget
Russ Fish's avatar
Russ Fish committed
553 554

# Extract a list of the active forms in the site.
Russ Fish's avatar
Russ Fish committed
555 556
SITE_FORMS	= $(RESDIR)/site_forms.list
SITE_FILES	= $(RESDIR)/site_files.list
557 558
site_list: $(SITE_FORMS) $(SITE_FILES)

Russ Fish's avatar
Russ Fish committed
559 560
# Ignore flyspray and Twiki for now.
# Ignore the search box form on every page, we'll treat it separately.
561
forms_cmd = find . \( -name distributions -prune \) \
Russ Fish's avatar
Russ Fish committed
562 563 564
		-o \( -name flyspray -prune \) \
		-o \( -name twiki -prune \) \
		-o -type f -print0 | xargs -0 grep -n '<form ' | \
565 566 567
	    fgrep -v /search.php3 ) | sort -u
# Filenames - Remove directory prefix and "Get" arg lists after the filename.
# Kill suffix after filename first: .../archive_view.php3/9/trunk?exptidx=9
568
files_cmd = sed -e 's|\(php3*\).*|\1|' -e 's|^[^:]*/||' 
569

Russ Fish's avatar
Russ Fish committed
570 571
PUBLIC_FORMS	= $(RESDIR)/public_forms.list
PUBLIC_FILES	= $(RESDIR)/public_files.list
572
public_list: $(PUBLIC_FORMS) $(PUBLIC_FILES)
573

574
$(PUBLIC_FORMS): public.wget/public.log
575
	(cd public.wget; $(forms_cmd) > $(PUBLIC_FORMS)
576
$(PUBLIC_FILES): $(PUBLIC_FORMS)
577
	$(files_cmd) $(PUBLIC_FORMS) | uniq > $(PUBLIC_FILES)
578

Russ Fish's avatar
Russ Fish committed
579 580
ADMIN_FORMS	= $(RESDIR)/admin_forms.list
ADMIN_FILES	= $(RESDIR)/admin_files.list
581
admin_list: $(ADMIN_FORMS) $(ADMIN_FILES)
582

583
$(ADMIN_FORMS): admin.wget/admin.log
584
	(cd admin.wget; $(forms_cmd) > $(ADMIN_FORMS)
585
$(ADMIN_FILES): $(ADMIN_FORMS)
586
	$(files_cmd) $(ADMIN_FORMS) | uniq > $(ADMIN_FILES)
587 588 589

$(SITE_FORMS): $(PUBLIC_FORMS) $(ADMIN_FORMS)
	cat $(PUBLIC_FORMS) $(ADMIN_FORMS) | sort -u > $(SITE_FORMS)
590

591
# The <forms under index.html are actually in menu.php3 via defs.php3.in .
Russ Fish's avatar
Russ Fish committed
592
# Ditto beginexp_{html,form}.php3 .
593 594 595 596 597
$(SITE_FILES): $(PUBLIC_FILES) $(ADMIN_FILES)
	cat $(PUBLIC_FILES) $(ADMIN_FILES) | \
	    sed -e 's/index\.html/menu.php3/' \
		-e 's/beginexp_html/beginexp_form/' | sort -u > $(SITE_FILES)

598
# Dump a stats message.
599
site_msg: site_list public_list admin_list
600
	@echo "** Spider: `wc -l < $(SITE_FORMS)` (`wc -l < $(PUBLIC_FORMS)` +" \
601 602
	      "`wc -l < $(ADMIN_FORMS)` ) forms instances" \
	      "are in `wc -l < $(SITE_FILES)` (` wc -l < $(PUBLIC_FILES)` +" \
Russ Fish's avatar
Russ Fish committed
603 604 605
	      "`wc -l < $(ADMIN_FILES)` ) web pages. **" | tr -s " "
	@echo "** (See *_{forms,files}.list in $(RESDIR) .) **"
	@echo "**"
Russ Fish's avatar
Russ Fish committed
606 607

#================================================================
Russ Fish's avatar
Russ Fish committed
608
# forms_coverage: Compare the two lists to find uncovered (unlinked) forms.
609
#
610
.PHONY:         files_missing forms_msg
Russ Fish's avatar
Russ Fish committed
611 612
forms_coverage: files_missing forms_msg

Russ Fish's avatar
Russ Fish committed
613
FILES_MISSING = $(RESDIR)/files_missing.list
Russ Fish's avatar
Russ Fish committed
614
files_missing: $(FILES_MISSING)
615
$(FILES_MISSING): $(SRC_FILES) $(SITE_FILES)
Russ Fish's avatar
Russ Fish committed
616
	diff $(SRC_FILES) $(SITE_FILES) | grep '^[<>] [^.]' > $(FILES_MISSING)
617

618
# Dump a stats message.
619
forms_msg: files_missing src_msg site_msg
620 621 622
	@echo "** Forms: `wc -l < $(FILES_MISSING)`" \
	    "out of `wc -l < $(SRC_FILES)`" \
	    "forms files are not covered. **" | tr -s " "
Russ Fish's avatar
Russ Fish committed
623 624
	@echo "** (See $(FILES_MISSING) .) **"
	@echo "**"
Russ Fish's avatar
Russ Fish committed
625 626 627 628 629

# Look at files_missing.list and see README-howto.txt for the
# procedure to activate coverage of more forms.

#================================================================
Russ Fish's avatar
Russ Fish committed
630
# input_coverage: Grep spidered forms for <input definitions, make values dictionary.
631
#
632 633 634
.PHONY:         input_list input_msg
input_coverage: input_list input_msg

Russ Fish's avatar
Russ Fish committed
635 636
SITE_INPUTS     = $(RESDIR)/site_inputs.list
INPUT_NAMES	= $(RESDIR)/input_names.list
637
input_list: $(SITE_INPUTS) $(INPUT_NAMES)
638

Russ Fish's avatar
Russ Fish committed
639 640
PUBLIC_INPUTS   = $(RESDIR)/public_inputs.list
ADMIN_INPUTS    = $(RESDIR)/admin_inputs.list
641
# XXX kluge to make imageid mtype checked by default since at least one is required.
642 643
# XXX Set a default newattribute_type radio button; nothing is clicked by default.
# XXX Clear node reservations instead of setting them.
644
$(SITE_INPUTS): $(PUBLIC_INPUTS) $(ADMIN_INPUTS)
645
	cat $(PUBLIC_INPUTS) $(ADMIN_INPUTS) | \
646 647 648 649 650 651
	   gawk '(/formfields\[mtype/ || /newattribute_type.*integer/) && !/checked/ \
		     { sub(" *>$$", " checked >"); } \
	         { print; } \
		 /action="prereserve_node.php3/ \
		     { print "<input type=\"hidden\" name=\"clear\" value=\"1\" >"; }' \
		 > $(SITE_INPUTS)
652 653 654

# Extract input fields and context from the html form files in the wget subdirs.
# Output sections terminated by a blank line contain: filename, <form, <input* .
655
# Canonicalize and reorder <input fields: <input type="..." name="..." value=... ...>
656
#
657
# inputs_cmd is parameterized by directory: {public,admin}.
658
# Input comes from $(dir)_forms.list ; output goes into $(dir)_inputs.list .
659 660
# Run the awk command on a long list of forms file names using xargs.
# Expand it in the shell so gmake -n output doesn't swamp us.
661 662 663 664
inputs_cmd = @echo "form-inputs from files in $(1)_forms.list to $(1)_inputs.list"; \
   (cd $(1).wget && \
    sed -e 's/:[0-9][0-9]*:.*//' ../$(RESDIR)/$(1)_forms.list | \
    xargs gawk -f ../$(SRCDIR)/form-input.gawk $$f ) > $(RESDIR)/$(1)_inputs.list
665
$(PUBLIC_INPUTS): $(PUBLIC_FORMS) $(SRCDIR)/form-input.gawk
666
	$(call inputs_cmd,public)
667
$(ADMIN_INPUTS): $(ADMIN_FORMS) $(SRCDIR)/form-input.gawk
668
	$(call inputs_cmd,admin)
669

Russ Fish's avatar
Russ Fish committed
670
# Get unique input field names: text(area), hidden, checkbox, select, radio/checked.
Russ Fish's avatar
Russ Fish committed
671
$(INPUT_NAMES): $(SITE_INPUTS)
Russ Fish's avatar
Russ Fish committed
672
	gawk '/type="(text|hidden|checkbox|select)/ || /\<checked\>/ \
673
		  { print $$3; }' $(SITE_INPUTS) | sort -u > $(INPUT_NAMES)
Russ Fish's avatar
Russ Fish committed
674

675
# Dump a stats message.
Russ Fish's avatar
Russ Fish committed
676
input_msg: input_list
677 678 679 680 681 682
	@echo "** Inputs: `grep -c '<input' $(SITE_INPUTS)` input fields," \
	    "`wc -l < $(INPUT_NAMES)` unique," \
	    "`wc -l < $(INPUT_VALUES)`  over-ridden. **" | tr -s " "
	@echo "** (See $(notdir $(SITE_INPUTS)) and $(notdir $(INPUT_NAMES))"
	@echo "**  in $(RESDIR),"
	@echo "** and $(notdir $(INPUT_VALUES)) in $(SRCDIR) .) **"
Russ Fish's avatar
Russ Fish committed
683
	@echo "**"
684

685 686
# Copy relevant name= lines from results/input_names.list to input_values.list .
# Add a space and default value onto the ends of the lines for auto-form-fill-in.
687 688
INPUT_VALUES_SRC = $(SRCDIR)/input_values.list

Russ Fish's avatar
Russ Fish committed
689
# Subst configure names of activate objs for @keyword@ in the values dictionary.
690
INPUT_VALUES = input_values.list
691
$(INPUT_VALUES): $(INPUT_VALUES_SRC) activate.wget
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
	sed -e "s/@uid@/$(uid)/" \
	    -e "s/@email@/$(real_email2)/" \
	    -e "s/@pcnode@/`$(node_sql)`/" \
	    -e "s/@usridx@/`$(usridx_sql)`/" \
	    -e "s/@exptidx@/`$(exptidx_sql)`/" \
	    $(INPUT_VALUES_SRC) > $(INPUT_VALUES)
node_sql = $(call boss_sql, select phys_nodeid from nodes where type like 'pc%')
show_node:
	echo `$(node_sql)`
usridx_sql = $(call boss_sql, select uid_idx from users where uid='$(usr1)')
show_usridx:
	echo `$(usridx_sql)`
exptidx_sql = $(call boss_sql, select idx from experiments where eid='$(exp1)')
show_exptidx:
	echo `$(exptidx_sql)`
707 708

#================================================================
709
# normal: Create, run, and categorize "normal operations" test cases.
710 711 712
#
# Convert the input list to normal test cases with input field values.
# Test until "normal" input tests work properly on all forms.
713
# Cases are divided into setup, show, and teardown subsets.
714
# 
715 716 717
gen_tasks = gen_setup gen_show gen_teardown
run_tasks = run_setup run_show run_teardown analyze
.PHONY: normal gen_all run_all $(gen_tasks) $(run_tasks)
718
#
719 720
normal: gen_all run_all
gen_all: $(gen_tasks)
721 722
# Analyze partial results in between run tasks.
run_all: run_setup analyze run_show analyze run_teardown analyze
723

724
URLS		= $(SHOW_URLS) $(SETUP_URLS) $(TEARDOWN_URLS)
725

726
# The "show" actions don't change persistent state.
727 728 729 730
SHOW_URLS	= $(RESDIR)/show_cases.urls
SHOW_WGET	= $(RESDIR)/show_cases.wget
SHOW_XML	= $(RESDIR)/show_cases.xml
gen_show: $(SHOW_URLS) $(SHOW_WGET) ###$(SHOW_XML)
731

732 733
# Separate out the setup and teardown URL's from the "show" ones.
SETUP_URLS	= $(RESDIR)/setup_cases.urls
Russ Fish's avatar
Russ Fish committed
734
SETUP_WGET	= $(RESDIR)/setup_cases.wget
735 736
SETUP_XML	= $(RESDIR)/setup_cases.xml
gen_setup: $(SETUP_URLS) $(SETUP_WGET) ###$(SETUP_XML)
737

738
TEARDOWN_URLS	= $(RESDIR)/teardown_cases.urls
Russ Fish's avatar
Russ Fish committed
739
TEARDOWN_WGET	= $(RESDIR)/teardown_cases.wget
740 741
TEARDOWN_XML	= $(RESDIR)/teardown_cases.xml
gen_teardown: $(TEARDOWN_URLS) $(TEARDOWN_WGET) ###$(TEARDOWN_XML)
742

Russ Fish's avatar
Russ Fish committed
743 744 745 746
sep_src		= $(SRCDIR)/sep-urls.gawk
sep_cmd		= gawk -f $(sep_src) -v SYSADMIN=$(uid)
f2u_src		= $(SRCDIR)/forms-to-urls.gawk
u2w_src		= $(SRCDIR)/urls-to-wget.gawk
747
u2w_cmd		= gawk -f $(u2w_src) -v SRCDIR=$(SRCDIR)
748 749
URL_PREREQS	= $(f2u_src) $(SITE_INPUTS) $(INPUT_NAMES) $(INPUT_VALUES) \
		  $(sep_src) $(SETUP_FORMS) $(TEARDOWN_FORMS)
Russ Fish's avatar
Russ Fish committed
750 751 752
SETUP_FORMS	= $(SRCDIR)/setup_forms.list
TEARDOWN_FORMS	= $(SRCDIR)/teardown_forms.list

753
# All of the URL's (setup, show, teardown) are mixed together at first.
754
tmp_urls: $(URL_PREREQS)
755 756 757 758 759
	gawk -f $(f2u_src) -v VALUES=$(INPUT_VALUES) $(SITE_INPUTS) > tmp_urls
# These are the forms covered by setup and teardown.  Everything else is "show".
tmp_form_files:
	sed -n '/^[ 	]*\//s||/|p' $(SETUP_FORMS) $(TEARDOWN_FORMS) > tmp_form_files

Russ Fish's avatar
Russ Fish committed
760
# Show action is the default for those that are neither setup nor teardown.
761
$(SHOW_URLS): tmp_form_files tmp_urls 
762
	fgrep -v -f tmp_form_files tmp_urls > $(SHOW_URLS)
763

Russ Fish's avatar
Russ Fish committed
764
# The setup and teardown actions are ordered: separated out and hacked by a script.
765
$(SETUP_URLS): tmp_urls
766
	$(sep_cmd) $(SETUP_FORMS) tmp_urls > $(SETUP_URLS)
767
$(TEARDOWN_URLS): tmp_urls
768 769
	$(sep_cmd) $(TEARDOWN_FORMS) tmp_urls > $(TEARDOWN_URLS)

770 771 772 773 774 775 776 777 778
# A little helper script to wait for the experiment to be active; run on Boss via ssh.
# Inserted between all "show" commands, but also used by the setup/teardown scripts.
waitexp_cmd = ssh $(boss) ./waitexp $(EinE_proj) $(exp1)
add_waitexp_cmds = gawk '{ print "$(waitexp_cmd)\n" $$0 }'
update_waitexp:
	scp $(SRCDIR)/waitexp $(boss):

# WebInject doesn't store the returned pages or keep login cookie state.
# Use wget instead and browse the html files to dig into what happened.
779
$(SHOW_WGET): $(SHOW_URLS) $(u2w_src)
780
	$(u2w_cmd) $(SHOW_URLS) | $(add_waitexp_cmds) > $(SHOW_WGET)
Russ Fish's avatar
Russ Fish committed
781
$(SETUP_WGET): $(SETUP_URLS) $(u2w_src)
782
	$(u2w_cmd) $(SETUP_URLS) > $(SETUP_WGET)
Russ Fish's avatar
Russ Fish committed
783
$(TEARDOWN_WGET): $(TEARDOWN_URLS) $(u2w_src)
784
	$(u2w_cmd) $(TEARDOWN_URLS) > $(TEARDOWN_WGET)
785 786

# XML test cases for WebInject.
787 788
$(SHOW_XML): $(SHOW_URLS) $(SRCDIR)/urls-to-webinject.gawk
	gawk -f $(SRCDIR)/urls-to-webinject.gawk $(SHOW_URLS) > $(SHOW_XML)
789

790
# Test until "normal" input test cases work properly in all forms.
791
RUN_ENV = MYBOSS=$(boss) MYOPS=$(ops) SRCDIR=$(SRCDIR)
792 793 794

run_setup: $(SETUP_WGET) update_waitexp
	@echo ================ Running setup ================
795
	$(RUN_ENV) csh -f $(SETUP_WGET)
796 797 798
# "Show" commands depend on activation object state, not setup/teardown.
run_show: $(SHOW_WGET) admin update_waitexp
	@echo ================ Running show ================
Russ Fish's avatar
Russ Fish committed
799 800
	scp $(SRCDIR)/waitexp $(boss):
	$(RUN_ENV) csh -f $(SHOW_WGET)
801 802 803
run_teardown: $(TEARDOWN_WGET) update_waitexp
	@echo ================ Running teardown ================
	scp $(SRCDIR)/waitexp $(boss):
804
	$(RUN_ENV) csh -f $(TEARDOWN_WGET)
805

806 807 808 809 810
#================================================================
# Analyze: Categorize the html results returned from wget actions.
#
.PHONY: analyze analyze_make analyze_msg
# These are over-ridden in a subdir analysis.
811
analyze_output = $(RESDIR)/analyze_output.txt
812 813 814 815 816 817 818 819
analysis_kind = Run
#
analyze: analyze_make analyze_msg
#
# Have to do this in a recursive make so the html file list is expanded *after* running.
analyze_make:
	@$(MAKE) --no-print-directory $(analyze_output)
$(analyze_output): $(analysis_patterns) *.html
820 821
	truncate -s 0 $(matches) $(analyze_output)
	$(call analyze_hdr,success)
822
	-$(call analyze_cmd,success.txt)
823
	$(call analyze_hdr,failure)
824
	-$(call analyze_cmd,failure.txt)
825 826
	$(call analyze_hdr,problem)
	-$(call analyze_cmd,problem.txt)
827 828
	$(call analyze_hdr,UNKNOWN)
	sed -n 's/:.*//p' $(matches) | sort -u > recognized_output.files
829
	ls *.html | fgrep -v -f recognized_output.files $(tee)
830 831
analyze_msg: $(analyze_output) 
	@echo -n "** $(analysis_kind) analysis: "
Russ Fish's avatar
Russ Fish committed
832 833 834 835
	@gawk '/^==/{if (type!="") printf "%s %s, ", type, count; type=$$2; count=0; next}\
	     /^[^ ]/{count++} END{printf "%s %s **\n", type, count;}' $(analyze_output)
	@echo "** (See $(notdir $(analyze_output)) in $(RESDIR) .) **"
	@echo "**"
836

837 838 839 840 841 842 843 844 845 846 847 848
matches = match_success.txt match_failure.txt match_problem.txt
tee = | tee >> $(analyze_output)
##cut = | cut -c -80
analyze_hdr = echo ================  $(1)  ================ $(tee)

# Group the match lines to improve comprehension.
# Output has filenames on a line by themselves, with match lines indented below.
analyze_cmd = grep -H -i -f $(SRCDIR)/$(1) *.html | tr -s " " >> match_$(1); \
	      gawk '{ cl = index($$0, ":"); fn = substr($$0, 1, cl-1); \
		      if ( file != fn ) { file = fn; print file; }; \
		      print "    ", substr($$0, cl+1); }' match_$(1) $(cut) $(tee)

849 850 851
SHOW_OUTPUT	= $(RESDIR)/show_output.xml
run_webinject: $(SHOW_OUTPUT)
$(SHOW_OUTPUT): $(SHOW_XML)
852
	(cd $(SRCDIR)/webinject;
853 854
	    webinject.pl ../$(SHOW_XML);
	    mv results.xml ../$(SHOW_OUTPUT)
Russ Fish's avatar
Russ Fish committed
855 856

#================================================================
Russ Fish's avatar
Russ Fish committed
857
# probe: Create and run probes to test the checking code of all input fields.
858
#
859
.PHONY: probe gen_probes probe_all run_probes
860
probe:  gen_probes probe_all ##run_probes
Russ Fish's avatar
Russ Fish committed
861

862
# These also need to be separated into setup, show, and teardown subsets,
863 864 865
# because of unrepeatable operations being caught by checking code, e.g. can't
# ask it to create a project when it already exists...  So the setup probing
# has to be done in the teardown state, and vice versa.
Russ Fish's avatar
Russ Fish committed
866
#
867
PROBE_URLS	= $(PROBE_SETUP_URLS) $(PROBE_SHOW_URLS) $(PROBE_TEARDOWN_URLS)
Russ Fish's avatar
Russ Fish committed
868
PROBE_SETUP_URLS = $(RESDIR)/setup_probe.urls
869
PROBE_SHOW_URLS = $(RESDIR)/show_probe.urls
870
PROBE_TEARDOWN_URLS = $(RESDIR)/teardown_probe.urls
Russ Fish's avatar
Russ Fish committed
871
#
872 873 874 875
PROBE_WGET	= $(PROBE_SETUP_WGET) $(PROBE_SHOW_WGET) $(PROBE_TEARDOWN_WGET)
PROBE_SETUP_WGET = $(RESDIR)/setup_probe.wget
PROBE_SHOW_WGET = $(RESDIR)/show_probe.wget
PROBE_TEARDOWN_WGET = $(RESDIR)/teardown_probe.wget
Russ Fish's avatar
Russ Fish committed
876

877 878
# Generate labeled mock SQL injection probes in individual fields.
# Probe strings are labeled with the form and field names that caused the hole.
Russ Fish's avatar
Russ Fish committed
879
gen_probes: $(PROBE_URLS) $(PROBE_WGET)
880

881
# Generate mixed together, then use the forms lists to separate and order.
882
tmp_probe_urls: $(URL_PREREQS)
Russ Fish's avatar
Russ Fish committed
883
	gawk -f $(f2u_src) -v PROBE=1 -v VALUES=$(INPUT_VALUES) \
884
	    $(SITE_INPUTS) > tmp_probe_urls
885
$(PROBE_SETUP_URLS): tmp_probe_urls
Russ Fish's avatar
Russ Fish committed
886
	$(sep_cmd) $(SETUP_FORMS) tmp_probe_urls > $(PROBE_SETUP_URLS)
887 888
$(PROBE_SHOW_URLS): tmp_form_files tmp_probe_urls
	fgrep -v -f tmp_form_files tmp_probe_urls > $(PROBE_SHOW_URLS)
889
$(PROBE_TEARDOWN_URLS): tmp_probe_urls
Russ Fish's avatar
Russ Fish committed
890 891
	$(sep_cmd) $(TEARDOWN_FORMS) tmp_probe_urls > $(PROBE_TEARDOWN_URLS)

892 893
# Output pages go to a subdir, using the cookies.txt file in the current dir.
U2W_ARG = -v FAILFILE=$(FAIL_FILE) -v OUTDIR=probes.wget
Russ Fish's avatar
Russ Fish committed
894
$(PROBE_SETUP_WGET): $(PROBE_SETUP_URLS) $(u2w_src)
895
	$(u2w_cmd) $(U2W_ARG) $(PROBE_SETUP_URLS) > $(PROBE_SETUP_WGET)
896 897 898
$(PROBE_SHOW_WGET): $(PROBE_SHOW_URLS) $(u2w_src)
	$(u2w_cmd) $(U2W_ARG) $(PROBE_SHOW_URLS) \
	| $(add_waitexp_cmds) > $(PROBE_SHOW_WGET)
Russ Fish's avatar
Russ Fish committed
899
$(PROBE_TEARDOWN_WGET): $(PROBE_TEARDOWN_URLS) $(u2w_src)
900
	$(u2w_cmd) $(U2W_ARG) $(PROBE_TEARDOWN_URLS) > $(PROBE_TEARDOWN_WGET)
Russ Fish's avatar
Russ Fish committed
901

902 903 904
probe_tasks = probe_setup probe_show probe_teardown probe_hdr probes_msg
.PHONY: $(probe_tasks) analyze_probes
probe_all: gen_probes probes.wget $(probe_tasks)
905

906 907
probe_setup: $(PROBE_SETUP_WGET) update_waitexp run_teardown
	@echo ================ Probing setup ================
908
	$(RUN_ENV) csh -f $(PROBE_SETUP_WGET)
909 910 911
# "Show" commands depend on activation object state, not setup/teardown.
probe_show: $(PROBE_SHOW_WGET) admin update_waitexp
	@echo ================ Probing show ================
912
	csh -f $(PROBE_SHOW_WGET)
913 914
probe_teardown: $(PROBE_TEARDOWN_WGET) update_waitexp run_setup
	@echo ================ Probing teardown ================
915
	$(RUN_ENV) csh -f $(PROBE_TEARDOWN_WGET)
916 917
probe_hdr:
	@echo ================ Analyzing probes ================
Russ Fish's avatar
Russ Fish committed
918

919
# Re-use the "analyze" action, running it in the probes.wget subdirectory.
920
analyze_probes:
921 922 923 924
	@cd probes.wget && $(MAKE) -f ../GNUmakefile --no-print-directory \
	    analysis_kind=Probe analyze_output=../$(PROBE_ANALYSIS) \
	    SRCDIR=../$(SRCDIR) TESTBED_SRCDIR=../$(TESTBED_SRCDIR) \
	    analyze_make
925
PROBE_ANALYSIS = $(RESDIR)/analyze_probes.txt
926 927

probe_outputs = $(PROBE_LABELS) $(UNCAUGHT_PROBES) $(UNCAUGHT_FILES)
Russ Fish's avatar
Russ Fish committed
928 929 930
PROBE_LABELS = $(RESDIR)/probe-labels.list
UNCAUGHT_PROBES = $(RESDIR)/uncaught-probes.list
UNCAUGHT_FILES = $(RESDIR)/uncaught-files.list
931

932
# Dump a stats message.
933
probes_msg $(probe_outputs): analyze_probes
934
	@echo -n "** Probe analysis: "
935 936 937 938 939
	@gawk '/^=/ { type = $$2; next; } # === success, failure, or UNKNOWN. \
	       /^[a-z]/ { 		  # Probe output file lines. \
		 # When both match, failure supercedes success; . \
		 if ( types[$$1] == "" ) { types[$$1]=type; n[type]++; nprobes++; } \
		 else if ( types[$$1] == "success" && type == "failure" ) { \
940
		     dups++; types[$$1]=type; n[type]++; n["success"]--; } \
941
		 next; } \
942
	       END{ print nprobes, "probes", \
943
		    "out of '"`cat $(PROBE_WGET) | grep -c '^wget'`"' executed:", \
944 945
		    n["success"]+0, "showed success,\n**    ", \
		    n["failure"]+0, "failure (or probes caught),", \
946
		    dups+0, "dups,", n["UNKNOWN"]+0, "UNKNOWN."; }' $(PROBE_ANALYSIS)
Russ Fish's avatar
Russ Fish committed
947 948 949
	@cat probes.wget/*.html | fgrep 'Probe label:' > $(PROBE_LABELS)
	@fgrep ": '" < $(PROBE_LABELS) | sort > $(UNCAUGHT_PROBES)
	@sed 's/.*{\([^:]*\).*/\1/' $(UNCAUGHT_PROBES) | uniq > $(UNCAUGHT_FILES)
950 951 952
	@echo "** Probes to" \
	    ` grep '^http' $(URLS) | sed 's/?.*//' | sort -u | wc -l`" pages gave" \
	    `wc -l < $(PROBE_LABELS)`" hits: " \
953 954
	    `fgrep -c ': \' < $(PROBE_LABELS)`" backslashed, " \
	    `wc -l < $(UNCAUGHT_PROBES)`" UNCAUGHT in " \
955
	    `wc -l < $(UNCAUGHT_FILES)`" pages." | tr -s " "
956 957
	@echo "** (See $(notdir $(PROBE_LABELS)) and $(notdir $(UNCAUGHT_FILES))"
	@echo "**  in $(RESDIR) .) **"
Russ Fish's avatar
Russ Fish committed
958
	@echo "**"
Russ Fish's avatar
Russ Fish committed
959 960 961 962

# Run the probes through webinject.
# Successfully caught cases should produce "invalid input" warnings.
# Potential penetrations will log SQL errors with the form/field name.
963
PROBE_OUTPUT = $(RESDIR)/probe_output.xml
Russ Fish's avatar
Russ Fish committed
964
###run_probes: $(PROBE_OUTPUT)
965
$(PROBE_OUTPUT): $(PROBE_XML)
966
	(cd $(SRCDIR)/webinject;
967
	   webinject.pl ../$(PROBE_XML);
Russ Fish's avatar
Russ Fish committed
968
	   mv results.xml ../$(PROBE_OUTPUT)