summaryrefslogtreecommitdiff
path: root/accel-pptpd/ppp_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/ppp_auth.c')
-rw-r--r--accel-pptpd/ppp_auth.c282
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;
}
}
}