GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/pap.c Lines: 0 208 0.0 %
Date: 2017-11-07 Branches: 0 104 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: pap.c,v 1.10 2016/03/22 04:11:27 yasuoka Exp $ */
2
3
/*-
4
 * Copyright (c) 2009 Internet Initiative Japan Inc.
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
/* $Id: pap.c,v 1.10 2016/03/22 04:11:27 yasuoka Exp $ */
29
/**@file
30
 * This file provides Password Authentication Protocol (PAP) handlers.
31
 * @author Yasuoka Masahiko
32
 */
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
#include <sys/time.h>
36
#include <net/if_dl.h>
37
#include <netinet/in.h>
38
39
#include <event.h>
40
#include <md5.h>
41
#include <stdarg.h>
42
#include <stdio.h>
43
#include <stdlib.h>
44
#include <string.h>
45
#include <syslog.h>
46
#include <errno.h>
47
#include <vis.h>
48
49
#include "slist.h"
50
#include "npppd.h"
51
#include "ppp.h"
52
53
#ifdef USE_NPPPD_RADIUS
54
#include <radius.h>
55
#include "radius_chap_const.h"
56
#include "npppd_radius.h"
57
#endif
58
59
#include "debugutil.h"
60
61
#define	AUTHREQ				0x01
62
#define	AUTHACK				0x02
63
#define	AUTHNAK				0x03
64
65
#define	PAP_STATE_INITIAL		0
66
#define	PAP_STATE_STARTING		1
67
#define	PAP_STATE_AUTHENTICATING	2
68
#define	PAP_STATE_SENT_RESPONSE		3
69
#define	PAP_STATE_STOPPED		4
70
#define	PAP_STATE_PROXY_AUTHENTICATION	5
71
72
#define	DEFAULT_SUCCESS_MESSAGE		"OK"
73
#define	DEFAULT_FAILURE_MESSAGE		"Unknown username or password"
74
#define	DEFAULT_ERROR_MESSAGE		"Unknown failure"
75
76
#ifdef	PAP_DEBUG
77
#define	PAP_DBG(x)	pap_log x
78
#define	PAP_ASSERT(cond)					\
79
	if (!(cond)) {						\
80
	    fprintf(stderr,					\
81
		"\nASSERT(" #cond ") failed on %s() at %s:%d.\n"\
82
		, __func__, __FILE__, __LINE__);		\
83
	    abort(); 						\
84
	}
