18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap-new.c - New CHAP implementation.
38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Copyright (c) 2003 Paul Mackerras. All rights reserved.
58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Redistribution and use in source and binary forms, with or without
78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * modification, are permitted provided that the following conditions
88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * are met:
98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * 2. The name(s) of the authors of this software must not be used to
148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *    endorse or promote products derived from this software without
158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *    prior written permission.
168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * 3. Redistributions of any form whatsoever must retain the following
188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *    acknowledgment:
198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *    "This product includes software developed by Paul Mackerras
208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *     <paulus@samba.org>".
218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
311286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#define RCSID	"$Id: chap-new.c,v 1.9 2007/06/19 02:08:35 carlsonj Exp $"
328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdlib.h>
348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <string.h>
358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "pppd.h"
361286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include "session.h"
378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "chap-new.h"
388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "chap-md5.h"
391286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#if defined(__ANDROID__)
40e7f221f12403dcb4081d08e28c54d3b2a1ab05eeChung-yih Wang#include "openssl-hash.h"
41e7f221f12403dcb4081d08e28c54d3b2a1ab05eeChung-yih Wang#endif
428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef CHAPMS
448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "chap_ms.h"
458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define MDTYPE_ALL (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5)
468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#else
478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define MDTYPE_ALL (MDTYPE_MD5)
488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint chap_mdtype_all = MDTYPE_ALL;
518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* Hook for a plugin to validate CHAP challenge */
538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint (*chap_verify_hook)(char *name, char *ourname, int id,
548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			struct chap_digest_type *digest,
558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			unsigned char *challenge, unsigned char *response,
568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			char *message, int message_space) = NULL;
578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Option variables.
608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint chap_timeout_time = 3;
628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint chap_max_transmits = 10;
638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint chap_rechallenge_time = 0;
648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Command-line options.
678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic option_t chap_option_list[] = {
698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{ "chap-restart", o_int, &chap_timeout_time,
708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	  "Set timeout for CHAP", OPT_PRIO },
718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{ "chap-max-challenge", o_int, &chap_max_transmits,
728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	  "Set max #xmits for challenge", OPT_PRIO },
738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{ "chap-interval", o_int, &chap_rechallenge_time,
748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	  "Set interval for rechallenge", OPT_PRIO },
758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{ NULL }
768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project};
778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Internal state.
808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic struct chap_client_state {
828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int flags;
838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char *name;
848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_digest_type *digest;
858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char priv[64];		/* private area for digest's use */
868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} client;
878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * These limits apply to challenge and response packets we send.
908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * The +4 is the +1 that we actually need rounded up.
918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define CHAL_MAX_PKTLEN	(PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN)
938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define RESP_MAX_PKTLEN	(PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN)
948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic struct chap_server_state {
968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int flags;
978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int id;
988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char *name;
998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_digest_type *digest;
1008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int challenge_xmits;
1018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int challenge_pktlen;
1028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char challenge[CHAL_MAX_PKTLEN];
1031286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley	char message[256];
1048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} server;
1058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* Values for flags in chap_client_state and chap_server_state */
1078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define LOWERUP			1
1088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define AUTH_STARTED		2
1098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define AUTH_DONE		4
1108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define AUTH_FAILED		8
1118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define TIMEOUT_PENDING		0x10
1128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#define CHALLENGE_VALID		0x20
1138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
1158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Prototypes.
1168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
1178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_init(int unit);
1188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_lowerup(int unit);
1198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_lowerdown(int unit);
1208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_timeout(void *arg);
1218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_generate_challenge(struct chap_server_state *ss);
1228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_handle_response(struct chap_server_state *ss, int code,
1238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		unsigned char *pkt, int len);
1248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic int chap_verify_response(char *name, char *ourname, int id,
1258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		struct chap_digest_type *digest,
1268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		unsigned char *challenge, unsigned char *response,
1278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		char *message, int message_space);
1288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_respond(struct chap_client_state *cs, int id,
1298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		unsigned char *pkt, int len);
1308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_handle_status(struct chap_client_state *cs, int code, int id,
1318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		unsigned char *pkt, int len);
1328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_protrej(int unit);
1338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void chap_input(int unit, unsigned char *pkt, int pktlen);
1348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic int chap_print_pkt(unsigned char *p, int plen,
1358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		void (*printer) __P((void *, char *, ...)), void *arg);
1368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* List of digest types that we know about */
1388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic struct chap_digest_type *chap_digests;
1398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
1418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_init - reset to initial state.
1428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
1438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
1448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_init(int unit)
1458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memset(&client, 0, sizeof(client));
1478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memset(&server, 0, sizeof(server));
1488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_md5_init();
1508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef CHAPMS
1518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chapms_init();
1528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
1538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
1568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Add a new digest type to the list.
1578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
1588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
1598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_register_digest(struct chap_digest_type *dp)
1608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	dp->next = chap_digests;
1628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_digests = dp;
1638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
1668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_lowerup - we can start doing stuff now.
1678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
1688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
1698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_lowerup(int unit)
1708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_client_state *cs = &client;
1728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_server_state *ss = &server;
1738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cs->flags |= LOWERUP;
1758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->flags |= LOWERUP;
1768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ss->flags & AUTH_STARTED)
1778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		chap_timeout(ss);
1788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
1818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_lowerdown(int unit)
1828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_client_state *cs = &client;
1848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_server_state *ss = &server;
1858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cs->flags = 0;
1878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ss->flags & TIMEOUT_PENDING)
1888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		UNTIMEOUT(chap_timeout, ss);
1898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->flags = 0;
1908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
1938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_auth_peer - Start authenticating the peer.
1948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * If the lower layer is already up, we start sending challenges,
1958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * otherwise we wait for the lower layer to come up.
1968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
1978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
1988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_auth_peer(int unit, char *our_name, int digest_code)
1998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_server_state *ss = &server;
2018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_digest_type *dp;
2028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ss->flags & AUTH_STARTED) {
2048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("CHAP: peer authentication already started!");
2058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
2068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	for (dp = chap_digests; dp != NULL; dp = dp->next)
2088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (dp->code == digest_code)
2098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			break;
2108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (dp == NULL)
2118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fatal("CHAP digest 0x%x requested but not available",
2128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		      digest_code);
2138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->digest = dp;
2158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->name = our_name;
2168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Start with a random ID value */
2178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->id = (unsigned char)(drand48() * 256);
2188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->flags |= AUTH_STARTED;
2198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ss->flags & LOWERUP)
2208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		chap_timeout(ss);
2218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
2228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
2248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_auth_with_peer - Prepare to authenticate ourselves to the peer.
2258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * There isn't much to do until we receive a challenge.
2268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
2278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
2288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_auth_with_peer(int unit, char *our_name, int digest_code)
2298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_client_state *cs = &client;
2318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_digest_type *dp;
2328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (cs->flags & AUTH_STARTED) {
2348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("CHAP: authentication with peer already started!");
2358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
2368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	for (dp = chap_digests; dp != NULL; dp = dp->next)
2388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (dp->code == digest_code)
2398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			break;
2408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (dp == NULL)
2418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fatal("CHAP digest 0x%x requested but not available",
2428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		      digest_code);
2438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cs->digest = dp;
2458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cs->name = our_name;
2468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cs->flags |= AUTH_STARTED;
2478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
2488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
2508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_timeout - It's time to send another challenge to the peer.
2518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * This could be either a retransmission of a previous challenge,
2528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * or a new challenge to start re-authentication.
2538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
2548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
2558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_timeout(void *arg)
2568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_server_state *ss = arg;
2588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->flags &= ~TIMEOUT_PENDING;
2608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((ss->flags & CHALLENGE_VALID) == 0) {
2618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ss->challenge_xmits = 0;
2628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		chap_generate_challenge(ss);
2638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ss->flags |= CHALLENGE_VALID;
2648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	} else if (ss->challenge_xmits >= chap_max_transmits) {
2658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ss->flags &= ~CHALLENGE_VALID;
2668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ss->flags |= AUTH_DONE | AUTH_FAILED;
2678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		auth_peer_fail(0, PPP_CHAP);
2688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
2698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	output(0, ss->challenge, ss->challenge_pktlen);
2728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	++ss->challenge_xmits;
2738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->flags |= TIMEOUT_PENDING;
2748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	TIMEOUT(chap_timeout, arg, chap_timeout_time);
2758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
2768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
2788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_generate_challenge - generate a challenge string and format
2798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * the challenge packet in ss->challenge_pkt.
2808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
2818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
2828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_generate_challenge(struct chap_server_state *ss)
2838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int clen = 1, nlen, len;
2858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char *p;
2868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p = ss->challenge;
2888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	MAKEHEADER(p, PPP_CHAP);
2898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p += CHAP_HDRLEN;
2908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->digest->generate_challenge(p);
2918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	clen = *p;
2928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	nlen = strlen(ss->name);
2938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(p + 1 + clen, ss->name, nlen);
2948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	len = CHAP_HDRLEN + 1 + clen + nlen;
2968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ss->challenge_pktlen = PPP_HDRLEN + len;
2978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p = ss->challenge + PPP_HDRLEN;
2998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[0] = CHAP_CHALLENGE;
3008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[1] = ++ss->id;
3018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[2] = len >> 8;
3028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[3] = len;
3038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
3048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
3068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_handle_response - check the response to our challenge.
3078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
3088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
3098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_handle_response(struct chap_server_state *ss, int id,
3108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		     unsigned char *pkt, int len)
3118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
3128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int response_len, ok, mlen;
3138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char *response, *p;
3148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char *name = NULL;	/* initialized to shut gcc up */
3158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int (*verifier)(char *, char *, int, struct chap_digest_type *,
3168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		unsigned char *, unsigned char *, char *, int);
3178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char rname[MAXNAMELEN+1];
3188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((ss->flags & LOWERUP) == 0)
3208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
3218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (id != ss->challenge[PPP_HDRLEN+1] || len < 2)
3228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
3231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley	if (ss->flags & CHALLENGE_VALID) {
3248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		response = pkt;
3258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		GETCHAR(response_len, pkt);
3268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		len -= response_len + 1;	/* length of name */
3278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		name = (char *)pkt + response_len;
3288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (len < 0)
3298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			return;
3308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (ss->flags & TIMEOUT_PENDING) {
3328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			ss->flags &= ~TIMEOUT_PENDING;
3338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			UNTIMEOUT(chap_timeout, ss);
3348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
3358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (explicit_remote) {
3378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			name = remote_name;
3388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		} else {
3398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			/* Null terminate and clean remote name. */
3408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			slprintf(rname, sizeof(rname), "%.*v", len, name);
3418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			name = rname;
3428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
3438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (chap_verify_hook)
3458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			verifier = chap_verify_hook;
3468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		else
3478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			verifier = chap_verify_response;
3488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ok = (*verifier)(name, ss->name, id, ss->digest,
3498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				 ss->challenge + PPP_HDRLEN + CHAP_HDRLEN,
3501286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley				 response, ss->message, sizeof(ss->message));
3518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (!ok || !auth_number()) {
3528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			ss->flags |= AUTH_FAILED;
3538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			warn("Peer %q failed CHAP authentication", name);
3548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
3551286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley	} else if ((ss->flags & AUTH_DONE) == 0)
3561286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		return;
3578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* send the response */
3598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p = outpacket_buf;
3608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	MAKEHEADER(p, PPP_CHAP);
3611286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley	mlen = strlen(ss->message);
3628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	len = CHAP_HDRLEN + mlen;
3638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[0] = (ss->flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS;
3648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[1] = id;
3658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[2] = len >> 8;
3668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[3] = len;
3678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (mlen > 0)
3681286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		memcpy(p + CHAP_HDRLEN, ss->message, mlen);
3698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	output(0, outpacket_buf, PPP_HDRLEN + len);
3708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3711286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley	if (ss->flags & CHALLENGE_VALID) {
3721286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		ss->flags &= ~CHALLENGE_VALID;
3731286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		if (!(ss->flags & AUTH_DONE) && !(ss->flags & AUTH_FAILED)) {
3741286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		    /*
3751286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		     * Auth is OK, so now we need to check session restrictions
3761286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		     * to ensure everything is OK, but only if we used a
3771286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		     * plugin, and only if we're configured to check.  This
3781286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		     * allows us to do PAM checks on PPP servers that
3791286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		     * authenticate against ActiveDirectory, and use AD for
3801286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		     * account info (like when using Winbind integrated with
3811286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		     * PAM).
3821286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		     */
3831286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		    if (session_mgmt &&
3841286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley			session_check(name, NULL, devnam, NULL) == 0) {
3851286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley			ss->flags |= AUTH_FAILED;
3861286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley			warn("Peer %q failed CHAP Session verification", name);
3871286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		    }
3881286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		}
3898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (ss->flags & AUTH_FAILED) {
3908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			auth_peer_fail(0, PPP_CHAP);
3918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		} else {
3921286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley			if ((ss->flags & AUTH_DONE) == 0)
3931286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley				auth_peer_success(0, PPP_CHAP,
3941286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley						  ss->digest->code,
3951286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley						  name, strlen(name));
3968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			if (chap_rechallenge_time) {
3978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				ss->flags |= TIMEOUT_PENDING;
3988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				TIMEOUT(chap_timeout, ss,
3998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project					chap_rechallenge_time);
4008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			}
4018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
4021286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		ss->flags |= AUTH_DONE;
4038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
4058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
4078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_verify_response - check whether the peer's response matches
4088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * what we think it should be.  Returns 1 if it does (authentication
4098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * succeeded), or 0 if it doesn't.
4108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
4118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic int
4128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_verify_response(char *name, char *ourname, int id,
4138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		     struct chap_digest_type *digest,
4148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		     unsigned char *challenge, unsigned char *response,
4158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		     char *message, int message_space)
4168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
4178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int ok;
4188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char secret[MAXSECRETLEN];
4198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int secret_len;
4208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Get the secret that the peer is supposed to know */
4228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) {
4238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("No CHAP secret found for authenticating %q", name);
4248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return 0;
4258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	ok = digest->verify_response(id, name, secret, secret_len, challenge,
4288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				     response, message, message_space);
4298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memset(secret, 0, sizeof(secret));
4308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return ok;
4328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
4338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
4358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_respond - Generate and send a response to a challenge.
4368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
4378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
4388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_respond(struct chap_client_state *cs, int id,
4398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	     unsigned char *pkt, int len)
4408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
4418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int clen, nlen;
4428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int secret_len;
4438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char *p;
4448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char response[RESP_MAX_PKTLEN];
4458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char rname[MAXNAMELEN+1];
4468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char secret[MAXSECRETLEN+1];
4478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((cs->flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED))
4498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;		/* not ready */
4508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (len < 2 || len < pkt[0] + 1)
4518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;		/* too short */
4528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	clen = pkt[0];
4538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	nlen = len - (clen + 1);
4548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Null terminate and clean remote name. */
4568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1);
4578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Microsoft doesn't send their name back in the PPP packet */
4598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (explicit_remote || (remote_name[0] != 0 && rname[0] == 0))
4608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		strlcpy(rname, remote_name, sizeof(rname));
4618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* get secret for authenticating ourselves with the specified host */
4638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (!get_secret(0, cs->name, rname, secret, &secret_len, 0)) {
4648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		secret_len = 0;	/* assume null secret if can't find one */
4658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		warn("No CHAP secret found for authenticating us to %q", rname);
4668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p = response;
4698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	MAKEHEADER(p, PPP_CHAP);
4708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p += CHAP_HDRLEN;
4718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cs->digest->make_response(p, id, cs->name, pkt,
4738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				  secret, secret_len, cs->priv);
4748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memset(secret, 0, secret_len);
4758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	clen = *p;
4778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	nlen = strlen(cs->name);
4788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(p + clen + 1, cs->name, nlen);
4798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p = response + PPP_HDRLEN;
4818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	len = CHAP_HDRLEN + clen + 1 + nlen;
4828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[0] = CHAP_RESPONSE;
4838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[1] = id;
4848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[2] = len >> 8;
4858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p[3] = len;
4868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	output(0, response, PPP_HDRLEN + len);
4888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
4898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
4918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_handle_status(struct chap_client_state *cs, int code, int id,
4928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   unsigned char *pkt, int len)
4938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
4948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	const char *msg = NULL;
4958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((cs->flags & (AUTH_DONE|AUTH_STARTED|LOWERUP))
4978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    != (AUTH_STARTED|LOWERUP))
4988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
4998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cs->flags |= AUTH_DONE;
5008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (code == CHAP_SUCCESS) {
5028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/* used for MS-CHAP v2 mutual auth, yuck */
5038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (cs->digest->check_success != NULL) {
5041286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley			if (!(*cs->digest->check_success)(id, pkt, len))
5058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				code = CHAP_FAILURE;
5068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		} else
5078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			msg = "CHAP authentication succeeded";
5088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	} else {
5098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (cs->digest->handle_failure != NULL)
5108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			(*cs->digest->handle_failure)(pkt, len);
5118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		else
5128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			msg = "CHAP authentication failed";
5138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (msg) {
5158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (len > 0)
5168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			info("%s: %.*v", msg, len, pkt);
5178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		else
5188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			info("%s", msg);
5198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (code == CHAP_SUCCESS)
5218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		auth_withpeer_success(0, PPP_CHAP, cs->digest->code);
5228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	else {
5238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		cs->flags |= AUTH_FAILED;
5241286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		error("CHAP authentication failed");
5258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		auth_withpeer_fail(0, PPP_CHAP);
5268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
5288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
5308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_input(int unit, unsigned char *pkt, int pktlen)
5318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
5328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_client_state *cs = &client;
5338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_server_state *ss = &server;
5348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char code, id;
5358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int len;
5368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (pktlen < CHAP_HDRLEN)
5388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
5398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	GETCHAR(code, pkt);
5408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	GETCHAR(id, pkt);
5418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	GETSHORT(len, pkt);
5428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (len < CHAP_HDRLEN || len > pktlen)
5438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
5448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	len -= CHAP_HDRLEN;
5458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	switch (code) {
5478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case CHAP_CHALLENGE:
5488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		chap_respond(cs, id, pkt, len);
5498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		break;
5508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case CHAP_RESPONSE:
5518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		chap_handle_response(ss, id, pkt, len);
5528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		break;
5538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case CHAP_FAILURE:
5548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case CHAP_SUCCESS:
5558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		chap_handle_status(cs, code, id, pkt, len);
5568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		break;
5578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
5598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
5618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_protrej(int unit)
5628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
5638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_client_state *cs = &client;
5648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct chap_server_state *ss = &server;
5658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ss->flags & TIMEOUT_PENDING) {
5678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ss->flags &= ~TIMEOUT_PENDING;
5688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		UNTIMEOUT(chap_timeout, ss);
5698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ss->flags & AUTH_STARTED) {
5718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		ss->flags = 0;
5728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		auth_peer_fail(0, PPP_CHAP);
5738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((cs->flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) {
5758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		cs->flags &= ~AUTH_STARTED;
5761286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley		error("CHAP authentication failed due to protocol-reject");
5778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		auth_withpeer_fail(0, PPP_CHAP);
5788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
5808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
5828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * chap_print_pkt - print the contents of a CHAP packet.
5838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
5848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic char *chap_code_names[] = {
5858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	"Challenge", "Response", "Success", "Failure"
5868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project};
5878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic int
5898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchap_print_pkt(unsigned char *p, int plen,
5908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	       void (*printer) __P((void *, char *, ...)), void *arg)
5918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
5928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int code, id, len;
5938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int clen, nlen;
5948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char x;
5958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (plen < CHAP_HDRLEN)
5978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return 0;
5988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	GETCHAR(code, p);
5998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	GETCHAR(id, p);
6008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	GETSHORT(len, p);
6018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (len < CHAP_HDRLEN || len > plen)
6028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return 0;
6038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (code >= 1 && code <= sizeof(chap_code_names) / sizeof(char *))
6058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printer(arg, " %s", chap_code_names[code-1]);
6068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	else
6078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printer(arg, " code=0x%x", code);
6088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	printer(arg, " id=0x%x", id);
6098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	len -= CHAP_HDRLEN;
6108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	switch (code) {
6118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case CHAP_CHALLENGE:
6128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case CHAP_RESPONSE:
6138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (len < 1)
6148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			break;
6158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		clen = p[0];
6168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (len < clen + 1)
6178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			break;
6188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		++p;
6198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		nlen = len - clen - 1;
6208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printer(arg, " <");
6218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		for (; clen > 0; --clen) {
6228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			GETCHAR(x, p);
6238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			printer(arg, "%.2x", x);
6248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
6258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printer(arg, ">, name = ");
6268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		print_string((char *)p, nlen, printer, arg);
6278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		break;
6288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case CHAP_FAILURE:
6298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case CHAP_SUCCESS:
6308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printer(arg, " ");
6318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		print_string((char *)p, len, printer, arg);
6328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		break;
6338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	default:
6348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		for (clen = len; clen > 0; --clen) {
6358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			GETCHAR(x, p);
6368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			printer(arg, " %.2x", x);
6378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
6388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
6398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return len + CHAP_HDRLEN;
6418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
6428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstruct protent chap_protent = {
6448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	PPP_CHAP,
6458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_init,
6468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_input,
6478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_protrej,
6488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_lowerup,
6498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_lowerdown,
6508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	NULL,		/* open */
6518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	NULL,		/* close */
6528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_print_pkt,
6538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	NULL,		/* datainput */
6548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	1,		/* enabled_flag */
6558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	"CHAP",		/* name */
6568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	NULL,		/* data_name */
6578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	chap_option_list,
6588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	NULL,		/* check_options */
6598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project};
660