diff options
Diffstat (limited to 'accel-pptpd/ppp_auth.c')
-rw-r--r-- | accel-pptpd/ppp_auth.c | 282 |
1 files changed, 197 insertions, 85 deletions
diff --git a/accel-pptpd/ppp_auth.c b/accel-pptpd/ppp_auth.c index 1117c211..6fc48016 100644 --- a/accel-pptpd/ppp_auth.c +++ b/accel-pptpd/ppp_auth.c @@ -1,129 +1,245 @@ -#include "triton/triton.h" +#include <stdlib.h> +#include <string.h> +#include <arpa/inet.h> #include "ppp.h" #include "ppp_lcp.h" -#include "ppp_fsm.h" +#include "log.h" + #include "ppp_auth.h" -static LIST_HEAD(drv_list); -int auth_register(struct auth_driver_t *new) +static LIST_HEAD(auth_handlers); +static int extra_opt_len=0; + +static struct lcp_option_t *auth_init(struct ppp_lcp_t *lcp); +static void auth_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt); +static int auth_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr); +static int auth_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr); +static int auth_recv_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr); +static int auth_recv_conf_rej(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr); +static int auth_recv_conf_ack(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr); +static void auth_print(void (*print)(const char *fmt,...),struct lcp_option_t*, uint8_t *ptr); + +struct auth_option_t +{ + struct lcp_option_t opt; + struct list_head auth_list; + struct auth_data_t *auth; + struct auth_data_t *peer_auth; +}; + +static struct lcp_option_handler_t auth_opt_hnd= { - struct auth_driver_t *drv; + .init=auth_init, + .send_conf_req=auth_send_conf_req, + .send_conf_nak=auth_send_conf_req, + .recv_conf_req=auth_recv_conf_req, + .recv_conf_nak=auth_recv_conf_nak, + .recv_conf_rej=auth_recv_conf_rej, + .recv_conf_ack=auth_recv_conf_ack, + .free=auth_free, + .print=auth_print, +}; - list_for_each_entry(drv,&drv_list,entry) +static struct lcp_option_t *auth_init(struct ppp_lcp_t *lcp) +{ + struct ppp_auth_handler_t *h; + struct auth_data_t *d; + struct auth_option_t *auth_opt=malloc(sizeof(*auth_opt)); + memset(auth_opt,0,sizeof(*auth_opt)); + auth_opt->opt.id=CI_AUTH; + auth_opt->opt.len=4+extra_opt_len; + + INIT_LIST_HEAD(&auth_opt->auth_list); + + list_for_each_entry(h,&auth_handlers,entry) { - if (drv->type==new->type) - return -1; + d=h->init(lcp->ppp); + d->h=h; + list_add_tail(&d->entry,&auth_opt->auth_list); } - list_add_tail(&new->entry,&drv_list); - return 0; + + return &auth_opt->opt; } -int auth_get_conf_req(struct ppp_layer_t *l, struct lcp_opt32_t *opt) +static void auth_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt) { - int i,n; - struct auth_driver_t *drv; + struct auth_option_t *auth_opt=container_of(opt,typeof(*auth_opt),opt); + struct auth_data_t *d; - for(i=0; i<AUTH_MAX; i++) - { - if (l->ppp->auth[i] && l->options.lcp.neg_auth[i]>0) - goto cont; - } - for(i=0; i<AUTH_MAX; i++) + while(!list_empty(&auth_opt->auth_list)) { - if (l->ppp->auth[i] && l->options.lcp.neg_auth[i]==0) - goto cont; + d=list_entry(auth_opt->auth_list.next,typeof(*d),entry); + list_del(&d->entry); + d->h->free(lcp->ppp,d); } - return -1; -cont: - list_for_each_entry(drv,&drv_list,entry) + free(auth_opt); +} + +static int auth_send_conf_req(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; + int n; + + if (list_empty(&auth_opt->auth_list)) return 0; + + if (!auth_opt->auth) { - if (drv->type==l->ppp->auth[i]) - break; + d=list_entry(auth_opt->auth_list.next,typeof(*d),entry); + auth_opt->auth=d; } - n=drv->get_conf_req(drv,l,opt); - opt->val=l->auth[i]; - opt->hdr.len=6+n; - return 0; + + opt16->hdr.id=CI_AUTH; + opt16->val=htons(auth_opt->auth->proto); + n=auth_opt->auth->h->send_conf_req(lcp->ppp,auth_opt->auth,(uint8_t*)(opt16+1)); + opt16->hdr.len=4+n; + + return 4+n; } -int auth_recv_conf_req(struct ppp_layer_t *l, struct lcp_opt_hdr_t *hdr) + +static int auth_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr) { - struct lcp_opt32_t *opt=(struct lcp_opt32_t*)hdr; - struct auth_driver_t *drv; - int i; + 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; - for(i=0; i<AUTH_MAX; i++) + if (list_empty(&auth_opt->auth_list)) + return LCP_OPT_REJ; + + list_for_each_entry(d,&auth_opt->auth_list,entry) { - if (l->ppp->auth[i]==opt->val) + if (d->proto==ntohs(opt16->val)) { - list_for_each_entry(drv,&drv_list,entry) - { - if (drv->type==l->ppp->auth[i]) - { - if (drv->recv_conf_req(drv,l->ppp,opt)) - return -1; - l->options.lcp.neg_auth[i]=1; - return 0; - } - } - return -1; + if (d->h->recv_conf_req(lcp->ppp,d,(uint8_t*)(opt16+1))) + break; + auth_opt->peer_auth=d; + return LCP_OPT_ACK; } } - return -1; + + list_for_each_entry(d,&auth_opt->auth_list,entry) + { + if (d->state!=LCP_OPT_NAK) + { + auth_opt->peer_auth=d; + return LCP_OPT_NAK; + } + } + + log_msg("cann't negotiate authentication type\n"); + return LCP_OPT_FAIL; } -int auth_recv_conf_rej(struct ppp_layer_t *l, struct lcp_opt_hdr_t *hdr) + +static int auth_recv_conf_ack(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr) { - struct lcp_opt32_t *opt=(struct lcp_opt32_t*)hdr; - int i; + struct auth_option_t *auth_opt=container_of(opt,typeof(*auth_opt),opt); + + auth_opt->peer_auth=NULL; - for(i=0; i<AUTH_MAX; i++) + return 0; +} + +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 (l->ppp->auth[i]==opt->val) + if (d->proto==ntohs(opt16->val)) { - l->options.lcp.neg_auth[i]=-1; - break; + 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; } } - for(i=0; i<AUTH_MAX; i++) + + list_for_each_entry(d,&auth_opt->auth_list,entry) { - if (l->ppp->auth[i] && l->options.lcp.neg_auth[i]!=-1) + if (d->state!=LCP_OPT_NAK) return 0; } + + log_msg("cann't negotiate authentication type\n"); + return -1; +} + +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); + + if (list_empty(&auth_opt->auth_list)) + return 0; + + log_msg("cann't negotiate authentication type\n"); return -1; } -int auth_recv_conf_nak(struct ppp_layer_t *l, struct lcp_opt_hdr_t *hdr) + +static void auth_print(void (*print)(const char *fmt,...),struct lcp_option_t *opt, uint8_t *ptr) { - struct lcp_opt32_t *opt=(struct lcp_opt32_t*)hdr; - int i; + 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; - for(i=0; i<AUTH_MAX; i++) + if (ptr) { - if (l->ppp->auth[i]==opt->val) + list_for_each_entry(d,&auth_opt->auth_list,entry) { - l->options.lcp.neg_auth[i]=2; - return 0; + if (d->proto==ntohs(opt16->val)) + goto print_d; } + + print("<auth %02x>",ntohs(opt16->val)); + return; } - return -1; + else if (auth_opt->auth) d=auth_opt->auth; + else return; + +print_d: + print("<auth %s>",d->h->name); } +int ppp_auth_register_handler(struct ppp_auth_handler_t *h) +{ + list_add_tail(&h->entry,&auth_handlers); + return 0; +} + +static void __init auth_opt_init() +{ + lcp_option_register(&auth_opt_hnd); +} + + + + + + + + int auth_start(struct ppp_t *ppp) { - int i; - struct auth_driver_t *drv; + struct lcp_option_t *opt; + struct auth_option_t *auth_opt; - for(i=0; i<AUTH_MAX; i++) + list_for_each_entry(opt,&ppp->lcp->options,entry) { - if (ppp->lcp_layer->options.lcp.neg_auth[i]==1) + if (opt->id==CI_AUTH) { - list_for_each_entry(drv,&drv_list,entry) + auth_opt=container_of(opt,typeof(*auth_opt),opt); + if (auth_opt->auth) { - if (drv->type==ppp->auth[i]) - return drv->start(ppp); + auth_opt->auth->h->start(ppp,auth_opt->auth); + return 1; } - return -1; + break; } } @@ -132,21 +248,17 @@ int auth_start(struct ppp_t *ppp) void auth_finish(struct ppp_t *ppp) { - int i; - struct auth_driver_t *drv; + struct lcp_option_t *opt; + struct auth_option_t *auth_opt; - for(i=0; i<AUTH_MAX; i++) + list_for_each_entry(opt,&ppp->lcp->options,entry) { - if (ppp->lcp_layer->options.lcp.neg_auth[i]==1) + if (opt->id==CI_AUTH) { - list_for_each_entry(drv,&drv_list,entry) - { - if (drv->type==ppp->auth[i]) - { - drv->finish(ppp); - return; - } - } + auth_opt=container_of(opt,typeof(*auth_opt),opt); + if (auth_opt->auth) + auth_opt->auth->h->finish(ppp,auth_opt->auth); + break; } } } |