85
#else
86
#define	PAP_ASSERT(cond)
87
#define	PAP_DBG(x)
88
#endif
89
90
static void  pap_log (pap *, uint32_t, const char *, ...) __printflike(3,4);
91
static void  pap_response (pap *, int, const char *);
92
static void  pap_authenticate(pap *, const char *);
93
static void  pap_local_authenticate (pap *, const char *, const char *);
94
#ifdef USE_NPPPD_RADIUS
95
static void  pap_radius_authenticate (pap *, const char *, const char *);
96
static void  pap_radius_response (void *, RADIUS_PACKET *, int, RADIUS_REQUEST_CTX);
97
#endif
98
99
#ifdef __cplusplus
100
extern "C" {
101
#endif
102
103
void  pap_init (pap *, npppd_ppp *);
104
int   pap_start (pap *);
105
int   pap_stop (pap *);
106
int   pap_input (pap *, u_char *, int);
107
108
#ifdef __cplusplus
109
}
110
#endif
111
112
void
113
pap_init(pap *_this, npppd_ppp *ppp)
114
{
115
	_this->ppp = ppp;
116
	_this->state = PAP_STATE_INITIAL;
117
	_this->auth_id = -1;
118
}
119
120
int
121
pap_start(pap *_this)
122
{
123
	pap_log(_this, LOG_DEBUG, "%s", __func__);
124
125
	if (_this->state == PAP_STATE_PROXY_AUTHENTICATION) {
126
		_this->state = PAP_STATE_AUTHENTICATING;
127
		pap_authenticate(_this, _this->ppp->proxy_authen_resp);
128
		return 0;
129
	}
130
131
	_this->state = PAP_STATE_STARTING;
132
	return 0;
133
}
134
135
int
136
pap_stop(pap *_this)
137
{
138
	_this->state = PAP_STATE_STOPPED;
139
	_this->auth_id = -1;
140
141
#ifdef USE_NPPPD_RADIUS
142
	if (_this->radctx != NULL) {
143
		radius_cancel_request(_this->radctx);
144
		_this->radctx = NULL;
145
	}
146
#endif
147
	return 0;
148
}
149
150
/** Receiving PAP packet */
151
int
152
pap_input(pap *_this, u_char *pktp, int lpktp)
153
{
154
	int code, id, length, len;
155
	u_char *pktp1;
156
	char name[MAX_USERNAME_LENGTH], password[MAX_PASSWORD_LENGTH];
157
158
	if (_this->state == PAP_STATE_STOPPED ||
159
	    _this->state == PAP_STATE_INITIAL) {
160
		pap_log(_this, LOG_ERR, "Received pap packet.  But pap is "
161
		    "not started.");
162
		return -1;
163
	}
164
	pktp1 = pktp;
165
166
	GETCHAR(code, pktp1);
167
	GETCHAR(id, pktp1);
168
	GETSHORT(length, pktp1);
169
170
	if (code != AUTHREQ) {
171
		pap_log(_this, LOG_ERR, "%s: Received unknown code=%d",
172
		    __func__, code);
173
		return -1;
174
	}
175
	if (lpktp < length) {
176
		pap_log(_this, LOG_ERR, "%s: Received broken packet.",
177
		    __func__);
178
		return -1;
179
	}
180
181
	/* retribute the username */
182
#define	remlen		(lpktp - (pktp1 - pktp))
183
	if (remlen < 1)
184
		goto fail;
185
	GETCHAR(len, pktp1);
186
	if (len <= 0)
187
		goto fail;
188
	if (remlen < len)
189
		goto fail;
190
	if (len > 0)
191
		memcpy(name, pktp1, len);
192
	name[len] = '\0';
193
	pktp1 += len;
194
195
	if (_this->state != PAP_STATE_STARTING) {
196
		/*
197
		 * Receiving identical message again, it must be the message
198
		 * retransmit by the peer.  Continue if the username is same.
199
		 */
200
		if ((_this->state == PAP_STATE_AUTHENTICATING ||
201
		    _this->state == PAP_STATE_SENT_RESPONSE) &&
202
		    strcmp(_this->name, name) == 0) {
203
			/* continue */
204
		} else {
205
			pap_log(_this, LOG_ERR,
206
			    "Received AuthReq is not same as before.  "
207
			    "(%d,%s) != (%d,%s)", id, name, _this->auth_id,
208
			    _this->name);
209
			_this->auth_id = id;
210
			goto fail;
211
		}
212
	}
213
	if (_this->state == PAP_STATE_AUTHENTICATING)
214
		return 0;
215
	_this->auth_id = id;
216
	strlcpy(_this->name, name, sizeof(_this->name));
217
218
	_this->state = PAP_STATE_AUTHENTICATING;
219
220
	/* retribute the password */
221
	if (remlen < 1)
222
		goto fail;
223
	GETCHAR(len, pktp1);
224
	if (remlen < len)
225
		goto fail;
226
	if (len > 0)
227
		memcpy(password, pktp1, len);
228
229
	password[len] = '\0';
230
	pap_authenticate(_this, password);
231
232
	return 0;
233
fail:
234
	pap_response(_this, 0, DEFAULT_FAILURE_MESSAGE);
235
	return -1;
236
}
237
238
static void
239
pap_authenticate(pap *_this, const char *password)
240
{
241
	if (npppd_ppp_bind_realm(_this->ppp->pppd, _this->ppp, _this->name, 0)
242
	    == 0) {
243
		if (!npppd_ppp_is_realm_ready(_this->ppp->pppd, _this->ppp)) {
244
			pap_log(_this, LOG_INFO,
245
			    "username=\"%s\" realm is not ready.", _this->name);
246
			goto fail;
247
			/* NOTREACHED */
248
		}
249
#if USE_NPPPD_RADIUS
250
		if (npppd_ppp_is_realm_radius(_this->ppp->pppd, _this->ppp)) {
251
			pap_radius_authenticate(_this, _this->name, password);
252
			return;
253
			/* NOTREACHED */
254
		} else
255
#endif
256
		if (npppd_ppp_is_realm_local(_this->ppp->pppd, _this->ppp)) {
257
			pap_local_authenticate(_this, _this->name, password);
258
			return;
259
			/* NOTREACHED */
260
		}
261
	}
262
fail:
263
	pap_response(_this, 0, DEFAULT_FAILURE_MESSAGE);
264
}
265
266
static void
267
pap_log(pap *_this, uint32_t prio, const char *fmt, ...)
268
{
269
	char logbuf[BUFSIZ];
270
	va_list ap;
271
272
	va_start(ap, fmt);
273
	snprintf(logbuf, sizeof(logbuf), "ppp id=%u layer=pap %s",
274
	    _this->ppp->id, fmt);
275
	vlog_printf(prio, logbuf, ap);
276
	va_end(ap);
277
}
278
279
static void
280
pap_response(pap *_this, int authok, const char *mes)
281
{
282
	int lpktp, lmes;
283
	u_char *pktp, *pktp1;
284
	const char *realm;
285
286
	pktp = ppp_packetbuf(_this->ppp, PPP_PROTO_PAP) + HEADERLEN;
287
	lpktp = _this->ppp->mru - HEADERLEN;
288
	realm = npppd_ppp_get_realm_name(_this->ppp->pppd, _this->ppp);
289
290
	pktp1 = pktp;
291
	if (mes == NULL)
292
		lmes = 0;
293
	else
294
		lmes = strlen(mes);
295
	lmes = MINIMUM(lmes, lpktp - 1);
296
297
	PUTCHAR(lmes, pktp1);
298
	if (lmes > 0)
299
		memcpy(pktp1, mes, lmes);
300
	lpktp = lmes + 1;
301
302
	if (authok)
303
		ppp_output(_this->ppp, PPP_PROTO_PAP, AUTHACK, _this->auth_id,
304
		    pktp, lpktp);
305
	else
306
		ppp_output(_this->ppp, PPP_PROTO_PAP, AUTHNAK, _this->auth_id,
307
		    pktp, lpktp);
308
309
	if (!authok) {
310
		pap_log(_this, LOG_ALERT,
311
		    "logtype=Failure username=\"%s\" realm=%s", _this->name,
312
		    realm);
313
		pap_stop(_this);
314
		ppp_set_disconnect_cause(_this->ppp,
315
		    PPP_DISCON_AUTH_FAILED, PPP_PROTO_PAP, 1 /* peer */, NULL);
316
		ppp_stop(_this->ppp, "Authentication Required");
317
	} else {
318
		strlcpy(_this->ppp->username, _this->name,
319
		    sizeof(_this->ppp->username));
320
		pap_log(_this, LOG_INFO,
321
		    "logtype=Success username=\"%s\" realm=%s", _this->name,
322
		    realm);
323
		pap_stop(_this);
324
		ppp_auth_ok(_this->ppp);
325
		/* reset the state to response request of retransmision. */
326
		_this->state = PAP_STATE_SENT_RESPONSE;
327
	}
328
}
329
330
static void
331
pap_local_authenticate(pap *_this, const char *username, const char *password)
332
{
333
	int lpassword0;
334
	char password0[MAX_PASSWORD_LENGTH];
335
336
	lpassword0 = sizeof(password0);
337
338
	if (npppd_get_user_password(_this->ppp->pppd, _this->ppp, username,
339
	    password0, &lpassword0) == 0) {
340
		if (!strcmp(password0, password)) {
341
			pap_response(_this, 1, DEFAULT_SUCCESS_MESSAGE);
342
			return;
343
		}
344
	}
345
	pap_response(_this, 0, DEFAULT_FAILURE_MESSAGE);
346
}
347
348
/***********************************************************************
349
 * Proxy Authentication
350
 ***********************************************************************/
351
int
352
pap_proxy_authen_prepare(pap *_this, dialin_proxy_info *dpi)
353
{
354
355
	PAP_ASSERT(dpi->auth_type == PPP_AUTH_PAP);
356
	PAP_ASSERT(_this->state == PAP_STATE_INITIAL);
357
358
	_this->auth_id = dpi->auth_id;
359
	if (strlen(dpi->username) >= sizeof(_this->name)) {
360
		pap_log(_this, LOG_NOTICE,
361
		    "\"Proxy Authen Name\" is too long.");
362
		return -1;
363
	}
364
365
	/* copy the authenticaiton properties */
366
	PAP_ASSERT(_this->ppp->proxy_authen_resp == NULL);
367
	if ((_this->ppp->proxy_authen_resp = malloc(dpi->lauth_resp + 1)) ==
368
	    NULL) {
369
		pap_log(_this, LOG_ERR, "malloc() failed in %s(): %m",
370
		    __func__);
371
		return -1;
372
	}
373
	memcpy(_this->ppp->proxy_authen_resp, dpi->auth_resp,
374
	    dpi->lauth_resp);
375
	_this->ppp->proxy_authen_resp[dpi->lauth_resp] = '\0';
376
	strlcpy(_this->name, dpi->username, sizeof(_this->name));
377
378
	_this->state = PAP_STATE_PROXY_AUTHENTICATION;
379
380
	return 0;
381
}
382
383
#ifdef USE_NPPPD_RADIUS
384
static void
385
pap_radius_authenticate(pap *_this, const char *username, const char *password)
386
{
387
	void *radctx;
388
	RADIUS_PACKET *radpkt;
389
	MD5_CTX md5ctx;
390
	int i, j, s_len, passlen;
391
	u_char ra[16], digest[16], pass[128];
392
	const char *s;
393
	radius_req_setting *rad_setting = NULL;
394
	char buf0[MAX_USERNAME_LENGTH];
395
396
	if ((rad_setting = npppd_get_radius_auth_setting(_this->ppp->pppd,
397
	    _this->ppp)) == NULL)
398
		goto fail;
399
400
	if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST))
401
	    == NULL)
402
		goto fail;
403
404
	if (radius_prepare(rad_setting, _this, &radctx, pap_radius_response)
405
	    != 0) {
406
		radius_delete_packet(radpkt);
407
		goto fail;
408
	}
409
410
	if (ppp_set_radius_attrs_for_authreq(_this->ppp, rad_setting, radpkt)
411
	    != 0)
412
		goto fail;
413
414
	if (radius_put_string_attr(radpkt, RADIUS_TYPE_USER_NAME,
415
	    npppd_ppp_get_username_for_auth(_this->ppp->pppd, _this->ppp,
416
	    username, buf0)) != 0)
417
		goto fail;
418
419
	if (_this->radctx != NULL)
420
		radius_cancel_request(_this->radctx);
421
422
	_this->radctx = radctx;
423
424
	/* Create RADIUS User-Password Attribute (RFC 2865, 5.2.) */
425
	s = radius_get_server_secret(_this->radctx);
426
	s_len = strlen(s);
427
428
	memset(pass, 0, sizeof(pass)); /* null padding */
429
	passlen = MINIMUM(strlen(password), sizeof(pass));
430
	memcpy(pass, password, passlen);
431
	if ((passlen % 16) != 0)
432
		passlen += 16 - (passlen % 16);
