提交 38a497e4 编写于 作者: K Kozlov Dmitry 提交者: Dmitry Kozlov

implemented chap authentication

fixed auth type selection when configure-nak received
上级 33e8d91d
......@@ -20,6 +20,7 @@ ADD_EXECUTABLE(pptpd
ppp_auth.c
auth_pap.c
auth_chap.c
ppp_ipcp.c
ipcp_opt_ipaddr.c
......@@ -30,4 +31,4 @@ ADD_EXECUTABLE(pptpd
pwdb.c
ipdb.c
)
TARGET_LINK_LIBRARIES(pptpd pthread triton)
TARGET_LINK_LIBRARIES(pptpd pthread triton ssl)
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <openssl/md5.h>
#include "log.h"
#include "ppp.h"
#include "ppp_auth.h"
#include "ppp_lcp.h"
#include "pwdb.h"
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE 2
#define CHAP_SUCCESS 3
#define CHAP_FAILURE 4
#define VALUE_SIZE 16
#define MSG_FAILURE "Authentication failed"
#define MSG_SUCCESS "Authentication successed"
#define HDR_LEN (sizeof(struct chap_hdr_t)-2)
static int urandom_fd;
struct chap_hdr_t
{
uint16_t proto;
uint8_t code;
uint8_t id;
uint16_t len;
} __attribute__((packed));
struct chap_challenge_t
{
struct chap_hdr_t hdr;
uint8_t val_size;
uint8_t val[VALUE_SIZE];
char name[0];
} __attribute__((packed));
struct chap_failure_t
{
struct chap_hdr_t hdr;
char message[sizeof(MSG_FAILURE)];
} __attribute__((packed));
struct chap_success_t
{
struct chap_hdr_t hdr;
char message[sizeof(MSG_SUCCESS)];
} __attribute__((packed));
struct chap_auth_data_t
{
struct auth_data_t auth;
struct ppp_handler_t h;
struct ppp_t *ppp;
int id;
uint8_t val[VALUE_SIZE];
};
static void chap_send_challenge(struct chap_auth_data_t *ad);
static void chap_recv(struct ppp_handler_t *h);
static void print_buf(const uint8_t *buf,int size)
{
int i;
for(i=0;i<size;i++)
log_debug("%x ",buf[i]);
}
static void print_str(const char *buf,int size)
{
int i;
for(i=0;i<size;i++)
log_debug("%c",buf[i]);
}
static struct auth_data_t* auth_data_init(struct ppp_t *ppp)
{
struct chap_auth_data_t *d=malloc(sizeof(*d));
memset(d,0,sizeof(*d));
d->auth.proto=PPP_CHAP;
d->ppp=ppp;
return &d->auth;
}
static void auth_data_free(struct ppp_t *ppp,struct auth_data_t *auth)
{
struct chap_auth_data_t *d=container_of(auth,typeof(*d),auth);
free(d);
}
static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth)
{
struct chap_auth_data_t *d=container_of(auth,typeof(*d),auth);
d->h.proto=PPP_CHAP;
d->h.recv=chap_recv;
ppp_register_chan_handler(ppp,&d->h);
chap_send_challenge(d);
return 0;
}
static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth)
{
struct chap_auth_data_t *d=container_of(auth,typeof(*d),auth);
ppp_unregister_handler(ppp,&d->h);
return 0;
}
static int lcp_send_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
{
*ptr=5;
return 1;
}
static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
{
if (*ptr==5)
return LCP_OPT_ACK;
return LCP_OPT_REJ;
}
static void chap_send_failure(struct chap_auth_data_t *ad)
{
struct chap_failure_t msg=
{
.hdr.proto=htons(PPP_CHAP),
.hdr.code=CHAP_FAILURE,
.hdr.id=++ad->id,
.hdr.len=htons(sizeof(msg)-1-2),
.message=MSG_FAILURE,
};
log_debug("send [CHAP Failure id=%x \"%s\"]\n",msg.hdr.id,MSG_FAILURE);
ppp_chan_send(ad->ppp,&msg,ntohs(msg.hdr.len)+2);
}
static void chap_send_success(struct chap_auth_data_t *ad)
{
struct chap_success_t msg=
{
.hdr.proto=htons(PPP_CHAP),
.hdr.code=CHAP_SUCCESS,
.hdr.id=++ad->id,
.hdr.len=htons(sizeof(msg)-1-2),
.message=MSG_SUCCESS,
};
log_debug("send [CHAP Success id=%x \"%s\"]\n",msg.hdr.id,MSG_SUCCESS);
ppp_chan_send(ad->ppp,&msg,ntohs(msg.hdr.len)+2);
}
static void chap_send_challenge(struct chap_auth_data_t *ad)
{
struct chap_challenge_t msg=
{
.hdr.proto=htons(PPP_CHAP),
.hdr.code=CHAP_CHALLENGE,
.hdr.id=++ad->id,
.hdr.len=htons(sizeof(msg)-2),
.val_size=VALUE_SIZE,
};
read(urandom_fd,ad->val,VALUE_SIZE);
memcpy(msg.val,ad->val,VALUE_SIZE);
log_debug("send [CHAP Challenge id=%x <",msg.hdr.id);
print_buf(msg.val,VALUE_SIZE);
log_debug(">]\n");
ppp_chan_send(ad->ppp,&msg,ntohs(msg.hdr.len)+2);
}
static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *hdr)
{
MD5_CTX md5_ctx;
uint8_t md5[MD5_DIGEST_LENGTH];
char *passwd;
char *name;
struct chap_challenge_t *msg=(struct chap_challenge_t*)hdr;
log_debug("recv [CHAP Response id=%x <", msg->hdr.id);
print_buf(msg->val,msg->val_size);
log_debug(">, name=\"");
print_str(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
log_debug("\"]\n");
if (msg->hdr.id!=ad->id)
{
log_error("chap-md5: id mismatch\n");
chap_send_failure(ad);
ppp_terminate(ad->ppp);
}
if (msg->val_size!=VALUE_SIZE)
{
log_error("chap-md5: value-size should be %i, expected %i\n",VALUE_SIZE,msg->val_size);
chap_send_failure(ad);
ppp_terminate(ad->ppp);
}
name=strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
passwd=pwdb_get_passwd(ad->ppp,name);
if (!passwd)
{
free(name);
log_debug("chap-md5: user not found\n");
chap_send_failure(ad);
return;
}
MD5_Init(&md5_ctx);
MD5_Update(&md5_ctx,&msg->hdr.id,1);
MD5_Update(&md5_ctx,passwd,strlen(passwd));
MD5_Update(&md5_ctx,ad->val,VALUE_SIZE);
MD5_Final(md5,&md5_ctx);
if (memcmp(md5,msg->val,sizeof(md5)))
{
log_debug("chap-md5: challenge response mismatch\n");
chap_send_failure(ad);
auth_failed(ad->ppp);
}else
{
chap_send_success(ad);
auth_successed(ad->ppp);
}
free(name);
free(passwd);
}
static struct ppp_auth_handler_t chap=
{
.name="CHAP-md5",
.init=auth_data_init,
.free=auth_data_free,
.send_conf_req=lcp_send_conf_req,
.recv_conf_req=lcp_recv_conf_req,
.start=chap_start,
.finish=chap_finish,
};
static void chap_recv(struct ppp_handler_t *h)
{
struct chap_auth_data_t *d=container_of(h,typeof(*d),h);
struct chap_hdr_t *hdr=(struct chap_hdr_t *)d->ppp->chan_buf;
if (d->ppp->chan_buf_size<sizeof(*hdr) || ntohs(hdr->len)<HDR_LEN || ntohs(hdr->len)<d->ppp->chan_buf_size-2)
{
log_warn("CHAP: short packet received\n");
return;
}
if (hdr->code==CHAP_RESPONSE) chap_recv_response(d,hdr);
else
{
log_warn("CHAP: unknown code received %x\n",hdr->code);
}
}
static void __init auth_chap_md5_init()
{
urandom_fd=open("/dev/urandom",O_RDONLY);
if (urandom_fd<0)
{
log_error("chap-md5: failed to open /dev/urandom: %s\n",strerror(errno));
return;
}
if (ppp_auth_register_handler(&chap))
log_error("chap-md5: failed to register handler\n");
}
......@@ -6,6 +6,8 @@
#include "log.h"
#include "ppp.h"
#include "ppp_auth.h"
#include "ppp_lcp.h"
#include "pwdb.h"
#define MSG_FAILED "Authentication failed"
#define MSG_SUCCESSED "Authentication successed"
......@@ -104,7 +106,7 @@ static int lcp_send_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *
static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
{
return 0;
return LCP_OPT_ACK;
}
static void pap_send_ack(struct pap_auth_data_t *p, int id)
......@@ -168,7 +170,7 @@ static int pap_recv_req(struct pap_auth_data_t *p,struct pap_hdr_t *hdr)
peer_id=strndup((const char*)peer_id,peer_id_len);
passwd=strndup((const char*)ptr,passwd_len);
if (pwdb_check(peer_id,passwd))
if (pwdb_check(p->ppp,peer_id,passwd))
{
log_warn("PAP: authentication error\n");
pap_send_nak(p,hdr->id);
......
......@@ -12,6 +12,7 @@ static void ipaddr_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt);
static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr);
static int ipaddr_send_conf_nak(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr);
static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr);
static int ipaddr_recv_conf_ack(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr);
static void ipaddr_print(void (*print)(const char *fmt,...),struct ipcp_option_t*, uint8_t *ptr);
struct ipaddr_option_t
......
......@@ -33,7 +33,7 @@
#define LOG_INFO 2
#define LOG_DEBUG 3
static FILE *log_file=NULL;
static FILE *log_file;
static int log_level=10;
static int log_color=1;
static const char* level_name[]={"error","warning","info","debug"};
......@@ -47,6 +47,8 @@ static void do_log(int level,const char *fmt,va_list ap)
struct timeval tv;
//pthread_mutex_lock(&lock);
if (!log_file)
log_file=stdout;
if (msg_completed)
{
gettimeofday(&tv,NULL);
......
......@@ -107,10 +107,15 @@ static int auth_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, u
if (list_empty(&auth_opt->auth_list)) return 0;
if (!auth_opt->auth)
if (!auth_opt->auth || auth_opt->auth->state==LCP_OPT_NAK)
{
d=list_entry(auth_opt->auth_list.next,typeof(*d),entry);
auth_opt->auth=d;
list_for_each_entry(d,&auth_opt->auth_list,entry)
{
if (d->state==LCP_OPT_NAK || d->state==LCP_OPT_REJ)
continue;
auth_opt->auth=d;
break;
}
}
opt16->hdr.id=CI_AUTH;
......@@ -126,6 +131,7 @@ static int auth_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, u
struct auth_option_t *auth_opt=container_of(opt,typeof(*auth_opt),opt);
struct lcp_opt16_t *opt16=(struct lcp_opt16_t*)ptr;
struct auth_data_t *d;
int r;
if (list_empty(&auth_opt->auth_list))
return LCP_OPT_REJ;
......@@ -134,10 +140,13 @@ static int auth_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, u
{
if (d->proto==ntohs(opt16->val))
{
if (d->h->recv_conf_req(lcp->ppp,d,(uint8_t*)(opt16+1)))
r=d->h->recv_conf_req(lcp->ppp,d,(uint8_t*)(opt16+1));
if (r==LCP_OPT_FAIL)
return LCP_OPT_FAIL;
if (r==LCP_OPT_REJ)
break;
auth_opt->peer_auth=d;
return LCP_OPT_ACK;
return r;
}
}
......@@ -166,20 +175,16 @@ static int auth_recv_conf_ack(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, u
static int auth_recv_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
struct auth_option_t *auth_opt=container_of(opt,typeof(*auth_opt),opt);
struct lcp_opt16_t *opt16=(struct lcp_opt16_t*)ptr;
struct auth_data_t *d;
list_for_each_entry(d,&auth_opt->auth_list,entry)
if (!auth_opt->auth)
{
if (d->proto==ntohs(opt16->val))
{
d->state=LCP_OPT_NAK;
if (d->h->recv_conf_req(lcp->ppp,d,(uint8_t*)(opt16+1)))
break;
auth_opt->auth=d;
return 0;
}
log_error("auth: unexcepcted configure-nak\n");
return -1;
}
auth_opt->auth->state=LCP_OPT_NAK;
if (auth_opt->peer_auth)
auth_opt->auth=auth_opt->peer_auth;
list_for_each_entry(d,&auth_opt->auth_list,entry)
{
......@@ -194,9 +199,22 @@ static int auth_recv_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, u
static int auth_recv_conf_rej(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
struct auth_option_t *auth_opt=container_of(opt,typeof(*auth_opt),opt);
struct auth_data_t *d;
if (list_empty(&auth_opt->auth_list))
return 0;
if (!auth_opt->auth)
{
log_error("auth: unexcepcted configure-reject\n");
return -1;
}
auth_opt->auth->state=LCP_OPT_NAK;
if (auth_opt->peer_auth)
auth_opt->auth=auth_opt->peer_auth;
list_for_each_entry(d,&auth_opt->auth_list,entry)
{
if (d->state!=LCP_OPT_NAK)
return 0;
}
log_msg("cann't negotiate authentication type\n");
return -1;
......
......@@ -449,8 +449,10 @@ static int ccp_recv_conf_ack(struct ppp_ccp_t *ccp,uint8_t *data,int size)
{
log_debug(" ");
lopt->h->print(log_debug,lopt,data);
if (lopt->h->recv_conf_ack)
lopt->h->recv_conf_ack(ccp,lopt,data);
if (!lopt->h->recv_conf_ack)
break;
if (lopt->h->recv_conf_ack(ccp,lopt,data))
res=-1;
break;
}
}
......@@ -468,7 +470,13 @@ static void ccp_recv(struct ppp_handler_t*h)
struct ppp_ccp_t *ccp=container_of(h,typeof(*ccp),hnd);
int r;
char *term_msg;
if (ccp->fsm.fsm_state==FSM_Initial || ccp->fsm.fsm_state==FSM_Closed)
{
log_error("CCP: discaring packet\n");
return;
}
if (ccp->ppp->unit_buf_size<PPP_HEADERLEN+2)
{
log_warn("CCP: short packet received\n");
......@@ -504,8 +512,10 @@ static void ccp_recv(struct ppp_handler_t*h)
ppp_terminate(ccp->ppp);
break;
case CONFACK:
ccp_recv_conf_ack(ccp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
ppp_fsm_recv_conf_ack(&ccp->fsm);
if (ccp_recv_conf_ack(ccp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
ppp_terminate(ccp->ppp);
else
ppp_fsm_recv_conf_ack(&ccp->fsm);
break;
case CONFNAK:
ccp_recv_conf_nak(ccp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
......
......@@ -440,8 +440,10 @@ static int ipcp_recv_conf_ack(struct ppp_ipcp_t *ipcp,uint8_t *data,int size)
{
log_debug(" ");
lopt->h->print(log_debug,lopt,data);
if (lopt->h->recv_conf_ack)
lopt->h->recv_conf_ack(ipcp,lopt,data);
if (!lopt->h->recv_conf_ack)
break;
if (lopt->h->recv_conf_ack(ipcp,lopt,data))
res=-1;
break;
}
}
......@@ -459,7 +461,13 @@ static void ipcp_recv(struct ppp_handler_t*h)
struct ppp_ipcp_t *ipcp=container_of(h,typeof(*ipcp),hnd);
int r;
char *term_msg;
if (ipcp->fsm.fsm_state==FSM_Initial || ipcp->fsm.fsm_state==FSM_Closed)
{
log_error("IPCP: discaring packet\n");
return;
}
if (ipcp->ppp->unit_buf_size<PPP_HEADERLEN+2)
{
log_warn("IPCP: short packet received\n");
......@@ -495,8 +503,10 @@ static void ipcp_recv(struct ppp_handler_t*h)
ppp_terminate(ipcp->ppp);
break;
case CONFACK:
ipcp_recv_conf_ack(ipcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
ppp_fsm_recv_conf_ack(&ipcp->fsm);
if (ipcp_recv_conf_ack(ipcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
ppp_terminate(ipcp->ppp);
else
ppp_fsm_recv_conf_ack(&ipcp->fsm);
break;
case CONFNAK:
ipcp_recv_conf_nak(ipcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
......
......@@ -436,8 +436,10 @@ static int lcp_recv_conf_ack(struct ppp_lcp_t *lcp,uint8_t *data,int size)
{
log_debug(" ");
lopt->h->print(log_debug,lopt,data);
if (lopt->h->recv_conf_ack)
lopt->h->recv_conf_ack(lcp,lopt,data);
if (!lopt->h->recv_conf_ack)
break;
if (lopt->h->recv_conf_ack(lcp,lopt,data))
res=-1;
break;
}
}
......@@ -514,8 +516,10 @@ static void lcp_recv(struct ppp_handler_t*h)
ppp_terminate(lcp->ppp);
break;
case CONFACK:
lcp_recv_conf_ack(lcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
ppp_fsm_recv_conf_ack(&lcp->fsm);
if (lcp_recv_conf_ack(lcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
ppp_terminate(lcp->ppp);
else
ppp_fsm_recv_conf_ack(&lcp->fsm);
break;
case CONFNAK:
lcp_recv_conf_nak(lcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
......
......@@ -5,3 +5,8 @@ int pwdb_check(struct ppp_t *ppp,const char *username,const char *password)
{
return 0;
}
char *pwdb_get_passwd(struct ppp_t *ppp, const char *username)
{
return strdup("test");
}
......@@ -4,6 +4,7 @@
struct ppp_t;
int pwdb_check(struct ppp_t*,const char *username,const char *password);
char *pwdb_get_passwd(struct ppp_t*, const char *username);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册