auth_mschap_v1.c 12.1 KB
Newer Older
K
Kozlov Dmitry 已提交
1 2 3 4 5 6 7
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
8
#include <byteswap.h>
K
Kozlov Dmitry 已提交
9 10
#include <arpa/inet.h>

11
#include "crypto.h"
K
Kozlov Dmitry 已提交
12 13 14

#include "log.h"
#include "ppp.h"
15
#include "events.h"
K
Kozlov Dmitry 已提交
16 17 18 19
#include "ppp_auth.h"
#include "ppp_lcp.h"
#include "pwdb.h"

D
Dmitry Kozlov 已提交
20 21
#include "memdebug.h"

22 23
#define MSCHAP_V1 0x80

K
Kozlov Dmitry 已提交
24 25 26 27 28
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE  2
#define CHAP_SUCCESS   3
#define CHAP_FAILURE   4

29 30
#define VALUE_SIZE 8
#define RESPONSE_VALUE_SIZE (24+24+1)
K
Kozlov Dmitry 已提交
31 32 33

#define HDR_LEN (sizeof(struct chap_hdr_t)-2)

K
Kozlov Dmitry 已提交
34
static int conf_timeout = 5;
D
Dmitry Kozlov 已提交
35
static int conf_interval = 0;
K
Kozlov Dmitry 已提交
36
static int conf_max_failure = 3;
37
static int conf_any_login = 0;
38
static char *conf_msg_failure = "E=691 R=0";
39
static char *conf_msg_success = "Authentication succeeded";
D
Dmitry Kozlov 已提交
40

41
struct chap_hdr_t {
K
Kozlov Dmitry 已提交
42 43 44 45 46 47
	uint16_t proto;
	uint8_t code;
	uint8_t id;
	uint16_t len;
} __attribute__((packed));

48
struct chap_challenge_t {
K
Kozlov Dmitry 已提交
49 50 51 52 53 54
	struct chap_hdr_t hdr;
	uint8_t val_size;
	uint8_t val[VALUE_SIZE];
	char name[0];
} __attribute__((packed));

55
struct chap_response_t {
56 57 58 59
	struct chap_hdr_t hdr;
	uint8_t val_size;
	uint8_t lm_hash[24];
	uint8_t nt_hash[24];
60
	uint8_t flags;
61 62 63
	char name[0];
} __attribute__((packed));

64
struct chap_auth_data_t {
K
Kozlov Dmitry 已提交
65 66 67
	struct auth_data_t auth;
	struct ppp_handler_t h;
	struct ppp_t *ppp;
68
	uint8_t id;
K
Kozlov Dmitry 已提交
69
	uint8_t val[VALUE_SIZE];
D
Dmitry Kozlov 已提交
70 71 72 73
	struct triton_timer_t timeout;
	struct triton_timer_t interval;
	int failure;
	int started:1;
K
Kozlov Dmitry 已提交
74 75
};

76
static void chap_send_challenge(struct chap_auth_data_t *ad, int new);
K
Kozlov Dmitry 已提交
77
static void chap_recv(struct ppp_handler_t *h);
78
static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *res, const char *name);
79 80
static void chap_timeout_timer(struct triton_timer_t *t);
static void chap_restart_timer(struct triton_timer_t *t);
81
static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash);
K
Kozlov Dmitry 已提交
82 83 84 85

static void print_buf(const uint8_t *buf,int size)
{
	int i;
K
Kozlov Dmitry 已提交
86
	for (i = 0; i < size; i++)
87
		log_ppp_info2("%x", buf[i]);
K
Kozlov Dmitry 已提交
88
}
K
Kozlov Dmitry 已提交
89
static void print_str(const char *buf, int size)
K
Kozlov Dmitry 已提交
90 91
{
	int i;
K
Kozlov Dmitry 已提交
92
	for(i = 0; i < size; i++)
93
		log_ppp_info2("%c", buf[i]);
K
Kozlov Dmitry 已提交
94 95 96 97
}