433
434
	radius_get_authenticator(radpkt, ra);
435
436
	MD5Init(&md5ctx);
437
	MD5Update(&md5ctx, s, s_len);
438
	MD5Update(&md5ctx, ra, 16);
439
	MD5Final(digest, &md5ctx);
440
441
	for (i = 0; i < 16; i++)
442
		pass[i] ^= digest[i];
443
444
	while (i < passlen) {
445
		MD5Init(&md5ctx);
446
		MD5Update(&md5ctx, s, s_len);
447
		MD5Update(&md5ctx, &pass[i - 16], 16);
448
		MD5Final(digest, &md5ctx);
449
450
		for (j = 0; j < 16; j++, i++)
451
			pass[i] ^= digest[j];
452
	}
453
454
	if (radius_put_raw_attr(radpkt, RADIUS_TYPE_USER_PASSWORD, pass,
455
	    passlen) != 0)
456
		goto fail;
457
458
	radius_request(_this->radctx, radpkt);
459
460
	return;
461
fail:
462
	if (_this->radctx != NULL)
463
		radius_cancel_request(_this->radctx);
464
	pap_log(_this, LOG_ERR, "%s() failed: %m", __func__);
465
	pap_response(_this, 0, DEFAULT_ERROR_MESSAGE);
466
467
	return;
468
}
469
470
static void
471
pap_radius_response(void *context, RADIUS_PACKET *pkt, int flags,
472
    RADIUS_REQUEST_CTX reqctx)
473
{
474
	int code = -1;
475
	const char *reason = NULL;
476
	RADIUS_REQUEST_CTX radctx;
477
	pap *_this;
478
479
	_this = context;
480
	radctx = _this->radctx;
481
	_this->radctx = NULL;	/* important */
482
483
	if (pkt == NULL) {
484
		if (flags & RADIUS_REQUEST_TIMEOUT)
485
			reason = "timeout";
486
		else if (flags & RADIUS_REQUEST_ERROR)
487
			reason = strerror(errno);
488
		else
489
			reason = "error";
490
		goto auth_failed;
491
	}
492
	code = radius_get_code(pkt);
493
	if (code == RADIUS_CODE_ACCESS_REJECT) {
494
		reason="reject";
495
		goto auth_failed;
496
	} else if (code != RADIUS_CODE_ACCESS_ACCEPT) {
497
		reason="error";
498
		goto auth_failed;
499
	}
500
	if ((flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_OK) == 0 &&
501
	    (flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_NO_CHECK) == 0) {
502
		reason="bad_authenticator";
503
		goto auth_failed;
504
	}
505
	/* Autentication succeeded */
506
	pap_response(_this, 1, DEFAULT_SUCCESS_MESSAGE);
507
	ppp_process_radius_framed_ip(_this->ppp, pkt);
508
509
	return;
510
auth_failed:
511
	/* Autentication failure */
512
	pap_log(_this, LOG_WARNING, "Radius authentication request failed: %s",
513
	    reason);
514
	/* log reply messages from radius server */
515
	if (pkt != NULL) {
516
		char radmsg[255], vissed[1024];
517
		size_t rmlen = 0;
518
		if ((radius_get_raw_attr(pkt, RADIUS_TYPE_REPLY_MESSAGE,
519
		    radmsg, &rmlen)) == 0) {
520
			if (rmlen != 0) {
521
				strvisx(vissed, radmsg, rmlen, VIS_WHITE);
522
				pap_log(_this, LOG_WARNING,
523
				    "Radius reply message: %s", vissed);
524
			}
525
		}
526
	}
527
528
	pap_response(_this, 0, DEFAULT_FAILURE_MESSAGE);
529
}
530
#endif