[BACK]Return to cookie.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ftp

Annotation of src/usr.bin/ftp/cookie.c, Revision 1.2

1.2     ! pyr         1: /* $OpenBSD: cookie.c,v 1.1 2007/06/13 13:52:26 pyr Exp $      */
1.1       pyr         2: /*
                      3:  * Copyright (c) 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: #ifndef SMALL
                     19: #include <sys/types.h>
                     20: #include <sys/queue.h>
                     21:
                     22: #include <err.h>
                     23: #include <errno.h>
                     24: #include <fnmatch.h>
                     25: #include <stdio.h>
                     26: #include <string.h>
                     27: #include <stdlib.h>
                     28: #include <time.h>
                     29:
                     30: #include "ftp_var.h"
                     31:
                     32: struct cookie {
                     33:        TAILQ_ENTRY(cookie)      entry;
                     34:        TAILQ_ENTRY(cookie)      tempentry;
                     35:        u_int8_t                 flags;
                     36: #define F_SECURE                0x01
                     37: #define F_TAILMATCH             0x02
                     38: #define F_NOEXPIRY              0x04
                     39: #define F_MATCHPATH             0x08
                     40:        time_t                   expires;
                     41:        char                    *domain;
                     42:        char                    *path;
                     43:        char                    *key;
                     44:        char                    *val;
                     45: };
                     46: TAILQ_HEAD(cookiejar, cookie);
                     47:
                     48: typedef enum {
                     49:        DOMAIN = 0, TAILMATCH = 1, PATH = 2, SECURE = 3,
                     50:        EXPIRES = 4, NAME = 5, VALUE = 6, DONE = 7
                     51: } field_t;
                     52:
                     53: static struct cookiejar jar;
                     54:
                     55: void
                     56: cookie_load(void)
                     57: {
                     58:        field_t          field;
                     59:        size_t           len;
                     60:        time_t           date;
                     61:        char            *line;
                     62:        char            *lbuf;
                     63:        char            *param;
                     64:        const char      *estr;
                     65:        FILE            *fp;
                     66:        struct cookie   *ck;
                     67:
                     68:        if (cookiefile == NULL)
                     69:                return;
                     70:
                     71:        TAILQ_INIT(&jar);
                     72:        fp = fopen(cookiefile, "r");
                     73:        if (fp == NULL)
                     74:                err(1, "cannot open cookie file %s", cookiefile);
                     75:        date = time(NULL);
                     76:        lbuf = NULL;
                     77:        while ((line = fgetln(fp, &len)) != NULL) {
                     78:                if (line[len - 1] == '\n') {
                     79:                        line[len - 1] = '\0';
                     80:                        --len;
                     81:                } else {
                     82:                        if ((lbuf = malloc(len + 1)) == NULL)
                     83:                                err(1, NULL);
                     84:                        memcpy(lbuf, line, len);
                     85:                        lbuf[len] = '\0';
                     86:                        line = lbuf;
                     87:                }
1.2     ! pyr        88:                line[strcspn(line, "\r")] = '\0';
1.1       pyr        89:
                     90:                line += strspn(line, " \t");
                     91:                if ((*line == '#') || (*line == '\0')) {
                     92:                        continue;
                     93:                }
                     94:                field = DOMAIN;
                     95:                ck = calloc(1, sizeof(*ck));
                     96:                if (ck == NULL)
                     97:                        err(1, NULL);
                     98:                while ((param = strsep(&line, "\t")) != NULL) {
                     99:                        switch (field) {
                    100:                        case DOMAIN:
                    101:                                if (*param == '.') {
                    102:                                        if (asprintf(&ck->domain,
                    103:                                            "*%s", param) == -1)
                    104:                                                err(1, NULL);
                    105:                                } else {
                    106:                                        ck->domain = strdup(param);
                    107:                                        if (ck->domain == NULL)
                    108:                                                err(1, NULL);
                    109:                                }
                    110:                                break;
                    111:                        case TAILMATCH:
                    112:                                if (strcasecmp(param, "TRUE") == 0) {
                    113:                                        ck->flags |= F_TAILMATCH;
                    114:                                } else if (strcasecmp(param, "FALSE") != 0) {
                    115:                                        errx(1, "invalid cookie file");
                    116:                                }
                    117:                                break;
                    118:                        case PATH:
                    119:                                if (strcmp(param, "/") != 0) {
                    120:                                        ck->flags |= F_MATCHPATH;
                    121:                                        if (asprintf(&ck->path,
                    122:                                            "%s*", param) == -1)
                    123:                                                err(1, NULL);
                    124:                                }
                    125:                                break;
                    126:                        case SECURE:
                    127:                                if (strcasecmp(param, "TRUE") == 0) {
                    128:                                        ck->flags |= F_SECURE;
                    129:                                } else if (strcasecmp(param, "FALSE") != 0) {
                    130:                                        errx(1, "invalid cookie file");
                    131:                                }
                    132:                                break;
                    133:                        case EXPIRES:
                    134:                                /*
                    135:                                 * rely on sizeof(time_t) being 4
                    136:                                 */
                    137:                                ck->expires = strtonum(param, 0,
                    138:                                    UINT_MAX, &estr);
                    139:                                if (estr) {
                    140:                                        if (errno == ERANGE)
                    141:                                                ck->flags |= F_NOEXPIRY;
                    142:                                        else
                    143:                                                errx(1, "invalid cookie file");
                    144:                                }
                    145:                                break;
                    146:                        case NAME:
                    147:                                ck->key = strdup(param);
                    148:                                if (ck->key == NULL)
                    149:                                        err(1, NULL);
                    150:                                break;
                    151:                        case VALUE:
                    152:                                ck->val = strdup(param);
                    153:                                if (ck->val == NULL)
                    154:                                        err(1, NULL);
                    155:                                break;
                    156:                        case DONE:
                    157:                                errx(1, "invalid cookie file");
                    158:                                break;
                    159:                        }
                    160:                        field++;
                    161:                }
                    162:                if (field != DONE)
                    163:                        errx(1, "invalid cookie file");
                    164:                if (ck->expires < date && !(ck->flags & F_NOEXPIRY)) {
                    165:                        free(ck->val);
                    166:                        free(ck->key);
                    167:                        free(ck->path);
                    168:                        free(ck->domain);
                    169:                        free(ck);
                    170:                } else
                    171:                        TAILQ_INSERT_TAIL(&jar, ck, entry);
                    172:        }
                    173:        free(lbuf);
                    174:        fclose(fp);
                    175: }
                    176:
                    177: void
                    178: cookie_get(const char *domain, const char *path, int secure, char **pstr)
                    179: {
                    180:        size_t           len;
                    181:        size_t           headlen;
                    182:        char            *head;
                    183:        char            *str;
                    184:        struct cookie   *ck;
                    185:        struct cookiejar tempjar;
                    186:
                    187:        *pstr = NULL;
                    188:
                    189:        if (cookiefile == NULL)
                    190:                return;
                    191:
                    192:        TAILQ_INIT(&tempjar);
                    193:        len = strlen("Cookie\r\n");
                    194:
                    195:        TAILQ_FOREACH(ck, &jar, entry) {
                    196:                if (fnmatch(ck->domain, domain, 0) == 0 &&
                    197:                    (secure || !(ck->flags & F_SECURE))) {
                    198:
                    199:                        if (ck->flags & F_MATCHPATH &&
                    200:                            fnmatch(ck->path, path, 0) != 0)
                    201:                                continue;
                    202:
                    203:                        len += strlen(ck->key) + strlen(ck->val) +
                    204:                            strlen("; =");
                    205:                        TAILQ_INSERT_TAIL(&tempjar, ck, tempentry);
                    206:                }
                    207:        }
                    208:        if (TAILQ_EMPTY(&tempjar))
                    209:                return;
                    210:        len += 1;
                    211:        str = malloc(len);
                    212:        if (str == NULL)
                    213:                err(1, NULL);
                    214:
                    215:        (void)strlcpy(str, "Cookie:", len);
                    216:        TAILQ_FOREACH(ck, &tempjar, tempentry) {
                    217:                head = str + strlen(str);
                    218:                headlen = len - strlen(str);
                    219:
                    220:                snprintf(head, headlen, "%s %s=%s",
                    221:                    (ck == TAILQ_FIRST(&tempjar))? "" : ";", ck->key, ck->val);
                    222:        }
                    223:        if (strlcat(str, "\r\n", len) >= len)
                    224:                errx(1, "cookie header truncated");
                    225:        *pstr = str;
                    226: }
                    227:
                    228: #endif /* ! SMALL */