📄 login.c
字号:
// $Id: login2.c,v 1.3 2003/07/06 07:56:09 lemit Exp $
// original : login2.c 2003/01/28 02:29:17 Rev.1.1.1.1
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <arpa/inet.h>
#include "core.h"
#include "socket.h"
#include "login.h"
#include "mmo.h"
#include "version.h"
#include "db.h"
#include "lock.h"
#ifdef PASSWORDENC
#include "md5calc.h"
#endif
#ifdef MEMWATCH
#include "memwatch.h"
#endif
int account_id_count = START_ACCOUNT_NUM;
int server_num;
int new_account_flag = 0;
int login_port = 6900;
char account_filename[1024] = "save/account.txt";
char GM_account_filename[1024] = "conf/GM_account.txt";
char login_log_filename[1024] = "log/login.log";
struct mmo_char_server server[MAX_SERVERS];
int server_fd[MAX_SERVERS];
enum {
ACO_DENY_ALLOW=0,
ACO_ALLOW_DENY,
ACO_MUTUAL_FAILTURE,
ACO_STRSIZE=128,
};
int access_order=ACO_DENY_ALLOW;
int access_allownum=0;
int access_denynum=0;
char *access_allow=NULL;
char *access_deny=NULL;
struct login_session_data {
int md5keylen;
char md5key[20];
};
#define AUTH_FIFO_SIZE 256
struct {
int account_id,login_id1,login_id2;
int sex,delflag;
} auth_fifo[AUTH_FIFO_SIZE];
int auth_fifo_pos=0;
struct {
int account_id,sex;
char userid[24],pass[24],lastlogin[24];
int logincount;
int state;
int account_reg2_num;
struct global_reg account_reg2[ACCOUNT_REG2_NUM];
} *auth_dat;
int auth_num=0,auth_max=0;
char admin_pass[64]="";
char gm_pass[64]="";
const int gm_start=704554,gm_last=704583;
static struct dbt *gm_account_db;
int login_log(char *fmt,...)
{
FILE *logfp;
va_list ap;
va_start(ap,fmt);
logfp=fopen(login_log_filename,"a");
if(logfp){
vfprintf(logfp,fmt,ap);
fclose(logfp);
}
va_end(ap);
return 0;
}
int isGM(int account_id)
{
struct gm_account *p;
p = numdb_search(gm_account_db,account_id);
if( p == NULL)
return 0;
return p->level;
}
int read_gm_account()
{
char line[8192];
struct gm_account *p;
FILE *fp;
int c=0;
gm_account_db = numdb_init();
if( (fp=fopen(GM_account_filename,"r"))==NULL )
return 1;
while(fgets(line,sizeof(line),fp)){
if(line[0] == '/' && line[1] == '/')
continue;
p=calloc(sizeof(struct gm_account), 1);
if(p==NULL){
printf("gm_account: out of memory!\n");
exit(0);
}
if(sscanf(line,"%d %d",&p->account_id,&p->level) != 2 || p->level <= 0) {
printf("gm_account: broken data [%s] line %d\n",GM_account_filename,c);
}
else {
if(p->level > 99)
p->level = 99;
numdb_insert(gm_account_db,p->account_id,p);
}
c++;
}
fclose(fp);
// printf("gm_account: %s read done (%d gm account ID)\n",gm_account_txt,c);
return 0;
}
// IP儅僗僋僠僃僢僋
int check_ipmask(unsigned int ip,const unsigned char *str)
{
unsigned int mask=0,i,m,ip2, a0,a1,a2,a3;
unsigned char *p=(unsigned char *)&ip2, *p2=(unsigned char *)&mask;
if( sscanf(str,"%d.%d.%d.%d/%n",&a0,&a1,&a2,&a3,&i)!=4 )
return 0;
p[0]=a0; p[1]=a1; p[2]=a2; p[3]=a3;
if( sscanf(str+i,"%d.%d.%d.%d",&a0,&a1,&a2,&a3)==4 ){
p2[0]=a0; p2[1]=a1; p2[2]=a2; p2[3]=a3;
mask=ntohl(mask);
}else if( sscanf(str+i,"%d",&m)==1 ){
for(i=0;i<m;i++)
mask=(mask>>1)|0x80000000;
}else
return 0;
// printf("%08x %08x %08x\n",
// (unsigned int)ntohl(ip),(unsigned int)ntohl(ip2),(unsigned int)mask);
return ( (ntohl(ip)&mask) == (ntohl(ip2)&mask) );
}
// 傾僋僙僗僐儞僩儘乕儖
int check_ip(unsigned int ip)
{
int i;
unsigned char *p=(unsigned char *)&ip;
char buf[128];
enum { ACF_DEF, ACF_ALLOW, ACF_DENY } flag = ACF_DEF;
if( access_allownum==0 && access_denynum==0 )
return 1; // 惂尷傪巊傢側偄応崌偼忢偵嫋壜
// + 012.345. 宍幃偺慜曽堦抳偲 all乮慡偰偺IP偵儅僢僠乯偍傛傃丄
// 012.345.678.901/24 宍幃丄012.345.678.901/234.567.890.123 宍幃偺
// 僱僢僩儅僗僋晅偒昞婰偵懳墳丅
// + .ne.jp側偳偺DNS屻曽堦抳偼儂僗僩柤媡堷偒偺僐僗僩傪峫偊傞偲
// 懳墳偟側偄傎偆偑偄偄偲巚傢傟傞丅(抁偄帪娫偱DNS偑堷偗傞曐忈偼側偄偟丄
// 幚嵺偵僞僀儉傾僂僩傑偱1暘嬤偔懸偨偝傟傞働乕僗偑偁傞偙偲傪妋擣偟偰偄傞)
// 懳墳偝偣傞側傜旕摨婜偵DNS傪堷偔偐丄嬌抁偄帪娫偱僞僀儉傾僂僩傪偲傞傋偒.
sprintf(buf,"%d.%d.%d.%d",p[0],p[1],p[2],p[3]);
for(i=0;i<access_allownum;i++){
const char *p=access_allow+i*ACO_STRSIZE;
if( memcmp(p,buf,strlen(p))==0 || check_ipmask(ip,p)){
flag=ACF_ALLOW;
if( access_order==ACO_DENY_ALLOW )
return 1; // deny,allow 側傜allow偵偁偭偨帪揰偱嫋壜
break;
}
}
for(i=0;i<access_denynum;i++){
const char *p=access_deny+i*ACO_STRSIZE;
if( memcmp(p,buf,strlen(p))==0 || check_ipmask(ip,p)){
flag=ACF_DENY;
return 0; // deny偵偁傞偲晄嫋壜
break;
}
}
return (flag==ACF_ALLOW || access_order==ACO_ALLOW_DENY)? 1:0;
// allow,deny偺偲偒偼柍忦審偱乮deny埲奜偟偐偙偙傑偱偙側偄乯偼嫋壜
// mutual-failture偺偲偒偼丄婰弎側偟側傜晄嫋壜
}
// 傾僇僂儞僩僨乕僞儀乕僗偺撉傒崬傒
int mmo_auth_init(void)
{
FILE *fp;
int i,account_id,logincount,state,n,j,v;
char line[1024],*p,userid[24],pass[24],lastlogin[24],sex;
char str[64];
fp=fopen(account_filename,"r");
auth_dat=calloc(sizeof(auth_dat[0])*256, 1);
auth_max=256;
if(fp==NULL)
return 0;
while(fgets(line,1023,fp)!=NULL){
p=line;
i=sscanf(line,"%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t%n",
&account_id,userid,pass,lastlogin,&sex,&logincount,&state,&n);
if(i>=5){
if(auth_num>=auth_max){
auth_max+=256;
auth_dat=realloc(auth_dat,sizeof(auth_dat[0])*auth_max);
}
auth_dat[auth_num].account_id=account_id;
strncpy(auth_dat[auth_num].userid,userid,24);
strncpy(auth_dat[auth_num].pass,pass,24);
strncpy(auth_dat[auth_num].lastlogin,lastlogin,24);
auth_dat[auth_num].sex = sex == 'S' ? 2 : sex=='M';
//僨乕僞偑懌傝側偄偲偒偺曗姰
if(i>=6)
auth_dat[auth_num].logincount=logincount;
else
auth_dat[auth_num].logincount=1;
if(i>=7)
auth_dat[auth_num].state=state;
else
auth_dat[auth_num].state=0;
for(j=0;j<ACCOUNT_REG2_NUM;j++){
p+=n;
if(sscanf(p,"%[^\t,],%d %n",str,&v,&n)!=2)
break;
strcpy(auth_dat[auth_num].account_reg2[j].str,str);
auth_dat[auth_num].account_reg2[j].value=v;
}
auth_dat[auth_num].account_reg2_num=j;
auth_num++;
if(account_id>=account_id_count)
account_id_count=account_id+1;
}else{
i=0;
if( sscanf(line,"%d\t%%newid%%\n%n",&account_id,&i)==1 &&
i>0 && account_id>account_id_count)
account_id_count=account_id;
}
}
fclose(fp);
return 0;
}
// 傾僇僂儞僩僨乕僞儀乕僗偺彂偒崬傒
void mmo_auth_sync(void)
{
FILE *fp;
int i,j,maxid=0,lock;
fp=lock_fopen(account_filename,&lock);
if(fp==NULL)
return;
for(i=0;i<auth_num;i++){
if(auth_dat[i].account_id<0)
continue;
fprintf(fp,"%d\t%s\t%s\t%s\t%c\t%d\t%d\t",auth_dat[i].account_id,
auth_dat[i].userid,auth_dat[i].pass,auth_dat[i].lastlogin,
auth_dat[i].sex==2 ? 'S' : (auth_dat[i].sex ? 'M' : 'F'),
auth_dat[i].logincount,auth_dat[i].state);
for(j=0;j<auth_dat[i].account_reg2_num;j++){
fprintf(fp,"%s,%d ",
auth_dat[i].account_reg2[j].str,
auth_dat[i].account_reg2[j].value);
}
fprintf(fp,RETCODE);
if(maxid<auth_dat[i].account_id)
maxid=auth_dat[i].account_id;
}
fprintf(fp,"%d\t%%newid%%\n",account_id_count);
lock_fclose(fp,account_filename,&lock);
}
// 傾僇僂儞僩嶌惉
int mmo_auth_new( struct mmo_account* account,const char *tmpstr,char sex )
{
int j,i=auth_num,c;
login_log("auth new %s %s %s" RETCODE,
tmpstr,account->userid,account->passwd);
for(j=0;j<24 && (c=account->userid[j]);j++){
if(c<0x20 || c==0x7f)
return 0;
}
if(auth_num>=auth_max){
auth_max+=256;
auth_dat=realloc(auth_dat,sizeof(auth_dat[0])*auth_max);
}
while(isGM(account_id_count) > 0)
account_id_count++;
auth_dat[i].account_id=account_id_count++;
strncpy(auth_dat[i].userid,account->userid,24);
strncpy(auth_dat[i].pass,account->passwd,24);
memcpy(auth_dat[i].lastlogin,"-",2);
auth_dat[i].sex= sex=='M';
auth_dat[i].logincount=0;
auth_dat[i].state = 0;
auth_dat[i].account_reg2_num = 0;
auth_num++;
return 1;
}
// 擣徹
int mmo_auth( struct mmo_account* account, int fd )
{
int i;
struct timeval tv;
char tmpstr[256];
int len,newaccount=0;
char md5str[64],md5bin[32];
len=strlen(account->userid)-2;
if(account->passwdenc==0 && account->userid[len]=='_' &&
(account->userid[len+1]=='F' || account->userid[len+1]=='M') &&
new_account_flag == 1 && account_id_count < END_ACCOUNT_NUM){
char *adm_pass=strchr(account->passwd,'@');
if(adm_pass==NULL)
adm_pass="";
else
adm_pass++;
if(strcmp(adm_pass,admin_pass)==0){
if(adm_pass[0])
*(adm_pass-1)=0;
newaccount=1;
account->userid[len]=0;
}else
account->userid[0]=0;
}
gettimeofday(&tv,NULL);
strftime(tmpstr,24,"%Y-%m-%d %H:%M:%S",localtime(&(tv.tv_sec)));
sprintf(tmpstr+19,".%03d",(int)tv.tv_usec/1000);
for(i=0;i<auth_num;i++){
if(strcmp(account->userid,auth_dat[i].userid)==0)
break;
}
if(i!=auth_num){
int encpasswdok=0;
struct login_session_data *ld=session[fd]->session_data;
#ifdef PASSWORDENC
if(account->passwdenc>0){
int j=account->passwdenc;
if(!ld){
login_log("md5key not created %s %s" RETCODE,
tmpstr,account->userid);
return 1;
}
if(j>2)j=1;
do{
if(j==1){
strcpy(md5str,ld->md5key);
strcat(md5str,auth_dat[i].pass);
}else if(j==2){
strcpy(md5str,auth_dat[i].pass);
strcat(md5str,ld->md5key);
}else
md5str[0]=0;
MD5_String2binary(md5str,md5bin);
encpasswdok = ( memcmp( account->passwd, md5bin, 16) == 0);
}while(j<2 && !encpasswdok && (j++)!=account->passwdenc);
// printf("key[%s] md5 [%s] ",md5key,md5);
// printf("client [%s] accountpass [%s]\n",account->passwd,auth_dat[i].pass);
}
#endif
if( (strcmp(account->passwd,auth_dat[i].pass) && !encpasswdok) || newaccount){
if(account->passwdenc==0)
login_log("auth failed pass error %s %s %s %d" RETCODE,tmpstr,account->userid,account->passwd,newaccount);
#ifdef PASSWORDENC
else{
char logbuf[1024],*p=logbuf;
int j;
p+=sprintf(p,"auth failed pass error %s %s recv-md5[",tmpstr,account->userid);
for(j=0;j<16;j++)
p+=sprintf(p,"%02x",((unsigned char *)account->passwd)[j]);
p+=sprintf(p,"] calc-md5[");
for(j=0;j<16;j++)
p+=sprintf(p,"%02x",((unsigned char *)md5bin)[j]);
p+=sprintf(p,"] md5key[");
for(j=0;j<ld->md5keylen;j++)
p+=sprintf(p,"%02x",((unsigned char *)ld->md5key)[j]);
p+=sprintf(p,"] %d" RETCODE,newaccount);
login_log(logbuf);
}
#endif
return 1;
}
login_log("auth ok %s %s new=%d" RETCODE,
tmpstr,account->userid,newaccount);
} else {
if(newaccount==0){
login_log("auth failed no account %s %s %s %d" RETCODE,
tmpstr,account->userid,account->passwd,newaccount);
return 0;
}
/* login_log("auth new %s %s %s %d" RETCODE,
tmpstr,account->userid,account->passwd,newaccount);
if(auth_num>=auth_max){
auth_max+=256;
auth_dat=realloc(auth_dat,sizeof(auth_dat[0])*auth_max);
}
auth_dat[i].account_id=account_id_count++;
strncpy(auth_dat[i].userid,account->userid,24);
strncpy(auth_dat[i].pass,account->passwd,24);
auth_dat[i].sex=account->userid[len+1]=='M';
auth_dat[i].logincount=0;
auth_num++;*/
if( !mmo_auth_new(account,tmpstr,account->userid[len+1]) ){
login_log("auth new failed %s %s %s %d" RETCODE,
tmpstr,account->userid,account->passwd,newaccount);
return 0;
}
}
if(auth_dat[i].state){
login_log("auth banned account %s %s %s %d\n" RETCODE,
tmpstr,account->userid,account->passwd,auth_dat[i].state);
switch(auth_dat[i].state) {
case 1:
return 2;
break;
case 2:
return 3;
break;
case 3:
return 4;
break;
}
}
account->account_id = auth_dat[i].account_id;
account->login_id1 = rand();
account->login_id2 = rand();
memcpy(account->lastlogin,auth_dat[i].lastlogin,24);
memcpy(auth_dat[i].lastlogin,tmpstr,24);
account->sex = auth_dat[i].sex;
auth_dat[i].logincount++;
mmo_auth_sync();
return 100;
}
// 帺暘埲奜偺慡偰偺char僒乕僶乕偵僨乕僞憲怣乮憲怣偟偨map嶪偺悢傪曉偡乯
int charif_sendallwos(int sfd,unsigned char *buf,unsigned int len)
{
int i,c;
for(i=0,c=0;i<MAX_SERVERS;i++){
int fd;
if((fd=server_fd[i])>0 && fd!=sfd){
memcpy(WFIFOP(fd,0),buf,len);
WFIFOSET(fd,len);
c++;
}
}
return c;
}
int parse_fromchar(int fd)
{
int i,id;
for(id=0;id<MAX_SERVERS;id++)
if(server_fd[id]==fd)
break;
if(id==MAX_SERVERS)
session[fd]->eof=1;
if(session[fd]->eof){
for(i=0;i<MAX_SERVERS;i++)
if(server_fd[i]==fd)
server_fd[i]=-1;
close(fd);
delete_session(fd);
return 0;
}
while(RFIFOREST(fd)>=2){
switch(RFIFOW(fd,0)){
case 0x2712:
if(RFIFOREST(fd)<15)
return 0;
for(i=0;i<AUTH_FIFO_SIZE;i++){
if(auth_fifo[i].account_id==RFIFOL(fd,2) &&
auth_fifo[i].login_id1==RFIFOL(fd,6) &&
/*auth_fifo[i].login_id2==RFIFOL(fd,10) &&*/
auth_fifo[i].sex==RFIFOB(fd,14) &&
!auth_fifo[i].delflag){
auth_fifo[i].delflag=1;
// printf("%d\n",i);
break;
}
}
if(i!=AUTH_FIFO_SIZE){ // account_reg憲怣
int p,j,i;
for(i=0;i<auth_num;i++){
if(auth_dat[i].account_id==RFIFOL(fd,2))
break;
}
if(i<auth_num){
WFIFOW(fd,0)=0x2729;
WFIFOL(fd,4)=RFIFOL(fd,2);
for(p=8,j=0;j<auth_dat[i].account_reg2_num;p+=36,j++){
memcpy(WFIFOP(fd,p),auth_dat[i].account_reg2[j].str,32);
WFIFOL(fd,p+32)=auth_dat[i].account_reg2[j].value;
}
WFIFOW(fd,2)=p;
WFIFOSET(fd,p);
// printf("account_reg2 send : login->char (auth fifo)\n");
}
}
WFIFOW(fd,0)=0x2713;
WFIFOL(fd,2)=RFIFOL(fd,2);
if(i!=AUTH_FIFO_SIZE){
WFIFOB(fd,6)=0;
} else {
WFIFOB(fd,6)=1;
}
WFIFOSET(fd,7);
RFIFOSKIP(fd,15);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -