荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: jjk (Linux Device Driver), 信区: InstallBBS
标 题: [转寄] 为FB2000增加密码保护机制[转载]
发信站: 荔园晨风BBS站 (Mon Jun 17 17:02:02 2002), 转信
【 以下文字转载自 jjk 的信箱 】
【 原文由 jjk.bbs@bbs.nju.edu.cn 所发表 】
发信人: quickmouse (碰猫死翘翘★偷得浮生半日闲), 信区: BBSDev
标 题: 为FB2000增加密码保护机制
发信站: 南京大学小百合站 (Sun Jun 16 13:14:50 2002), 站内信件
版本:FB2000
修改类型:功能增强
说明:这是一个在整理FB2000->FB2002时增加的一个功能,用于向用户提供帐号的保护
机制。该机制类似于普通email注册时要求填写的密码丢失提示问题和答案。所
不同的是由于bbs密码的单向加密功能使其无法反馈用户原有的密码而只能是重
新设定用户密码。
这套机制提供用户80字符密码提示问题和40字符密码问题回答的存储能力,其中
40字符密码回答问题采取加密方式,拥有主机权限的人员也无法获取该问题答案。
补充说明:该机制目前仅在fb2002测试站通过测试,作者不负担由于程序原因导致的
帐号安全问题。使用者可以修改该功能的提示信息以符合站点需要,
但请保留提示中的版权信息。
修改分多个部分:
userinfo.c:
//struct used for passwd recall, add by quickmouse 2002-6
struct ResetPass
{
unsigned int failed;
char question[STRLEN];
char answer[5][ENCPASSLEN];
};
// check passwd-recall passwd, which is 40B length,
// add by quickmouse 2002-6
int CheckResetPass(char *username)
{
char filename[STRLEN];
FILE *fp;
struct ResetPass strp;
struct stat st;
int returnvalue = -1;
int randomnum, i;
char answer[STRLEN], pass[9];
sethomefile(filename, username, "resetpasswd");
if(stat(filename, &st) < 0)
return 0;
pass[8] = 0;
if((fp = fopen(filename, "r")) != NULL)
{
fread(&strp, sizeof(strp), 1, fp);
fclose(fp);
srand(time(0) % getpid());
while(1)
{
move(3, 0);
clrtobot();
prints("序列号:%d", (randomnum = random()&0x7fff));
getdata(4, 0, "请输入上面显示的序列号(回车退出):", answer, 8, DOECHO, YEA
);
if(atoi(answer) != randomnum)
{
prints("输入错误!");
pressanykey();
break;
}
if(strp.failed >= 3)
if(st.st_mtime < time(0) - (3600 + (time(0)%10) * 360))
strp.failed = 0;
else
{
prints("尝试密码次数太多,请稍后再来\n");
pressanykey();
sleep(1);
break;
}
prints("密码提示问题:%s", strp.question);
getdata(6, 0, "请回答:", answer, STRLEN - 1, DOECHO, YEA);
if( answer[0] == 0 )
break;
strp.failed ++;
returnvalue = 1;
for(i = 0; i < 5 && strp.answer[i][0] != 0; i++)
{
strncpy(pass, answer + (i * 8), 8);
if(!checkpasswd(strp.answer[i], pass))
{
prints("回答错误!\n");
returnvalue = -1;
refresh();
sleep(1 << strp.failed);
break;
}
}
if( returnvalue == 1)
strp.failed = 0;
if((fp = fopen(filename, "w")) != NULL)
{
fwrite(&strp, sizeof(strp), 1, fp);
fclose(fp);
if(returnvalue)
break;
}
}
}
return returnvalue;
}
//set passwd-recall passwd,which is a 40B length passwd,
// the passwd is crypt, add by quickmouse, 2002-6
void SetResetPass(char *username)
{
struct ResetPass strp;
char buf[STRLEN], pass[9], buf1[STRLEN];
int i = 0, askdel = 0, tmp;
FILE *fp;
pass[8] = 0;
memset(&strp, 0 , sizeof(strp));
clear();
sethomefile(buf1, username, "resetpasswd");
askdel = dashf(buf1);
do
{
getdata(1, 0, "请输入密码提示问题(<80字符):", buf, STRLEN - 1, DOECHO, YEA
);
if(buf[0] == 0)
break;
strncpy(strp.question, buf, STRLEN-1);
getdata(2, 0, "请输入密码问题的回答(<40字符):", buf, 40, DOECHO, YEA);
if(buf[0] == 0)
break;
buf[40] = 0;
getdata(3, 0, "请再次输入密码问题的回答(<40字符):", buf1, 40, DOECHO, YEA)
;
if(strcmp(buf, buf1))
{
prints("两次输入不一致,设置无效");
pressanykey();
askdel = 0;
break;
}
tmp = strlen(buf);
for( i = 0; i < 5 && i*8 <tmp; i++ )
{
strncpy(pass, buf + i * 8 , 8);
#ifdef ENCPASSLEN
strncpy(strp.answer[i], genpasswd(pass), ENCPASSLEN);
#else
strncpy(strp.answer[i], genpasswd(pass), PASSLEN);
#endif
}
sethomefile(buf, username, "resetpasswd");
if((fp = fopen(buf, "w")) != NULL)
{
fwrite(&strp, sizeof(strp), 1, fp);
fclose(fp);
}
prints("密码提示问题设置完毕!");
pressanykey();
return;
}while(0);
if(askdel)
{
if(askyn("您想删除原有的密码提示问题吗?", 0, 0) == 1)
{
unlink(buf1);
prints("旧的密码提示问题已经删除");
pressanykey();
}
}
else
{
prints("未改变/设置密码提示问题及答案");
pressanykey();
}
return;
}
// passwd recall main function, add a link to it
// in the comm_lists.c, add by quickmouse 2002-6
int GetLostPass(void)
{
// 首先清屏,接着询问选项,如果为guest用户,则只有取回id密码
// 普通用户有设置遗忘密码功能和取回id密码功能
char ans[ENCPASSLEN], buf[STRLEN];
int temp;
struct userec record;
//此处增加功能说明
modify_user_mode(RESETPASS);
clear();
prints("设置密码丢失提示问题/重置丢失密码功能说明:\n");
prints("用户可自行设置最大80字符长度的密码提示问题和最大40字符长度的回答\n"
);
prints("用于在用户密码遗忘时通过其他帐号重置遗忘的密码。\n");
prints("未设置提示问题及回答的帐号将无法通过此手段重置密码\n");
prints("修改密码提示问题及答案需要输入帐号密码,及原有提示答案(没有可忽略)\
n");
prints("所以请妥善保管密码丢失提示问题的答案\n\nDeveloped by quickmouse, co
pyright, 2002");
pressanykey();
clear();
if(!strcmp(currentuser.userid, "guest")) // guest user
{
getdata(1, 0, "请选择 (0)结束 (1)重置其他id的密码==> [0]" , ans, 2, DOECHO
, YEA);
if(ans[0] > '1' || ans[0] < '0')
ans[0] = '0';
}
else
getdata(1, 0, "请选择 (0)结束 (1)重置其他id的密码 (2) 设置当前id重置密码问
题==> [0]", ans, 2, DOECHO, YEA);
switch(ans[0])
{
case '2':
getdata(2, 0, "请输入登陆密码: ", ans, PASSLEN, NOECHO, YEA);
if (ans[0] == 0 || !checkpasswd(currentuser.passwd, ans))
{
prints("\n\n很抱歉, 您输入的密码不正确。\n");
pressanykey();
break;
}
if(CheckResetPass(currentuser.userid) >= 0)
SetResetPass(currentuser.userid);
break;
case '1':
if (!gettheuserid(2,"请输入要重置密码的用户名: ",&temp))
break;
record = lookupuser;
if(CheckResetPass(record.userid) <= 0)
{
prints("该用户未设置密码丢失问题或回答错误");
sprintf(buf, "by %s from %s", currentuser.userid, fromhost);
logattempt(record.userid, buf);
pressanykey();
break;
}
prints("重置用户%s的密码\n", record.userid);
if(ChangePasswd(NULL, record.passwd, record.userid, 8) < 0)
{
prints("密码设置失败,请重新来过");
}
else
{
if(substitute_record(PASSFILE, &record, sizeof(record), temp)< 0)
prints("密码设置失败,请重新来过");
else
{
sprintf(buf, "%s 重置 %s 的密码", currentuser.userid, record.userid);
securityreport(buf);
prints("密码设置成功!");
}
}
pressanykey();
break;
case '0':
default:
break;
}
return 0;
}
// change user passwd in PASSWD file
// this is a standard routine for set user passwd
// it may be used in register.c and userinfo.c in
// which would set user passwd
int ChangePasswd(char *oldpass, char *newpass, char *userid, int line)
{
char buf[PASSLEN], buf1[PASSLEN];
if(oldpass != NULL)
{
getdata(line++, 0, "请输入原密码: ", buf, PASSLEN, NOECHO, YEA);
if (*buf == '\0' || !checkpasswd(oldpass, buf))
{
prints("\n\n很抱歉, 您输入的密码不正确。\n");
return -1;
}
}
while(1)
{
getdata(line, 0, "请设定您的密码 (Setup Password): ", buf, PASSLEN, NOECHO
, YEA);
if (strlen(buf) < 4 || !strcasecmp(buf, userid))
{
prints("密码太短或与使用者代号相同, 请重新输入\n");
continue;
}
getdata(line+1, 0, "请再次输入您的密码 (Reconfirm Password): ", buf1, PASS
LEN, NOECHO, YEA);
if(strcmp(buf1, buf))
{
prints("密码输入错误!\n");
return -1;
}
else
{
#ifdef ENCPASSLEN
strncpy(newpass, genpasswd(buf), ENCPASSLEN);
#else
strncpy(newpass, genpasswd(buf), PASSLEN);
#endif
break;
}
}
return 0;
}
// end of add, by quickmouse 2002-6
comm_lists.c:
在前面声明
int GetLostPass(void); // by quickmouse 2002-6 密码查询问题
在sysconf_cmdlist[]里面增加
{"GetLostPd", GetLostPass, 0}, // passwd recall function by quickmouse
modes.h
#define RESETPASS 56
modetype.c:
case RESETPASS:
return "忘了密码?:)";
修改menu.ini
在I个人工具箱当中增加:
如果希望guest用户也能看到这个功能,则:
@GetLostPd 0, 0, 0, "GetPass", "(G)etPass 密码丢失帮助"
否则,把这个 ^^改为PERM_BASIC或者其他限制权限
编译之后刷新菜单即可。
--
☆两个人相互辉映,光芒胜过夜晚繁星☆
QuickMouse_China@yahoo.com.cn
※ 修改:.quickmouse 於 Jun 16 13:15:29 修改本文.[FROM: 211.69.197.73]
※ 来源:.南京大学小百合站 bbs.nju.edu.cn.[FROM: 211.69.197.73]
--
※ 转寄:.南京大学小百合站 bbs.nju.edu.cn.[FROM: 深圳大学BBS]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店