[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.7

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