Common Lisp Package: RFC2109

This package implements RFC2109 - the original cookie specification. Use it to generate (and eventually parse) cookies in an RFC-compliant way.

README:

FUNCTION

Public

DOMAIN-MATCH-P (HOST-A HOST-B)

Checks to see if host-a "domain-matches" host-b, per RFC2109 From the RFC: Hosts names can be specified either as an IP address or a FQHN string. Sometimes we compare one host name with another. Host A's name domain-matches host B's if * both host names are IP addresses and their host name strings match exactly; or * both host names are FQDN strings and their host name strings match exactly; or * A is a FQDN string and has the form NB, where N is a non-empty name string, B has the form .B', and B' is a FQDN string. (So, x.y.com domain-matches .y.com but not y.com.) Note that domain-match is not a commutative operation: a.b.c.com domain-matches .c.com, but not the reverse.

PARSE-COOKIES (COOKIE-STRING)

Parses cookies in a Cookie: request header, returning a list of COOKIE structs. The only information that is passed back for each cookie is: name, value, path, domain, so don't go looking for comments or the like. Note that this function does not want the Cookie: portion of the header So if the request header looked like: Cookie: $Version=1; mycookie=value1; myothercookie=value2 You'd leave off the Cookie: bit at the front. The other parser is SAFE-PARSE-COOKIES, which is the version to use when you can.

SAFE-PARSE-COOKIES (COOKIE-STRING &OPTIONAL (DOMAIN-RESTRICTION ))

Parse a cookie string (see parse-cookies), but only allow domain cookies that match domain-restriction RFC 2109 specifies that, in order to avoid a cookie spoofing attack, one should check that the domain being handed back in your cookie is the domain you gave out. A walkthrough of the mechanics: - If you hand out a cookie with no domain=, then it is restricted to your host - If you specify a domain, the cookie is "unlocked" for the domain specified If you don't expect to use domain cookies, it's best to ignore all domain cookies, as they're not from your website. The default call to SAFE-PARSE-COOKIES will ignore all domain cookies. Later on, if you need domain cookies, pass the domains you'll be using to SAFE-PARSE-COOKIES, and those specific domains will not be dropped. RFC text below: 8.2 Cookie Spoofing Proper application design can avoid spoofing attacks from related domains. Consider: 1. User agent makes request to victim.cracker.edu, gets back cookie session_id="1234" and sets the default domain victim.cracker.edu. 2. User agent makes request to spoof.cracker.edu, gets back cookie session-id="1111", with Domain=".cracker.edu". 3. User agent makes request to victim.cracker.edu again, and passes Cookie: $Version="1"; session_id="1234"; session_id="1111"; $Domain=".cracker.edu" The server at victim.cracker.edu should detect that the second cookie was not one it originated by noticing that the Domain attribute is not for itself and ignore it.

Undocumented

Private

ATTR? (ELEMENT)

Determine if element is an attr

ENSURE-PAIR (LIST DELIM)

Ensure that the LIST has only two elements, by joining the elements of the tail with DELIM. Gentle failure: shorter lists are just returned. LIST should be a list of strings.

PARSE-COOKIES-V1 (COOKIE-STRING CHOPPED)

Parses RFC2109 cookies - do not use directly

PARSE-COOKIES-VNETSCAPE (COOKIE-STRING)

Parses old netscape-style cookies

QUOTE-AROUND (STRING)

Adds quotes around a string

REMOVE-QUOTES-AROUND (STRING)

If there are quotes, remove them

SPLIT-ALONG-LWS (STRING)

Chops up a string along linear whitespace, returns a list

SPLIT-ALONG-QUOTED-LWS (STRING)

Chops up a string along linear whitespace, but this version knows about quote marks

VALID-NAME? (NAME)

Verifies that NAME is a valid name

VALUE? (ELEMENT)

Determine if element is a value

WORD? (ELEMENT)

Determine if element is a word

Undocumented

ASSEMBLE-MATCHES (COOKIE-STRING COOKIE KEY VALUE MATCHES)

CHAR-EL? (EL)

CRLF-EL? (EL)

CTL-EL? (EL)

LWS-EL? (EL)

OCTET-EL? (DATUM)

QDTEXT? (ELEMENT)

QUOTED-STRING? (ELEMENT)

REMOVE-ESCAPED-QUOTES (STRING)

TEXT-EL? (EL)

TEXT? (ELEMENT)

TOKEN-EL? (EL)

TOKEN? (ELEMENT)

TRIM-SPACES (STRING)

TSPECIAL-EL? (EL)

VALID-DOMAIN? (DOMAIN)

MACRO

Private

CORRECT (SLOT TEST &OPTIONAL FAILURE-MESSAGE)

Checks to see if slot obeys test, or throws an invalid-cookie-parameter. If test is a simple function name it will be turned into (test slot)

TRY-QUOTES (SLOT TEST &BODY ELSE)

If slot doesn't match test, try adding quotes around it - if that doesn't work go to else

Undocumented

OPTIONAL (ELEMENT REQUIREMENT)

GENERIC-FUNCTION

Private

Undocumented

VARIABLE

Private

Undocumented

*CR*

*HT*

*LF*

CLASS

Private

CONDITION

Private

Undocumented