Annotation of embedaddon/libpdel/http/servlet/http_servlet_cookieauth.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (c) 2001-2002 Packet Design, LLC.
4: * All rights reserved.
5: *
6: * Subject to the following obligations and disclaimer of warranty,
7: * use and redistribution of this software, in source or object code
8: * forms, with or without modifications are expressly permitted by
9: * Packet Design; provided, however, that:
10: *
11: * (i) Any and all reproductions of the source or object code
12: * must include the copyright notice above and the following
13: * disclaimer of warranties; and
14: * (ii) No rights are granted, in any manner or form, to use
15: * Packet Design trademarks, including the mark "PACKET DESIGN"
16: * on advertising, endorsements, or otherwise except as such
17: * appears in the above copyright notice or in the software.
18: *
19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
36: * THE POSSIBILITY OF SUCH DAMAGE.
37: *
38: * Author: Archie Cobbs <archie@freebsd.org>
39: */
40:
41: #include <sys/types.h>
42:
43: #include <netinet/in.h>
44:
45: #include <stdlib.h>
46: #include <stddef.h>
47: #include <stdio.h>
48: #include <string.h>
49: #include <stdarg.h>
50: #include <syslog.h>
51: #include <errno.h>
52: #include <ctype.h>
53: #include <assert.h>
54: #include <pthread.h>
55:
56: #include <openssl/ssl.h>
57: #include <openssl/md5.h>
58:
59: #include "structs/structs.h"
60: #include "structs/type/array.h"
61: #include "structs/type/boolean.h"
62: #include "structs/type/data.h"
63: #include "structs/type/int.h"
64: #include "structs/type/null.h"
65: #include "structs/type/string.h"
66: #include "structs/type/struct.h"
67: #include "structs/type/time.h"
68: #include "structs/xml.h"
69:
70: #include "http/http_defs.h"
71: #include "http/http_server.h"
72: #include "http/http_servlet.h"
73: #include "http/servlet/redirect.h"
74: #include "http/servlet/cookieauth.h"
75:
76: #include "sys/alog.h"
77: #include "io/string_fp.h"
78: #include "util/rsa_util.h"
79: #include "util/typed_mem.h"
80: #include "debug/debug.h"
81:
82: #ifndef __FreeBSD__
83: #define __printflike(x,y)
84: #endif
85:
86: /*
87: * Ref: http://home.netscape.com/newsref/std/cookie_spec.html
88: */
89:
90: #define MEM_TYPE "http_servlet_cookieauth"
91: #define DATA_MEM_TYPE "http_servlet_cookieauth.data"
92: #define COOKIE_TIME_FMT "%a, %d-%b-%Y %T GMT"
93: #define COOKIE_LINGER_TIME (30 * 60) /* 30 minutes */
94:
95: /* Per-servlet private info */
96: struct cookieauth_private {
97: struct http_servlet *redirect; /* private redirect servlet */
98: http_servlet_cookieauth_reqd_t
99: *authreqd; /* checks if auth required */
100: void *arg; /* argument for authreqd() */
101: void (*destroy)(void *); /* destructor for arg */
102: char *privkey; /* rsa private key file */
103: char *cookiename; /* name of cookie */
104: struct structs_data id; /* unique system id */
105: };
106:
107: /* Structure of the cookie data */
108: struct cookieauth {
109: char *username; /* login username */
110: char *path; /* cookie path */
111: char *domain; /* cookie domain */
112: u_char secure; /* cookie 'secure' bit */
113: u_char session_only; /* this browser session only */
114: time_t timestamp; /* time cookie was set */
115: time_t expire; /* expiration time, or zero */
116: u_int32_t linger; /* max linger time, or zero */
117: struct structs_data id; /* unique system id */
118: struct structs_data sig; /* rsa signature */
119: };
120:
121: /* Internal functions */
122: static http_servlet_run_t http_servlet_cookieauth_run;
123: static http_servlet_destroy_t http_servlet_cookieauth_destroy;
124:
125: static int http_servlet_cookieauth_get(const char *privkey,
126: const struct structs_data *id, const char *cookiename,
127: struct http_request *req, struct cookieauth *auth);
128: static int http_servlet_cookieauth_md5(const struct cookieauth *auth,
129: u_char *md5);
130:
131: #if PDEL_DEBUG
132: static void dump_data(const void *data, u_int plen, const char *fmt, ...)
133: __printflike(3, 4);
134: #endif
135:
136: /* Internal variables */
137: static const struct structs_type authcookie_data_type
138: = STRUCTS_DATA_TYPE(NULL, DATA_MEM_TYPE);
139:
140: static const struct structs_field cookieauth_fields[] = {
141: STRUCTS_STRUCT_FIELD(cookieauth, username, &structs_type_string),
142: STRUCTS_STRUCT_FIELD(cookieauth, path, &structs_type_string_null),
143: STRUCTS_STRUCT_FIELD(cookieauth, domain, &structs_type_string_null),
144: STRUCTS_STRUCT_FIELD(cookieauth, secure, &structs_type_boolean_char),
145: STRUCTS_STRUCT_FIELD(cookieauth,
146: session_only, &structs_type_boolean_char),
147: STRUCTS_STRUCT_FIELD(cookieauth, timestamp, &structs_type_time_gmt),
148: STRUCTS_STRUCT_FIELD(cookieauth, expire, &structs_type_time_gmt),
149: STRUCTS_STRUCT_FIELD(cookieauth, linger, &structs_type_uint32),
150: STRUCTS_STRUCT_FIELD(cookieauth, id, &authcookie_data_type),
151: STRUCTS_STRUCT_FIELD(cookieauth, sig, &authcookie_data_type),
152: STRUCTS_STRUCT_FIELD_END
153: };
154: static const struct structs_type cookieauth_type
155: = STRUCTS_STRUCT_TYPE(cookieauth, &cookieauth_fields);
156:
157: /*
158: * Create a new cookieauth servlet.
159: */
160: struct http_servlet *
161: http_servlet_cookieauth_create(const char *redirect, int append,
162: http_servlet_cookieauth_reqd_t *authreqd, void *arg,
163: void (*destroy)(void *), const char *privkey,
164: const void *id, size_t idlen, const char *cookiename)
165: {
166: struct http_servlet *servlet;
167: struct cookieauth_private *priv;
168: struct structs_data id_data;
169: const char *s;
170:
171: /* Validate cookiename */
172: for (s = cookiename; *s != '\0'; s++) {
173: if (!isgraph((u_char)*s) || strchr(",;=", *s) != NULL)
174: break;
175: }
176: if (s == cookiename || *s != '\0') {
177: errno = EINVAL;
178: return (NULL);
179: }
180:
181: /* Create new servlet */
182: if ((servlet = MALLOC(MEM_TYPE, sizeof(*servlet))) == NULL)
183: return (NULL);
184: memset(servlet, 0, sizeof(*servlet));
185: servlet->run = http_servlet_cookieauth_run;
186: servlet->destroy = http_servlet_cookieauth_destroy;
187:
188: /* Set up private info */
189: if ((priv = MALLOC(MEM_TYPE, sizeof(*priv))) == NULL)
190: goto fail;
191: memset(priv, 0, sizeof(*priv));
192: if ((priv->redirect
193: = http_servlet_redirect_create(redirect, append)) == NULL)
194: goto fail;
195: priv->authreqd = authreqd;
196: priv->arg = arg;
197: priv->destroy = destroy;
198: if ((priv->privkey = STRDUP(MEM_TYPE, privkey)) == NULL)
199: goto fail;
200: if ((priv->cookiename = STRDUP(MEM_TYPE, cookiename)) == NULL)
201: goto fail;
202: id_data.data = (u_char *)id;
203: id_data.length = idlen;
204: if (structs_get(&authcookie_data_type, NULL, &id_data, &priv->id) == -1)
205: goto fail;
206: servlet->arg = priv;
207:
208: /* Done */
209: return (servlet);
210:
211: fail:
212: /* Clean up after failure */
213: if (priv != NULL) {
214: structs_free(&authcookie_data_type, NULL, &priv->id);
215: FREE(MEM_TYPE, priv->cookiename);
216: FREE(MEM_TYPE, priv->privkey);
217: http_server_destroy_servlet(&priv->redirect);
218: FREE(MEM_TYPE, priv);
219: }
220: FREE(MEM_TYPE, servlet);
221: return (NULL);
222: }
223:
224: /*
225: * Execute cookie authorization servlet.
226: */
227: static int
228: http_servlet_cookieauth_run(struct http_servlet *servlet,
229: struct http_request *req, struct http_response *resp)
230: {
231: struct cookieauth_private *const priv = servlet->arg;
232: struct cookieauth auth;
233:
234: /* Always allow access to the logon page */
235: if (priv->authreqd != NULL && !(*priv->authreqd)(priv->arg, req))
236: goto allow;
237:
238: /* Get valid authorization structure, if there is one */
239: if (http_servlet_cookieauth_get(priv->privkey,
240: &priv->id, priv->cookiename, req, &auth) == -1) {
241:
242: /* Invalid authorization -> redirect to logon page */
243: if (errno == EACCES) {
244: return ((*priv->redirect->run)(priv->redirect,
245: req, resp));
246: }
247:
248: /* Other errors -> generate server error */
249: http_response_send_errno_error(resp);
250: return (1);
251: }
252:
253: /* Update cookie for linger timer */
254: if (auth.linger != 0) {
255: (void)http_servlet_cookieauth_login(resp, priv->privkey,
256: auth.username, auth.linger, auth.expire, auth.session_only,
257: priv->id.data, priv->id.length, priv->cookiename, auth.path,
258: auth.domain, auth.secure);
259: }
260:
261: /* Free authorization info */
262: structs_free(&cookieauth_type, NULL, &auth);
263:
264: allow:
265: /* Allow request to continue */
266: return (0);
267: }
268:
269: /*
270: * Destroy an auth servlet.
271: */
272: static void
273: http_servlet_cookieauth_destroy(struct http_servlet *servlet)
274: {
275: struct cookieauth_private *const priv = servlet->arg;
276:
277: if (priv->destroy != NULL)
278: (*priv->destroy)(priv->arg);
279: structs_free(&authcookie_data_type, NULL, &priv->id);
280: FREE(MEM_TYPE, priv->privkey);
281: FREE(MEM_TYPE, priv->cookiename);
282: http_server_destroy_servlet(&priv->redirect);
283: FREE(MEM_TYPE, priv);
284: FREE(MEM_TYPE, servlet);
285: }
286:
287: /*
288: * Add a cookie that will cause the servlet to not redirect.
289: */
290: int
291: http_servlet_cookieauth_login(struct http_response *resp,
292: const char *privkey, const char *username, u_int max_linger,
293: time_t expire, int session_only, const u_char *id, size_t idlen,
294: const char *cookiename, const char *path, const char *domain,
295: int secure)
296: {
297: struct structs_data data; /* binary encoding of "auth" */
298: struct cookieauth auth; /* authorization info struct */
299: u_char md5[MD5_DIGEST_LENGTH];
300: u_char sigbuf[1024];
301: char ebuf[128];
302: int siglen;
303: char *hval;
304: FILE *sb;
305:
306: /* Build auth structure */
307: if (structs_init(&cookieauth_type, NULL, &auth) == -1)
308: return (-1);
309: if (structs_set_string(&cookieauth_type,
310: "username", username, &auth, ebuf, sizeof(ebuf)) == -1) {
311: alogf(LOG_ERR, "%s: %s", "structs_set_string", ebuf);
312: structs_free(&cookieauth_type, NULL, &auth);
313: return (-1);
314: }
315: if (path != NULL
316: && structs_set_string(&cookieauth_type,
317: "path", path, &auth, ebuf, sizeof(ebuf)) == -1) {
318: alogf(LOG_ERR, "%s: %s", "structs_set_string", ebuf);
319: structs_free(&cookieauth_type, NULL, &auth);
320: return (-1);
321: }
322: if (domain != NULL
323: && structs_set_string(&cookieauth_type,
324: "domain", domain, &auth, ebuf, sizeof(ebuf)) == -1) {
325: alogf(LOG_ERR, "%s: %s", "structs_set_string", ebuf);
326: structs_free(&cookieauth_type, NULL, &auth);
327: return (-1);
328: }
329: auth.secure = !!secure;
330: auth.session_only = !!session_only;
331: auth.timestamp = time(NULL);
332: auth.linger = max_linger;
333: auth.expire = expire;
334: data.data = (u_char *)id;
335: data.length = idlen;
336: if (structs_get(&authcookie_data_type, NULL, &data, &auth.id) == -1) {
337: alogf(LOG_ERR, "%s: %m", "structs_get");
338: structs_free(&cookieauth_type, NULL, &auth);
339: return (-1);
340: }
341:
342: /* Add RSA signature */
343: if (http_servlet_cookieauth_md5(&auth, md5) == -1) {
344: alogf(LOG_ERR, "%s: %m", "http_servlet_cookieauth_md5");
345: structs_free(&cookieauth_type, NULL, &auth);
346: return (-1);
347: }
348: if ((siglen = rsa_util_sign(privkey,
349: md5, sigbuf, sizeof(sigbuf))) == -1) {
350: alogf(LOG_ERR, "%s: %m", "rsa_util_sign");
351: structs_free(&cookieauth_type, NULL, &auth);
352: return (-1);
353: }
354: data.data = sigbuf;
355: data.length = siglen;
356: if (structs_get(&authcookie_data_type, NULL, &data, &auth.sig) == -1) {
357: alogf(LOG_ERR, "%s: %m", "structs_get");
358: structs_free(&cookieauth_type, NULL, &auth);
359: return (-1);
360: }
361:
362: /* Encode auth structure into binary */
363: if (structs_get_binary(&cookieauth_type,
364: NULL, &auth, DATA_MEM_TYPE, &data) == -1) {
365: alogf(LOG_ERR, "%s: %m", "structs_get_binary");
366: structs_free(&cookieauth_type, NULL, &auth);
367: return (-1);
368: }
369:
370: #if PDEL_DEBUG
371: if (PDEL_DEBUG_ENABLED(HTTP_SERVLET_COOKIEAUTH)) {
372: printf("COOKIE AUTH STRUCTURE\n");
373: structs_xml_output(&cookieauth_type,
374: "auth", NULL, &auth, stdout, NULL, STRUCTS_XML_FULL);
375: dump_data(data.data, data.length, "COOKIE DATA");
376: }
377: #endif
378:
379: structs_free(&cookieauth_type, NULL, &auth);
380:
381: /* Base64 encode it */
382: if ((hval = structs_get_string(&authcookie_data_type,
383: NULL, &data, TYPED_MEM_TEMP)) == NULL) {
384: alogf(LOG_ERR, "%s: %m", "structs_get_string");
385: structs_free(&authcookie_data_type, NULL, &data);
386: return (-1);
387: }
388: structs_free(&authcookie_data_type, NULL, &data);
389:
390: /* Create string output buffer */
391: if ((sb = string_buf_output(TYPED_MEM_TEMP)) == NULL) {
392: FREE(TYPED_MEM_TEMP, hval);
393: return (-1);
394: }
395:
396: /* Construct cookie header value */
397: fprintf(sb, "%s=%s", cookiename, hval);
398: FREE(TYPED_MEM_TEMP, hval);
399: if (!session_only) {
400: char tbuf[64];
401: struct tm tm;
402:
403: strftime(tbuf, sizeof(tbuf),
404: COOKIE_TIME_FMT, gmtime_r(&expire, &tm));
405: fprintf(sb, "; expires=%s", tbuf);
406: }
407: if (domain != NULL)
408: fprintf(sb, "; domain=%s", domain);
409: if (path != NULL)
410: fprintf(sb, "; path=%s", path);
411: if (secure)
412: fprintf(sb, "; secure");
413: hval = string_buf_content(sb, 1);
414: fclose(sb);
415: if (hval == NULL)
416: return (-1);
417:
418: /* Set cookie header value */
419: if (http_response_set_header(resp,
420: 0, HTTP_HEADER_SET_COOKIE, "%s", hval) == -1) {
421: FREE(TYPED_MEM_TEMP, hval);
422: return (-1);
423: }
424: FREE(TYPED_MEM_TEMP, hval);
425:
426: /* Done */
427: return (0);
428: }
429:
430: /*
431: * Remove authorization cookie.
432: */
433: int
434: http_servlet_cookieauth_logout(const char *cookiename, const char *path,
435: const char *domain, struct http_response *resp)
436: {
437: static const time_t past = 0;
438: char tbuf[64];
439: struct tm tm;
440: char *hval;
441: FILE *sb;
442:
443: /* Create string output buffer */
444: if ((sb = string_buf_output(TYPED_MEM_TEMP)) == NULL)
445: return (-1);
446:
447: /* Construct cookie header value */
448: strftime(tbuf, sizeof(tbuf), COOKIE_TIME_FMT, gmtime_r(&past, &tm));
449: fprintf(sb, "%s=x; expires=%s", cookiename, tbuf);
450: if (domain != NULL)
451: fprintf(sb, "; domain=%s", domain);
452: if (path != NULL)
453: fprintf(sb, "; path=%s", path);
454: hval = string_buf_content(sb, 1);
455: fclose(sb);
456: if (hval == NULL)
457: return (-1);
458:
459: /* Set cookie header value */
460: if (http_response_set_header(resp, 0,
461: HTTP_HEADER_SET_COOKIE, "%s", hval) == -1) {
462: FREE(TYPED_MEM_TEMP, hval);
463: return (-1);
464: }
465: FREE(TYPED_MEM_TEMP, hval);
466:
467: /* Done */
468: return (0);
469: }
470:
471: /*
472: * Get username.
473: */
474: char *
475: http_servlet_cookieauth_user(const char *privkey, const void *id, size_t idlen,
476: const char *cookiename, struct http_request *req, const char *mtype)
477: {
478: struct cookieauth auth;
479: struct structs_data idd;
480: char *username;
481:
482: /* Get valid authorization structure, if there is one */
483: idd.data = (u_char *)id;
484: idd.length = idlen;
485: if (http_servlet_cookieauth_get(privkey,
486: &idd, cookiename, req, &auth) == -1)
487: return (NULL);
488:
489: /* Get copy of username */
490: if ((username = structs_get_string(&cookieauth_type,
491: "username", &auth, mtype)) == NULL)
492: alogf(LOG_ERR, "%s: %m", "structs_get_string");
493:
494: /* Free auth structure */
495: structs_free(&cookieauth_type, NULL, &auth);
496:
497: /* Return username */
498: return (username);
499: }
500:
501: /*
502: * Get valid authorization structure if there is one.
503: */
504: static int
505: http_servlet_cookieauth_get(const char *privkey, const struct structs_data *id,
506: const char *cookiename, struct http_request *req,
507: struct cookieauth *auth)
508: {
509: const int namelen = strlen(cookiename);
510: const time_t now = time(NULL);
511: const char *hval;
512: const char *next;
513:
514: /* Get cookie header */
515: if ((hval = http_request_get_header(req, HTTP_HEADER_COOKIE)) == NULL)
516: goto invalid;
517:
518: /* Find our cookie */
519: for ( ; *hval != '\0'; hval = next) {
520: u_char md5[MD5_DIGEST_LENGTH];
521: struct structs_data data;
522: char valbuf[512];
523: const char *eq;
524: char ebuf[128];
525: int vallen;
526:
527: /* Get next cookie and compare name */
528: while (isspace((u_char)*hval))
529: hval++;
530: if ((eq = strchr(hval, '=')) == NULL)
531: break;
532: if ((next = strchr(eq + 1, ';')) == NULL) {
533: next = eq + strlen(eq);
534: vallen = strlen(eq + 1);
535: } else {
536: vallen = next - (eq + 1);
537: next++;
538: }
539: if (strncmp(hval, cookiename, namelen) != 0
540: || hval + namelen != eq)
541: continue;
542:
543: /* Isolate cookie value */
544: if (vallen > sizeof(valbuf) - 1) {
545: DBG(HTTP_SERVLET_COOKIEAUTH, "cookie too long");
546: continue;
547: }
548: memcpy(valbuf, hval + namelen + 1, vallen);
549: valbuf[vallen] = '\0';
550:
551: /* Decode base64 data into binary data */
552: if (structs_init(&authcookie_data_type, NULL, &data) == -1) {
553: alogf(LOG_ERR, "%s: %m", "structs_init");
554: continue;
555: }
556: if (structs_set_string(&authcookie_data_type,
557: NULL, valbuf, &data, NULL, 0) == -1) {
558: DBG(HTTP_SERVLET_COOKIEAUTH,
559: "error decoding base64: %s", ebuf);
560: structs_free(&authcookie_data_type, NULL, &data);
561: continue;
562: }
563:
564: #if PDEL_DEBUG
565: if (PDEL_DEBUG_ENABLED(HTTP_SERVLET_COOKIEAUTH))
566: dump_data(data.data, data.length, "COOKIE DATA");
567: #endif
568:
569: /* Initialize the struct cookieauth */
570: if (structs_init(&cookieauth_type, NULL, auth) == -1) {
571: alogf(LOG_ERR, "%s: %m", "structs_init");
572: continue;
573: }
574:
575: /* Decode binary data into the struct cookieauth */
576: if (structs_set_binary(&cookieauth_type, NULL, &data,
577: auth, ebuf, sizeof(ebuf)) == -1) {
578: DBG(HTTP_SERVLET_COOKIEAUTH,
579: "error decoding auth data: %s", ebuf);
580: structs_free(&cookieauth_type, NULL, auth);
581: structs_free(&authcookie_data_type, NULL, &data);
582: continue;
583: }
584: structs_free(&authcookie_data_type, NULL, &data);
585:
586: #if PDEL_DEBUG
587: if (PDEL_DEBUG_ENABLED(HTTP_SERVLET_COOKIEAUTH)) {
588: printf("COOKIE AUTH STRUCTURE\n");
589: structs_xml_output(&cookieauth_type,
590: "auth", NULL, auth, stdout, NULL, STRUCTS_XML_FULL);
591: }
592: #endif
593:
594: /* Validate auth cookie timestamp and expiration */
595: if (auth->timestamp > now
596: || (auth->expire != 0 && now >= auth->expire)
597: || (auth->linger != 0
598: && now >= auth->timestamp + auth->linger)) {
599: DBG(HTTP_SERVLET_COOKIEAUTH, "expired cookie");
600: structs_free(&cookieauth_type, NULL, auth);
601: continue;
602: }
603:
604: /* Validate auth cookie identifier */
605: if (structs_equal(&authcookie_data_type,
606: NULL, &auth->id, id) != 1) {
607: DBG(HTTP_SERVLET_COOKIEAUTH, "wrong system id");
608: structs_free(&cookieauth_type, NULL, auth);
609: continue;
610: }
611:
612: /* Validate auth cookie RSA signature */
613: if (http_servlet_cookieauth_md5(auth, md5) == -1) {
614: alogf(LOG_ERR, "%s: %m", "http_servlet_cookieauth_md5");
615: structs_free(&cookieauth_type, NULL, auth);
616: return (-1);
617: }
618: if (!rsa_util_verify_priv(privkey, md5,
619: auth->sig.data, auth->sig.length)) {
620: DBG(HTTP_SERVLET_COOKIEAUTH, "invalid RSA signature");
621: structs_free(&cookieauth_type, NULL, auth);
622: continue;
623: }
624:
625: /* OK */
626: return (0);
627: }
628:
629: invalid:
630: /* No valid cookie found */
631: errno = EACCES;
632: return (-1);
633: }
634:
635: /*
636: * Compute MD5 for RSA signature.
637: */
638: static int
639: http_servlet_cookieauth_md5(const struct cookieauth *auth, u_char *md5)
640: {
641: struct structs_data data;
642: struct cookieauth copy;
643: MD5_CTX ctx;
644:
645: /* Copy supplied auth structure */
646: if (structs_get(&cookieauth_type, NULL, auth, ©) == -1)
647: return (-1);
648:
649: /* Zero out the 'sig' field */
650: FREE(DATA_MEM_TYPE, copy.sig.data);
651: memset(©.sig, 0, sizeof(copy.sig));
652:
653: /* Create binary encoding of 'copy' */
654: if (structs_get_binary(&cookieauth_type,
655: NULL, ©, DATA_MEM_TYPE, &data) == -1) {
656: alogf(LOG_ERR, "%s: %m", "structs_get_binary");
657: structs_free(&cookieauth_type, NULL, ©);
658: return (-1);
659: }
660: structs_free(&cookieauth_type, NULL, ©);
661:
662: /* Compute MD5 of that */
663: MD5_Init(&ctx);
664: MD5_Update(&ctx, data.data, data.length);
665: MD5_Final(md5, &ctx);
666:
667: /* Done */
668: structs_free(&authcookie_data_type, NULL, &data);
669: return (0);
670: }
671:
672: #if PDEL_DEBUG
673: /*
674: * Dump some data.
675: */
676: static void
677: dump_data(const void *data, u_int plen, const char *fmt, ...)
678: {
679: const u_char *pkt = data;
680: const int num = 16;
681: va_list args;
682: int i, j;
683:
684: va_start(args, fmt);
685: vprintf(fmt, args);
686: printf("\n");
687: va_end(args);
688: for (i = 0; i < ((plen + num - 1) / num) * num; i += num) {
689: printf("0x%04x ", i);
690: for (j = i; j < i + num; j++) {
691: if (j < plen)
692: printf("%02x", pkt[j]);
693: else
694: printf(" ");
695: if ((j % 2) == 1)
696: printf(" ");
697: }
698: printf(" ");
699: for (j = i; j < i + num; j++) {
700: if (j < plen) {
701: printf("%c", isprint((u_char)pkt[j]) ?
702: pkt[j] : '.');
703: }
704: }
705: printf("\n");
706: }
707: }
708: #endif
709:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>