xref: /openbsd-src/usr.sbin/npppd/npppd/pap.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
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
531