⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 login.c

📁 传奇3源程序, 用vc开发的
💻 C
📖 第 1 页 / 共 2 页
字号:
// $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 + -