diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2014-09-20 12:18:49 +0400 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-09-20 12:18:49 +0400 |
commit | 62e89248160d3592c2d754fcaa15e37586a5b091 (patch) | |
tree | a6513cfd1e8ef6c6079ea2436e8573b122cc1ec6 /accel-pppd/auth | |
parent | 0a58c20b44136c1fba996becea18696b3f67a1f9 (diff) | |
download | accel-ppp-62e89248160d3592c2d754fcaa15e37586a5b091.tar.gz accel-ppp-62e89248160d3592c2d754fcaa15e37586a5b091.zip |
rewrite of authentication/accounting procedures
This patch gets rid of synchronuos style of authentication/accounting.
Synchronous style of authentication/accounting produced sleeping threads
which becomes a problem when lots of sessions started/stopped and all they want authorization/accounting.
Diffstat (limited to 'accel-pppd/auth')
-rw-r--r-- | accel-pppd/auth/auth_chap_md5.c | 101 | ||||
-rw-r--r-- | accel-pppd/auth/auth_mschap_v1.c | 126 | ||||
-rw-r--r-- | accel-pppd/auth/auth_mschap_v2.c | 142 | ||||
-rw-r--r-- | accel-pppd/auth/auth_pap.c | 91 |
4 files changed, 330 insertions, 130 deletions
diff --git a/accel-pppd/auth/auth_chap_md5.c b/accel-pppd/auth/auth_chap_md5.c index 9a52581c..5be8b875 100644 --- a/accel-pppd/auth/auth_chap_md5.c +++ b/accel-pppd/auth/auth_chap_md5.c @@ -30,39 +30,39 @@ #define MSG_FAILURE "Authentication failed" #define MSG_SUCCESS "Authentication succeeded" -#define HDR_LEN (sizeof(struct chap_hdr_t)-2) +#define HDR_LEN (sizeof(struct chap_hdr)-2) static int conf_timeout = 5; static int conf_interval = 0; static int conf_max_failure = 3; static int conf_any_login = 0; -struct chap_hdr_t { +struct chap_hdr { uint16_t proto; uint8_t code; uint8_t id; uint16_t len; } __attribute__((packed)); -struct chap_challenge_t { - struct chap_hdr_t hdr; +struct chap_challenge { + struct chap_hdr hdr; uint8_t val_size; uint8_t val[VALUE_SIZE]; char name[0]; } __attribute__((packed)); -struct chap_failure_t { - struct chap_hdr_t hdr; +struct chap_failure { + struct chap_hdr hdr; char message[sizeof(MSG_FAILURE)]; } __attribute__((packed)); -struct chap_success_t { - struct chap_hdr_t hdr; +struct chap_success { + struct chap_hdr hdr; char message[sizeof(MSG_SUCCESS)]; } __attribute__((packed)); -struct chap_auth_data_t { +struct chap_auth_data { struct auth_data_t auth; struct ppp_handler_t h; struct ppp_t *ppp; @@ -71,10 +71,12 @@ struct chap_auth_data_t { struct triton_timer_t timeout; struct triton_timer_t interval; int failure; + char *name; + char *mschap_error; int started:1; }; -static void chap_send_challenge(struct chap_auth_data_t *ad, int new); +static void chap_send_challenge(struct chap_auth_data *ad, int new); static void chap_recv(struct ppp_handler_t *h); static void chap_timeout_timer(struct triton_timer_t *t); static void chap_restart_timer(struct triton_timer_t *t); @@ -94,7 +96,7 @@ static void print_str(const char *buf, int size) static struct auth_data_t* auth_data_init(struct ppp_t *ppp) { - struct chap_auth_data_t *d = _malloc(sizeof(*d)); + struct chap_auth_data *d = _malloc(sizeof(*d)); memset(d, 0, sizeof(*d)); d->auth.proto = PPP_CHAP; @@ -105,7 +107,7 @@ static struct auth_data_t* auth_data_init(struct ppp_t *ppp) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); if (d->timeout.tpd) triton_timer_del(&d->timeout); @@ -118,7 +120,7 @@ static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); d->h.proto = PPP_CHAP; d->h.recv = chap_recv; @@ -127,6 +129,7 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth) d->interval.expire = chap_restart_timer; d->interval.period = conf_interval * 1000; d->id = 1; + d->name = NULL; ppp_register_chan_handler(ppp, &d->h); @@ -137,13 +140,16 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); if (d->timeout.tpd) triton_timer_del(&d->timeout); if (d->interval.tpd) triton_timer_del(&d->interval); + + if (d->name) + _free(d->name); ppp_unregister_handler(ppp, &d->h); @@ -152,7 +158,7 @@ static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth) static void chap_timeout_timer(struct triton_timer_t *t) { - struct chap_auth_data_t *d = container_of(t, typeof(*d), timeout); + struct chap_auth_data *d = container_of(t, typeof(*d), timeout); if (conf_ppp_verbose) log_ppp_warn("chap-md5: timeout\n"); @@ -168,7 +174,7 @@ static void chap_timeout_timer(struct triton_timer_t *t) static void chap_restart_timer(struct triton_timer_t *t) { - struct chap_auth_data_t *d = container_of(t, typeof(*d), interval); + struct chap_auth_data *d = container_of(t, typeof(*d), interval); chap_send_challenge(d, 1); } @@ -186,9 +192,9 @@ static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t * return LCP_OPT_NAK; } -static void chap_send_failure(struct chap_auth_data_t *ad) +static void chap_send_failure(struct chap_auth_data *ad) { - struct chap_failure_t msg = { + struct chap_failure msg = { .hdr.proto = htons(PPP_CHAP), .hdr.code = CHAP_FAILURE, .hdr.id = ad->id, @@ -202,9 +208,9 @@ static void chap_send_failure(struct chap_auth_data_t *ad) ppp_chan_send(ad->ppp, &msg, ntohs(msg.hdr.len) + 2); } -static void chap_send_success(struct chap_auth_data_t *ad, int id) +static void chap_send_success(struct chap_auth_data *ad, int id) { - struct chap_success_t msg = { + struct chap_success msg = { .hdr.proto = htons(PPP_CHAP), .hdr.code = CHAP_SUCCESS, .hdr.id = id, @@ -218,9 +224,9 @@ static void chap_send_success(struct chap_auth_data_t *ad, int id) ppp_chan_send(ad->ppp, &msg, ntohs(msg.hdr.len) + 2); } -static void chap_send_challenge(struct chap_auth_data_t *ad, int new) +static void chap_send_challenge(struct chap_auth_data *ad, int new) { - struct chap_challenge_t msg = { + struct chap_challenge msg = { .hdr.proto = htons(PPP_CHAP), .hdr.code = CHAP_CHALLENGE, .hdr.id = ad->id, @@ -245,14 +251,45 @@ static void chap_send_challenge(struct chap_auth_data_t *ad, int new) triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->timeout, 0); } -static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *hdr) +static void auth_result(struct chap_auth_data *ad, int res) +{ + char *name = ad->name; + + ad->name = NULL; + + if (res == PWDB_DENIED) { + chap_send_failure(ad); + if (ad->started) + ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); + else + ppp_auth_failed(ad->ppp, name); + } else { + if (ppp_auth_succeeded(ad->ppp, name)) { + chap_send_failure(ad); + ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); + } else { + chap_send_success(ad, ad->id); + ad->started = 1; + if (conf_interval) + triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->interval, 0); + name = NULL; + } + } + + ad->id++; + + if (name) + _free(name); +} + +static void chap_recv_response(struct chap_auth_data *ad, struct chap_hdr *hdr) { MD5_CTX md5_ctx; uint8_t md5[MD5_DIGEST_LENGTH]; char *passwd; char *name; int r; - struct chap_challenge_t *msg = (struct chap_challenge_t*)hdr; + struct chap_challenge *msg = (struct chap_challenge*)hdr; if (ad->timeout.tpd) triton_timer_del(&ad->timeout); @@ -270,6 +307,9 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h return; } + if (ad->name) + return; + if (msg->hdr.id != ad->id) { if (conf_ppp_verbose) log_ppp_warn("chap-md5: id mismatch\n"); @@ -301,7 +341,12 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h return; } - r = pwdb_check(&ad->ppp->ses, name, PPP_CHAP, CHAP_MD5, ad->id, ad->val, VALUE_SIZE, msg->val); + r = pwdb_check(&ad->ppp->ses, (pwdb_callback)auth_result, ad, name, PPP_CHAP, CHAP_MD5, ad->id, ad->val, VALUE_SIZE, msg->val); + + if (r == PWDB_WAIT) { + ad->name = name; + return; + } if (r == PWDB_NO_IMPL) { passwd = pwdb_get_passwd(&ad->ppp->ses, name); @@ -383,7 +428,7 @@ static int chap_check(uint8_t *ptr) static int chap_restart(struct ppp_t *ppp, struct auth_data_t *auth) { - struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); chap_send_challenge(d, 1); @@ -405,8 +450,8 @@ static struct ppp_auth_handler_t chap= 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->buf; + struct chap_auth_data *d = container_of(h, typeof(*d), h); + struct chap_hdr *hdr = (struct chap_hdr *)d->ppp->buf; if (d->ppp->buf_size < sizeof(*hdr) || ntohs(hdr->len) < HDR_LEN || ntohs(hdr->len) > d->ppp->buf_size - 2) { log_ppp_warn("chap-md5: short packet received\n"); diff --git a/accel-pppd/auth/auth_mschap_v1.c b/accel-pppd/auth/auth_mschap_v1.c index 1576c837..d9232cc9 100644 --- a/accel-pppd/auth/auth_mschap_v1.c +++ b/accel-pppd/auth/auth_mschap_v1.c @@ -29,7 +29,7 @@ #define VALUE_SIZE 8 #define RESPONSE_VALUE_SIZE (24+24+1) -#define HDR_LEN (sizeof(struct chap_hdr_t)-2) +#define HDR_LEN (sizeof(struct chap_hdr)-2) static int conf_timeout = 5; static int conf_interval = 0; @@ -38,22 +38,22 @@ static int conf_any_login = 0; static char *conf_msg_failure = "E=691 R=0"; static char *conf_msg_success = "Authentication succeeded"; -struct chap_hdr_t { +struct chap_hdr { uint16_t proto; uint8_t code; uint8_t id; uint16_t len; } __attribute__((packed)); -struct chap_challenge_t { - struct chap_hdr_t hdr; +struct chap_challenge { + struct chap_hdr hdr; uint8_t val_size; uint8_t val[VALUE_SIZE]; char name[0]; } __attribute__((packed)); -struct chap_response_t { - struct chap_hdr_t hdr; +struct chap_response { + struct chap_hdr hdr; uint8_t val_size; uint8_t lm_hash[24]; uint8_t nt_hash[24]; @@ -61,7 +61,7 @@ struct chap_response_t { char name[0]; } __attribute__((packed)); -struct chap_auth_data_t { +struct chap_auth_data { struct auth_data_t auth; struct ppp_handler_t h; struct ppp_t *ppp; @@ -70,15 +70,17 @@ struct chap_auth_data_t { struct triton_timer_t timeout; struct triton_timer_t interval; int failure; + char *name; + char *mschap_error; int started:1; }; -static void chap_send_challenge(struct chap_auth_data_t *ad, int new); +static void chap_send_challenge(struct chap_auth_data *ad, int new); static void chap_recv(struct ppp_handler_t *h); -static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *res, const char *name); +static int chap_check_response(struct chap_auth_data *ad, struct chap_response *res, const char *name); static void chap_timeout_timer(struct triton_timer_t *t); static void chap_restart_timer(struct triton_timer_t *t); -static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash); +static void set_mppe_keys(struct chap_auth_data *ad, uint8_t *z_hash); static void print_buf(const uint8_t *buf,int size) { @@ -95,7 +97,7 @@ static void print_str(const char *buf, int size) static struct auth_data_t* auth_data_init(struct ppp_t *ppp) { - struct chap_auth_data_t *d = _malloc(sizeof(*d)); + struct chap_auth_data *d = _malloc(sizeof(*d)); memset(d, 0, sizeof(*d)); d->auth.proto = PPP_CHAP; @@ -106,7 +108,7 @@ static struct auth_data_t* auth_data_init(struct ppp_t *ppp) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); if (d->timeout.tpd) triton_timer_del(&d->timeout); @@ -119,7 +121,7 @@ static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); d->h.proto = PPP_CHAP; d->h.recv = chap_recv; @@ -128,6 +130,7 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth) d->interval.expire = chap_restart_timer; d->interval.period = conf_interval * 1000; d->id = 1; + d->name = NULL; ppp_register_chan_handler(ppp, &d->h); @@ -138,7 +141,7 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); if (d->timeout.tpd) triton_timer_del(&d->timeout); @@ -146,6 +149,9 @@ static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth) if (d->interval.tpd) triton_timer_del(&d->interval); + if (d->name) + _free(d->name); + ppp_unregister_handler(ppp, &d->h); return 0; @@ -153,7 +159,7 @@ static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth) static void chap_timeout_timer(struct triton_timer_t *t) { - struct chap_auth_data_t *d = container_of(t, typeof(*d), timeout); + struct chap_auth_data *d = container_of(t, typeof(*d), timeout); if (conf_ppp_verbose) log_ppp_warn("mschap-v1: timeout\n"); @@ -169,7 +175,7 @@ static void chap_timeout_timer(struct triton_timer_t *t) static void chap_restart_timer(struct triton_timer_t *t) { - struct chap_auth_data_t *d = container_of(t, typeof(*d), interval); + struct chap_auth_data *d = container_of(t, typeof(*d), interval); chap_send_challenge(d, 1); } @@ -187,9 +193,9 @@ static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t * return LCP_OPT_NAK; } -static void chap_send_failure(struct chap_auth_data_t *ad, char *mschap_error) +static void chap_send_failure(struct chap_auth_data *ad, char *mschap_error) { - struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(mschap_error) + 1); + struct chap_hdr *hdr = _malloc(sizeof(*hdr) + strlen(mschap_error) + 1); hdr->proto = htons(PPP_CHAP); hdr->code = CHAP_FAILURE; hdr->id = ad->id; @@ -204,9 +210,9 @@ static void chap_send_failure(struct chap_auth_data_t *ad, char *mschap_error) _free(hdr); } -static void chap_send_success(struct chap_auth_data_t *ad, int id) +static void chap_send_success(struct chap_auth_data *ad, int id) { - struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(conf_msg_success) + 1); + struct chap_hdr *hdr = _malloc(sizeof(*hdr) + strlen(conf_msg_success) + 1); hdr->proto = htons(PPP_CHAP); hdr->code = CHAP_SUCCESS; hdr->id = id; @@ -221,9 +227,9 @@ static void chap_send_success(struct chap_auth_data_t *ad, int id) _free(hdr); } -static void chap_send_challenge(struct chap_auth_data_t *ad, int new) +static void chap_send_challenge(struct chap_auth_data *ad, int new) { - struct chap_challenge_t msg = { + struct chap_challenge msg = { .hdr.proto = htons(PPP_CHAP), .hdr.code = CHAP_CHALLENGE, .hdr.id = ad->id, @@ -248,11 +254,46 @@ static void chap_send_challenge(struct chap_auth_data_t *ad, int new) triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->timeout, 0); } -static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *hdr) +static void auth_result(struct chap_auth_data *ad, int res) +{ + char *name = ad->name; + + ad->name = NULL; + + if (res == PWDB_DENIED) { + chap_send_failure(ad, ad->mschap_error); + if (ad->started) + ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); + else + ppp_auth_failed(ad->ppp, name); + } else { + if (ppp_auth_succeeded(ad->ppp, name)) { + chap_send_failure(ad, ad->mschap_error); + ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); + } else { + chap_send_success(ad, ad->id); + ad->started = 1; + if (conf_interval) + triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->interval, 0); + name = NULL; + } + } + + ad->id++; + + if (ad->mschap_error != conf_msg_failure) { + _free(ad->mschap_error); + ad->mschap_error = conf_msg_failure; + } + + if (name) + _free(name); +} + +static void chap_recv_response(struct chap_auth_data *ad, struct chap_hdr *hdr) { - struct chap_response_t *msg = (struct chap_response_t*)hdr; + struct chap_response *msg = (struct chap_response*)hdr; char *name; - char *mschap_error = conf_msg_failure; int r; if (ad->timeout.tpd) @@ -273,6 +314,9 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h return; } + if (ad->name) + return; + if (msg->hdr.id != ad->id) { if (conf_ppp_verbose) log_ppp_warn("mschap-v1: id mismatch\n"); @@ -300,7 +344,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h if (conf_any_login) { if (ppp_auth_succeeded(ad->ppp, name)) { - chap_send_failure(ad, mschap_error); + chap_send_failure(ad, ad->mschap_error); ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); _free(name); return; @@ -311,24 +355,34 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h return; } - r = pwdb_check(&ad->ppp->ses, name, PPP_CHAP, MSCHAP_V1, ad->id, ad->val, VALUE_SIZE, msg->lm_hash, msg->nt_hash, msg->flags, &mschap_error); + ad->mschap_error = conf_msg_failure; + + r = pwdb_check(&ad->ppp->ses, (pwdb_callback)auth_result, ad, name, PPP_CHAP, MSCHAP_V1, ad->id, ad->val, VALUE_SIZE, msg->lm_hash, msg->nt_hash, msg->flags, &ad->mschap_error); + + if (r == PWDB_WAIT) { + ad->name = name; + return; + } + if (r == PWDB_NO_IMPL) if (chap_check_response(ad, msg, name)) r = PWDB_DENIED; if (r == PWDB_DENIED) { - chap_send_failure(ad, mschap_error); + chap_send_failure(ad, ad->mschap_error); if (ad->started) ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); else ppp_auth_failed(ad->ppp, name); _free(name); - if (mschap_error != conf_msg_failure) - _free(mschap_error); + if (ad->mschap_error != conf_msg_failure) { + _free(ad->mschap_error); + ad->mschap_error = conf_msg_failure; + } } else { if (!ad->started) { if (ppp_auth_succeeded(ad->ppp, name)) { - chap_send_failure(ad, mschap_error); + chap_send_failure(ad, ad->mschap_error); ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); _free(name); } else { @@ -375,7 +429,7 @@ static void des_encrypt(const uint8_t *input, const uint8_t *key, uint8_t *outpu memcpy(output, res, 8); } -static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name) +static int chap_check_response(struct chap_auth_data *ad, struct chap_response *msg, const char *name) { MD4_CTX md4_ctx; uint8_t z_hash[21]; @@ -420,7 +474,7 @@ static int chap_check(uint8_t *ptr) return *ptr == MSCHAP_V1; } -static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash) +static void set_mppe_keys(struct chap_auth_data *ad, uint8_t *z_hash) { MD4_CTX md4_ctx; SHA_CTX sha_ctx; @@ -450,7 +504,7 @@ static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash) static int chap_restart(struct ppp_t *ppp, struct auth_data_t *auth) { - struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); chap_send_challenge(d, 1); @@ -471,8 +525,8 @@ static struct ppp_auth_handler_t chap = { 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->buf; + struct chap_auth_data *d = container_of(h, typeof(*d), h); + struct chap_hdr *hdr = (struct chap_hdr *)d->ppp->buf; if (d->ppp->buf_size < sizeof(*hdr) || ntohs(hdr->len) < HDR_LEN || ntohs(hdr->len) > d->ppp->buf_size - 2) { log_ppp_warn("mschap-v1: short packet received\n"); diff --git a/accel-pppd/auth/auth_mschap_v2.c b/accel-pppd/auth/auth_mschap_v2.c index 29f37495..0235ddf0 100644 --- a/accel-pppd/auth/auth_mschap_v2.c +++ b/accel-pppd/auth/auth_mschap_v2.c @@ -29,7 +29,7 @@ #define VALUE_SIZE 16 #define RESPONSE_VALUE_SIZE (16+8+24+1) -#define HDR_LEN (sizeof(struct chap_hdr_t)-2) +#define HDR_LEN (sizeof(struct chap_hdr)-2) static int conf_timeout = 5; static int conf_interval = 0; @@ -38,7 +38,7 @@ static char *conf_msg_failure = "E=691 R=0 V=3"; static char *conf_msg_failure2 = "Authentication failure"; static char *conf_msg_success = "Authentication succeeded"; -struct chap_hdr_t { +struct chap_hdr { uint16_t proto; uint8_t code; uint8_t id; @@ -46,14 +46,14 @@ struct chap_hdr_t { } __attribute__((packed)); struct chap_challenge_t { - struct chap_hdr_t hdr; + struct chap_hdr hdr; uint8_t val_size; uint8_t val[VALUE_SIZE]; char name[0]; } __attribute__((packed)); -struct chap_response_t { - struct chap_hdr_t hdr; +struct chap_response { + struct chap_hdr hdr; uint8_t val_size; uint8_t peer_challenge[16]; uint8_t reserved[8]; @@ -62,7 +62,7 @@ struct chap_response_t { char name[0]; } __attribute__((packed)); -struct chap_auth_data_t { +struct chap_auth_data { struct auth_data_t auth; struct ppp_handler_t h; struct ppp_t *ppp; @@ -71,16 +71,19 @@ struct chap_auth_data_t { struct triton_timer_t timeout; struct triton_timer_t interval; char authenticator[41]; + char *name; + char *mschap_error; + char *reply_msg; int failure; int started:1; }; -static void chap_send_challenge(struct chap_auth_data_t *ad, int new); +static void chap_send_challenge(struct chap_auth_data *ad, int new); static void chap_recv(struct ppp_handler_t *h); -static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name); +static int chap_check_response(struct chap_auth_data *ad, struct chap_response *msg, const char *name); static void chap_timeout_timer(struct triton_timer_t *t); static void chap_restart_timer(struct triton_timer_t *t); -static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash, uint8_t *nt_hash); +static void set_mppe_keys(struct chap_auth_data *ad, uint8_t *z_hash, uint8_t *nt_hash); static void print_buf(const uint8_t *buf, int size) { @@ -98,7 +101,7 @@ static void print_str(const char *buf, int size) static struct auth_data_t* auth_data_init(struct ppp_t *ppp) { - struct chap_auth_data_t *d = _malloc(sizeof(*d)); + struct chap_auth_data *d = _malloc(sizeof(*d)); memset(d, 0, sizeof(*d)); d->auth.proto = PPP_CHAP; @@ -109,7 +112,7 @@ static struct auth_data_t* auth_data_init(struct ppp_t *ppp) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); if (d->timeout.tpd) triton_timer_del(&d->timeout); @@ -122,7 +125,7 @@ static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); d->h.proto = PPP_CHAP; d->h.recv = chap_recv; @@ -131,6 +134,7 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth) d->interval.expire = chap_restart_timer; d->interval.period = conf_interval * 1000; d->id = 1; + d->name = NULL; ppp_register_chan_handler(ppp, &d->h); @@ -141,7 +145,7 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth) 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); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); if (d->timeout.tpd) triton_timer_del(&d->timeout); @@ -156,7 +160,7 @@ static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth) static void chap_timeout_timer(struct triton_timer_t *t) { - struct chap_auth_data_t *d = container_of(t, typeof(*d), timeout); + struct chap_auth_data *d = container_of(t, typeof(*d), timeout); if (conf_ppp_verbose) log_ppp_warn("mschap-v2: timeout\n"); @@ -172,7 +176,7 @@ static void chap_timeout_timer(struct triton_timer_t *t) static void chap_restart_timer(struct triton_timer_t *t) { - struct chap_auth_data_t *d = container_of(t, typeof(*d), interval); + struct chap_auth_data *d = container_of(t, typeof(*d), interval); chap_send_challenge(d, 1); } @@ -190,9 +194,9 @@ static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t * return LCP_OPT_NAK; } -static void chap_send_failure(struct chap_auth_data_t *ad, char *mschap_error, char *reply_msg) +static void chap_send_failure(struct chap_auth_data *ad, char *mschap_error, char *reply_msg) { - struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(mschap_error) + strlen(reply_msg) + 4); + struct chap_hdr *hdr = _malloc(sizeof(*hdr) + strlen(mschap_error) + strlen(reply_msg) + 4); hdr->proto = htons(PPP_CHAP); hdr->code = CHAP_FAILURE; hdr->id = ad->id; @@ -208,9 +212,9 @@ static void chap_send_failure(struct chap_auth_data_t *ad, char *mschap_error, c _free(hdr); } -static void chap_send_success(struct chap_auth_data_t *ad, int id, const char *authenticator) +static void chap_send_success(struct chap_auth_data *ad, int id, const char *authenticator) { - struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(conf_msg_success) + 1 + 45); + struct chap_hdr *hdr = _malloc(sizeof(*hdr) + strlen(conf_msg_success) + 1 + 45); hdr->proto = htons(PPP_CHAP), hdr->code = CHAP_SUCCESS, hdr->id = id, @@ -226,7 +230,7 @@ static void chap_send_success(struct chap_auth_data_t *ad, int id, const char *a _free(hdr); } -static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name, char *authenticator) +static int generate_response(struct chap_auth_data *ad, struct chap_response *msg, const char *name, char *authenticator) { MD4_CTX md4_ctx; SHA_CTX sha_ctx; @@ -296,7 +300,7 @@ static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t return 0; } -static void chap_send_challenge(struct chap_auth_data_t *ad, int new) +static void chap_send_challenge(struct chap_auth_data *ad, int new) { struct chap_challenge_t msg = { .hdr.proto = htons(PPP_CHAP), @@ -323,14 +327,54 @@ static void chap_send_challenge(struct chap_auth_data_t *ad, int new) triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->timeout, 0); } -static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *hdr) +static void auth_result(struct chap_auth_data *ad, int res) +{ + char *name = ad->name; + + ad->name = NULL; + + if (res == PWDB_DENIED) { + chap_send_failure(ad, ad->mschap_error, ad->reply_msg); + if (ad->started) + ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); + else + ppp_auth_failed(ad->ppp, name); + } else { + if (ppp_auth_succeeded(ad->ppp, name)) { + chap_send_failure(ad, ad->mschap_error, ad->reply_msg); + ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); + } else { + chap_send_success(ad, ad->id, ad->authenticator); + ad->started = 1; + if (conf_interval) + triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->interval, 0); + name = NULL; + } + } + + ad->id++; + + if (ad->mschap_error != conf_msg_failure) { + _free(ad->mschap_error); + ad->mschap_error = conf_msg_failure; + } + + if (ad->reply_msg != conf_msg_failure2) { + _free(ad->reply_msg); + ad->reply_msg = conf_msg_failure2; + } + + if (name) + _free(name); +} + + +static void chap_recv_response(struct chap_auth_data *ad, struct chap_hdr *hdr) { - struct chap_response_t *msg = (struct chap_response_t*)hdr; + struct chap_response *msg = (struct chap_response*)hdr; char *name; - char authenticator[41]; + char *authenticator = ad->authenticator; int r; - char *mschap_error = conf_msg_failure; - char *reply_msg = conf_msg_failure2; authenticator[40] = 0; @@ -352,6 +396,12 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h return; } + if (ad->name) + return; + + ad->mschap_error = conf_msg_failure; + ad->reply_msg = conf_msg_failure2; + if (msg->hdr.id != ad->id) { if (conf_ppp_verbose) log_ppp_warn("mschap-v2: id mismatch\n"); @@ -360,7 +410,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h if (msg->val_size != RESPONSE_VALUE_SIZE) { log_ppp_error("mschap-v2: incorrect value-size (%i)\n", msg->val_size); - chap_send_failure(ad, mschap_error, reply_msg); + chap_send_failure(ad, ad->mschap_error, ad->reply_msg); if (ad->started) ap_session_terminate(&ad->ppp->ses, TERM_USER_ERROR, 0); else @@ -378,7 +428,12 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h return; } - r = pwdb_check(&ad->ppp->ses, name, PPP_CHAP, MSCHAP_V2, ad->id, ad->val, msg->peer_challenge, msg->reserved, msg->nt_hash, msg->flags, authenticator, &mschap_error, &reply_msg); + r = pwdb_check(&ad->ppp->ses, (pwdb_callback)auth_result, ad, name, PPP_CHAP, MSCHAP_V2, ad->id, ad->val, msg->peer_challenge, msg->reserved, msg->nt_hash, msg->flags, authenticator, &ad->mschap_error, &ad->reply_msg); + + if (r == PWDB_WAIT) { + ad->name = name; + return; + } if (r == PWDB_NO_IMPL) { r = chap_check_response(ad, msg, name); @@ -389,20 +444,27 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h } if (r == PWDB_DENIED) { - chap_send_failure(ad, mschap_error, reply_msg); + chap_send_failure(ad, ad->mschap_error, ad->reply_msg); if (ad->started) ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); else ppp_auth_failed(ad->ppp, name); + _free(name); - if (mschap_error != conf_msg_failure) - _free(mschap_error); - if (reply_msg != conf_msg_failure2) - _free(reply_msg); + + if (ad->mschap_error != conf_msg_failure) { + _free(ad->mschap_error); + ad->mschap_error = conf_msg_failure; + } + + if (ad->reply_msg != conf_msg_failure2) { + _free(ad->reply_msg); + ad->reply_msg = conf_msg_failure2; + } } else { if (!ad->started) { if (ppp_auth_succeeded(ad->ppp, name)) { - chap_send_failure(ad, mschap_error, reply_msg); + chap_send_failure(ad, ad->mschap_error, ad->reply_msg); ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0); _free(name); } else { @@ -416,8 +478,6 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h _free(name); } - memcpy(ad->authenticator, authenticator, 41); - ad->id++; } } @@ -451,7 +511,7 @@ static void des_encrypt(const uint8_t *input, const uint8_t *key, uint8_t *outpu memcpy(output,res,8); } -static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name) +static int chap_check_response(struct chap_auth_data *ad, struct chap_response *msg, const char *name) { MD4_CTX md4_ctx; SHA_CTX sha_ctx; @@ -499,7 +559,7 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response return memcmp(nt_hash, msg->nt_hash, 24); } -static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash, uint8_t *nt_hash) +static void set_mppe_keys(struct chap_auth_data *ad, uint8_t *z_hash, uint8_t *nt_hash) { MD4_CTX md4_ctx; SHA_CTX sha_ctx; @@ -591,7 +651,7 @@ static int chap_check(uint8_t *ptr) static int chap_restart(struct ppp_t *ppp, struct auth_data_t *auth) { - struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth); + struct chap_auth_data *d = container_of(auth, typeof(*d), auth); chap_send_challenge(d, 1); @@ -613,8 +673,8 @@ static struct ppp_auth_handler_t chap= 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->buf; + struct chap_auth_data *d = container_of(h, typeof(*d), h); + struct chap_hdr *hdr = (struct chap_hdr *)d->ppp->buf; if (d->ppp->buf_size < sizeof(*hdr) || ntohs(hdr->len) < HDR_LEN || ntohs(hdr->len) > d->ppp->buf_size - 2) { log_ppp_warn("mschap-v2: short packet received\n"); diff --git a/accel-pppd/auth/auth_pap.c b/accel-pppd/auth/auth_pap.c index 5f073370..9aab3775 100644 --- a/accel-pppd/auth/auth_pap.c +++ b/accel-pppd/auth/auth_pap.c @@ -15,12 +15,14 @@ #define MSG_FAILED "Authentication failed" #define MSG_SUCCESSED "Authentication succeeded" -#define HDR_LEN (sizeof(struct pap_hdr_t)-2) +#define HDR_LEN (sizeof(struct pap_hdr)-2) #define PAP_REQ 1 #define PAP_ACK 2 #define PAP_NAK 3 +struct pap_auth_data; + static int conf_timeout = 5; static int conf_any_login = 0; @@ -32,33 +34,32 @@ static int pap_start(struct ppp_t*, struct auth_data_t*); static int pap_finish(struct ppp_t*, struct auth_data_t*); static void pap_recv(struct ppp_handler_t*h); static void pap_timeout(struct triton_timer_t *t); +static void pap_auth_result(struct pap_auth_data *, int); -struct pap_auth_data_t -{ +struct pap_auth_data { struct auth_data_t auth; struct ppp_handler_t h; struct ppp_t *ppp; - int started:1; struct triton_timer_t timeout; + char *peer_id; + int req_id; + int started:1; }; -struct pap_hdr_t -{ +struct pap_hdr { uint16_t proto; uint8_t code; uint8_t id; uint16_t len; } __attribute__((packed)); -struct pap_ack_t -{ - struct pap_hdr_t hdr; +struct pap_ack { + struct pap_hdr hdr; uint8_t msg_len; char msg[0]; } __attribute__((packed)); -static struct ppp_auth_handler_t pap= -{ +static struct ppp_auth_handler_t pap= { .name = "PAP", .init = auth_data_init, .free = auth_data_free, @@ -70,7 +71,7 @@ static struct ppp_auth_handler_t pap= static struct auth_data_t* auth_data_init(struct ppp_t *ppp) { - struct pap_auth_data_t *d = _malloc(sizeof(*d)); + struct pap_auth_data *d = _malloc(sizeof(*d)); memset(d, 0, sizeof(*d)); d->auth.proto = PPP_PAP; @@ -81,14 +82,14 @@ static struct auth_data_t* auth_data_init(struct ppp_t *ppp) static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth) { - struct pap_auth_data_t *d = container_of(auth, typeof(*d), auth); + struct pap_auth_data *d = container_of(auth, typeof(*d), auth); _free(d); } static int pap_start(struct ppp_t *ppp, struct auth_data_t *auth) { - struct pap_auth_data_t *d = container_of(auth, typeof(*d), auth); + struct pap_auth_data *d = container_of(auth, typeof(*d), auth); d->h.proto = PPP_PAP; d->h.recv = pap_recv; @@ -103,10 +104,13 @@ static int pap_start(struct ppp_t *ppp, struct auth_data_t *auth) } static int pap_finish(struct ppp_t *ppp, struct auth_data_t *auth) { - struct pap_auth_data_t *d = container_of(auth, typeof(*d), auth); + struct pap_auth_data *d = container_of(auth, typeof(*d), auth); if (d->timeout.tpd) triton_timer_del(&d->timeout); + + if (d->peer_id) + _free(d->peer_id); ppp_unregister_handler(ppp, &d->h); @@ -115,7 +119,7 @@ static int pap_finish(struct ppp_t *ppp, struct auth_data_t *auth) static void pap_timeout(struct triton_timer_t *t) { - struct pap_auth_data_t *d = container_of(t, typeof(*d), timeout); + struct pap_auth_data *d = container_of(t, typeof(*d), timeout); if (conf_ppp_verbose) log_ppp_warn("pap: timeout\n"); @@ -133,10 +137,10 @@ static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t * return LCP_OPT_ACK; } -static void pap_send_ack(struct pap_auth_data_t *p, int id) +static void pap_send_ack(struct pap_auth_data *p, int id) { uint8_t buf[128]; - struct pap_ack_t *msg = (struct pap_ack_t*)buf; + struct pap_ack *msg = (struct pap_ack*)buf; msg->hdr.proto = htons(PPP_PAP); msg->hdr.code = PAP_ACK; msg->hdr.id = id; @@ -150,10 +154,10 @@ static void pap_send_ack(struct pap_auth_data_t *p, int id) ppp_chan_send(p->ppp, msg, ntohs(msg->hdr.len) + 2); } -static void pap_send_nak(struct pap_auth_data_t *p, int id) +static void pap_send_nak(struct pap_auth_data *p, int id) { uint8_t buf[128]; - struct pap_ack_t *msg = (struct pap_ack_t*)buf; + struct pap_ack *msg = (struct pap_ack*)buf; msg->hdr.proto = htons(PPP_PAP); msg->hdr.code = PAP_NAK; msg->hdr.id = id; @@ -167,7 +171,33 @@ static void pap_send_nak(struct pap_auth_data_t *p, int id) ppp_chan_send(p->ppp, msg, ntohs(msg->hdr.len) + 2); } -static int pap_recv_req(struct pap_auth_data_t *p, struct pap_hdr_t *hdr) +static void pap_auth_result(struct pap_auth_data *p, int res) +{ + char *peer_id = p->peer_id; + + p->peer_id = NULL; + + if (res == PWDB_DENIED) { + pap_send_nak(p, p->req_id); + if (p->started) + ap_session_terminate(&p->ppp->ses, TERM_AUTH_ERROR, 0); + else + ppp_auth_failed(p->ppp, peer_id); + } else { + if (ppp_auth_succeeded(p->ppp, peer_id)) { + pap_send_nak(p, p->req_id); + ap_session_terminate(&p->ppp->ses, TERM_AUTH_ERROR, 0); + } else { + pap_send_ack(p, p->req_id); + p->started = 1; + return; + } + } + + _free(peer_id); +} + +static int pap_recv_req(struct pap_auth_data *p, struct pap_hdr *hdr) { int ret, r; char *peer_id; @@ -182,17 +212,21 @@ static int pap_recv_req(struct pap_auth_data_t *p, struct pap_hdr_t *hdr) if (conf_ppp_verbose) log_ppp_info2("recv [PAP AuthReq id=%x]\n", hdr->id); - + if (p->started) { pap_send_ack(p, hdr->id); return 0; } + if (p->peer_id) + return 0; + peer_id_len = *(uint8_t*)ptr; ptr++; if (peer_id_len > ntohs(hdr->len) - sizeof(*hdr) + 2 - 1) { log_ppp_warn("PAP: short packet received\n"); return -1; } + peer_id = (char*)ptr; ptr += peer_id_len; passwd_len = *(uint8_t*)ptr; ptr++; @@ -217,7 +251,14 @@ static int pap_recv_req(struct pap_auth_data_t *p, struct pap_hdr_t *hdr) passwd = _strndup((const char*)ptr, passwd_len); - r = pwdb_check(&p->ppp->ses, peer_id, PPP_PAP, passwd); + r = pwdb_check(&p->ppp->ses, (pwdb_callback)pap_auth_result, p, peer_id, PPP_PAP, passwd); + if (r == PWDB_WAIT) { + p->peer_id = peer_id; + p->req_id = hdr->id; + _free(passwd); + return 0; + } + if (r == PWDB_NO_IMPL) { passwd2 = pwdb_get_passwd(&p->ppp->ses, peer_id); if (!passwd2) { @@ -268,8 +309,8 @@ failed: static void pap_recv(struct ppp_handler_t *h) { - struct pap_auth_data_t *d = container_of(h, typeof(*d), h); - struct pap_hdr_t *hdr = (struct pap_hdr_t *)d->ppp->buf; + struct pap_auth_data *d = container_of(h, typeof(*d), h); + struct pap_hdr *hdr = (struct pap_hdr *)d->ppp->buf; if (d->ppp->buf_size < sizeof(*hdr) || ntohs(hdr->len) < HDR_LEN || ntohs(hdr->len) < d->ppp->buf_size - 2) { log_ppp_warn("PAP: short packet received\n"); |