static struct auth_data_t* auth_data_init(struct ppp_t *ppp)
{
K
Kozlov Dmitry 已提交
98
	struct chap_auth_data_t *d = _malloc(sizeof(*d));
K
Kozlov Dmitry 已提交
99

K
Kozlov Dmitry 已提交
100 101 102
	memset(d, 0, sizeof(*d));
	d->auth.proto = PPP_CHAP;
	d->ppp = ppp;
K
Kozlov Dmitry 已提交
103 104 105 106

	return &d->auth;
}

K
Kozlov Dmitry 已提交
107
static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth)
K
Kozlov Dmitry 已提交
108
{
K
Kozlov Dmitry 已提交
109
	struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
K
Kozlov Dmitry 已提交
110

111 112 113 114 115 116
	if (d->timeout.tpd)
		triton_timer_del(&d->timeout);

	if (d->interval.tpd)
		triton_timer_del(&d->interval);

D
Dmitry Kozlov 已提交
117
	_free(d);
K
Kozlov Dmitry 已提交
118 119 120 121
}

static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth)
{
K
Kozlov Dmitry 已提交
122
	struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
K
Kozlov Dmitry 已提交
123

K
Kozlov Dmitry 已提交
124 125
	d->h.proto = PPP_CHAP;
	d->h.recv = chap_recv;
126
	d->timeout.expire = chap_timeout_timer;
K
Kozlov Dmitry 已提交
127
	d->timeout.period = conf_timeout * 1000;
128
	d->interval.expire = chap_restart_timer;
K
Kozlov Dmitry 已提交
129
	d->interval.period = conf_interval * 1000;
130
	d->id = 1;
K
Kozlov Dmitry 已提交
131

K
Kozlov Dmitry 已提交
132
	ppp_register_chan_handler(ppp, &d->h);
K
Kozlov Dmitry 已提交
133

134
	chap_send_challenge(d, 1);
K
Kozlov Dmitry 已提交
135 136 137 138 139 140

	return 0;
}

static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth)
{
K
Kozlov Dmitry 已提交
141
	struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
K
Kozlov Dmitry 已提交
142

D
Dmitry Kozlov 已提交
143 144 145 146 147 148
	if (d->timeout.tpd)
		triton_timer_del(&d->timeout);

	if (d->interval.tpd)
		triton_timer_del(&d->interval);

K
Kozlov Dmitry 已提交
149
	ppp_unregister_handler(ppp, &d->h);
K
Kozlov Dmitry 已提交
150 151 152 153

	return 0;
}

154
static void chap_timeout_timer(struct triton_timer_t *t)
D
Dmitry Kozlov 已提交
155 156 157
{
	struct chap_auth_data_t *d = container_of(t, typeof(*d), timeout);

K
Kozlov Dmitry 已提交
158 159
	if (conf_ppp_verbose)
		log_ppp_warn("mschap-v1: timeout\n");
D
Dmitry Kozlov 已提交
160 161 162

	if (++d->failure == conf_max_failure) {
		if (d->started)
163
			ap_session_terminate(&d->ppp->ses, TERM_USER_ERROR, 0);
D
Dmitry Kozlov 已提交
164
		else
165
			ppp_auth_failed(d->ppp, NULL);
D
Dmitry Kozlov 已提交
166 167
	} else {
		--d->id;
168
		chap_send_challenge(d, 0);
D
Dmitry Kozlov 已提交
169 170 171
	}
}

172
static void chap_restart_timer(struct triton_timer_t *t)
D
Dmitry Kozlov 已提交
173 174 175
{
	struct chap_auth_data_t *d = container_of(t, typeof(*d), interval);
	
176
	chap_send_challenge(d, 1);
D
Dmitry Kozlov 已提交
177 178
}

K
Kozlov Dmitry 已提交
179 180
static int lcp_send_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
{
K
Kozlov Dmitry 已提交
181
	*ptr = MSCHAP_V1;
K
Kozlov Dmitry 已提交
182 183 184 185 186
	return 1;
}

