1 /*
2 ** Licensed to the Apache Software Foundation (ASF) under one or more
3 ** contributor license agreements. See the NOTICE file distributed with
4 ** this work for additional information regarding copyright ownership.
5 ** The ASF licenses this file to You under the Apache License, Version 2.0
6 ** (the "License"); you may not use this file except in compliance with
7 ** the License. You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #ifndef APREQ_COOKIE_H
19 #define APREQ_COOKIE_H
20
21 #include "apreq.h"
22 #include "apr_time.h"
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 /**
29 * @file apreq_cookie.h
30 * @brief Cookies and Jars.
31 * @ingroup libapreq2
32 *
33 * apreq_cookie.h describes a common server-side API for request (incoming)
34 * and response (outgoing) cookies. It aims towards compliance with the
35 * standard cookie specifications listed below.
36 *
37 * @see http://wp.netscape.com/newsref/std/cookie_spec.html
38 * @see http://www.ietf.org/rfc/rfc2109.txt
39 * @see http://www.ietf.org/rfc/rfc2964.txt
40 * @see http://www.ietf.org/rfc/rfc2965.txt
41 *
42 */
43
44 /** This macro is deprecated.
45 *
46 * Maximum length of a single Set-Cookie(2) header.
47 */
48 #define APREQ_COOKIE_MAX_LENGTH 4096
49
50 /** @brief Cookie type, supporting both Netscape and RFC cookie specifications.
51 */
52
53 typedef struct apreq_cookie_t {
54
55 char *path; /**< Restricts url path */
56 char *domain; /**< Restricts server domain */
57 char *port; /**< Restricts server port */
58 char *comment; /**< RFC cookies may send a comment */
59 char *commentURL; /**< RFC cookies may place an URL here */
60 apr_time_t max_age; /**< total duration of cookie: -1 == session */
61 unsigned flags; /**< charsets, taint marks, app-specific bits */
62 const apreq_value_t v; /**< "raw" cookie value */
63
64 } apreq_cookie_t;
65
66
67 /** Upgrades a jar's table values to apreq_cookie_t structs. */
68 static APR_INLINE
apreq_value_to_cookie(const char * val)69 apreq_cookie_t *apreq_value_to_cookie(const char *val)
70 {
71 union { const char *in; char *out; } deconst;
72
73 deconst.in = val;
74 return apreq_attr_to_type(apreq_cookie_t, v,
75 apreq_attr_to_type(apreq_value_t, data, deconst.out));
76 }
77
78 /**@return 1 if this is an RFC cookie, 0 if its a Netscape cookie. */
79 static APR_INLINE
apreq_cookie_version(const apreq_cookie_t * c)80 unsigned apreq_cookie_version(const apreq_cookie_t *c) {
81 return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_VERSION);
82 }
83
84 /** Sets the cookie's protocol version. */
85 static APR_INLINE
apreq_cookie_version_set(apreq_cookie_t * c,unsigned v)86 void apreq_cookie_version_set(apreq_cookie_t *c, unsigned v) {
87 APREQ_FLAGS_SET(c->flags, APREQ_COOKIE_VERSION, v);
88 }
89
90 /** @return 1 if the secure flag is set, 0 otherwise. */
91 static APR_INLINE
apreq_cookie_is_secure(const apreq_cookie_t * c)92 unsigned apreq_cookie_is_secure(const apreq_cookie_t *c) {
93 return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_SECURE);
94 }
95
96 /** Sets the cookie's secure flag, meaning it only
97 * comes back over an SSL-encrypted connction.
98 */
99 static APR_INLINE
apreq_cookie_secure_on(apreq_cookie_t * c)100 void apreq_cookie_secure_on(apreq_cookie_t *c) {
101 APREQ_FLAGS_ON(c->flags, APREQ_COOKIE_SECURE);
102 }
103
104 /** Turns off the cookie's secure flag. */
105 static APR_INLINE
apreq_cookie_secure_off(apreq_cookie_t * c)106 void apreq_cookie_secure_off(apreq_cookie_t *c) {
107 APREQ_FLAGS_OFF(c->flags, APREQ_COOKIE_SECURE);
108 }
109
110 /** @return 1 if the HttpOnly flag is set, 0 otherwise. */
111 static APR_INLINE
apreq_cookie_is_httponly(const apreq_cookie_t * c)112 unsigned apreq_cookie_is_httponly(const apreq_cookie_t *c) {
113 return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_HTTPONLY);
114 }
115
116 /** Sets the cookie's HttpOnly flag, meaning it is not
117 * accessible through client-side script in supported
118 * browsers.
119 */
120 static APR_INLINE
apreq_cookie_httponly_on(apreq_cookie_t * c)121 void apreq_cookie_httponly_on(apreq_cookie_t *c) {
122 APREQ_FLAGS_ON(c->flags, APREQ_COOKIE_HTTPONLY);
123 }
124
125 /** Turns off the cookie's HttpOnly flag. */
126 static APR_INLINE
apreq_cookie_httponly_off(apreq_cookie_t * c)127 void apreq_cookie_httponly_off(apreq_cookie_t *c) {
128 APREQ_FLAGS_OFF(c->flags, APREQ_COOKIE_HTTPONLY);
129 }
130
131
132 /** @return 1 if the taint flag is set, 0 otherwise. */
133 static APR_INLINE
apreq_cookie_is_tainted(const apreq_cookie_t * c)134 unsigned apreq_cookie_is_tainted(const apreq_cookie_t *c) {
135 return APREQ_FLAGS_GET(c->flags, APREQ_TAINTED);
136 }
137
138 /** Sets the cookie's tainted flag. */
139 static APR_INLINE
apreq_cookie_tainted_on(apreq_cookie_t * c)140 void apreq_cookie_tainted_on(apreq_cookie_t *c) {
141 APREQ_FLAGS_ON(c->flags, APREQ_TAINTED);
142 }
143
144 /** Turns off the cookie's tainted flag. */
145 static APR_INLINE
apreq_cookie_tainted_off(apreq_cookie_t * c)146 void apreq_cookie_tainted_off(apreq_cookie_t *c) {
147 APREQ_FLAGS_OFF(c->flags, APREQ_TAINTED);
148 }
149
150 /**
151 * Parse a cookie header and store the cookies in an apr_table_t.
152 *
153 * @param pool pool which allocates the cookies
154 * @param jar table where parsed cookies are stored
155 * @param header the header value
156 *
157 * @return APR_SUCCESS.
158 * @return ::APREQ_ERROR_BADSEQ if an unparseable character sequence appears.
159 * @return ::APREQ_ERROR_MISMATCH if an rfc-cookie attribute appears in a
160 * netscape cookie header.
161 * @return ::APR_ENOTIMPL if an unrecognized rfc-cookie attribute appears.
162 * @return ::APREQ_ERROR_NOTOKEN if a required token was not present.
163 * @return ::APREQ_ERROR_BADCHAR if an unexpected token was present.
164 */
165 APREQ_DECLARE(apr_status_t) apreq_parse_cookie_header(apr_pool_t *pool,
166 apr_table_t *jar,
167 const char *header);
168
169 /**
170 * Returns a new cookie, made from the argument list.
171 *
172 * @param pool Pool which allocates the cookie.
173 * @param name The cookie's name.
174 * @param nlen Length of name.
175 * @param value The cookie's value.
176 * @param vlen Length of value.
177 *
178 * @return the new cookie
179 */
180 APREQ_DECLARE(apreq_cookie_t *) apreq_cookie_make(apr_pool_t *pool,
181 const char *name,
182 const apr_size_t nlen,
183 const char *value,
184 const apr_size_t vlen);
185
186 /**
187 * Returns a string that represents the cookie as it would appear
188 * in a valid "Set-Cookie*" header.
189 *
190 * @param c cookie.
191 * @param p pool which allocates the returned string.
192 *
193 * @return header string.
194 */
195 APREQ_DECLARE(char*) apreq_cookie_as_string(const apreq_cookie_t *c,
196 apr_pool_t *p);
197
198
199 /**
200 * Same functionality as apreq_cookie_as_string. Stores the string
201 * representation in buf, using up to len bytes in buf as storage.
202 * The return value has the same semantics as that of apr_snprintf,
203 * including the special behavior for a "len = 0" argument.
204 *
205 * @param c cookie.
206 * @param buf storage location for the result.
207 * @param len size of buf's storage area.
208 *
209 * @return size of resulting header string.
210 */
211 APREQ_DECLARE(int) apreq_cookie_serialize(const apreq_cookie_t *c,
212 char *buf, apr_size_t len);
213
214 /**
215 * Set the Cookie's expiration date.
216 *
217 * @param c The cookie.
218 * @param time_str If NULL, the Cookie's expiration date is unset,
219 * making it a session cookie. This means no "expires" or "max-age"
220 * attribute will appear in the cookie's serialized form. If time_str
221 * is not NULL, the expiration date will be reset to the offset (from now)
222 * represented by time_str. The time_str should be in a format that
223 * apreq_atoi64t() can understand, namely /[+-]?\\d+\\s*[YMDhms]/.
224 *
225 * @remarks Now time_str may also be a fixed date; see apr_date_parse_rfc()
226 * for admissible formats.
227 */
228 APREQ_DECLARE(void) apreq_cookie_expires(apreq_cookie_t *c,
229 const char *time_str);
230
231 #ifdef __cplusplus
232 }
233 #endif
234
235 #endif /*APREQ_COOKIE_H*/
236
237
238