/* Fri Jul 23 14:05:14 EDT 1999 */ ulong parsedatev(char **a) { char *p; Tm tm; memset(&tm, 0, sizeof tm); if((tm.mon=getmon(a[1])) == -1) goto Err; tm.mday = strtol(a[2], &p, 10); if(*p != '\0') goto Err; tm.hour = strtol(a[3], &p, 10); if(*p != ':') goto Err; tm.min = strtol(p+1, &p, 10); if(*p != ':') goto Err; tm.sec = strtol(p+1, &p, 10); if(*p != '\0') goto Err; if(strlen(a[4]) != 3) goto Err; strcpy(tm.zone, a[4]); if(strlen(a[5]) != 4) goto Err; tm.year = strtol(a[5], &p, 10); if(*p != '\0') goto Err; tm.year -= 1900; return tm2sec(&tm); Err: return time(0); }
/* * Return the time since the epoch in microseconds * The epoch is defined at 1 Jan 1970 */ vlong osusectime(void) { SYSTEMTIME tm; vlong secs; GetSystemTime(&tm); secs = tm2sec(&tm); return secs * 1000000 + tm.wMilliseconds * 1000; }
static ulong cracktime(char *month, char *day, char *yr, char *hms) { Tm tm; int i; char *p; /* default time */ if(now.year == 0) now = *localtime(time(0)); tm = now; tm.yday = 0; /* convert ascii month to a number twixt 1 and 12 */ if(*month >= '0' && *month <= '9'){ tm.mon = atoi(month) - 1; if(tm.mon < 0 || tm.mon > 11) tm.mon = 5; } else { for(p = month; *p; p++) *p = tolower(*p); for(i = 0; i < 12; i++) if(strncmp(&monthchars[i*3], month, 3) == 0){ tm.mon = i; break; } } tm.mday = atoi(day); if(hms){ tm.hour = strtol(hms, &p, 0); if(*p == ':'){ tm.min = strtol(p+1, &p, 0); if(*p == ':') tm.sec = strtol(p+1, &p, 0); } if(tolower(*p) == 'p') tm.hour += 12; } if(yr){ tm.year = atoi(yr); if(tm.year >= 1900) tm.year -= 1900; } else { if(tm.mon > now.mon || (tm.mon == now.mon && tm.mday > now.mday+1)) tm.year--; } /* convert to epoch seconds */ return tm2sec(&tm); }
long getexpiration(char *db, char *u) { char buf[Maxpath]; char prompt[128]; char cdate[32]; Tm date; ulong secs, now; int n, fd; /* read current expiration (if any) */ snprint(buf, sizeof buf, "%s/%s/expire", db, u); fd = open(buf, OREAD); buf[0] = 0; if(fd >= 0){ n = read(fd, buf, sizeof(buf)-1); if(n > 0) buf[n-1] = 0; close(fd); } if(buf[0]){ if(strncmp(buf, "never", 5)){ secs = atoi(buf); memmove(&date, localtime(secs), sizeof(date)); snprint(buf, sizeof buf, "%4.4d%2.2d%2.2d", date.year+1900, date.mon+1, date.mday); } else buf[5] = 0; } else strcpy(buf, "never"); snprint(prompt, sizeof prompt, "Expiration date (YYYYMMDD or never)[return = %s]: ", buf); now = time(0); for(;;){ readln(prompt, cdate, sizeof cdate, 0); if(*cdate == 0) return -1; if(strcmp(cdate, "never") == 0) return 0; date = getdate(cdate); secs = tm2sec(&date); if(secs > now && secs < now + 2*365*24*60*60) break; print("expiration time must fall between now and 2 years from now\n"); } return secs; }
long fromdatetime(int date, int time) { Tm tm; strcpy(tm.zone, "GMT"); tm.mday = date & 0x1f; tm.mon = ((date >> 5) & 0xf) - 1; tm.year = (date >> 9) + 80; tm.yday = 0; tm.sec = (time & 0x1f) << 1; tm.min = (time >> 5) & 0x3f; tm.hour = time >> 11; return tm2sec(&tm); }
static int32_t msdos2time(int time, int date) { Tm tm; tm.hour = time >> 11; tm.min = (time >> 5) & 63; tm.sec = (time & 31) << 1; tm.year = 80 + (date >> 9); tm.mon = ((date >> 5) & 15) - 1; tm.mday = date & 31; tm.zone[0] = '\0'; tm.yday = 0; return tm2sec(&tm); }
void main(int argc, char **argv) { int isnew; char *id, buf[Maxmsg], home[Maxmsg], prompt[100], *hexHi; char *pass, *passck; long expsecs; mpint *H = mpnew(0), *Hi = mpnew(0); PW *pw; Tm *tm; ARGBEGIN{ case 'v': verbose++; break; }ARGEND; if(argc!=1){ fprint(2, "usage: secuser [-v] <user>\n"); exits("usage"); } ensure_exists(SECSTORE_DIR, DMDIR|0755L); snprint(home, sizeof(home), "%s/who", SECSTORE_DIR); ensure_exists(home, DMDIR|0755L); snprint(home, sizeof(home), "%s/store", SECSTORE_DIR); ensure_exists(home, DMDIR|0700L); id = argv[0]; if(verbose) fprint(2,"secuser %s\n", id); if((pw = getPW(id,1)) == nil){ isnew = 1; print("new account (because %s/%s %r)\n", SECSTORE_DIR, id); pw = emalloc(sizeof(*pw)); pw->id = estrdup(id); snprint(home, sizeof(home), "%s/store/%s", SECSTORE_DIR, id); if(access(home, AEXIST) == 0) sysfatal("new user, but directory %s already exists", home); }else{ isnew = 0; } /* get main password for id */ for(;;){ if(isnew) snprint(prompt, sizeof(prompt), "%s password: "******"%s password [default = don't change]: ", id); pass = getpassm(prompt); if(pass == nil) sysfatal("getpassm failed"); if(verbose) print("%ld characters\n", strlen(pass)); if(pass[0] == '\0' && isnew == 0) break; if(strlen(pass) >= 7) break; print("password must be at least 7 characters\n"); } if(pass[0] != '\0'){ snprint(prompt, sizeof(prompt), "retype password: "******"confirming...\n"); passck = getpassm(prompt); if(passck == nil) sysfatal("getpassm failed"); if(strcmp(pass, passck) != 0) sysfatal("passwords didn't match"); memset(passck, 0, strlen(passck)); free(passck); hexHi = PAK_Hi(id, pass, H, Hi); memset(pass, 0, strlen(pass)); free(pass); free(hexHi); mpfree(H); pw->Hi = Hi; } /* get expiration time (midnight of date specified) */ if(isnew) expsecs = time(0) + 365*24*60*60; else expsecs = pw->expire; for(;;){ tm = localtime(expsecs); print("expires [DDMMYYYY, default = %2.2d%2.2d%4.4d]: ", tm->mday, tm->mon+1, tm->year+1900); userinput(buf, sizeof(buf)); if(strlen(buf) == 0) break; if(strlen(buf) != 8){ print("!bad date format: %s\n", buf); continue; } tm->mday = (buf[0]-'0')*10 + (buf[1]-'0'); if(tm->mday > 31 || tm->mday < 1){ print("!bad day of month: %d\n", tm->mday); continue; } tm->mon = (buf[2]-'0')*10 + (buf[3]-'0') - 1; if(tm->mon > 11 || tm->mon < 0){ print("!bad month: %d\n", tm->mon + 1); continue; } tm->year = atoi(buf+4) - 1900; if(tm->year < 70){ print("!bad year: %d\n", tm->year + 1900); continue; } tm->sec = 59; tm->min = 59; tm->hour = 23; tm->yday = 0; expsecs = tm2sec(tm); break; } pw->expire = expsecs; /* failed logins */ if(pw->failed != 0 ) print("clearing %d failed login attempts\n", pw->failed); pw->failed = 0; /* status bits */ if(isnew) pw->status = Enabled; for(;;){ print("Enabled or Disabled [default %s]: ", (pw->status & Enabled) ? "Enabled" : "Disabled" ); userinput(buf, sizeof(buf)); if(strlen(buf) == 0) break; if(buf[0]=='E' || buf[0]=='e'){ pw->status |= Enabled; break; } if(buf[0]=='D' || buf[0]=='d'){ pw->status = pw->status & ~Enabled; break; } } for(;;){ print("require STA? [default %s]: ", (pw->status & STA) ? "yes" : "no" ); userinput(buf, sizeof(buf)); if(strlen(buf) == 0) break; if(buf[0]=='Y' || buf[0]=='y'){ pw->status |= STA; break; } if(buf[0]=='N' || buf[0]=='n'){ pw->status = pw->status & ~STA; break; } } /* free form field */ if(isnew) pw->other = nil; print("comments [default = %s]: ", (pw->other == nil) ? "" : pw->other); userinput(buf, 72); /* 72 comes from password.h */ if(buf[0]) if((pw->other = strdup(buf)) == nil) sysfatal("strdup"); syslog(0, LOG, "CHANGELOGIN for '%s'", pw->id); if(putPW(pw) < 0) sysfatal("can't write password file: %r"); else{ print("change written\n"); if(isnew && create(home, OREAD, DMDIR | 0775L) < 0) sysfatal("unable to create %s: %r", home); } exits(""); }
/* * Parses an HTTP date in one of three standard forms: * * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format * * and returns the time_t number of seconds since 1 Jan 1970 GMT, or * 0 if this would be out of range or if the date is invalid. * * The restricted HTTP syntax is * * HTTP-date = rfc1123-date | rfc850-date | asctime-date * * rfc1123-date = wkday "," SP date1 SP time SP "GMT" * rfc850-date = weekday "," SP date2 SP time SP "GMT" * asctime-date = wkday SP date3 SP time SP 4DIGIT * * date1 = 2DIGIT SP month SP 4DIGIT * ; day month year (e.g., 02 Jun 1982) * date2 = 2DIGIT "-" month "-" 2DIGIT * ; day-month-year (e.g., 02-Jun-82) * date3 = month SP ( 2DIGIT | ( SP 1DIGIT )) * ; month day (e.g., Jun 2) * * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT * ; 00:00:00 - 23:59:59 * * wkday = "Mon" | "Tue" | "Wed" * | "Thu" | "Fri" | "Sat" | "Sun" * * weekday = "Monday" | "Tuesday" | "Wednesday" * | "Thursday" | "Friday" | "Saturday" | "Sunday" * * month = "Jan" | "Feb" | "Mar" | "Apr" * | "May" | "Jun" | "Jul" | "Aug" * | "Sep" | "Oct" | "Nov" | "Dec" * * However, for the sake of robustness (and Netscapeness), we ignore the * weekday and anything after the time field (including the timezone). * * This routine is intended to be very fast; 10x faster than using sscanf. * * Originally from Andrew Daviel <*****@*****.**>, 29 Jul 96 * but many changes since then. * */ time_t parseHTTPdate(const char *date) { struct tm ds; int mint, mon; const char *monstr, *timstr; const int months[12] = { ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b', ('M' << 16) | ('a' << 8) | 'r', ('A' << 16) | ('p' << 8) | 'r', ('M' << 16) | ('a' << 8) | 'y', ('J' << 16) | ('u' << 8) | 'n', ('J' << 16) | ('u' << 8) | 'l', ('A' << 16) | ('u' << 8) | 'g', ('S' << 16) | ('e' << 8) | 'p', ('O' << 16) | ('c' << 8) | 't', ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c'}; if (!date) return BAD_DATE; while (*date && isspace((int) *date)) /* Find first non-whitespace char */ ++date; if (*date == '\0') return BAD_DATE; if ((date = strchr(date, ' ')) == NULL) /* Find space after weekday */ return BAD_DATE; ++date; /* Now pointing to first char after space, which should be */ /* start of the actual date information for all 3 formats. */ if (checkmask(date, "## @$$ #### ##:##:## *")) { /* RFC 1123 format */ ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100; if (ds.tm_year < 0) return BAD_DATE; ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0'); ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0'); monstr = date + 3; timstr = date + 12; } else if (checkmask(date, "##-@$$-## ##:##:## *")) { /* RFC 850 format */ ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0'); if (ds.tm_year < 70) ds.tm_year += 100; ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0'); monstr = date + 3; timstr = date + 10; } else if (checkmask(date, "@$$ ~# ##:##:## ####*")) { /* asctime format */ ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100; if (ds.tm_year < 0) return BAD_DATE; ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0'); if (date[4] == ' ') ds.tm_mday = 0; else ds.tm_mday = (date[4] - '0') * 10; ds.tm_mday += (date[5] - '0'); monstr = date; timstr = date + 7; } else return BAD_DATE; if (ds.tm_mday <= 0 || ds.tm_mday > 31) return BAD_DATE; ds.tm_hour = ((timstr[0] - '0') * 10) + (timstr[1] - '0'); ds.tm_min = ((timstr[3] - '0') * 10) + (timstr[4] - '0'); ds.tm_sec = ((timstr[6] - '0') * 10) + (timstr[7] - '0'); if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61)) return BAD_DATE; mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2]; for (mon = 0; mon < 12; mon++) if (mint == months[mon]) break; if (mon == 12) return BAD_DATE; if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10)) return BAD_DATE; /* February gets special check for leapyear */ if ((mon == 1) && ((ds.tm_mday > 29) || ((ds.tm_mday == 29) && ((ds.tm_year & 3) || (((ds.tm_year % 100) == 0) && (((ds.tm_year % 400) != 100))))))) return BAD_DATE; ds.tm_mon = mon; return tm2sec(&ds); }
/* * parse a date and return the seconds since the epoch * return 0 for a failure */ uint32_t hdate2sec(char *date) { Tm tm; char buf[32]; /* * Weekday|Wday */ date = dateword(date, buf); tm.wday = dateindex(buf, wdayname, 7); if(tm.wday < 0) tm.wday = dateindex(buf, weekdayname, 7); if(tm.wday < 0) return 0; /* * check for the two major formats */ date = dateword(date, buf); tm.mon = dateindex(buf, monname, 12); if(tm.mon >= 0){ /* * MM */ tm.mday = datenum(&date); if(tm.mday < 1 || tm.mday > 31) return 0; /* * HH:MM:SS */ tm.hour = datenum(&date); if(tm.hour < 0 || tm.hour >= 24) return 0; tm.min = datenum(&date); if(tm.min < 0 || tm.min >= 60) return 0; tm.sec = datenum(&date); if(tm.sec < 0 || tm.sec >= 60) return 0; /* * YYYY */ tm.year = datenum(&date); if(tm.year < 70 || (tm.year > 99 && tm.year < 1970)) return 0; if(tm.year >= 1970) tm.year -= 1900; }else{ /* * MM-Mon-(YY|YYYY) */ tm.mday = datenum(&date); if(tm.mday < 1 || tm.mday > 31) return 0; date = dateword(date, buf); tm.mon = dateindex(buf, monname, 12); if(tm.mon < 0 || tm.mon >= 12) return 0; tm.year = datenum(&date); if(tm.year < 70 || (tm.year > 99 && tm.year < 1970)) return 0; if(tm.year >= 1970) tm.year -= 1900; /* * HH:MM:SS */ tm.hour = datenum(&date); if(tm.hour < 0 || tm.hour >= 24) return 0; tm.min = datenum(&date); if(tm.min < 0 || tm.min >= 60) return 0; tm.sec = datenum(&date); if(tm.sec < 0 || tm.sec >= 60) return 0; /* * timezone */ dateword(date, buf); if(strncmp(buf, "gmt", 3) != 0) return 0; } strcpy(tm.zone, "GMT"); tm.tzoff = 0; tm.yday = 0; return tm2sec(&tm); }