static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
{
K
Kozlov Dmitry 已提交
187
	if (*ptr == MSCHAP_V1)
K
Kozlov Dmitry 已提交
188
		return LCP_OPT_ACK;
189
	return LCP_OPT_NAK;
K
Kozlov Dmitry 已提交
190 191
}

192
static void chap_send_failure(struct chap_auth_data_t *ad, char *mschap_error)
K
Kozlov Dmitry 已提交
193
{
194 195 196 197 198 199 200
	struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(mschap_error) + 1);
	hdr->proto = htons(PPP_CHAP);
	hdr->code = CHAP_FAILURE;
	hdr->id = ad->id;
	hdr->len = htons(HDR_LEN + strlen(mschap_error));
	strcpy((char *)(hdr + 1), mschap_error);

K
Kozlov Dmitry 已提交
201
	if (conf_ppp_verbose)
202 203 204
		log_ppp_info2("send [MSCHAP-v1 Failure id=%x \"%s\"]\n", hdr->id, mschap_error);

	ppp_chan_send(ad->ppp, hdr, ntohs(hdr->len) + 2);
K
Kozlov Dmitry 已提交
205

206
	_free(hdr);
K
Kozlov Dmitry 已提交
207 208
}

209
static void chap_send_success(struct chap_auth_data_t *ad, int id)
K
Kozlov Dmitry 已提交
210
{
211 212 213
	struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(conf_msg_success) + 1);
	hdr->proto = htons(PPP_CHAP);
	hdr->code = CHAP_SUCCESS;
214
	hdr->id = id;
215 216
	hdr->len = htons(HDR_LEN + strlen(conf_msg_success));
	strcpy((char *)(hdr + 1), conf_msg_success);
K
Kozlov Dmitry 已提交
217
	
K
Kozlov Dmitry 已提交
218
	if (conf_ppp_verbose)
219
		log_ppp_info2("send [MSCHAP-v1 Success id=%x \"%s\"]\n", hdr->id, conf_msg_success);
K
Kozlov Dmitry 已提交
220

221 222 223
	ppp_chan_send(ad->ppp, hdr, ntohs(hdr->len) + 2);

	_free(hdr);
K
Kozlov Dmitry 已提交
224 225
}

226
static void chap_send_challenge(struct chap_auth_data_t *ad, int new)
K
Kozlov Dmitry 已提交
227
{
K
Kozlov Dmitry 已提交
228 229 230
	struct chap_challenge_t msg = {
		.hdr.proto = htons(PPP_CHAP),
		.hdr.code = CHAP_CHALLENGE,
231
		.hdr.id = ad->id,
K
Kozlov Dmitry 已提交
232 233
		.hdr.len = htons(sizeof(msg) - 2),
		.val_size = VALUE_SIZE,
K
Kozlov Dmitry 已提交
234 235
	};

236 237 238
	if (new)
		read(urandom_fd, ad->val, VALUE_SIZE);

K
Kozlov Dmitry 已提交
239
	memcpy(msg.val, ad->val, VALUE_SIZE);
K
Kozlov Dmitry 已提交
240

K
Kozlov Dmitry 已提交
241
	if (conf_ppp_verbose) {
242
		log_ppp_info2("send [MSCHAP-v1 Challenge id=%x <", msg.hdr.id);
K
Kozlov Dmitry 已提交
243
		print_buf(msg.val, VALUE_SIZE);
244
		log_ppp_info2(">]\n");
K
Kozlov Dmitry 已提交
245
	}
K
Kozlov Dmitry 已提交
246

K
Kozlov Dmitry 已提交
247
	ppp_chan_send(ad->ppp, &msg, ntohs(msg.hdr.len) + 2);
D
Dmitry Kozlov 已提交
248 249

	if (conf_timeout && !ad->timeout.tpd)
250
		triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->timeout, 0);
K
Kozlov Dmitry 已提交
251 252 253 254
}

