X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2Fcmd%2Fwebcookies.c;h=42ec744f68f523a5d6ed865facdcc6f87bdb99cc;hb=2d4504d9011f1accb6fbdb87a5d428423ed7bf33;hp=1ae358cff3853e91ba912d0cd624756035ce8472;hpb=a9060cc06bee66e12fe16644511f181a4b0cdbd3;p=plan9front.git diff --git a/sys/src/cmd/webcookies.c b/sys/src/cmd/webcookies.c index 1ae358cff..42ec744f6 100644 --- a/sys/src/cmd/webcookies.c +++ b/sys/src/cmd/webcookies.c @@ -349,29 +349,35 @@ expirejar(Jar *jar, int exiting) int syncjar(Jar *jar) { - int i, fd; + int i, fd, doread, dowrite; char *line; - Dir *d; Biobuf *b; + Dir *d; Qid q; if(jar->file==nil) return 0; - memset(&q, 0, sizeof q); - if((d = dirstat(jar->file)) != nil){ - q = d->qid; - if(d->qid.path != jar->qid.path || d->qid.vers != jar->qid.vers) - jar->dirty = 1; + doread = 0; + dowrite = jar->dirty; + + q = jar->qid; + if((d = dirstat(jar->file)) == nil) + dowrite = 1; + else { + if(q.path != d->qid.path || q.vers != d->qid.vers){ + q = d->qid; + doread = 1; + } free(d); } - if(jar->dirty == 0) + if(!doread && !dowrite) return 0; fd = -1; for(i=0; i<50; i++){ - if((fd = create(jar->lockfile, OWRITE, DMEXCL|0666)) < 0){ + if((fd = create(jar->lockfile, OWRITE, DMEXCL|0600)) < 0){ sleep(100); continue; } @@ -384,55 +390,85 @@ syncjar(Jar *jar) return -1; } - for(i=0; inc; i++) /* mark is cleared by addcookie */ - jar->c[i].mark = jar->c[i].ondisk; + if(doread){ + for(i=0; inc; i++) /* mark is cleared by addcookie */ + jar->c[i].mark = jar->c[i].ondisk; - if((b = Bopen(jar->file, OREAD)) == nil){ - if(debug) - fprint(2, "Bopen %s: %r", jar->file); - werrstr("cannot read cookie file %s: %r", jar->file); - close(fd); - return -1; - } - for(; (line = Brdstr(b, '\n', 1)) != nil; free(line)){ - if(*line == '#') - continue; - addtojar(jar, line, 1); - } - Bterm(b); + if((b = Bopen(jar->file, OREAD)) == nil){ + if(debug) + fprint(2, "Bopen %s: %r", jar->file); + werrstr("cannot read cookie file %s: %r", jar->file); + close(fd); + return -1; + } + for(; (line = Brdstr(b, '\n', 1)) != nil; free(line)){ + if(*line == '#') + continue; + addtojar(jar, line, 1); + } + Bterm(b); - for(i=0; inc; i++) - if(jar->c[i].mark) - delcookie(jar, &jar->c[i]); + for(i=0; inc; i++) + if(jar->c[i].mark) + delcookie(jar, &jar->c[i]); + } purgejar(jar); - b = Bopen(jar->file, OWRITE); - if(b == nil){ - if(debug) - fprint(2, "Bopen write %s: %r", jar->file); - close(fd); - return -1; - } - Bprint(b, "# webcookies cookie jar\n"); - Bprint(b, "# comments and non-standard fields will be lost\n"); - for(i=0; inc; i++){ - if(jar->c[i].expire == ~0) - continue; - Bprint(b, "%K\n", &jar->c[i]); - jar->c[i].ondisk = 1; + if(dowrite){ + i = create(jar->file, OWRITE, 0600); + if(i < 0 || (b = Bfdopen(i, OWRITE)) == nil){ + if(debug) + fprint(2, "Bopen write %s: %r", jar->file); + if(i >= 0) + close(i); + close(fd); + return -1; + } + Bprint(b, "# webcookies cookie jar\n"); + Bprint(b, "# comments and non-standard fields will be lost\n"); + for(i=0; inc; i++){ + if(jar->c[i].expire == ~0) + continue; + Bprint(b, "%K\n", &jar->c[i]); + jar->c[i].ondisk = 1; + } + Bflush(b); + if((d = dirfstat(Bfildes(b))) != nil){ + q = d->qid; + free(d); + } + Bterm(b); } - Bterm(b); + jar->qid = q; jar->dirty = 0; + close(fd); - if((d = dirstat(jar->file)) != nil){ - jar->qid = d->qid; - free(d); - } return 0; } +void +closejar(Jar *jar) +{ + int i; + + if(jar == nil) + return; + expirejar(jar, 0); + if(jar->dirty) + if(syncjar(jar) < 0) + fprint(2, "warning: cannot rewrite cookie jar: %r\n"); + + for(i=0; inc; i++) + freecookie(&jar->c[i]); + + free(jar->lockfile); + free(jar->file); + free(jar->c); + free(jar); +} + Jar* readjar(char *file) { @@ -440,6 +476,7 @@ readjar(char *file) Jar *jar; jar = newjar(); + file = estrdup9p(file); lock = emalloc9p(strlen(file)+10); strcpy(lock, file); if((p = strrchr(lock, '/')) != nil) @@ -451,32 +488,15 @@ readjar(char *file) p[1] = '.'; jar->lockfile = lock; jar->file = file; - jar->dirty = 1; + jar->dirty = 0; if(syncjar(jar) < 0){ - free(jar->file); - free(jar->lockfile); - free(jar); + closejar(jar); return nil; } return jar; } -void -closejar(Jar *jar) -{ - int i; - - expirejar(jar, 0); - if(syncjar(jar) < 0) - fprint(2, "warning: cannot rewrite cookie jar: %r\n"); - - for(i=0; inc; i++) - freecookie(&jar->c[i]); - - free(jar->file); - free(jar); -} /* * Domain name matching is per RFC2109, section 2: @@ -505,7 +525,7 @@ isdomainmatch(char *name, char *pattern) { int lname, lpattern; - if(cistrcmp(name, pattern)==0) + if(cistrcmp(name, pattern + (pattern[0]=='.'))==0) return 1; if(strcmp(ipattr(name), "dom")==0 && pattern[0]=='.'){ @@ -541,13 +561,16 @@ cookiesearch(Jar *jar, char *dom, char *path, int issecure) { int i; Jar *j; + Cookie *c; uint now; now = time(0); j = newjar(); - for(i=0; inc; i++) - if((issecure || !jar->c[i].secure) && iscookiematch(&jar->c[i], dom, path, now)) - addcookie(j, &jar->c[i]); + for(i=0; inc; i++){ + c = &jar->c[i]; + if(!c->deleted && (issecure || !c->secure) && iscookiematch(c, dom, path, now)) + addcookie(j, c); + } if(j->nc == 0){ closejar(j); werrstr("no cookies found"); @@ -569,13 +592,13 @@ isbadcookie(Cookie *c, char *dom, char *path) if(c->explicitdom && c->dom[0] != '.') return "cookie domain doesn't start with dot"; - if(memchr(c->dom+1, '.', strlen(c->dom)-1-1) == nil) + if(strlen(c->dom)<=2 || memchr(c->dom+1, '.', strlen(c->dom)-2) == nil) return "cookie domain doesn't have embedded dots"; if(!isdomainmatch(dom, c->dom)) return "request host does not match cookie domain"; - if(strcmp(ipattr(dom), "dom")==0 + if(strcmp(ipattr(dom), "dom")==0 && strlen(dom)>strlen(c->dom) && memchr(dom, '.', strlen(dom)-strlen(c->dom)) != nil) return "request host contains dots before cookie domain"; @@ -583,141 +606,25 @@ isbadcookie(Cookie *c, char *dom, char *path) } /* + * Parse a date in one of these formats: * Sunday, 25-Jan-2002 12:24:36 GMT * Sunday, 25 Jan 2002 12:24:36 GMT * Sun, 25 Jan 02 12:24:36 GMT */ -int -isleap(int year) -{ - return year%4==0 && (year%100!=0 || year%400==0); -} - uint strtotime(char *s) { - char *os; - int i; - Tm tm; - - static int mday[2][12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, - 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, - }; - static char *wday[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday", + char **f, *fmts[] = { + "?WW, ?DD-?MM-?YYYY hh:mm:ss ?Z", + "?WW, ?DD ?MM ?YYYY hh:mm:ss ?Z", + nil, }; - static char *mon[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - }; - - os = s; - /* Sunday, */ - for(i=0; i mday[isleap(tm.year)][tm.mon]){ - if(debug) - fprint(2, "invalid day of month (%s)\n", os); - return -1; - } - tm.year -= 1900; - if(*s++ != ' '){ - if(debug) - fprint(2, "bad year separator (%s)\n", os); - return -1; - } - - if(!isdigit(s[0]) || !isdigit(s[1]) || s[2]!=':' - || !isdigit(s[3]) || !isdigit(s[4]) || s[5]!=':' - || !isdigit(s[6]) || !isdigit(s[7]) || s[8]!=' '){ - if(debug) - fprint(2, "bad time (%s)\n", os); - return -1; - } - - tm.hour = atoi(s); - tm.min = atoi(s+3); - tm.sec = atoi(s+6); - if(tm.hour >= 24 || tm.min >= 60 || tm.sec >= 60){ - if(debug) - fprint(2, "invalid time (%s)\n", os); - return -1; - } - s += 9; + Tm tm; - if(cistrcmp(s, "GMT") != 0){ - if(debug) - fprint(2, "time zone not GMT (%s)\n", os); - return -1; - } - strcpy(tm.zone, "GMT"); - tm.yday = 0; - return tm2sec(&tm); + for(f = fmts; *f != nil; f++) + if(tmparse(&tm, *f, s, nil, nil) != nil) + return tmnorm(&tm); + return -1; } /* @@ -948,22 +855,34 @@ parsecookie(Cookie *c, char *p, char **e, int isns, char *dom, char *path) if(cistrcmp(attr, "secure") == 0) c->secure = 1; } + *e = p; - if(c->dom) + if(c->dom){ + /* add leading dot for explicit domain */ + if(c->dom[0] != '.' && strcmp(ipattr(c->dom), "dom") == 0){ + static char ddom[1024]; + + ddom[0] = '.'; + ddom[sizeof(ddom)-1] = '\0'; + strncpy(ddom+1, c->dom, sizeof(ddom)-2); + c->dom = ddom; + } c->explicitdom = 1; - else + }else c->dom = dom; if(c->path) c->explicitpath = 1; - else{ - c->path = path; - if((t = strchr(c->path, '?')) != 0) - *t = '\0'; - if((t = strrchr(c->path, '/')) != 0) - *t = '\0'; + else { + static char dpath[1024]; + + /* implicit path is "directory" of request-uri's path component */ + dpath[sizeof(dpath)-1] = '\0'; + strncpy(dpath, path, sizeof(dpath)-1); + if((t = strrchr(dpath, '/')) != nil) + t[1] = '\0'; + c->path = dpath; } c->netscapestyle = isns; - *e = p; return nil; } @@ -1097,9 +1016,14 @@ fswrite(Req *r) p = strchr(buf+hlen, '/'); if(p == nil) a->path = estrdup9p("/"); - else{ + else { a->path = estrdup9p(p); *p = '\0'; + + if((p = strchr(a->path, '#')) != nil) + *p = '\0'; + if((p = strchr(a->path, '?')) != nil) + *p = '\0'; } a->dom = estrdup9p(buf+hlen); a->state = HaveUrl; @@ -1113,8 +1037,7 @@ fswrite(Req *r) } } snprint(a->outhttp, AuxBuf, "%J", j); - if(j) - closejar(j); + closejar(j); }else{ if(strlen(a->inhttp)+r->ifcall.count >= AuxBuf){ respond(r, "http headers too large"); @@ -1176,7 +1099,8 @@ fsdestroyfid(Fid *fid) delcookie(jar, &jar->c[i]); break; } - syncjar(jar); + if(jar->dirty) + syncjar(jar); free(a->dom); free(a->path); free(a->inhttp); @@ -1250,8 +1174,6 @@ main(int argc, char **argv) strcpy(file, home); strcat(file, "/lib/webcookies"); } - if(access(file, AEXIST) < 0) - close(create(file, OWRITE, 0666)); jar = readjar(file); if(jar == nil)