精華區beta SetupBBS 關於我們 聯絡資訊
#undef VACATION /*-------------------------------------------------------*/ /* register.c ( NTHU CS MapleBBS Ver 2.36 ) */ /*-------------------------------------------------------*/ /* target : user register routines */ /* create : 95/03/29 */ /* update : 95/12/15 */ /*-------------------------------------------------------*/ #include "bbs.h" /* ------------------- */ /* password encryption */ /* ------------------- */ char *crypt(); static char pwbuf[14]; char * genpasswd(pw) char *pw; { if (pw[0]) { char saltc[2], c; int i; i = 9 * getpid(); saltc[0] = i & 077; saltc[1] = (i >> 6) & 077; for (i = 0; i < 2; i++) { c = saltc[i] + '.'; if (c > '9') c += 7; if (c > 'Z') c += 6; saltc[i] = c; } strcpy(pwbuf, pw); return crypt(pwbuf, saltc); } return ""; } int checkpasswd(passwd, test) char *passwd, *test; { char *pw; strncpy(pwbuf, test, 14); pw = crypt(pwbuf, passwd); return (!strncmp(pw, passwd, 14)); } /* ------------------ */ /* 檢查 user 註冊情況 */ /* ------------------ */ int bad_user_id(userid) char *userid; { register char ch; if (strlen(userid) < 2) return 1; if (not_alpha(*userid)) return 1; if (!ci_strcmp(userid, str_new)) return 1; while (ch = *(++userid)) { if (not_alnum(ch)) return 1; } return 0; } /* -------------------------------- */ /* New policy for allocate new user */ /* (a) is the worst user currently */ /* (b) is the object to be compared */ /* -------------------------------- */ static int compute_user_value(urec, clock) userec *urec; time_t clock; { int value; /* if (urec) has XEMPT permission, don't kick it */ if ((urec->userid[0] == '\0') || (urec->userlevel & PERM_XEMPT)) return 9999; value = (clock - urec->lastlogin) / 60; /* minutes */ /* new user should register in 30 mins */ if (strcmp(urec->userid, str_new) == 0) return (30 - value); #ifdef VACATION return 120 * 24 * 60 - value; /* 寒暑假保存帳號 120 天 */ #else if (!urec->numlogins) /* 未 login 成功者,不保留 */ return -1; if (urec->numlogins <= 3) /* #login 少於三者,保留 20 天 */ return 20 * 24 * 60 - value; /* 未完成註冊者,保留 15 天 */ /* 一般情況,保留 120 天 */ return (urec->userlevel & PERM_LOGINOK ? 120 : 15) * 24 * 60 - value; #endif } static int getnewuserid() { static char *fn_fresh = ".fresh"; extern struct UCACHE *uidshm; userec utmp, zerorec; time_t clock; struct stat st; int fd, val, i; char genbuf[200]; char genbuf2[200]; memset(&zerorec, 0, sizeof(zerorec)); clock = time(NULL); /* -------------------------------------- */ /* Lazy method : 先找尋已經清除的過期帳號 */ /* -------------------------------------- */ if ((i = searchnewuser(0)) == 0) { /* ------------------------------- */ /* 每 1 個小時,清理 user 帳號一次 */ /* ------------------------------- */ if ((stat(fn_fresh, &st) == -1) || (st.st_mtime < clock - 3600)) { if ((fd = open(fn_fresh, O_RDWR | O_CREAT, 0600)) == -1) return -1; write(fd, ctime(&clock), 25); close(fd); log_usies("CLEAN", "dated users"); printf("尋找新帳號中, 請稍待片刻...\n\r"); if ((fd = open(fn_passwd, O_RDWR | O_CREAT, 0600)) == -1) return -1; i = 0; /* Ptt解決第一個帳號老是被砍問題 */ while (i < MAXUSERS) { i++; if (read(fd, &utmp, sizeof(userec)) != sizeof(userec)) break; if(i==1) continue; /* woju */ if ((val = compute_user_value(&utmp, clock)) < 0) { sprintf(genbuf, "#%d %-12s %15.15s %d %d %d", i, utmp.userid, ctime(&(utmp.lastlogin)) + 4, utmp.numlogins, utmp.numposts, val); if (val > -1 * 60 * 24 * 365) { log_usies("CLEAN", genbuf); sprintf(genbuf, "home/%s", utmp.userid); sprintf(genbuf2, "tmp/%s", utmp.userid); if (dashd(genbuf) && Rename(genbuf, genbuf2)) { sprintf(genbuf, "/bin/rm -fr home/%s", utmp.userid); system(genbuf); } lseek(fd, (i - 1) * sizeof(userec), SEEK_SET); write(fd, &zerorec, sizeof(utmp)); } else log_usies("DATED", genbuf); } } close(fd); time(&(uidshm->touchtime)); } } if ((fd = open(fn_passwd, O_RDWR | O_CREAT, 0600)) == -1) return -1; flock(fd, LOCK_EX); i = searchnewuser(1); if ((i <= 0) || (i > MAXUSERS)) { flock(fd, LOCK_UN); close(fd); if (more("etc/user_full", NA) == -1) printf("抱歉,使用者帳號已經滿了,無法註冊新的帳號\n\r"); val = (st.st_mtime - clock + 3660) / 60; printf("請等待 %d 分鐘後再試一次,祝你好運\n\r", val); sleep(2); exit(1); } sprintf(genbuf, "uid %d", i); log_usies("APPLY", genbuf); strcpy(zerorec.userid, str_new); zerorec.lastlogin = clock; if (lseek(fd, sizeof(zerorec) * (i - 1), SEEK_SET) == -1) { flock(fd, LOCK_UN); close(fd); return -1; } write(fd, &zerorec, sizeof(zerorec)); setuserid(i, zerorec.userid); flock(fd, LOCK_UN); close(fd); return i; } int u_register(); void new_register() { userec newuser; char passbuf[STRLEN]; int allocid, try; char genbuf[200]; #if 0 time_t now; /* ------------------ */ /* 限定星期幾不准註冊 */ /* ------------------ */ now = time(0); sprintf(genbuf, "etc/no_register_%3.3s", ctime(&now)); if (more(genbuf, NA) != -1) { pressanykey(); exit(1); } #endif memset(&newuser, 0, sizeof(newuser)); more("etc/register", NA); try = 0; while (1) { if (++try >= 6) { outs("\n您嘗試錯誤的輸入太多,請下次再來吧\n"); refresh(); pressanykey(); oflush(); exit(1); } getdata(0, 0, msg_uid, newuser.userid, IDLEN + 1, DOECHO); if (bad_user_id(newuser.userid)) outs("無法接受這個代號,請使用英文字母,並且不要包含空格\n"); else if (searchuser(newuser.userid)) outs("此代號已經有人使用\n"); else break; } try = 0; while (1) { if (++try >= 6) { outs("\n您嘗試錯誤的輸入太多,請下次再來吧\n"); refresh(); pressanykey(); oflush(); exit(1); /* return; */ /*longjmp(byebye, -1);*/ } if ((getdata(0, 0, "請設定密碼:", passbuf, PASSLEN, NOECHO) < 3) || !strcmp(passbuf, newuser.userid)) { outs("密碼太簡單,易遭入侵,至少要 4 個字,請重新輸入\n"); continue; } strncpy(newuser.passwd, passbuf, PASSLEN); getdata(0, 0, "請檢查密碼:", passbuf, PASSLEN, NOECHO); if (strncmp(passbuf, newuser.passwd, PASSLEN)) { outs("密碼輸入錯誤, 請重新輸入密碼.\n"); continue; } passbuf[8] = '\0'; strncpy(newuser.passwd, genpasswd(passbuf), PASSLEN); break; } /* getdata(0, 0, "終端機形態 [vt100]:", newuser.termtype, 8, ECHO); if (newuser.termtype[0] == '\0') strcpy(newuser.termtype, "vt100"); */ newuser.userlevel = PERM_DEFAULT; newuser.uflag = COLOR_FLAG | BRDSORT_FLAG | MOVIE_FLAG; newuser.firstlogin = newuser.lastlogin = time(NULL); newuser.money = 0; allocid = getnewuserid(); if (allocid > MAXUSERS || allocid <= 0) { fprintf(stderr, "本站人口已達飽和!\n"); exit(1); } if (substitute_record(fn_passwd, &newuser, sizeof(newuser), allocid) == -1) { fprintf(stderr, "客滿了,再見!\n"); exit(1); } setuserid(allocid, newuser.userid); if (!dosearchuser(newuser.userid)) { fprintf(stderr, "無法建立帳號\n"); exit(1); } } void check_register() { char *ptr; char genbuf[200]; stand_title("請詳細填寫個人資料"); while (strlen(cuser.username) < 2) getdata(2, 0, "綽號暱稱:", cuser.username, 24, DOECHO); for (ptr = cuser.username; *ptr; ptr++) { if (*ptr == 9) /* TAB convert */ *ptr == ' '; } while (strlen(cuser.realname) < 4) getdata(4, 0, "真實姓名:", cuser.realname, 20, DOECHO); while (strlen(cuser.address) < 8) getdata(6, 0, "聯絡地址:", cuser.address, 50, DOECHO); if (!strchr(cuser.email, '@')) { bell(); move(t_lines - 4, 0); prints("\ ※ 為了您的權益,請填寫真實的 E-mail address, 以資確認閣下身份,\n\ 格式為 user@domain_nameuser@\\[ip_number\\]。\n\n\ ※ 如果您真的沒有 E-mail,請直接按 [return] 即可。"); do { getdata(8, 0, "電子信箱:", cuser.email, 50, DOECHO); if (!cuser.email[0]) sprintf(cuser.email, "%s%s", cuser.userid, str_mail_address); } while (!strchr(cuser.email, '@')); } cuser.userlevel |= PERM_DEFAULT; if (!HAS_PERM(PERM_SYSOP) && !(cuser.userlevel & PERM_LOGINOK)) { /* 回覆過身份認證信函,或曾經 E-mail post 過 */ setuserfile(genbuf, "email"); if (dashf(genbuf)) { /*Leeym*/ cuser.userlevel |= ( PERM_POST | PERM_LOGINOK ); /* 關於權限各站請依自己規定.蔽站採嚴格認證.未確認不得 post */ /* mark out by ptt unlink(genbuf); { fileheader mhdr; char title[128], buf1[80]; FILE* fp; sethomepath(buf1, cuser.userid); stampfile(buf1, &mhdr); strcpy(mhdr.owner, "站長"); strncpy(mhdr.title, "[確認成功\]", TTLEN); mhdr.savemode = 0; mhdr.filemode = 0; sethomedir(title, cuser.userid); append_record(title, &mhdr, sizeof(mhdr)); Link("etc/registered", buf1); } */ } #ifdef STRICT else { cuser.userlevel &= ~PERM_POST; more("etc/justify", YEA); } #endif /* by Ptt */ clear(); move(9,3); prints("恭喜您完成第一階段帳號建立,請續填寫註冊申請單,通告站長以獲\ 得進階使用權力。\n\n\n\n"); u_register(); } #ifdef NEWUSER_LIMIT /*if (cuser.lastlogin - cuser.firstlogin < 3 * 86400 && ...)*/ if (!(cuser.userlevel & PERM_LOGINOK) && !HAS_PERM(PERM_SYSOP)) { if (cuser.lastlogin - cuser.firstlogin < 3 * 86400) cuser.userlevel &= ~PERM_POST; more("etc/newuser", YEA); } #endif if (HAS_PERM(PERM_DENYPOST) && !HAS_PERM(PERM_SYSOP)) cuser.userlevel &= ~PERM_POST; }