static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *hdr)
{
K
Kozlov Dmitry 已提交
255
	struct chap_response_t *msg = (struct chap_response_t*)hdr;
256
	char *name;
257
	char *mschap_error = conf_msg_failure;
258
	int r;
K
Kozlov Dmitry 已提交
259

D
Dmitry Kozlov 已提交
260 261 262
	if (ad->timeout.tpd)
		triton_timer_del(&ad->timeout);

K
Kozlov Dmitry 已提交
263
	if (conf_ppp_verbose) {
264
		log_ppp_info2("recv [MSCHAP-v1 Response id=%x <", msg->hdr.id);
K
Kozlov Dmitry 已提交
265
		print_buf(msg->lm_hash, 24);
266
		log_ppp_info2(">, <");
K
Kozlov Dmitry 已提交
267
		print_buf(msg->nt_hash, 24);
268
		log_ppp_info2(">, F=%i, name=\"", msg->flags);
K
Kozlov Dmitry 已提交
269
		print_str(msg->name, ntohs(msg->hdr.len) - sizeof(*msg) + 2);
270
		log_ppp_info2("\"]\n");
K
Kozlov Dmitry 已提交
271
	}
K
Kozlov Dmitry 已提交
272

273 274 275 276 277
	if (ad->started && msg->hdr.id == ad->id - 1) {
		chap_send_success(ad, msg->hdr.id);
		return;
	}

K
Kozlov Dmitry 已提交
278 279
	if (msg->hdr.id != ad->id) {
		if (conf_ppp_verbose)
D
Dmitry Kozlov 已提交
280 281
			log_ppp_warn("mschap-v1: id mismatch\n");
		return;
K
Kozlov Dmitry 已提交
282 283
	}

K
Kozlov Dmitry 已提交
284 285
	if (msg->val_size != RESPONSE_VALUE_SIZE)	{
		log_ppp_error("mschap-v1: incorrect value-size (%i)\n", msg->val_size);
D
Dmitry Kozlov 已提交
286
		if (ad->started)
287
			ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0);
D
Dmitry Kozlov 已提交
288
		else
289
			ppp_auth_failed(ad->ppp, NULL);
D
Dmitry Kozlov 已提交
290
		return;
K
Kozlov Dmitry 已提交
291 292
	}

K
Kozlov Dmitry 已提交
293
	name = _strndup(msg->name, ntohs(msg->hdr.len) - sizeof(*msg) + 2);
294
	if (!name) {
K
Kozlov Dmitry 已提交
295
		log_emerg("mschap-v1: out of memory\n");
D
Dmitry Kozlov 已提交
296
		if (ad->started)
297
			ap_session_terminate(&ad->ppp->ses, TERM_NAS_ERROR, 0);
D
Dmitry Kozlov 已提交
298
		else
299
			ppp_auth_failed(ad->ppp, NULL);
300 301
		return;
	}
302 303

	if (conf_any_login) {
304
		if (ppp_auth_succeeded(ad->ppp, name)) {
305
			chap_send_failure(ad, mschap_error);
306
			ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0);
307 308 309
			_free(name);
			return;
		}
310
		chap_send_success(ad, ad->id);
311
		ad->started = 1;
312
		ad->id++;
313 314 315
		return;
	}

316
	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);
317
	if (r == PWDB_NO_IMPL)
318 319
		if (chap_check_response(ad, msg, name))
			r = PWDB_DENIED;
320 321
	
	if (r == PWDB_DENIED) {
322
		chap_send_failure(ad, mschap_error);
D
Dmitry Kozlov 已提交
323
		if (ad->started)
324
			ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0);
D
Dmitry Kozlov 已提交
325
		else
326
			ppp_auth_failed(ad->ppp, name);
D
Dmitry Kozlov 已提交
327
		_free(name);
328 329
		if (mschap_error != conf_msg_failure)
			_free(mschap_error);
