Treat a malformed route line carrying an auth policy as a config error - #165
Conversation
A LOC=/MOD= line whose positional token is missing and whose first
token is an AUTH=/RES= option was dropped with a warning, and the
server started:
LOC=AUTH=BASIC RES=FACILITY:HTTPD.ADMIN
published exactly the subtree it named, because an unregistered route
is served under the global LOGIN default. Same fail-open as #161 but
reachable from a typo, no allocation failure needed.
MOD= was worse in a different direction: it never inspected tok[0], so
the option was folded into an 8-character program name ("AUTH=BAS")
and registered against a derived "*.auth=bas" pattern -- a route built
out of a typo that can never load. An empty MOD= said nothing at all.
Both now reject the line and classify what it carried through the
machinery #161 added: the remaining tokens are parsed only to decide
whether the policy binds, so a binding one raises HTTPD419E and stops
the server, while AUTH=NONE or no policy stays a warning. Nothing is
registered either way, so the RES= storage the classification parse
allocated is released again.
Fixes #164
|
Two notes from reviewing the test output. Ordering is not forgiven, deliberately. Out of scope, filed separately: both fatal tests end with CI: |
HTTPD404E printed the CONFIG= parm, which http_config() has ignored since the Parmlib migration -- and which the shipped STC procedure does not pass at all, so the one message naming what failed to process always read "processing (null)". After #163 and #165 gave the parser real reasons to refuse a startup, that message got a lot more visible. The configuration's real identity is the HTTPPRM DD, and the PROC allocates it as &D(&M), so which member is in effect is a startup choice an operator can genuinely need to confirm. parmlib_name() resolves it from the DSAB -> TIOT entry -> JFCB, read-only pointer chasing with no SVC and no allocation, falling back to the DD name if any link is missing. It is reported before parsing, so a later error is already attributed: HTTPD022I Configuration from SYS2.PARMLIB(HTTPPRM0) HTTPD404E drops the operand accordingly. CONFIG= is now answered rather than swallowed. Silently ignoring it is worse than not accepting it -- an operator who passes it believes it took effect, and migration.md still tells 3.x users to remove theirs, so a leftover is exactly what this catches. HTTPD024W says it did nothing and names the mechanism that does. Fixes #166
Fixes #164
Follow-up to #161/#163, which established the rule: a route that carries an auth
policy is registered or the server does not start. That fixed the allocation
failures. This is the same fail-open reached from a typo.
The defect
parse_loc()rejected a line whose first token was an option instead of a path,warned, and let the server start:
An unregistered route does not disappear — its requests are served under the
global
LOGINdefault. UnderLOGIN NONEthat line published exactly thesubtree it named, with one
Wmessage among the startup WTOs as the only trace.parse_mod()was wrong in the other direction: it never inspectedtok[0]atall, so
MOD=AUTH=BASIC /zosmf/*folded the option into an 8-character programname (
AUTH=BAS) and registered it against a derived*.auth=baspattern — aroute built out of a typo that can never load. An empty
MOD=returned silentlywith no message whatsoever.
The change
Both parsers now reject the line and hand it to
route_malformed(), whichclassifies it through the machinery #163 added: the remaining tokens are parsed
only to decide whether the policy binds. A binding policy (
RES=,AUTH=FORM/BASIC) raisesHTTPD419Eand setsHTTPD_FLAG_CFGERR, sohttp_config()stops the server withHTTPD420Ebeforedo_bind().AUTH=NONEor no policy stays a warning — the fallback can only be stricter. Nothing is
registered either way, so the
RES=storage the classification parse allocatedis released again.
MOD=also gainsHTTPD421Wfor the two cases that produced no message.Testing
Unlike #161 this path needs no allocation failure, so it is reproducible — and
was reproduced on the live system. Three alternate Parmlib members
(
S HTTPD,M=…, productionHTTPPRM0untouched, soS HTTPDwas always the wayback), against the deployed and activated build:
1. The line from the issue — must not start.
Address space ended; port 8080 unreachable, i.e. never bound. Before this
change the same member started a server serving that subtree.
2.
MOD=AUTH=BASIC /zosmf/*— must not start.3.
LOC=AUTH=NONE— must still start. The non-binding case, i.e. the checkthat this does not simply make every malformed line fatal:
Port 8080 answered 200.
Then restarted on
HTTPPRM0: all six production routes register,HTTPD001I Server is READY,/.dsrvand/zosmf/restfilesboth 200, test members deleted,production member verified byte-for-byte unchanged.
Also
make modules/make testclean under-Wall -Werror,make test-host4 suites / 63 assertions / 0 fail.
Docs
docs/configuration.mdnow lists all three routes to the refuse-to-start path —allocation failure, untokenizable line, and this one — with the two typo examples
spelled out.