diff options
-rw-r--r-- | accel-pptpd/CMakeLists.txt | 3 | ||||
-rw-r--r-- | accel-pptpd/auth_chap.c | 294 | ||||
-rw-r--r-- | accel-pptpd/auth_pap.c | 6 | ||||
-rw-r--r-- | accel-pptpd/ipcp_opt_ipaddr.c | 1 | ||||
-rw-r--r-- | accel-pptpd/log.c | 4 | ||||
-rw-r--r-- | accel-pptpd/ppp_auth.c | 52 | ||||
-rw-r--r-- | accel-pptpd/ppp_ccp.c | 20 | ||||
-rw-r--r-- | accel-pptpd/ppp_ipcp.c | 20 | ||||
-rw-r--r-- | accel-pptpd/ppp_lcp.c | 12 | ||||
-rw-r--r-- | accel-pptpd/pwdb.c | 5 | ||||
-rw-r--r-- | accel-pptpd/pwdb.h | 1 |
11 files changed, 383 insertions, 35 deletions
diff --git a/accel-pptpd/CMakeLists.txt b/accel-pptpd/CMakeLists.txt index bbe59b80..82c8a9e0 100644 --- a/accel-pptpd/CMakeLists.txt +++ b/accel-pptpd/CMakeLists.txt @@ -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) diff --git a/accel-pptpd/auth_chap.c b/accel-pptpd/auth_chap.c new file mode 100644 index 00000000..4b3d0398 --- /dev/null +++ b/accel-pptpd/auth_chap.c @@ -0,0 +1,294 @@ +#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"); +} + diff --git a/accel-pptpd/auth_pap.c b/accel-pptpd/auth_pap.c index 85e71e60..92ddef52 100644 --- a/accel-pptpd/auth_pap.c +++ b/accel-pptpd/auth_pap.c @@ -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); diff --git a/accel-pptpd/ipcp_opt_ipaddr.c b/accel-pptpd/ipcp_opt_ipaddr.c index a68212f1..8eae84b6 100644 --- a/accel-pptpd/ipcp_opt_ipaddr.c +++ b/accel-pptpd/ipcp_opt_ipaddr.c @@ -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 diff --git a/accel-pptpd/log.c b/accel-pptpd/log.c index 4ee86e1a..992f24d5 100644 --- a/accel-pptpd/log.c +++ b/accel-pptpd/log.c @@ -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); diff --git a/accel-pptpd/ppp_auth.c b/accel-pptpd/ppp_auth.c index ee173a79..c7075fb1 100644 --- a/accel-pptpd/ppp_auth.c +++ b/accel-pptpd/ppp_auth.c @@ -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; diff --git a/accel-pptpd/ppp_ccp.c b/accel-pptpd/ppp_ccp.c index 0a7246d6..3c8c5cdb 100644 --- a/accel-pptpd/ppp_ccp.c +++ b/accel-pptpd/ppp_ccp.c @@ -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); diff --git a/accel-pptpd/ppp_ipcp.c b/accel-pptpd/ppp_ipcp.c index fb089a5d..fc25230a 100644 --- a/accel-pptpd/ppp_ipcp.c +++ b/accel-pptpd/ppp_ipcp.c @@ -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); diff --git a/accel-pptpd/ppp_lcp.c b/accel-pptpd/ppp_lcp.c index b9d0de34..dbc819a1 100644 --- a/accel-pptpd/ppp_lcp.c +++ b/accel-pptpd/ppp_lcp.c @@ -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); diff --git a/accel-pptpd/pwdb.c b/accel-pptpd/pwdb.c index 12130b34..4a03846e 100644 --- a/accel-pptpd/pwdb.c +++ b/accel-pptpd/pwdb.c @@ -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"); +} diff --git a/accel-pptpd/pwdb.h b/accel-pptpd/pwdb.h index 820e269c..07c45b09 100644 --- a/accel-pptpd/pwdb.h +++ b/accel-pptpd/pwdb.h @@ -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 |