330
	} else {
D
Dmitry Kozlov 已提交
331
		if (!ad->started) {
332
			if (ppp_auth_succeeded(ad->ppp, name)) {
333
				chap_send_failure(ad, mschap_error);
334
				ap_session_terminate(&ad->ppp->ses, TERM_AUTH_ERROR, 0);
335 336
				_free(name);
			} else {
337
				chap_send_success(ad, ad->id);
338 339
				ad->started = 1;
				if (conf_interval)
340
					triton_timer_add(ad->ppp->ses.ctrl->ctx, &ad->interval, 0);
341 342
			}
		} else {
343
			chap_send_success(ad, ad->id);
344
			_free(name);
345
		}
346 347

		ad->id++;
348 349 350 351 352
	}
}

static void des_encrypt(const uint8_t *input, const uint8_t *key, uint8_t *output)
{
K
Kozlov Dmitry 已提交
353
	int i, j, parity;
354 355 356 357 358 359 360 361 362
	union
	{
		uint64_t u64;
		uint8_t buf[8];
	} p_key;
	DES_cblock cb;
	DES_cblock res;
	DES_key_schedule ks;

K
Kozlov Dmitry 已提交
363 364
	memcpy(p_key.buf, key, 7);
	p_key.u64 = bswap_64(p_key.u64);
365

K
Kozlov Dmitry 已提交
366 367 368 369 370 371
	for (i = 0; i < 8; i++) {
		cb[i] = (((p_key.u64 << (7 * i)) >> 56) & 0xfe);
		for( j = 0, parity = 0; j < 7; j++)
			if ((cb[i] >> (j + 1)) & 1)
				parity++;
		cb[i] |= (~parity) & 1;
372 373 374
	}

	DES_set_key_checked(&cb, &ks);
K
Kozlov Dmitry 已提交
375 376 377
	memcpy(cb, input, 8);
	DES_ecb_encrypt(&cb, &res, &ks, DES_ENCRYPT);
	memcpy(output, res, 8);	
378 379
}

380
static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name)
381 382 383 384 385 386 387 388
{
	MD4_CTX md4_ctx;
	uint8_t z_hash[21];
	uint8_t nt_hash[24];
	char *passwd;
	char *u_passwd;
	int i;
	
389
	passwd = pwdb_get_passwd(&ad->ppp->ses, name);
K
Kozlov Dmitry 已提交
390 391 392
	if (!passwd) {
		if (conf_ppp_verbose)
			log_ppp_warn("mschap-v1: user not found\n");
393
		chap_send_failure(ad, conf_msg_failure);
394
		return PWDB_DENIED;
K
Kozlov Dmitry 已提交
395 396
	}

K
Kozlov Dmitry 已提交
397 398 399 400
	u_passwd = _malloc(strlen(passwd) * 2);
	for (i = 0; i< strlen(passwd); i++) {
		u_passwd[i * 2] = passwd[i];
		u_passwd[i * 2 + 1] = 0;
K
Kozlov Dmitry 已提交
401 402
	}

K
Kozlov Dmitry 已提交
403
	memset(z_hash, 0, sizeof(z_hash));
404
	MD4_Init(&md4_ctx);
K
Kozlov Dmitry 已提交
405 406
	MD4_Update(&md4_ctx, u_passwd, strlen(passwd) * 2);
	MD4_Final(z_hash, &md4_ctx);
407

K
Kozlov Dmitry 已提交
408 409 410
	des_encrypt(ad->val, z_hash, nt_hash);
	des_encrypt(ad->val, z_hash + 7, nt_hash + 8);
	des_encrypt(ad->val, z_hash + 14, nt_hash + 16);
411

412 413
	set_mppe_keys(ad, z_hash);

D
Dmitry Kozlov 已提交
414 415
	_free(passwd);
	_free(u_passwd);
416

K
Kozlov Dmitry 已提交
417
	return memcmp(nt_hash, msg->nt_hash, 24) ? PWDB_DENIED : PWDB_SUCCESS;
K
Kozlov Dmitry 已提交
418 419
}

K
Kozlov Dmitry 已提交
420
static int chap_check(uint8_t *ptr)
K
Kozlov Dmitry 已提交
421
{
K
Kozlov Dmitry 已提交
422 423 424
	return *ptr == MSCHAP_V1;
}

425 426 427 428 429 430 431 432
static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash)
{
	MD4_CTX md4_ctx;
	SHA_CTX sha_ctx;
	uint8_t digest[20];

	struct ev_mppe_keys_t ev_mppe = {
		.ppp = ad->ppp,
K
Kozlov Dmitry 已提交
433
		.policy = -1,
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
		.recv_key = digest,
		.send_key = digest,
	};

	//NtPasswordHashHash
	MD4_Init(&md4_ctx);
	MD4_Update(&md4_ctx, z_hash, 16);
	MD4_Final(digest, &md4_ctx);

	//Get_Start_Key
	SHA1_Init(&sha_ctx);
	SHA1_Update(&sha_ctx, digest, 16);
	SHA1_Update(&sha_ctx, digest, 16);
	SHA1_Update(&sha_ctx, ad->val, VALUE_SIZE);
	SHA1_Final(digest, &sha_ctx);	

	triton_event_fire(EV_MPPE_KEYS, &ev_mppe);
}

453 454 455 456
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);
	
457
	chap_send_challenge(d, 1);
458 459 460 461

	return 0;
}

K
Kozlov Dmitry 已提交
462 463 464 465 466 467 468 469 470
static struct ppp_auth_handler_t chap = {
	.name          = "MSCHAP-v1",
	.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,
	.check         = chap_check,
471
	.restart       = chap_restart,
K
Kozlov Dmitry 已提交
472 473 474 475
};

static void chap_recv(struct ppp_handler_t *h)
{
K
Kozlov Dmitry 已提交
476
	struct chap_auth_data_t *d = container_of(h, typeof(*d), h);
D
Dmitry Kozlov 已提交
477
	struct chap_hdr_t *hdr = (struct chap_hdr_t *)d->ppp->buf;
K
Kozlov Dmitry 已提交
478

479
	if (d->ppp->buf_size < sizeof(*hdr) || ntohs(hdr->len) < HDR_LEN || ntohs(hdr->len) > d->ppp->buf_size - 2) {
480
		log_ppp_warn("mschap-v1: short packet received\n");
K
Kozlov Dmitry 已提交
481 482 483
		return;
	}

K
Kozlov Dmitry 已提交
484 485
	if (hdr->code == CHAP_RESPONSE)
		chap_recv_response(d, hdr);
K
Kozlov Dmitry 已提交
486
	else
K
Kozlov Dmitry 已提交
487
		log_ppp_warn("mschap-v1: unknown code received %x\n", hdr->code);
K
Kozlov Dmitry 已提交
488 489
}

K
Kozlov Dmitry 已提交
490
static void load_config(void)
K
Kozlov Dmitry 已提交
491
{
K
Kozlov Dmitry 已提交
492
	const char *opt;
D
Dmitry Kozlov 已提交
493 494 495 496 497 498 499 500 501 502 503 504 505

	opt = conf_get_opt("auth", "timeout");
	if (opt && atoi(opt) > 0)
		conf_timeout = atoi(opt);

	opt = conf_get_opt("auth", "interval");
	if (opt && atoi(opt) > 0)
		conf_interval = atoi(opt);

	opt = conf_get_opt("auth", "max-failure");
	if (opt && atoi(opt) > 0)
		conf_max_failure = atoi(opt);

506
	opt = conf_get_opt("auth", "any-login");
K
Kozlov Dmitry 已提交
507 508 509
	if (opt)
		conf_any_login = atoi(opt);
}
510

K
Kozlov Dmitry 已提交
511 512 513 514
static void auth_mschap_v1_init()
{
	load_config();

K
Kozlov Dmitry 已提交
515
	if (ppp_auth_register_handler(&chap))
D
Dmitry Kozlov 已提交
516
		log_emerg("mschap-v1: failed to register handler\n");
K
Kozlov Dmitry 已提交
517 518

	triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
K
Kozlov Dmitry 已提交
519 520
}

K
Kozlov Dmitry 已提交
521
DEFINE_INIT(4, auth_mschap_v1_init);