Home | History | Annotate | Line # | Download | only in pppd
eap.c revision 1.1.1.5
      1      1.1  christos /*
      2      1.1  christos  * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
      3      1.1  christos  *
      4      1.1  christos  * Copyright (c) 2001 by Sun Microsystems, Inc.
      5      1.1  christos  * All rights reserved.
      6      1.1  christos  *
      7      1.1  christos  * Non-exclusive rights to redistribute, modify, translate, and use
      8      1.1  christos  * this software in source and binary forms, in whole or in part, is
      9      1.1  christos  * hereby granted, provided that the above copyright notice is
     10      1.1  christos  * duplicated in any source form, and that neither the name of the
     11      1.1  christos  * copyright holder nor the author is used to endorse or promote
     12      1.1  christos  * products derived from this software.
     13      1.1  christos  *
     14      1.1  christos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     15      1.1  christos  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     16      1.1  christos  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     17      1.1  christos  *
     18      1.1  christos  * Original version by James Carlson
     19      1.1  christos  *
     20      1.1  christos  * This implementation of EAP supports MD5-Challenge and SRP-SHA1
     21      1.1  christos  * authentication styles.  Note that support of MD5-Challenge is a
     22      1.1  christos  * requirement of RFC 2284, and that it's essentially just a
     23      1.1  christos  * reimplementation of regular RFC 1994 CHAP using EAP messages.
     24      1.1  christos  *
     25      1.1  christos  * As an authenticator ("server"), there are multiple phases for each
     26      1.1  christos  * style.  In the first phase of each style, the unauthenticated peer
     27      1.1  christos  * name is queried using the EAP Identity request type.  If the
     28      1.1  christos  * "remotename" option is used, then this phase is skipped, because
     29      1.1  christos  * the peer's name is presumed to be known.
     30      1.1  christos  *
     31      1.1  christos  * For MD5-Challenge, there are two phases, and the second phase
     32      1.1  christos  * consists of sending the challenge itself and handling the
     33      1.1  christos  * associated response.
     34      1.1  christos  *
     35      1.1  christos  * For SRP-SHA1, there are four phases.  The second sends 's', 'N',
     36      1.1  christos  * and 'g'.  The reply contains 'A'.  The third sends 'B', and the
     37      1.1  christos  * reply contains 'M1'.  The forth sends the 'M2' value.
     38      1.1  christos  *
     39      1.1  christos  * As an authenticatee ("client"), there's just a single phase --
     40      1.1  christos  * responding to the queries generated by the peer.  EAP is an
     41      1.1  christos  * authenticator-driven protocol.
     42      1.1  christos  *
     43      1.1  christos  * Based on draft-ietf-pppext-eap-srp-03.txt.
     44      1.1  christos  */
     45      1.1  christos 
     46      1.1  christos /*
     47  1.1.1.4  christos  * Modification by Beniamino Galvani, Mar 2005
     48  1.1.1.4  christos  * Implemented EAP-TLS authentication
     49      1.1  christos  */
     50      1.1  christos 
     51  1.1.1.5  christos #ifdef HAVE_CONFIG_H
     52  1.1.1.5  christos #include "config.h"
     53  1.1.1.5  christos #endif
     54  1.1.1.5  christos 
     55      1.1  christos #include <stdio.h>
     56      1.1  christos #include <stdlib.h>
     57      1.1  christos #include <string.h>
     58      1.1  christos #include <unistd.h>
     59      1.1  christos #include <pwd.h>
     60      1.1  christos #include <sys/types.h>
     61      1.1  christos #include <sys/stat.h>
     62      1.1  christos #include <fcntl.h>
     63      1.1  christos #include <assert.h>
     64      1.1  christos #include <errno.h>
     65      1.1  christos 
     66  1.1.1.5  christos #include "pppd-private.h"
     67  1.1.1.5  christos #include "options.h"
     68      1.1  christos #include "pathnames.h"
     69  1.1.1.5  christos #include "crypto.h"
     70  1.1.1.5  christos #include "crypto_ms.h"
     71      1.1  christos #include "eap.h"
     72  1.1.1.5  christos #ifdef PPP_WITH_PEAP
     73  1.1.1.5  christos #include "peap.h"
     74  1.1.1.5  christos #endif /* PPP_WITH_PEAP */
     75  1.1.1.5  christos 
     76  1.1.1.5  christos #ifdef PPP_WITH_SRP
     77  1.1.1.5  christos #ifdef HAVE_TIME_H
     78  1.1.1.5  christos #include <time.h>
     79  1.1.1.4  christos #endif
     80      1.1  christos #include <t_pwd.h>
     81      1.1  christos #include <t_server.h>
     82      1.1  christos #include <t_client.h>
     83  1.1.1.5  christos #endif /* PPP_WITH_SRP */
     84      1.1  christos 
     85  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
     86  1.1.1.4  christos #include "eap-tls.h"
     87  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
     88  1.1.1.5  christos 
     89  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
     90  1.1.1.5  christos #include "chap.h"
     91  1.1.1.4  christos #include "chap_ms.h"
     92  1.1.1.5  christos 
     93  1.1.1.5  christos extern int chapms_strip_domain;
     94  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
     95      1.1  christos 
     96      1.1  christos eap_state eap_states[NUM_PPP];		/* EAP state; one for each unit */
     97  1.1.1.5  christos #ifdef PPP_WITH_SRP
     98      1.1  christos static char *pn_secret = NULL;		/* Pseudonym generating secret */
     99      1.1  christos #endif
    100      1.1  christos 
    101      1.1  christos /*
    102      1.1  christos  * Command-line options.
    103      1.1  christos  */
    104  1.1.1.5  christos static struct option eap_option_list[] = {
    105      1.1  christos     { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
    106      1.1  christos       "Set retransmit timeout for EAP Requests (server)" },
    107      1.1  christos     { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
    108      1.1  christos       "Set max number of EAP Requests sent (server)" },
    109      1.1  christos     { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
    110      1.1  christos       "Set time limit for peer EAP authentication" },
    111      1.1  christos     { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
    112      1.1  christos       "Set max number of EAP Requests allows (client)" },
    113      1.1  christos     { "eap-interval", o_int, &eap_states[0].es_rechallenge,
    114      1.1  christos       "Set interval for EAP rechallenge" },
    115  1.1.1.5  christos #ifdef PPP_WITH_SRP
    116      1.1  christos     { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
    117      1.1  christos       "Set interval for SRP lightweight rechallenge" },
    118      1.1  christos     { "srp-pn-secret", o_string, &pn_secret,
    119      1.1  christos       "Long term pseudonym generation secret" },
    120      1.1  christos     { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
    121      1.1  christos       "Use pseudonym if offered one by server", 1 },
    122      1.1  christos #endif
    123      1.1  christos     { NULL }
    124      1.1  christos };
    125      1.1  christos 
    126      1.1  christos /*
    127      1.1  christos  * Protocol entry points.
    128      1.1  christos  */
    129  1.1.1.4  christos static void eap_init (int unit);
    130  1.1.1.4  christos static void eap_input (int unit, u_char *inp, int inlen);
    131  1.1.1.4  christos static void eap_protrej (int unit);
    132  1.1.1.4  christos static void eap_lowerup (int unit);
    133  1.1.1.4  christos static void eap_lowerdown (int unit);
    134  1.1.1.4  christos static int  eap_printpkt (u_char *inp, int inlen,
    135  1.1.1.4  christos     void (*)(void *arg, char *fmt, ...), void *arg);
    136      1.1  christos 
    137      1.1  christos struct protent eap_protent = {
    138      1.1  christos 	PPP_EAP,		/* protocol number */
    139      1.1  christos 	eap_init,		/* initialization procedure */
    140      1.1  christos 	eap_input,		/* process a received packet */
    141      1.1  christos 	eap_protrej,		/* process a received protocol-reject */
    142      1.1  christos 	eap_lowerup,		/* lower layer has gone up */
    143      1.1  christos 	eap_lowerdown,		/* lower layer has gone down */
    144      1.1  christos 	NULL,			/* open the protocol */
    145      1.1  christos 	NULL,			/* close the protocol */
    146      1.1  christos 	eap_printpkt,		/* print a packet in readable form */
    147      1.1  christos 	NULL,			/* process a received data packet */
    148      1.1  christos 	1,			/* protocol enabled */
    149      1.1  christos 	"EAP",			/* text name of protocol */
    150      1.1  christos 	NULL,			/* text name of corresponding data protocol */
    151      1.1  christos 	eap_option_list,	/* list of command-line options */
    152      1.1  christos 	NULL,			/* check requested options; assign defaults */
    153      1.1  christos 	NULL,			/* configure interface for demand-dial */
    154      1.1  christos 	NULL			/* say whether to bring up link for this pkt */
    155      1.1  christos };
    156      1.1  christos 
    157  1.1.1.5  christos #ifdef PPP_WITH_SRP
    158      1.1  christos /*
    159      1.1  christos  * A well-known 2048 bit modulus.
    160      1.1  christos  */
    161      1.1  christos static const u_char wkmodulus[] = {
    162      1.1  christos 	0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
    163      1.1  christos 	0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
    164      1.1  christos 	0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
    165      1.1  christos 	0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
    166      1.1  christos 	0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
    167      1.1  christos 	0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
    168      1.1  christos 	0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
    169      1.1  christos 	0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
    170      1.1  christos 	0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
    171      1.1  christos 	0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
    172      1.1  christos 	0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
    173      1.1  christos 	0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
    174      1.1  christos 	0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
    175      1.1  christos 	0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
    176      1.1  christos 	0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
    177      1.1  christos 	0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
    178      1.1  christos 	0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
    179      1.1  christos 	0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
    180      1.1  christos 	0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
    181      1.1  christos 	0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
    182      1.1  christos 	0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
    183      1.1  christos 	0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
    184      1.1  christos 	0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
    185      1.1  christos 	0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
    186      1.1  christos 	0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
    187      1.1  christos 	0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
    188      1.1  christos 	0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
    189      1.1  christos 	0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
    190      1.1  christos 	0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
    191      1.1  christos 	0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
    192      1.1  christos 	0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
    193      1.1  christos 	0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
    194      1.1  christos };
    195  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    196      1.1  christos 
    197      1.1  christos /* Local forward declarations. */
    198  1.1.1.4  christos static void eap_server_timeout (void *arg);
    199      1.1  christos 
    200      1.1  christos /*
    201      1.1  christos  * Convert EAP state code to printable string for debug.
    202      1.1  christos  */
    203      1.1  christos static const char *
    204  1.1.1.4  christos eap_state_name(enum eap_state_code esc)
    205      1.1  christos {
    206      1.1  christos 	static const char *state_names[] = { EAP_STATES };
    207      1.1  christos 
    208      1.1  christos 	return (state_names[(int)esc]);
    209      1.1  christos }
    210      1.1  christos 
    211      1.1  christos /*
    212      1.1  christos  * eap_init - Initialize state for an EAP user.  This is currently
    213      1.1  christos  * called once by main() during start-up.
    214      1.1  christos  */
    215      1.1  christos static void
    216  1.1.1.4  christos eap_init(int unit)
    217      1.1  christos {
    218      1.1  christos 	eap_state *esp = &eap_states[unit];
    219      1.1  christos 
    220      1.1  christos 	BZERO(esp, sizeof (*esp));
    221      1.1  christos 	esp->es_unit = unit;
    222      1.1  christos 	esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
    223      1.1  christos 	esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
    224      1.1  christos 	esp->es_server.ea_id = (u_char)(drand48() * 0x100);
    225      1.1  christos 	esp->es_client.ea_timeout = EAP_DEFREQTIME;
    226      1.1  christos 	esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
    227  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
    228  1.1.1.4  christos 	esp->es_client.ea_using_eaptls = 0;
    229  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
    230  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
    231  1.1.1.5  christos 	esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2);
    232  1.1.1.5  christos 	esp->es_server.digest = chap_find_digest(CHAP_MICROSOFT_V2);
    233  1.1.1.4  christos #endif
    234      1.1  christos }
    235      1.1  christos 
    236      1.1  christos /*
    237      1.1  christos  * eap_client_timeout - Give up waiting for the peer to send any
    238      1.1  christos  * Request messages.
    239      1.1  christos  */
    240      1.1  christos static void
    241  1.1.1.4  christos eap_client_timeout(void *arg)
    242      1.1  christos {
    243      1.1  christos 	eap_state *esp = (eap_state *) arg;
    244      1.1  christos 
    245      1.1  christos 	if (!eap_client_active(esp))
    246      1.1  christos 		return;
    247      1.1  christos 
    248      1.1  christos 	error("EAP: timeout waiting for Request from peer");
    249      1.1  christos 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
    250      1.1  christos 	esp->es_client.ea_state = eapBadAuth;
    251      1.1  christos }
    252      1.1  christos 
    253      1.1  christos /*
    254      1.1  christos  * eap_authwithpeer - Authenticate to our peer (behave as client).
    255      1.1  christos  *
    256      1.1  christos  * Start client state and wait for requests.  This is called only
    257      1.1  christos  * after eap_lowerup.
    258      1.1  christos  */
    259      1.1  christos void
    260  1.1.1.4  christos eap_authwithpeer(int unit, char *localname)
    261      1.1  christos {
    262      1.1  christos 	eap_state *esp = &eap_states[unit];
    263      1.1  christos 
    264      1.1  christos 	/* Save the peer name we're given */
    265      1.1  christos 	esp->es_client.ea_name = localname;
    266      1.1  christos 	esp->es_client.ea_namelen = strlen(localname);
    267      1.1  christos 
    268      1.1  christos 	esp->es_client.ea_state = eapListen;
    269      1.1  christos 
    270      1.1  christos 	/*
    271      1.1  christos 	 * Start a timer so that if the other end just goes
    272      1.1  christos 	 * silent, we don't sit here waiting forever.
    273      1.1  christos 	 */
    274      1.1  christos 	if (esp->es_client.ea_timeout > 0)
    275      1.1  christos 		TIMEOUT(eap_client_timeout, (void *)esp,
    276      1.1  christos 		    esp->es_client.ea_timeout);
    277      1.1  christos }
    278      1.1  christos 
    279      1.1  christos /*
    280      1.1  christos  * Format a standard EAP Failure message and send it to the peer.
    281      1.1  christos  * (Server operation)
    282      1.1  christos  */
    283      1.1  christos static void
    284  1.1.1.4  christos eap_send_failure(eap_state *esp)
    285      1.1  christos {
    286      1.1  christos 	u_char *outp;
    287      1.1  christos 
    288      1.1  christos 	outp = outpacket_buf;
    289      1.1  christos 
    290      1.1  christos 	MAKEHEADER(outp, PPP_EAP);
    291      1.1  christos 
    292      1.1  christos 	PUTCHAR(EAP_FAILURE, outp);
    293      1.1  christos 	esp->es_server.ea_id++;
    294      1.1  christos 	PUTCHAR(esp->es_server.ea_id, outp);
    295      1.1  christos 	PUTSHORT(EAP_HEADERLEN, outp);
    296      1.1  christos 
    297      1.1  christos 	output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
    298      1.1  christos 
    299      1.1  christos 	esp->es_server.ea_state = eapBadAuth;
    300      1.1  christos 	auth_peer_fail(esp->es_unit, PPP_EAP);
    301      1.1  christos }
    302      1.1  christos 
    303      1.1  christos /*
    304      1.1  christos  * Format a standard EAP Success message and send it to the peer.
    305      1.1  christos  * (Server operation)
    306      1.1  christos  */
    307      1.1  christos static void
    308  1.1.1.4  christos eap_send_success(eap_state *esp)
    309      1.1  christos {
    310      1.1  christos 	u_char *outp;
    311      1.1  christos 
    312      1.1  christos 	outp = outpacket_buf;
    313      1.1  christos 
    314      1.1  christos 	MAKEHEADER(outp, PPP_EAP);
    315      1.1  christos 
    316      1.1  christos 	PUTCHAR(EAP_SUCCESS, outp);
    317      1.1  christos 	esp->es_server.ea_id++;
    318      1.1  christos 	PUTCHAR(esp->es_server.ea_id, outp);
    319      1.1  christos 	PUTSHORT(EAP_HEADERLEN, outp);
    320      1.1  christos 
    321      1.1  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
    322      1.1  christos 
    323      1.1  christos 	auth_peer_success(esp->es_unit, PPP_EAP, 0,
    324      1.1  christos 	    esp->es_server.ea_peer, esp->es_server.ea_peerlen);
    325      1.1  christos }
    326      1.1  christos 
    327  1.1.1.5  christos #ifdef PPP_WITH_SRP
    328      1.1  christos /*
    329      1.1  christos  * Set DES key according to pseudonym-generating secret and current
    330      1.1  christos  * date.
    331      1.1  christos  */
    332      1.1  christos static bool
    333  1.1.1.5  christos pncrypt_getkey(int timeoffs, unsigned char *key, int keylen)
    334      1.1  christos {
    335      1.1  christos 	struct tm *tp;
    336      1.1  christos 	char tbuf[9];
    337  1.1.1.5  christos 	PPP_MD_CTX *ctxt;
    338      1.1  christos 	time_t reftime;
    339      1.1  christos 
    340      1.1  christos 	if (pn_secret == NULL)
    341      1.1  christos 		return (0);
    342      1.1  christos 	reftime = time(NULL) + timeoffs;
    343      1.1  christos 	tp = localtime(&reftime);
    344  1.1.1.5  christos 
    345  1.1.1.5  christos 	ctxt = PPP_MD_CTX_new();
    346  1.1.1.5  christos 	if (ctxt) {
    347  1.1.1.5  christos 
    348  1.1.1.5  christos 	    strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
    349  1.1.1.5  christos 
    350  1.1.1.5  christos 	    PPP_DigestInit(ctxt, PPP_sha1());
    351  1.1.1.5  christos 	    PPP_DigestUpdate(ctxt, pn_secret, strlen(pn_secret));
    352  1.1.1.5  christos 	    PPP_DigestUpdate(ctxt, tbuf, strlen(tbuf));
    353  1.1.1.5  christos 	    PPP_DigestFinal(ctxt, key, &keylen);
    354  1.1.1.5  christos 
    355  1.1.1.5  christos 	    PPP_MD_CTX_free(ctxt);
    356  1.1.1.5  christos 	    return 1;
    357  1.1.1.5  christos 	}
    358  1.1.1.5  christos 
    359  1.1.1.5  christos 	return (0);
    360      1.1  christos }
    361      1.1  christos 
    362      1.1  christos static char base64[] =
    363      1.1  christos "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    364      1.1  christos 
    365      1.1  christos struct b64state {
    366      1.1  christos 	u_int32_t bs_bits;
    367      1.1  christos 	int bs_offs;
    368      1.1  christos };
    369      1.1  christos 
    370      1.1  christos static int
    371  1.1.1.4  christos b64enc(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
    372      1.1  christos {
    373      1.1  christos 	int outlen = 0;
    374      1.1  christos 
    375      1.1  christos 	while (inlen > 0) {
    376      1.1  christos 		bs->bs_bits = (bs->bs_bits << 8) | *inp++;
    377      1.1  christos 		inlen--;
    378      1.1  christos 		bs->bs_offs += 8;
    379      1.1  christos 		if (bs->bs_offs >= 24) {
    380      1.1  christos 			*outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
    381      1.1  christos 			*outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
    382      1.1  christos 			*outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
    383      1.1  christos 			*outp++ = base64[bs->bs_bits & 0x3F];
    384      1.1  christos 			outlen += 4;
    385      1.1  christos 			bs->bs_offs = 0;
    386      1.1  christos 			bs->bs_bits = 0;
    387      1.1  christos 		}
    388      1.1  christos 	}
    389      1.1  christos 	return (outlen);
    390      1.1  christos }
    391      1.1  christos 
    392      1.1  christos static int
    393  1.1.1.4  christos b64flush(struct b64state *bs, u_char *outp)
    394      1.1  christos {
    395      1.1  christos 	int outlen = 0;
    396      1.1  christos 
    397      1.1  christos 	if (bs->bs_offs == 8) {
    398      1.1  christos 		*outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
    399      1.1  christos 		*outp++ = base64[(bs->bs_bits << 4) & 0x3F];
    400      1.1  christos 		outlen = 2;
    401      1.1  christos 	} else if (bs->bs_offs == 16) {
    402      1.1  christos 		*outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
    403      1.1  christos 		*outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
    404      1.1  christos 		*outp++ = base64[(bs->bs_bits << 2) & 0x3F];
    405      1.1  christos 		outlen = 3;
    406      1.1  christos 	}
    407      1.1  christos 	bs->bs_offs = 0;
    408      1.1  christos 	bs->bs_bits = 0;
    409      1.1  christos 	return (outlen);
    410      1.1  christos }
    411      1.1  christos 
    412      1.1  christos static int
    413  1.1.1.4  christos b64dec(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
    414      1.1  christos {
    415      1.1  christos 	int outlen = 0;
    416      1.1  christos 	char *cp;
    417      1.1  christos 
    418      1.1  christos 	while (inlen > 0) {
    419      1.1  christos 		if ((cp = strchr(base64, *inp++)) == NULL)
    420      1.1  christos 			break;
    421      1.1  christos 		bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
    422      1.1  christos 		inlen--;
    423      1.1  christos 		bs->bs_offs += 6;
    424      1.1  christos 		if (bs->bs_offs >= 8) {
    425      1.1  christos 			*outp++ = bs->bs_bits >> (bs->bs_offs - 8);
    426      1.1  christos 			outlen++;
    427      1.1  christos 			bs->bs_offs -= 8;
    428      1.1  christos 		}
    429      1.1  christos 	}
    430      1.1  christos 	return (outlen);
    431      1.1  christos }
    432  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    433      1.1  christos 
    434      1.1  christos /*
    435      1.1  christos  * Assume that current waiting server state is complete and figure
    436      1.1  christos  * next state to use based on available authentication data.  'status'
    437      1.1  christos  * indicates if there was an error in handling the last query.  It is
    438      1.1  christos  * 0 for success and non-zero for failure.
    439      1.1  christos  */
    440      1.1  christos static void
    441  1.1.1.4  christos eap_figure_next_state(eap_state *esp, int status)
    442      1.1  christos {
    443  1.1.1.5  christos #ifdef PPP_WITH_SRP
    444  1.1.1.5  christos 	unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp, key[SHA_DIGEST_LENGTH];
    445      1.1  christos 	struct t_pw tpw;
    446      1.1  christos 	struct t_confent *tce, mytce;
    447      1.1  christos 	char *cp, *cp2;
    448      1.1  christos 	struct t_server *ts;
    449  1.1.1.5  christos 	int id, i, plen, clen, toffs, keylen;
    450      1.1  christos 	u_char vals[2];
    451      1.1  christos 	struct b64state bs;
    452  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    453  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
    454  1.1.1.4  christos 	struct eaptls_session *ets;
    455  1.1.1.4  christos 	int secret_len;
    456  1.1.1.4  christos 	char secret[MAXWORDLEN];
    457  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
    458      1.1  christos 
    459      1.1  christos 	esp->es_server.ea_timeout = esp->es_savedtime;
    460  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
    461  1.1.1.4  christos 	esp->es_server.ea_prev_state = esp->es_server.ea_state;
    462  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
    463      1.1  christos 	switch (esp->es_server.ea_state) {
    464      1.1  christos 	case eapBadAuth:
    465      1.1  christos 		return;
    466      1.1  christos 
    467      1.1  christos 	case eapIdentify:
    468  1.1.1.5  christos #ifdef PPP_WITH_SRP
    469      1.1  christos 		/* Discard any previous session. */
    470      1.1  christos 		ts = (struct t_server *)esp->es_server.ea_session;
    471      1.1  christos 		if (ts != NULL) {
    472      1.1  christos 			t_serverclose(ts);
    473      1.1  christos 			esp->es_server.ea_session = NULL;
    474      1.1  christos 			esp->es_server.ea_skey = NULL;
    475      1.1  christos 		}
    476  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    477      1.1  christos 		if (status != 0) {
    478      1.1  christos 			esp->es_server.ea_state = eapBadAuth;
    479      1.1  christos 			break;
    480      1.1  christos 		}
    481  1.1.1.5  christos #ifdef PPP_WITH_SRP
    482      1.1  christos 		/* If we've got a pseudonym, try to decode to real name. */
    483      1.1  christos 		if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
    484      1.1  christos 		    strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
    485      1.1  christos 			SRP_PSEUDO_LEN) == 0 &&
    486      1.1  christos 		    (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
    487      1.1  christos 		    sizeof (secbuf)) {
    488      1.1  christos 			BZERO(&bs, sizeof (bs));
    489      1.1  christos 			plen = b64dec(&bs,
    490      1.1  christos 			    esp->es_server.ea_peer + SRP_PSEUDO_LEN,
    491      1.1  christos 			    esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
    492      1.1  christos 			    secbuf);
    493      1.1  christos 			toffs = 0;
    494      1.1  christos 			for (i = 0; i < 5; i++) {
    495  1.1.1.5  christos 				pncrypt_getkey(toffs, key, keylen);
    496      1.1  christos 				toffs -= 86400;
    497  1.1.1.5  christos 
    498  1.1.1.5  christos 				if (!DesDecrypt(secbuf, key, clear)) {
    499      1.1  christos 					dbglog("no DES here; cannot decode "
    500  1.1.1.5  christos 						"pseudonym");
    501      1.1  christos 					return;
    502      1.1  christos 				}
    503      1.1  christos 				id = *(unsigned char *)clear;
    504      1.1  christos 				if (id + 1 <= plen && id + 9 > plen)
    505      1.1  christos 					break;
    506      1.1  christos 			}
    507      1.1  christos 			if (plen % 8 == 0 && i < 5) {
    508      1.1  christos 				/*
    509      1.1  christos 				 * Note that this is always shorter than the
    510      1.1  christos 				 * original stored string, so there's no need
    511      1.1  christos 				 * to realloc.
    512      1.1  christos 				 */
    513      1.1  christos 				if ((i = plen = *(unsigned char *)clear) > 7)
    514      1.1  christos 					i = 7;
    515      1.1  christos 				esp->es_server.ea_peerlen = plen;
    516      1.1  christos 				dp = (unsigned char *)esp->es_server.ea_peer;
    517      1.1  christos 				BCOPY(clear + 1, dp, i);
    518      1.1  christos 				plen -= i;
    519      1.1  christos 				dp += i;
    520      1.1  christos 				sp = secbuf + 8;
    521      1.1  christos 				while (plen > 0) {
    522  1.1.1.5  christos 					DesDecrypt(sp, key, dp);
    523      1.1  christos 					sp += 8;
    524      1.1  christos 					dp += 8;
    525      1.1  christos 					plen -= 8;
    526      1.1  christos 				}
    527      1.1  christos 				esp->es_server.ea_peer[
    528      1.1  christos 					esp->es_server.ea_peerlen] = '\0';
    529      1.1  christos 				dbglog("decoded pseudonym to \"%.*q\"",
    530      1.1  christos 				    esp->es_server.ea_peerlen,
    531      1.1  christos 				    esp->es_server.ea_peer);
    532      1.1  christos 			} else {
    533      1.1  christos 				dbglog("failed to decode real name");
    534      1.1  christos 				/* Stay in eapIdentfy state; requery */
    535      1.1  christos 				break;
    536      1.1  christos 			}
    537      1.1  christos 		}
    538      1.1  christos 		/* Look up user in secrets database. */
    539      1.1  christos 		if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
    540      1.1  christos 		    esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
    541      1.1  christos 			/* Set up default in case SRP entry is bad */
    542      1.1  christos 			esp->es_server.ea_state = eapMD5Chall;
    543      1.1  christos 			/* Get t_confent based on index in srp-secrets */
    544      1.1  christos 			id = strtol((char *)secbuf, &cp, 10);
    545      1.1  christos 			if (*cp++ != ':' || id < 0)
    546      1.1  christos 				break;
    547      1.1  christos 			if (id == 0) {
    548      1.1  christos 				mytce.index = 0;
    549      1.1  christos 				mytce.modulus.data = (u_char *)wkmodulus;
    550      1.1  christos 				mytce.modulus.len = sizeof (wkmodulus);
    551      1.1  christos 				mytce.generator.data = (u_char *)"\002";
    552      1.1  christos 				mytce.generator.len = 1;
    553      1.1  christos 				tce = &mytce;
    554      1.1  christos 			} else if ((tce = gettcid(id)) != NULL) {
    555      1.1  christos 				/*
    556      1.1  christos 				 * Client will have to verify this modulus/
    557      1.1  christos 				 * generator combination, and that will take
    558      1.1  christos 				 * a while.  Lengthen the timeout here.
    559      1.1  christos 				 */
    560      1.1  christos 				if (esp->es_server.ea_timeout > 0 &&
    561      1.1  christos 				    esp->es_server.ea_timeout < 30)
    562      1.1  christos 					esp->es_server.ea_timeout = 30;
    563      1.1  christos 			} else {
    564      1.1  christos 				break;
    565      1.1  christos 			}
    566      1.1  christos 			if ((cp2 = strchr(cp, ':')) == NULL)
    567      1.1  christos 				break;
    568      1.1  christos 			*cp2++ = '\0';
    569      1.1  christos 			tpw.pebuf.name = esp->es_server.ea_peer;
    570      1.1  christos 			tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
    571      1.1  christos 			    cp);
    572  1.1.1.5  christos 			tpw.pebuf.password.data = (char*) tpw.pwbuf;
    573      1.1  christos 			tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
    574      1.1  christos 			    cp2);
    575      1.1  christos 			tpw.pebuf.salt.data = tpw.saltbuf;
    576      1.1  christos 			if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
    577      1.1  christos 				break;
    578      1.1  christos 			esp->es_server.ea_session = (void *)ts;
    579      1.1  christos 			esp->es_server.ea_state = eapSRP1;
    580      1.1  christos 			vals[0] = esp->es_server.ea_id + 1;
    581      1.1  christos 			vals[1] = EAPT_SRP;
    582      1.1  christos 			t_serveraddexdata(ts, vals, 2);
    583      1.1  christos 			/* Generate B; must call before t_servergetkey() */
    584      1.1  christos 			t_servergenexp(ts);
    585      1.1  christos 			break;
    586      1.1  christos 		}
    587  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    588  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
    589  1.1.1.4  christos                 if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
    590  1.1.1.4  christos                     esp->es_server.ea_name, secret, &secret_len, 1)) {
    591  1.1.1.4  christos 
    592  1.1.1.4  christos 			esp->es_server.ea_state = eapTlsStart;
    593  1.1.1.4  christos 			break;
    594  1.1.1.4  christos 		}
    595  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
    596  1.1.1.4  christos 
    597      1.1  christos 		esp->es_server.ea_state = eapMD5Chall;
    598      1.1  christos 		break;
    599      1.1  christos 
    600  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
    601  1.1.1.4  christos 	case eapTlsStart:
    602  1.1.1.4  christos 		/* Initialize ssl session */
    603  1.1.1.4  christos 		if(!eaptls_init_ssl_server(esp)) {
    604  1.1.1.4  christos 			esp->es_server.ea_state = eapBadAuth;
    605  1.1.1.4  christos 			break;
    606  1.1.1.4  christos 		}
    607  1.1.1.4  christos 
    608  1.1.1.4  christos 		esp->es_server.ea_state = eapTlsRecv;
    609  1.1.1.4  christos 		break;
    610  1.1.1.4  christos 
    611  1.1.1.4  christos 	case eapTlsRecv:
    612  1.1.1.4  christos 		ets = (struct eaptls_session *) esp->es_server.ea_session;
    613  1.1.1.4  christos 
    614  1.1.1.4  christos 		if(ets->alert_sent) {
    615  1.1.1.4  christos 			esp->es_server.ea_state = eapTlsSendAlert;
    616  1.1.1.4  christos 			break;
    617  1.1.1.4  christos 		}
    618  1.1.1.4  christos 
    619  1.1.1.4  christos 		if (status) {
    620  1.1.1.4  christos 			esp->es_server.ea_state = eapBadAuth;
    621  1.1.1.4  christos 			break;
    622  1.1.1.4  christos 		}
    623  1.1.1.4  christos 		ets = (struct eaptls_session *) esp->es_server.ea_session;
    624  1.1.1.4  christos 
    625  1.1.1.4  christos 		if(ets->frag)
    626  1.1.1.4  christos 			esp->es_server.ea_state = eapTlsSendAck;
    627  1.1.1.4  christos 		else
    628  1.1.1.4  christos 			esp->es_server.ea_state = eapTlsSend;
    629  1.1.1.4  christos 		break;
    630  1.1.1.4  christos 
    631  1.1.1.4  christos 	case eapTlsSend:
    632  1.1.1.4  christos 		ets = (struct eaptls_session *) esp->es_server.ea_session;
    633  1.1.1.4  christos 
    634  1.1.1.4  christos 		if(ets->frag)
    635  1.1.1.4  christos 			esp->es_server.ea_state = eapTlsRecvAck;
    636  1.1.1.4  christos 		else
    637  1.1.1.4  christos 			if(SSL_is_init_finished(ets->ssl))
    638  1.1.1.4  christos 				esp->es_server.ea_state = eapTlsRecvClient;
    639  1.1.1.4  christos 			else
    640  1.1.1.4  christos 				/* JJK Add "TLS empty record" message here ??? */
    641  1.1.1.4  christos 				esp->es_server.ea_state = eapTlsRecv;
    642  1.1.1.4  christos 		break;
    643  1.1.1.4  christos 
    644  1.1.1.4  christos 	case eapTlsSendAck:
    645  1.1.1.4  christos 		esp->es_server.ea_state = eapTlsRecv;
    646  1.1.1.4  christos 		break;
    647  1.1.1.4  christos 
    648  1.1.1.4  christos 	case eapTlsRecvAck:
    649  1.1.1.4  christos 		if (status)
    650  1.1.1.4  christos 		{
    651  1.1.1.4  christos 			esp->es_server.ea_state = eapBadAuth;
    652  1.1.1.4  christos 			break;
    653  1.1.1.4  christos 		}
    654  1.1.1.4  christos 
    655  1.1.1.4  christos 		esp->es_server.ea_state = eapTlsSend;
    656  1.1.1.4  christos 		break;
    657  1.1.1.4  christos 
    658  1.1.1.4  christos 	case eapTlsSendAlert:
    659  1.1.1.4  christos 		esp->es_server.ea_state = eapTlsRecvAlertAck;
    660  1.1.1.4  christos 		break;
    661  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
    662  1.1.1.4  christos 
    663      1.1  christos 	case eapSRP1:
    664  1.1.1.5  christos #ifdef PPP_WITH_SRP
    665      1.1  christos 		ts = (struct t_server *)esp->es_server.ea_session;
    666      1.1  christos 		if (ts != NULL && status != 0) {
    667      1.1  christos 			t_serverclose(ts);
    668      1.1  christos 			esp->es_server.ea_session = NULL;
    669      1.1  christos 			esp->es_server.ea_skey = NULL;
    670      1.1  christos 		}
    671  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    672      1.1  christos 		if (status == 1) {
    673      1.1  christos 			esp->es_server.ea_state = eapMD5Chall;
    674      1.1  christos 		} else if (status != 0 || esp->es_server.ea_session == NULL) {
    675      1.1  christos 			esp->es_server.ea_state = eapBadAuth;
    676      1.1  christos 		} else {
    677      1.1  christos 			esp->es_server.ea_state = eapSRP2;
    678      1.1  christos 		}
    679      1.1  christos 		break;
    680      1.1  christos 
    681      1.1  christos 	case eapSRP2:
    682  1.1.1.5  christos #ifdef PPP_WITH_SRP
    683      1.1  christos 		ts = (struct t_server *)esp->es_server.ea_session;
    684      1.1  christos 		if (ts != NULL && status != 0) {
    685      1.1  christos 			t_serverclose(ts);
    686      1.1  christos 			esp->es_server.ea_session = NULL;
    687      1.1  christos 			esp->es_server.ea_skey = NULL;
    688      1.1  christos 		}
    689  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    690      1.1  christos 		if (status != 0 || esp->es_server.ea_session == NULL) {
    691      1.1  christos 			esp->es_server.ea_state = eapBadAuth;
    692      1.1  christos 		} else {
    693      1.1  christos 			esp->es_server.ea_state = eapSRP3;
    694      1.1  christos 		}
    695      1.1  christos 		break;
    696      1.1  christos 
    697      1.1  christos 	case eapSRP3:
    698      1.1  christos 	case eapSRP4:
    699  1.1.1.5  christos #ifdef PPP_WITH_SRP
    700      1.1  christos 		ts = (struct t_server *)esp->es_server.ea_session;
    701      1.1  christos 		if (ts != NULL && status != 0) {
    702      1.1  christos 			t_serverclose(ts);
    703      1.1  christos 			esp->es_server.ea_session = NULL;
    704      1.1  christos 			esp->es_server.ea_skey = NULL;
    705      1.1  christos 		}
    706  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    707      1.1  christos 		if (status != 0 || esp->es_server.ea_session == NULL) {
    708      1.1  christos 			esp->es_server.ea_state = eapBadAuth;
    709      1.1  christos 		} else {
    710      1.1  christos 			esp->es_server.ea_state = eapOpen;
    711      1.1  christos 		}
    712      1.1  christos 		break;
    713      1.1  christos 
    714  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
    715  1.1.1.4  christos 	case eapMSCHAPv2Chall:
    716  1.1.1.4  christos #endif
    717      1.1  christos 	case eapMD5Chall:
    718      1.1  christos 		if (status != 0) {
    719      1.1  christos 			esp->es_server.ea_state = eapBadAuth;
    720      1.1  christos 		} else {
    721      1.1  christos 			esp->es_server.ea_state = eapOpen;
    722      1.1  christos 		}
    723      1.1  christos 		break;
    724      1.1  christos 
    725      1.1  christos 	default:
    726      1.1  christos 		esp->es_server.ea_state = eapBadAuth;
    727      1.1  christos 		break;
    728      1.1  christos 	}
    729      1.1  christos 	if (esp->es_server.ea_state == eapBadAuth)
    730      1.1  christos 		eap_send_failure(esp);
    731  1.1.1.4  christos 
    732  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
    733  1.1.1.4  christos 	dbglog("EAP id=0x%2x '%s' -> '%s'", esp->es_server.ea_id, eap_state_name(esp->es_server.ea_prev_state), eap_state_name(esp->es_server.ea_state));
    734  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
    735  1.1.1.4  christos }
    736  1.1.1.4  christos 
    737  1.1.1.5  christos #if PPP_WITH_CHAPMS
    738  1.1.1.4  christos /*
    739  1.1.1.4  christos  * eap_chap_verify_response - check whether the peer's response matches
    740  1.1.1.4  christos  * what we think it should be.  Returns 1 if it does (authentication
    741  1.1.1.4  christos  * succeeded), or 0 if it doesn't.
    742  1.1.1.4  christos  */
    743  1.1.1.4  christos static int
    744  1.1.1.4  christos eap_chap_verify_response(char *name, char *ourname, int id,
    745  1.1.1.4  christos 			 struct chap_digest_type *digest,
    746  1.1.1.4  christos 			 unsigned char *challenge, unsigned char *response,
    747  1.1.1.4  christos 			 char *message, int message_space)
    748  1.1.1.4  christos {
    749  1.1.1.4  christos 	int ok;
    750  1.1.1.4  christos 	unsigned char secret[MAXSECRETLEN];
    751  1.1.1.4  christos 	int secret_len;
    752  1.1.1.4  christos 
    753  1.1.1.4  christos 	/* Get the secret that the peer is supposed to know */
    754  1.1.1.4  christos 	if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) {
    755  1.1.1.4  christos 		error("No CHAP secret found for authenticating %q", name);
    756  1.1.1.4  christos 		return 0;
    757  1.1.1.4  christos 	}
    758  1.1.1.4  christos 
    759  1.1.1.4  christos 	ok = digest->verify_response(id, name, secret, secret_len, challenge,
    760  1.1.1.4  christos 				     response, message, message_space);
    761  1.1.1.4  christos 	memset(secret, 0, sizeof(secret));
    762  1.1.1.4  christos 
    763  1.1.1.4  christos 	return ok;
    764      1.1  christos }
    765      1.1  christos 
    766      1.1  christos /*
    767  1.1.1.4  christos  * Format and send an CHAPV2-Success/Failure EAP Request message.
    768  1.1.1.4  christos  */
    769  1.1.1.4  christos static void
    770  1.1.1.4  christos eap_chapms2_send_request(eap_state *esp, u_char id,
    771  1.1.1.4  christos 			 u_char opcode, u_char chapid,
    772  1.1.1.4  christos 			 char *message, int message_len)
    773  1.1.1.4  christos {
    774  1.1.1.4  christos 	u_char *outp;
    775  1.1.1.4  christos 	int msglen;
    776  1.1.1.4  christos 
    777  1.1.1.4  christos 	outp = outpacket_buf;
    778  1.1.1.4  christos 
    779  1.1.1.4  christos 	MAKEHEADER(outp, PPP_EAP);
    780  1.1.1.4  christos 
    781  1.1.1.4  christos 	msglen = EAP_HEADERLEN + 5 * sizeof (u_char);
    782  1.1.1.4  christos 	msglen += message_len;
    783  1.1.1.4  christos 
    784  1.1.1.4  christos 	PUTCHAR(EAP_REQUEST, outp);
    785  1.1.1.4  christos 	PUTCHAR(id, outp);
    786  1.1.1.4  christos 	PUTSHORT(msglen, outp);
    787  1.1.1.4  christos 	PUTCHAR(EAPT_MSCHAPV2, outp);
    788  1.1.1.4  christos 	PUTCHAR(opcode, outp);
    789  1.1.1.4  christos 	PUTCHAR(chapid, outp);
    790  1.1.1.4  christos 	/* MS len */
    791  1.1.1.4  christos 	PUTSHORT(msglen - 5, outp);
    792  1.1.1.4  christos 	BCOPY(message, outp, message_len);
    793  1.1.1.4  christos 
    794  1.1.1.4  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
    795  1.1.1.4  christos 
    796  1.1.1.4  christos 	if (opcode == CHAP_SUCCESS) {
    797  1.1.1.4  christos 		auth_peer_success(esp->es_unit, PPP_EAP, 0,
    798  1.1.1.4  christos 				esp->es_server.ea_peer, esp->es_server.ea_peerlen);
    799  1.1.1.4  christos 	}
    800  1.1.1.4  christos 	else {
    801  1.1.1.4  christos 		esp->es_server.ea_state = eapBadAuth;
    802  1.1.1.4  christos 		auth_peer_fail(esp->es_unit, PPP_EAP);
    803  1.1.1.4  christos 	}
    804  1.1.1.4  christos }
    805  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
    806  1.1.1.4  christos 
    807  1.1.1.4  christos /*
    808      1.1  christos  * Format an EAP Request message and send it to the peer.  Message
    809      1.1  christos  * type depends on current state.  (Server operation)
    810      1.1  christos  */
    811      1.1  christos static void
    812  1.1.1.4  christos eap_send_request(eap_state *esp)
    813      1.1  christos {
    814      1.1  christos 	u_char *outp;
    815      1.1  christos 	u_char *lenloc;
    816      1.1  christos 	u_char *ptr;
    817      1.1  christos 	int outlen;
    818      1.1  christos 	int challen;
    819      1.1  christos 	char *str;
    820  1.1.1.5  christos #ifdef PPP_WITH_SRP
    821      1.1  christos 	struct t_server *ts;
    822  1.1.1.5  christos 	u_char clear[8], cipher[8], dig[SHA_DIGEST_LENGTH], *optr, *cp, key[SHA_DIGEST_LENGTH];
    823  1.1.1.5  christos 	int i, j, diglen, clen, keylen = sizeof(key);
    824      1.1  christos 	struct b64state b64;
    825  1.1.1.5  christos 	PPP_MD_CTX *ctxt;
    826  1.1.1.5  christos #endif /* PPP_WITH_SRP */
    827      1.1  christos 
    828      1.1  christos 	/* Handle both initial auth and restart */
    829      1.1  christos 	if (esp->es_server.ea_state < eapIdentify &&
    830      1.1  christos 	    esp->es_server.ea_state != eapInitial) {
    831      1.1  christos 		esp->es_server.ea_state = eapIdentify;
    832      1.1  christos 		if (explicit_remote) {
    833      1.1  christos 			/*
    834      1.1  christos 			 * If we already know the peer's
    835      1.1  christos 			 * unauthenticated name, then there's no
    836      1.1  christos 			 * reason to ask.  Go to next state instead.
    837      1.1  christos 			 */
    838      1.1  christos 			esp->es_server.ea_peer = remote_name;
    839      1.1  christos 			esp->es_server.ea_peerlen = strlen(remote_name);
    840      1.1  christos 			eap_figure_next_state(esp, 0);
    841      1.1  christos 		}
    842      1.1  christos 	}
    843      1.1  christos 
    844      1.1  christos 	if (esp->es_server.ea_maxrequests > 0 &&
    845      1.1  christos 	    esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
    846      1.1  christos 		if (esp->es_server.ea_responses > 0)
    847      1.1  christos 			error("EAP: too many Requests sent");
    848      1.1  christos 		else
    849      1.1  christos 			error("EAP: no response to Requests");
    850      1.1  christos 		eap_send_failure(esp);
    851      1.1  christos 		return;
    852      1.1  christos 	}
    853      1.1  christos 
    854      1.1  christos 	outp = outpacket_buf;
    855      1.1  christos 
    856      1.1  christos 	MAKEHEADER(outp, PPP_EAP);
    857      1.1  christos 
    858      1.1  christos 	PUTCHAR(EAP_REQUEST, outp);
    859      1.1  christos 	PUTCHAR(esp->es_server.ea_id, outp);
    860      1.1  christos 	lenloc = outp;
    861      1.1  christos 	INCPTR(2, outp);
    862      1.1  christos 
    863      1.1  christos 	switch (esp->es_server.ea_state) {
    864      1.1  christos 	case eapIdentify:
    865      1.1  christos 		PUTCHAR(EAPT_IDENTITY, outp);
    866      1.1  christos 		str = "Name";
    867      1.1  christos 		challen = strlen(str);
    868      1.1  christos 		BCOPY(str, outp, challen);
    869      1.1  christos 		INCPTR(challen, outp);
    870      1.1  christos 		break;
    871      1.1  christos 
    872      1.1  christos 	case eapMD5Chall:
    873      1.1  christos 		PUTCHAR(EAPT_MD5CHAP, outp);
    874      1.1  christos 		/*
    875      1.1  christos 		 * pick a random challenge length between
    876      1.1  christos 		 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
    877      1.1  christos 		 */
    878      1.1  christos 		challen = (drand48() *
    879      1.1  christos 		    (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
    880      1.1  christos 			    MIN_CHALLENGE_LENGTH;
    881      1.1  christos 		PUTCHAR(challen, outp);
    882      1.1  christos 		esp->es_challen = challen;
    883      1.1  christos 		ptr = esp->es_challenge;
    884      1.1  christos 		while (--challen >= 0)
    885      1.1  christos 			*ptr++ = (u_char) (drand48() * 0x100);
    886      1.1  christos 		BCOPY(esp->es_challenge, outp, esp->es_challen);
    887      1.1  christos 		INCPTR(esp->es_challen, outp);
    888      1.1  christos 		BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
    889      1.1  christos 		INCPTR(esp->es_server.ea_namelen, outp);
    890      1.1  christos 		break;
    891      1.1  christos 
    892  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
    893  1.1.1.4  christos 	case eapMSCHAPv2Chall:
    894  1.1.1.5  christos 		esp->es_server.digest->generate_challenge(esp->es_challenge);
    895  1.1.1.5  christos 		challen = esp->es_challenge[0];
    896  1.1.1.4  christos 		esp->es_challen = challen;
    897  1.1.1.4  christos 
    898  1.1.1.4  christos 		PUTCHAR(EAPT_MSCHAPV2, outp);
    899  1.1.1.4  christos 		PUTCHAR(CHAP_CHALLENGE, outp);
    900  1.1.1.4  christos 		PUTCHAR(esp->es_server.ea_id, outp);
    901  1.1.1.4  christos 		/* MS len */
    902  1.1.1.4  christos 		PUTSHORT(5 + challen +
    903  1.1.1.4  christos 				esp->es_server.ea_namelen,
    904  1.1.1.4  christos 				outp);
    905  1.1.1.4  christos 		/* challen + challenge */
    906  1.1.1.4  christos 		BCOPY(esp->es_challenge, outp, challen+1);
    907  1.1.1.4  christos 		INCPTR(challen+1, outp);
    908  1.1.1.4  christos 		BCOPY(esp->es_server.ea_name,
    909  1.1.1.4  christos 				outp,
    910  1.1.1.4  christos 				esp->es_server.ea_namelen);
    911  1.1.1.4  christos 		INCPTR(esp->es_server.ea_namelen, outp);
    912  1.1.1.4  christos 		break;
    913  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
    914  1.1.1.4  christos 
    915  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
    916  1.1.1.4  christos 	case eapTlsStart:
    917  1.1.1.4  christos 		PUTCHAR(EAPT_TLS, outp);
    918  1.1.1.4  christos 		PUTCHAR(EAP_TLS_FLAGS_START, outp);
    919  1.1.1.4  christos 		eap_figure_next_state(esp, 0);
    920  1.1.1.4  christos 		break;
    921  1.1.1.4  christos 
    922  1.1.1.4  christos 	case eapTlsSend:
    923  1.1.1.4  christos 		eaptls_send(esp->es_server.ea_session, &outp);
    924  1.1.1.4  christos 		eap_figure_next_state(esp, 0);
    925  1.1.1.4  christos 		break;
    926  1.1.1.4  christos 
    927  1.1.1.4  christos 	case eapTlsSendAck:
    928  1.1.1.4  christos 		PUTCHAR(EAPT_TLS, outp);
    929  1.1.1.4  christos 		PUTCHAR(0, outp);
    930  1.1.1.4  christos 		eap_figure_next_state(esp, 0);
    931  1.1.1.4  christos 		break;
    932  1.1.1.4  christos 
    933  1.1.1.4  christos 	case eapTlsSendAlert:
    934  1.1.1.4  christos 		eaptls_send(esp->es_server.ea_session, &outp);
    935  1.1.1.4  christos 		eap_figure_next_state(esp, 0);
    936  1.1.1.4  christos 		break;
    937  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
    938  1.1.1.4  christos 
    939  1.1.1.5  christos #ifdef PPP_WITH_SRP
    940      1.1  christos 	case eapSRP1:
    941      1.1  christos 		PUTCHAR(EAPT_SRP, outp);
    942      1.1  christos 		PUTCHAR(EAPSRP_CHALLENGE, outp);
    943      1.1  christos 
    944      1.1  christos 		PUTCHAR(esp->es_server.ea_namelen, outp);
    945      1.1  christos 		BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
    946      1.1  christos 		INCPTR(esp->es_server.ea_namelen, outp);
    947      1.1  christos 
    948      1.1  christos 		ts = (struct t_server *)esp->es_server.ea_session;
    949      1.1  christos 		assert(ts != NULL);
    950      1.1  christos 		PUTCHAR(ts->s.len, outp);
    951      1.1  christos 		BCOPY(ts->s.data, outp, ts->s.len);
    952      1.1  christos 		INCPTR(ts->s.len, outp);
    953      1.1  christos 
    954      1.1  christos 		if (ts->g.len == 1 && ts->g.data[0] == 2) {
    955      1.1  christos 			PUTCHAR(0, outp);
    956      1.1  christos 		} else {
    957      1.1  christos 			PUTCHAR(ts->g.len, outp);
    958      1.1  christos 			BCOPY(ts->g.data, outp, ts->g.len);
    959      1.1  christos 			INCPTR(ts->g.len, outp);
    960      1.1  christos 		}
    961      1.1  christos 
    962      1.1  christos 		if (ts->n.len != sizeof (wkmodulus) ||
    963      1.1  christos 		    BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
    964      1.1  christos 			BCOPY(ts->n.data, outp, ts->n.len);
    965      1.1  christos 			INCPTR(ts->n.len, outp);
    966      1.1  christos 		}
    967      1.1  christos 		break;
    968      1.1  christos 
    969      1.1  christos 	case eapSRP2:
    970      1.1  christos 		PUTCHAR(EAPT_SRP, outp);
    971      1.1  christos 		PUTCHAR(EAPSRP_SKEY, outp);
    972      1.1  christos 
    973      1.1  christos 		ts = (struct t_server *)esp->es_server.ea_session;
    974      1.1  christos 		assert(ts != NULL);
    975      1.1  christos 		BCOPY(ts->B.data, outp, ts->B.len);
    976      1.1  christos 		INCPTR(ts->B.len, outp);
    977      1.1  christos 		break;
    978      1.1  christos 
    979      1.1  christos 	case eapSRP3:
    980      1.1  christos 		PUTCHAR(EAPT_SRP, outp);
    981      1.1  christos 		PUTCHAR(EAPSRP_SVALIDATOR, outp);
    982      1.1  christos 		PUTLONG(SRPVAL_EBIT, outp);
    983      1.1  christos 		ts = (struct t_server *)esp->es_server.ea_session;
    984      1.1  christos 		assert(ts != NULL);
    985  1.1.1.5  christos 		BCOPY(t_serverresponse(ts), outp, SHA_DIGEST_LENGTH);
    986  1.1.1.5  christos 		INCPTR(SHA_DIGEST_LENGTH, outp);
    987      1.1  christos 
    988  1.1.1.5  christos 		if (pncrypt_getkey(0, key, keylen)) {
    989      1.1  christos 			/* Generate pseudonym */
    990      1.1  christos 			optr = outp;
    991      1.1  christos 			cp = (unsigned char *)esp->es_server.ea_peer;
    992      1.1  christos 			if ((j = i = esp->es_server.ea_peerlen) > 7)
    993      1.1  christos 				j = 7;
    994      1.1  christos 			clear[0] = i;
    995      1.1  christos 			BCOPY(cp, clear + 1, j);
    996      1.1  christos 			i -= j;
    997      1.1  christos 			cp += j;
    998  1.1.1.5  christos 
    999  1.1.1.5  christos 			if (!DesEncrypt(clear, key, cipher)) {
   1000      1.1  christos 				dbglog("no DES here; not generating pseudonym");
   1001      1.1  christos 				break;
   1002  1.1.1.5  christos             }
   1003  1.1.1.5  christos 
   1004      1.1  christos 			BZERO(&b64, sizeof (b64));
   1005      1.1  christos 			outp++;		/* space for pseudonym length */
   1006      1.1  christos 			outp += b64enc(&b64, cipher, 8, outp);
   1007      1.1  christos 			while (i >= 8) {
   1008  1.1.1.5  christos 				DesEncrypt(cp, key, cipher);
   1009      1.1  christos 				outp += b64enc(&b64, cipher, 8, outp);
   1010      1.1  christos 				cp += 8;
   1011      1.1  christos 				i -= 8;
   1012      1.1  christos 			}
   1013      1.1  christos 			if (i > 0) {
   1014      1.1  christos 				BCOPY(cp, clear, i);
   1015      1.1  christos 				cp += i;
   1016      1.1  christos 				while (i < 8) {
   1017      1.1  christos 					*cp++ = drand48() * 0x100;
   1018      1.1  christos 					i++;
   1019      1.1  christos 				}
   1020  1.1.1.5  christos 
   1021  1.1.1.5  christos 				DesEncrypt(clear, key, cipher);
   1022      1.1  christos 				outp += b64enc(&b64, cipher, 8, outp);
   1023      1.1  christos 			}
   1024      1.1  christos 			outp += b64flush(&b64, outp);
   1025      1.1  christos 
   1026      1.1  christos 			/* Set length and pad out to next 20 octet boundary */
   1027      1.1  christos 			i = outp - optr - 1;
   1028      1.1  christos 			*optr = i;
   1029  1.1.1.5  christos 			i %= SHA_DIGEST_LENGTH;
   1030      1.1  christos 			if (i != 0) {
   1031  1.1.1.5  christos 				while (i < SHA_DIGEST_LENGTH) {
   1032      1.1  christos 					*outp++ = drand48() * 0x100;
   1033      1.1  christos 					i++;
   1034      1.1  christos 				}
   1035      1.1  christos 			}
   1036      1.1  christos 
   1037      1.1  christos 			/* Obscure the pseudonym with SHA1 hash */
   1038  1.1.1.5  christos 			ctxt = PPP_MD_CTX_new();
   1039  1.1.1.5  christos 			if (ctxt) {
   1040  1.1.1.5  christos 
   1041  1.1.1.5  christos 				PPP_DigestInit(ctxt, PPP_sha1());
   1042  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
   1043  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, &esp->es_server.ea_skey,
   1044  1.1.1.5  christos 					SESSION_KEY_LEN);
   1045  1.1.1.5  christos 				PPP_DigestUpdate(ctxt,  esp->es_server.ea_peer,
   1046  1.1.1.5  christos 					esp->es_server.ea_peerlen);
   1047  1.1.1.5  christos 				while (optr < outp) {
   1048  1.1.1.5  christos 					diglen = SHA_DIGEST_LENGTH;
   1049  1.1.1.5  christos 					PPP_DigestFinal(ctxt, dig, &diglen);
   1050  1.1.1.5  christos 					cp = dig;
   1051  1.1.1.5  christos 					while (cp < dig + SHA_DIGEST_LENGTH)
   1052  1.1.1.5  christos 						*optr++ ^= *cp++;
   1053  1.1.1.5  christos 
   1054  1.1.1.5  christos 					PPP_DigestInit(ctxt, PPP_sha1());
   1055  1.1.1.5  christos 					PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
   1056  1.1.1.5  christos 					PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
   1057  1.1.1.5  christos 						SESSION_KEY_LEN);
   1058  1.1.1.5  christos 					PPP_DigestUpdate(ctxt, optr - SHA_DIGEST_LENGTH,
   1059  1.1.1.5  christos 						SHA_DIGEST_LENGTH);
   1060  1.1.1.5  christos 				}
   1061  1.1.1.5  christos 
   1062  1.1.1.5  christos 				PPP_MD_CTX_free(ctxt);
   1063      1.1  christos 			}
   1064      1.1  christos 		}
   1065      1.1  christos 		break;
   1066      1.1  christos 
   1067      1.1  christos 	case eapSRP4:
   1068      1.1  christos 		PUTCHAR(EAPT_SRP, outp);
   1069      1.1  christos 		PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
   1070      1.1  christos 		challen = MIN_CHALLENGE_LENGTH +
   1071      1.1  christos 		    ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
   1072      1.1  christos 		esp->es_challen = challen;
   1073      1.1  christos 		ptr = esp->es_challenge;
   1074      1.1  christos 		while (--challen >= 0)
   1075      1.1  christos 			*ptr++ = drand48() * 0x100;
   1076      1.1  christos 		BCOPY(esp->es_challenge, outp, esp->es_challen);
   1077      1.1  christos 		INCPTR(esp->es_challen, outp);
   1078      1.1  christos 		break;
   1079  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   1080      1.1  christos 
   1081      1.1  christos 	default:
   1082      1.1  christos 		return;
   1083      1.1  christos 	}
   1084      1.1  christos 
   1085      1.1  christos 	outlen = (outp - outpacket_buf) - PPP_HDRLEN;
   1086      1.1  christos 	PUTSHORT(outlen, lenloc);
   1087      1.1  christos 
   1088      1.1  christos 	output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
   1089      1.1  christos 
   1090      1.1  christos 	esp->es_server.ea_requests++;
   1091      1.1  christos 
   1092      1.1  christos 	if (esp->es_server.ea_timeout > 0)
   1093      1.1  christos 		TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
   1094      1.1  christos }
   1095      1.1  christos 
   1096      1.1  christos /*
   1097      1.1  christos  * eap_authpeer - Authenticate our peer (behave as server).
   1098      1.1  christos  *
   1099      1.1  christos  * Start server state and send first request.  This is called only
   1100      1.1  christos  * after eap_lowerup.
   1101      1.1  christos  */
   1102      1.1  christos void
   1103  1.1.1.4  christos eap_authpeer(int unit, char *localname)
   1104      1.1  christos {
   1105      1.1  christos 	eap_state *esp = &eap_states[unit];
   1106      1.1  christos 
   1107      1.1  christos 	/* Save the name we're given. */
   1108      1.1  christos 	esp->es_server.ea_name = localname;
   1109      1.1  christos 	esp->es_server.ea_namelen = strlen(localname);
   1110      1.1  christos 
   1111      1.1  christos 	esp->es_savedtime = esp->es_server.ea_timeout;
   1112      1.1  christos 
   1113      1.1  christos 	/* Lower layer up yet? */
   1114      1.1  christos 	if (esp->es_server.ea_state == eapInitial ||
   1115      1.1  christos 	    esp->es_server.ea_state == eapPending) {
   1116      1.1  christos 		esp->es_server.ea_state = eapPending;
   1117      1.1  christos 		return;
   1118      1.1  christos 	}
   1119      1.1  christos 
   1120      1.1  christos 	esp->es_server.ea_state = eapPending;
   1121      1.1  christos 
   1122      1.1  christos 	/* ID number not updated here intentionally; hashed into M1 */
   1123      1.1  christos 	eap_send_request(esp);
   1124      1.1  christos }
   1125      1.1  christos 
   1126      1.1  christos /*
   1127      1.1  christos  * eap_server_timeout - Retransmission timer for sending Requests
   1128      1.1  christos  * expired.
   1129      1.1  christos  */
   1130      1.1  christos static void
   1131  1.1.1.4  christos eap_server_timeout(void *arg)
   1132      1.1  christos {
   1133  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   1134  1.1.1.4  christos 	u_char *outp;
   1135  1.1.1.4  christos 	u_char *lenloc;
   1136  1.1.1.4  christos 	int outlen;
   1137  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   1138  1.1.1.4  christos 
   1139      1.1  christos 	eap_state *esp = (eap_state *) arg;
   1140      1.1  christos 
   1141      1.1  christos 	if (!eap_server_active(esp))
   1142      1.1  christos 		return;
   1143      1.1  christos 
   1144  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   1145  1.1.1.4  christos 	switch(esp->es_server.ea_prev_state) {
   1146  1.1.1.4  christos 
   1147  1.1.1.4  christos 	/*
   1148  1.1.1.4  christos 	 *  In eap-tls the state changes after a request, so we return to
   1149  1.1.1.4  christos 	 *  previous state ...
   1150  1.1.1.4  christos 	 */
   1151  1.1.1.4  christos 	case(eapTlsStart):
   1152  1.1.1.4  christos 	case(eapTlsSendAck):
   1153  1.1.1.4  christos 		esp->es_server.ea_state = esp->es_server.ea_prev_state;
   1154  1.1.1.4  christos 		break;
   1155  1.1.1.4  christos 
   1156  1.1.1.4  christos 	/*
   1157  1.1.1.4  christos 	 *  ... or resend the stored data
   1158  1.1.1.4  christos 	 */
   1159  1.1.1.4  christos 	case(eapTlsSend):
   1160  1.1.1.4  christos 	case(eapTlsSendAlert):
   1161  1.1.1.4  christos 		outp = outpacket_buf;
   1162  1.1.1.4  christos 		MAKEHEADER(outp, PPP_EAP);
   1163  1.1.1.4  christos 		PUTCHAR(EAP_REQUEST, outp);
   1164  1.1.1.4  christos 		PUTCHAR(esp->es_server.ea_id, outp);
   1165  1.1.1.4  christos 		lenloc = outp;
   1166  1.1.1.4  christos 		INCPTR(2, outp);
   1167  1.1.1.4  christos 
   1168  1.1.1.4  christos 		eaptls_retransmit(esp->es_server.ea_session, &outp);
   1169  1.1.1.4  christos 
   1170  1.1.1.4  christos 		outlen = (outp - outpacket_buf) - PPP_HDRLEN;
   1171  1.1.1.4  christos 		PUTSHORT(outlen, lenloc);
   1172  1.1.1.4  christos 		output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
   1173  1.1.1.4  christos 		esp->es_server.ea_requests++;
   1174  1.1.1.4  christos 
   1175  1.1.1.4  christos 		if (esp->es_server.ea_timeout > 0)
   1176  1.1.1.4  christos 			TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
   1177  1.1.1.4  christos 
   1178  1.1.1.4  christos 		return;
   1179  1.1.1.4  christos 	default:
   1180  1.1.1.4  christos 		break;
   1181  1.1.1.4  christos 	}
   1182  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   1183  1.1.1.4  christos 
   1184      1.1  christos 	/* EAP ID number must not change on timeout. */
   1185      1.1  christos 	eap_send_request(esp);
   1186      1.1  christos }
   1187      1.1  christos 
   1188      1.1  christos /*
   1189      1.1  christos  * When it's time to send rechallenge the peer, this timeout is
   1190      1.1  christos  * called.  Once the rechallenge is successful, the response handler
   1191      1.1  christos  * will restart the timer.  If it fails, then the link is dropped.
   1192      1.1  christos  */
   1193      1.1  christos static void
   1194  1.1.1.4  christos eap_rechallenge(void *arg)
   1195      1.1  christos {
   1196      1.1  christos 	eap_state *esp = (eap_state *)arg;
   1197      1.1  christos 
   1198      1.1  christos 	if (esp->es_server.ea_state != eapOpen &&
   1199      1.1  christos 	    esp->es_server.ea_state != eapSRP4)
   1200      1.1  christos 		return;
   1201      1.1  christos 
   1202      1.1  christos 	esp->es_server.ea_requests = 0;
   1203      1.1  christos 	esp->es_server.ea_state = eapIdentify;
   1204      1.1  christos 	eap_figure_next_state(esp, 0);
   1205      1.1  christos 	esp->es_server.ea_id++;
   1206      1.1  christos 	eap_send_request(esp);
   1207      1.1  christos }
   1208      1.1  christos 
   1209      1.1  christos static void
   1210  1.1.1.4  christos srp_lwrechallenge(void *arg)
   1211      1.1  christos {
   1212      1.1  christos 	eap_state *esp = (eap_state *)arg;
   1213      1.1  christos 
   1214      1.1  christos 	if (esp->es_server.ea_state != eapOpen ||
   1215      1.1  christos 	    esp->es_server.ea_type != EAPT_SRP)
   1216      1.1  christos 		return;
   1217      1.1  christos 
   1218      1.1  christos 	esp->es_server.ea_requests = 0;
   1219      1.1  christos 	esp->es_server.ea_state = eapSRP4;
   1220      1.1  christos 	esp->es_server.ea_id++;
   1221      1.1  christos 	eap_send_request(esp);
   1222      1.1  christos }
   1223      1.1  christos 
   1224      1.1  christos /*
   1225      1.1  christos  * eap_lowerup - The lower layer is now up.
   1226      1.1  christos  *
   1227      1.1  christos  * This is called before either eap_authpeer or eap_authwithpeer.  See
   1228      1.1  christos  * link_established() in auth.c.  All that's necessary here is to
   1229      1.1  christos  * return to closed state so that those two routines will do the right
   1230      1.1  christos  * thing.
   1231      1.1  christos  */
   1232      1.1  christos static void
   1233  1.1.1.4  christos eap_lowerup(int unit)
   1234      1.1  christos {
   1235      1.1  christos 	eap_state *esp = &eap_states[unit];
   1236      1.1  christos 
   1237      1.1  christos 	/* Discard any (possibly authenticated) peer name. */
   1238      1.1  christos 	if (esp->es_server.ea_peer != NULL &&
   1239      1.1  christos 	    esp->es_server.ea_peer != remote_name)
   1240      1.1  christos 		free(esp->es_server.ea_peer);
   1241      1.1  christos 	esp->es_server.ea_peer = NULL;
   1242      1.1  christos 	if (esp->es_client.ea_peer != NULL)
   1243      1.1  christos 		free(esp->es_client.ea_peer);
   1244      1.1  christos 	esp->es_client.ea_peer = NULL;
   1245      1.1  christos 
   1246      1.1  christos 	esp->es_client.ea_state = eapClosed;
   1247      1.1  christos 	esp->es_server.ea_state = eapClosed;
   1248      1.1  christos }
   1249      1.1  christos 
   1250      1.1  christos /*
   1251      1.1  christos  * eap_lowerdown - The lower layer is now down.
   1252      1.1  christos  *
   1253      1.1  christos  * Cancel all timeouts and return to initial state.
   1254      1.1  christos  */
   1255      1.1  christos static void
   1256  1.1.1.4  christos eap_lowerdown(int unit)
   1257      1.1  christos {
   1258      1.1  christos 	eap_state *esp = &eap_states[unit];
   1259      1.1  christos 
   1260      1.1  christos 	if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
   1261      1.1  christos 		UNTIMEOUT(eap_client_timeout, (void *)esp);
   1262      1.1  christos 	}
   1263      1.1  christos 	if (eap_server_active(esp)) {
   1264      1.1  christos 		if (esp->es_server.ea_timeout > 0) {
   1265      1.1  christos 			UNTIMEOUT(eap_server_timeout, (void *)esp);
   1266      1.1  christos 		}
   1267      1.1  christos 	} else {
   1268      1.1  christos 		if ((esp->es_server.ea_state == eapOpen ||
   1269      1.1  christos 		    esp->es_server.ea_state == eapSRP4) &&
   1270      1.1  christos 		    esp->es_rechallenge > 0) {
   1271      1.1  christos 			UNTIMEOUT(eap_rechallenge, (void *)esp);
   1272      1.1  christos 		}
   1273      1.1  christos 		if (esp->es_server.ea_state == eapOpen &&
   1274      1.1  christos 		    esp->es_lwrechallenge > 0) {
   1275      1.1  christos 			UNTIMEOUT(srp_lwrechallenge, (void *)esp);
   1276      1.1  christos 		}
   1277      1.1  christos 	}
   1278      1.1  christos 
   1279      1.1  christos 	esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
   1280      1.1  christos 	esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
   1281      1.1  christos }
   1282      1.1  christos 
   1283      1.1  christos /*
   1284      1.1  christos  * eap_protrej - Peer doesn't speak this protocol.
   1285      1.1  christos  *
   1286      1.1  christos  * This shouldn't happen.  If it does, it represents authentication
   1287      1.1  christos  * failure.
   1288      1.1  christos  */
   1289      1.1  christos static void
   1290  1.1.1.4  christos eap_protrej(int unit)
   1291      1.1  christos {
   1292      1.1  christos 	eap_state *esp = &eap_states[unit];
   1293      1.1  christos 
   1294      1.1  christos 	if (eap_client_active(esp)) {
   1295      1.1  christos 		error("EAP authentication failed due to Protocol-Reject");
   1296      1.1  christos 		auth_withpeer_fail(unit, PPP_EAP);
   1297      1.1  christos 	}
   1298      1.1  christos 	if (eap_server_active(esp)) {
   1299      1.1  christos 		error("EAP authentication of peer failed on Protocol-Reject");
   1300      1.1  christos 		auth_peer_fail(unit, PPP_EAP);
   1301      1.1  christos 	}
   1302      1.1  christos 	eap_lowerdown(unit);
   1303      1.1  christos }
   1304      1.1  christos 
   1305      1.1  christos /*
   1306      1.1  christos  * Format and send a regular EAP Response message.
   1307      1.1  christos  */
   1308      1.1  christos static void
   1309  1.1.1.4  christos eap_send_response(eap_state *esp, u_char id, u_char typenum,
   1310  1.1.1.4  christos 		  u_char *str, int lenstr)
   1311      1.1  christos {
   1312      1.1  christos 	u_char *outp;
   1313      1.1  christos 	int msglen;
   1314      1.1  christos 
   1315      1.1  christos 	outp = outpacket_buf;
   1316      1.1  christos 
   1317      1.1  christos 	MAKEHEADER(outp, PPP_EAP);
   1318      1.1  christos 
   1319      1.1  christos 	PUTCHAR(EAP_RESPONSE, outp);
   1320      1.1  christos 	PUTCHAR(id, outp);
   1321      1.1  christos 	esp->es_client.ea_id = id;
   1322      1.1  christos 	msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
   1323      1.1  christos 	PUTSHORT(msglen, outp);
   1324      1.1  christos 	PUTCHAR(typenum, outp);
   1325      1.1  christos 	if (lenstr > 0) {
   1326      1.1  christos 		BCOPY(str, outp, lenstr);
   1327      1.1  christos 	}
   1328      1.1  christos 
   1329      1.1  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
   1330      1.1  christos }
   1331      1.1  christos 
   1332      1.1  christos /*
   1333      1.1  christos  * Format and send an MD5-Challenge EAP Response message.
   1334      1.1  christos  */
   1335      1.1  christos static void
   1336  1.1.1.4  christos eap_chap_response(eap_state *esp, u_char id, u_char *hash,
   1337  1.1.1.4  christos 		  char *name, int namelen)
   1338      1.1  christos {
   1339      1.1  christos 	u_char *outp;
   1340      1.1  christos 	int msglen;
   1341      1.1  christos 
   1342      1.1  christos 	outp = outpacket_buf;
   1343  1.1.1.5  christos 
   1344      1.1  christos 	MAKEHEADER(outp, PPP_EAP);
   1345      1.1  christos 
   1346      1.1  christos 	PUTCHAR(EAP_RESPONSE, outp);
   1347      1.1  christos 	PUTCHAR(id, outp);
   1348      1.1  christos 	esp->es_client.ea_id = id;
   1349  1.1.1.5  christos 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_DIGEST_LENGTH +
   1350      1.1  christos 	    namelen;
   1351      1.1  christos 	PUTSHORT(msglen, outp);
   1352      1.1  christos 	PUTCHAR(EAPT_MD5CHAP, outp);
   1353  1.1.1.5  christos 	PUTCHAR(MD5_DIGEST_LENGTH, outp);
   1354  1.1.1.5  christos 	BCOPY(hash, outp, MD5_DIGEST_LENGTH);
   1355  1.1.1.5  christos 	INCPTR(MD5_DIGEST_LENGTH, outp);
   1356      1.1  christos 	if (namelen > 0) {
   1357      1.1  christos 		BCOPY(name, outp, namelen);
   1358      1.1  christos 	}
   1359      1.1  christos 
   1360      1.1  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
   1361      1.1  christos }
   1362      1.1  christos 
   1363  1.1.1.5  christos #ifdef PPP_WITH_SRP
   1364      1.1  christos /*
   1365      1.1  christos  * Format and send a SRP EAP Response message.
   1366      1.1  christos  */
   1367      1.1  christos static void
   1368  1.1.1.4  christos eap_srp_response(eap_state *esp, u_char id, u_char subtypenum,
   1369  1.1.1.4  christos 		 u_char *str, int lenstr)
   1370      1.1  christos {
   1371      1.1  christos 	u_char *outp;
   1372      1.1  christos 	int msglen;
   1373      1.1  christos 
   1374      1.1  christos 	outp = outpacket_buf;
   1375      1.1  christos 
   1376      1.1  christos 	MAKEHEADER(outp, PPP_EAP);
   1377      1.1  christos 
   1378      1.1  christos 	PUTCHAR(EAP_RESPONSE, outp);
   1379      1.1  christos 	PUTCHAR(id, outp);
   1380      1.1  christos 	esp->es_client.ea_id = id;
   1381      1.1  christos 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
   1382      1.1  christos 	PUTSHORT(msglen, outp);
   1383      1.1  christos 	PUTCHAR(EAPT_SRP, outp);
   1384      1.1  christos 	PUTCHAR(subtypenum, outp);
   1385      1.1  christos 	if (lenstr > 0) {
   1386      1.1  christos 		BCOPY(str, outp, lenstr);
   1387      1.1  christos 	}
   1388      1.1  christos 
   1389      1.1  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
   1390      1.1  christos }
   1391      1.1  christos 
   1392      1.1  christos /*
   1393      1.1  christos  * Format and send a SRP EAP Client Validator Response message.
   1394      1.1  christos  */
   1395      1.1  christos static void
   1396  1.1.1.4  christos eap_srpval_response(eap_state *esp, u_char id, u_int32_t flags, u_char *str)
   1397      1.1  christos {
   1398      1.1  christos 	u_char *outp;
   1399      1.1  christos 	int msglen;
   1400      1.1  christos 
   1401      1.1  christos 	outp = outpacket_buf;
   1402      1.1  christos 
   1403      1.1  christos 	MAKEHEADER(outp, PPP_EAP);
   1404      1.1  christos 
   1405      1.1  christos 	PUTCHAR(EAP_RESPONSE, outp);
   1406      1.1  christos 	PUTCHAR(id, outp);
   1407      1.1  christos 	esp->es_client.ea_id = id;
   1408      1.1  christos 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
   1409  1.1.1.5  christos 	    SHA_DIGEST_LENGTH;
   1410      1.1  christos 	PUTSHORT(msglen, outp);
   1411      1.1  christos 	PUTCHAR(EAPT_SRP, outp);
   1412      1.1  christos 	PUTCHAR(EAPSRP_CVALIDATOR, outp);
   1413      1.1  christos 	PUTLONG(flags, outp);
   1414  1.1.1.5  christos 	BCOPY(str, outp, SHA_DIGEST_LENGTH);
   1415      1.1  christos 
   1416      1.1  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
   1417      1.1  christos }
   1418  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   1419      1.1  christos 
   1420  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   1421  1.1.1.4  christos /*
   1422  1.1.1.4  christos  * Send an EAP-TLS response message with tls data
   1423  1.1.1.4  christos  */
   1424  1.1.1.4  christos static void
   1425  1.1.1.4  christos eap_tls_response(eap_state *esp, u_char id)
   1426  1.1.1.4  christos {
   1427  1.1.1.4  christos 	u_char *outp;
   1428  1.1.1.4  christos 	int outlen;
   1429  1.1.1.4  christos 	u_char *lenloc;
   1430  1.1.1.4  christos 
   1431  1.1.1.4  christos 	outp = outpacket_buf;
   1432  1.1.1.4  christos 
   1433  1.1.1.4  christos 	MAKEHEADER(outp, PPP_EAP);
   1434  1.1.1.4  christos 
   1435  1.1.1.4  christos 	PUTCHAR(EAP_RESPONSE, outp);
   1436  1.1.1.4  christos 	PUTCHAR(id, outp);
   1437  1.1.1.4  christos 
   1438  1.1.1.4  christos 	lenloc = outp;
   1439  1.1.1.4  christos 	INCPTR(2, outp);
   1440  1.1.1.4  christos 
   1441  1.1.1.4  christos 	/*
   1442  1.1.1.4  christos 	   If the id in the request is unchanged, we must retransmit
   1443  1.1.1.4  christos 	   the old data
   1444  1.1.1.4  christos 	*/
   1445  1.1.1.4  christos 	if(id == esp->es_client.ea_id)
   1446  1.1.1.4  christos 		eaptls_retransmit(esp->es_client.ea_session, &outp);
   1447  1.1.1.4  christos 	else
   1448  1.1.1.4  christos 		eaptls_send(esp->es_client.ea_session, &outp);
   1449  1.1.1.4  christos 
   1450  1.1.1.4  christos 	outlen = (outp - outpacket_buf) - PPP_HDRLEN;
   1451  1.1.1.4  christos 	PUTSHORT(outlen, lenloc);
   1452  1.1.1.4  christos 
   1453  1.1.1.4  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
   1454  1.1.1.4  christos 
   1455  1.1.1.4  christos 	esp->es_client.ea_id = id;
   1456  1.1.1.4  christos }
   1457  1.1.1.4  christos 
   1458  1.1.1.4  christos /*
   1459  1.1.1.4  christos  * Send an EAP-TLS ack
   1460  1.1.1.4  christos  */
   1461  1.1.1.4  christos static void
   1462  1.1.1.4  christos eap_tls_sendack(eap_state *esp, u_char id)
   1463  1.1.1.4  christos {
   1464  1.1.1.4  christos 	u_char *outp;
   1465  1.1.1.4  christos 	int outlen;
   1466  1.1.1.4  christos 	u_char *lenloc;
   1467  1.1.1.4  christos 
   1468  1.1.1.4  christos 	outp = outpacket_buf;
   1469  1.1.1.4  christos 
   1470  1.1.1.4  christos 	MAKEHEADER(outp, PPP_EAP);
   1471  1.1.1.4  christos 
   1472  1.1.1.4  christos 	PUTCHAR(EAP_RESPONSE, outp);
   1473  1.1.1.4  christos 	PUTCHAR(id, outp);
   1474  1.1.1.4  christos 	esp->es_client.ea_id = id;
   1475  1.1.1.4  christos 
   1476  1.1.1.4  christos 	lenloc = outp;
   1477  1.1.1.4  christos 	INCPTR(2, outp);
   1478  1.1.1.4  christos 
   1479  1.1.1.4  christos 	PUTCHAR(EAPT_TLS, outp);
   1480  1.1.1.4  christos 	PUTCHAR(0, outp);
   1481  1.1.1.4  christos 
   1482  1.1.1.4  christos 	outlen = (outp - outpacket_buf) - PPP_HDRLEN;
   1483  1.1.1.4  christos 	PUTSHORT(outlen, lenloc);
   1484  1.1.1.4  christos 
   1485  1.1.1.4  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
   1486  1.1.1.4  christos }
   1487  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   1488  1.1.1.4  christos 
   1489      1.1  christos static void
   1490  1.1.1.4  christos eap_send_nak(eap_state *esp, u_char id, u_char type)
   1491      1.1  christos {
   1492      1.1  christos 	u_char *outp;
   1493      1.1  christos 	int msglen;
   1494      1.1  christos 
   1495      1.1  christos 	outp = outpacket_buf;
   1496      1.1  christos 
   1497      1.1  christos 	MAKEHEADER(outp, PPP_EAP);
   1498      1.1  christos 
   1499      1.1  christos 	PUTCHAR(EAP_RESPONSE, outp);
   1500      1.1  christos 	PUTCHAR(id, outp);
   1501      1.1  christos 	esp->es_client.ea_id = id;
   1502      1.1  christos 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
   1503      1.1  christos 	PUTSHORT(msglen, outp);
   1504      1.1  christos 	PUTCHAR(EAPT_NAK, outp);
   1505      1.1  christos 	PUTCHAR(type, outp);
   1506      1.1  christos 
   1507      1.1  christos 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
   1508      1.1  christos }
   1509      1.1  christos 
   1510  1.1.1.5  christos #ifdef PPP_WITH_SRP
   1511      1.1  christos static char *
   1512  1.1.1.4  christos name_of_pn_file(void)
   1513      1.1  christos {
   1514      1.1  christos 	char *user, *path, *file;
   1515      1.1  christos 	struct passwd *pw;
   1516      1.1  christos 	size_t pl;
   1517      1.1  christos 	static bool pnlogged = 0;
   1518      1.1  christos 
   1519      1.1  christos 	pw = getpwuid(getuid());
   1520      1.1  christos 	if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
   1521      1.1  christos 		errno = EINVAL;
   1522      1.1  christos 		return (NULL);
   1523      1.1  christos 	}
   1524  1.1.1.5  christos 	file = PPP_PATH_PSEUDONYM;
   1525      1.1  christos 	pl = strlen(user) + strlen(file) + 2;
   1526      1.1  christos 	path = malloc(pl);
   1527      1.1  christos 	if (path == NULL)
   1528      1.1  christos 		return (NULL);
   1529      1.1  christos 	(void) slprintf(path, pl, "%s/%s", user, file);
   1530      1.1  christos 	if (!pnlogged) {
   1531      1.1  christos 		dbglog("pseudonym file: %s", path);
   1532      1.1  christos 		pnlogged = 1;
   1533      1.1  christos 	}
   1534      1.1  christos 	return (path);
   1535      1.1  christos }
   1536      1.1  christos 
   1537      1.1  christos static int
   1538  1.1.1.4  christos open_pn_file(mode_t modebits)
   1539      1.1  christos {
   1540      1.1  christos 	char *path;
   1541      1.1  christos 	int fd, err;
   1542      1.1  christos 
   1543      1.1  christos 	if ((path = name_of_pn_file()) == NULL)
   1544      1.1  christos 		return (-1);
   1545      1.1  christos 	fd = open(path, modebits, S_IRUSR | S_IWUSR);
   1546      1.1  christos 	err = errno;
   1547      1.1  christos 	free(path);
   1548      1.1  christos 	errno = err;
   1549      1.1  christos 	return (fd);
   1550      1.1  christos }
   1551      1.1  christos 
   1552      1.1  christos static void
   1553  1.1.1.4  christos remove_pn_file(void)
   1554      1.1  christos {
   1555      1.1  christos 	char *path;
   1556      1.1  christos 
   1557      1.1  christos 	if ((path = name_of_pn_file()) != NULL) {
   1558      1.1  christos 		(void) unlink(path);
   1559      1.1  christos 		(void) free(path);
   1560      1.1  christos 	}
   1561      1.1  christos }
   1562      1.1  christos 
   1563      1.1  christos static void
   1564  1.1.1.4  christos write_pseudonym(eap_state *esp, u_char *inp, int len, int id)
   1565      1.1  christos {
   1566      1.1  christos 	u_char val;
   1567      1.1  christos 	u_char *datp, *digp;
   1568  1.1.1.5  christos 	PPP_MD_CTX *ctxt;
   1569  1.1.1.5  christos 	u_char dig[SHA_DIGEST_LENGTH];
   1570  1.1.1.5  christos 	int dsize, fd, olen = len, diglen = sizeof(dig);
   1571      1.1  christos 
   1572      1.1  christos 	/*
   1573      1.1  christos 	 * Do the decoding by working backwards.  This eliminates the need
   1574      1.1  christos 	 * to save the decoded output in a separate buffer.
   1575      1.1  christos 	 */
   1576      1.1  christos 	val = id;
   1577      1.1  christos 	while (len > 0) {
   1578  1.1.1.5  christos 		if ((dsize = len % SHA_DIGEST_LENGTH) == 0)
   1579  1.1.1.5  christos 			dsize = SHA_DIGEST_LENGTH;
   1580      1.1  christos 		len -= dsize;
   1581      1.1  christos 		datp = inp + len;
   1582  1.1.1.5  christos 		ctxt = PPP_MD_CTX_new();
   1583  1.1.1.5  christos 		if (ctxt) {
   1584  1.1.1.5  christos 
   1585  1.1.1.5  christos 			PPP_DigestInit(ctxt, PPP_sha1());
   1586  1.1.1.5  christos 			PPP_DigestUpdate(ctxt, &val, 1);
   1587  1.1.1.5  christos 			PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
   1588  1.1.1.5  christos 					SESSION_KEY_LEN);
   1589  1.1.1.5  christos 			if (len > 0) {
   1590  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, datp, SHA_DIGEST_LENGTH);
   1591  1.1.1.5  christos 			} else {
   1592  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
   1593  1.1.1.5  christos 					esp->es_client.ea_namelen);
   1594  1.1.1.5  christos 			}
   1595  1.1.1.5  christos 			PPP_DigestFinal(ctxt, dig, &diglen);
   1596  1.1.1.5  christos 
   1597  1.1.1.5  christos 			for (digp = dig; digp < dig + SHA_DIGEST_LENGTH; digp++)
   1598  1.1.1.5  christos 				*datp++ ^= *digp;
   1599  1.1.1.5  christos 
   1600  1.1.1.5  christos 			PPP_MD_CTX_free(ctxt);
   1601      1.1  christos 		}
   1602      1.1  christos 	}
   1603      1.1  christos 
   1604      1.1  christos 	/* Now check that the result is sane */
   1605      1.1  christos 	if (olen <= 0 || *inp + 1 > olen) {
   1606      1.1  christos 		dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
   1607      1.1  christos 		return;
   1608      1.1  christos 	}
   1609      1.1  christos 
   1610      1.1  christos 	/* Save it away */
   1611      1.1  christos 	fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
   1612      1.1  christos 	if (fd < 0) {
   1613      1.1  christos 		dbglog("EAP: error saving pseudonym: %m");
   1614      1.1  christos 		return;
   1615      1.1  christos 	}
   1616      1.1  christos 	len = write(fd, inp + 1, *inp);
   1617      1.1  christos 	if (close(fd) != -1 && len == *inp) {
   1618      1.1  christos 		dbglog("EAP: saved pseudonym");
   1619      1.1  christos 		esp->es_usedpseudo = 0;
   1620      1.1  christos 	} else {
   1621      1.1  christos 		dbglog("EAP: failed to save pseudonym");
   1622      1.1  christos 		remove_pn_file();
   1623      1.1  christos 	}
   1624      1.1  christos }
   1625  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   1626      1.1  christos 
   1627  1.1.1.5  christos #if PPP_WITH_CHAPMS
   1628  1.1.1.4  christos /*
   1629  1.1.1.4  christos  * Format and send an CHAPV2-Challenge EAP Response message.
   1630  1.1.1.4  christos  */
   1631  1.1.1.4  christos static void
   1632  1.1.1.4  christos eap_chapv2_response(eap_state *esp, u_char id, u_char chapid, u_char *response, char *user, int user_len)
   1633  1.1.1.4  christos {
   1634  1.1.1.4  christos     u_char *outp;
   1635  1.1.1.4  christos     int msglen;
   1636  1.1.1.4  christos 
   1637  1.1.1.4  christos     outp = outpacket_buf;
   1638  1.1.1.4  christos 
   1639  1.1.1.4  christos     MAKEHEADER(outp, PPP_EAP);
   1640  1.1.1.4  christos 
   1641  1.1.1.4  christos     PUTCHAR(EAP_RESPONSE, outp);
   1642  1.1.1.4  christos     PUTCHAR(id, outp);
   1643  1.1.1.4  christos     esp->es_client.ea_id = id;
   1644  1.1.1.4  christos     msglen = EAP_HEADERLEN + 6 * sizeof (u_char) + MS_CHAP2_RESPONSE_LEN + user_len;
   1645  1.1.1.4  christos     PUTSHORT(msglen, outp);
   1646  1.1.1.4  christos     PUTCHAR(EAPT_MSCHAPV2, outp);
   1647  1.1.1.4  christos     PUTCHAR(CHAP_RESPONSE, outp);
   1648  1.1.1.4  christos     PUTCHAR(chapid, outp);
   1649  1.1.1.4  christos     PUTCHAR(0, outp);
   1650  1.1.1.4  christos     /* len */
   1651  1.1.1.4  christos     PUTCHAR(5 + user_len + MS_CHAP2_RESPONSE_LEN, outp);
   1652  1.1.1.4  christos     BCOPY(response, outp, MS_CHAP2_RESPONSE_LEN+1); // VLEN + VALUE
   1653  1.1.1.4  christos     INCPTR(MS_CHAP2_RESPONSE_LEN+1, outp);
   1654  1.1.1.4  christos     BCOPY(user, outp, user_len);
   1655  1.1.1.4  christos 
   1656  1.1.1.4  christos     output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
   1657  1.1.1.4  christos }
   1658  1.1.1.4  christos #endif
   1659  1.1.1.4  christos 
   1660      1.1  christos /*
   1661      1.1  christos  * eap_request - Receive EAP Request message (client mode).
   1662      1.1  christos  */
   1663      1.1  christos static void
   1664  1.1.1.4  christos eap_request(eap_state *esp, u_char *inp, int id, int len)
   1665      1.1  christos {
   1666      1.1  christos 	u_char typenum;
   1667      1.1  christos 	u_char vallen;
   1668      1.1  christos 	int secret_len;
   1669      1.1  christos 	char secret[MAXWORDLEN];
   1670      1.1  christos 	char rhostname[256];
   1671  1.1.1.5  christos 	PPP_MD_CTX *mdctx;
   1672  1.1.1.5  christos 	u_char hash[MD5_DIGEST_LENGTH];
   1673  1.1.1.5  christos 	int hashlen = MD5_DIGEST_LENGTH;
   1674  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   1675  1.1.1.4  christos 	u_char flags;
   1676  1.1.1.4  christos 	struct eaptls_session *ets = esp->es_client.ea_session;
   1677  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   1678  1.1.1.4  christos 
   1679  1.1.1.5  christos #ifdef PPP_WITH_SRP
   1680      1.1  christos 	struct t_client *tc;
   1681      1.1  christos 	struct t_num sval, gval, Nval, *Ap, Bval;
   1682      1.1  christos 	u_char vals[2];
   1683  1.1.1.5  christos 	PPP_MD_CTX *ctxt;
   1684  1.1.1.5  christos 	u_char dig[SHA_DIGEST_LENGTH];
   1685  1.1.1.5  christos 	int diglen = sizeof(dig);
   1686      1.1  christos 	int fd;
   1687  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   1688      1.1  christos 
   1689      1.1  christos 	/*
   1690  1.1.1.4  christos 	 * Ignore requests if we're not open
   1691  1.1.1.4  christos 	 */
   1692  1.1.1.4  christos 	if (esp->es_client.ea_state <= eapClosed)
   1693  1.1.1.4  christos 		return;
   1694  1.1.1.4  christos 
   1695  1.1.1.4  christos 	/*
   1696      1.1  christos 	 * Note: we update es_client.ea_id *only if* a Response
   1697      1.1  christos 	 * message is being generated.  Otherwise, we leave it the
   1698      1.1  christos 	 * same for duplicate detection purposes.
   1699      1.1  christos 	 */
   1700      1.1  christos 
   1701      1.1  christos 	esp->es_client.ea_requests++;
   1702      1.1  christos 	if (esp->es_client.ea_maxrequests != 0 &&
   1703      1.1  christos 	    esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
   1704      1.1  christos 		info("EAP: received too many Request messages");
   1705      1.1  christos 		if (esp->es_client.ea_timeout > 0) {
   1706      1.1  christos 			UNTIMEOUT(eap_client_timeout, (void *)esp);
   1707      1.1  christos 		}
   1708      1.1  christos 		auth_withpeer_fail(esp->es_unit, PPP_EAP);
   1709      1.1  christos 		return;
   1710      1.1  christos 	}
   1711      1.1  christos 
   1712      1.1  christos 	if (len <= 0) {
   1713      1.1  christos 		error("EAP: empty Request message discarded");
   1714      1.1  christos 		return;
   1715      1.1  christos 	}
   1716      1.1  christos 
   1717      1.1  christos 	GETCHAR(typenum, inp);
   1718      1.1  christos 	len--;
   1719      1.1  christos 
   1720      1.1  christos 	switch (typenum) {
   1721      1.1  christos 	case EAPT_IDENTITY:
   1722      1.1  christos 		if (len > 0)
   1723      1.1  christos 			info("EAP: Identity prompt \"%.*q\"", len, inp);
   1724  1.1.1.5  christos #ifdef PPP_WITH_SRP
   1725      1.1  christos 		if (esp->es_usepseudo &&
   1726      1.1  christos 		    (esp->es_usedpseudo == 0 ||
   1727      1.1  christos 			(esp->es_usedpseudo == 1 &&
   1728      1.1  christos 			    id == esp->es_client.ea_id))) {
   1729      1.1  christos 			esp->es_usedpseudo = 1;
   1730      1.1  christos 			/* Try to get a pseudonym */
   1731      1.1  christos 			if ((fd = open_pn_file(O_RDONLY)) >= 0) {
   1732      1.1  christos 				strcpy(rhostname, SRP_PSEUDO_ID);
   1733      1.1  christos 				len = read(fd, rhostname + SRP_PSEUDO_LEN,
   1734      1.1  christos 				    sizeof (rhostname) - SRP_PSEUDO_LEN);
   1735      1.1  christos 				/* XXX NAI unsupported */
   1736      1.1  christos 				if (len > 0) {
   1737      1.1  christos 					eap_send_response(esp, id, typenum,
   1738      1.1  christos 					    rhostname, len + SRP_PSEUDO_LEN);
   1739      1.1  christos 				}
   1740      1.1  christos 				(void) close(fd);
   1741      1.1  christos 				if (len > 0)
   1742      1.1  christos 					break;
   1743      1.1  christos 			}
   1744      1.1  christos 		}
   1745      1.1  christos 		/* Stop using pseudonym now. */
   1746      1.1  christos 		if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
   1747      1.1  christos 			remove_pn_file();
   1748      1.1  christos 			esp->es_usedpseudo = 2;
   1749      1.1  christos 		}
   1750  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   1751  1.1.1.4  christos 		eap_send_response(esp, id, typenum, (u_char *)esp->es_client.ea_name,
   1752      1.1  christos 		    esp->es_client.ea_namelen);
   1753      1.1  christos 		break;
   1754      1.1  christos 
   1755      1.1  christos 	case EAPT_NOTIFICATION:
   1756      1.1  christos 		if (len > 0)
   1757      1.1  christos 			info("EAP: Notification \"%.*q\"", len, inp);
   1758      1.1  christos 		eap_send_response(esp, id, typenum, NULL, 0);
   1759      1.1  christos 		break;
   1760      1.1  christos 
   1761      1.1  christos 	case EAPT_NAK:
   1762      1.1  christos 		/*
   1763      1.1  christos 		 * Avoid the temptation to send Response Nak in reply
   1764      1.1  christos 		 * to Request Nak here.  It can only lead to trouble.
   1765      1.1  christos 		 */
   1766      1.1  christos 		warn("EAP: unexpected Nak in Request; ignored");
   1767      1.1  christos 		/* Return because we're waiting for something real. */
   1768      1.1  christos 		return;
   1769      1.1  christos 
   1770      1.1  christos 	case EAPT_MD5CHAP:
   1771      1.1  christos 		if (len < 1) {
   1772      1.1  christos 			error("EAP: received MD5-Challenge with no data");
   1773      1.1  christos 			/* Bogus request; wait for something real. */
   1774      1.1  christos 			return;
   1775      1.1  christos 		}
   1776      1.1  christos 		GETCHAR(vallen, inp);
   1777      1.1  christos 		len--;
   1778      1.1  christos 		if (vallen < 8 || vallen > len) {
   1779      1.1  christos 			error("EAP: MD5-Challenge with bad length %d (8..%d)",
   1780      1.1  christos 			    vallen, len);
   1781      1.1  christos 			/* Try something better. */
   1782      1.1  christos 			eap_send_nak(esp, id, EAPT_SRP);
   1783      1.1  christos 			break;
   1784      1.1  christos 		}
   1785      1.1  christos 
   1786      1.1  christos 		/* Not so likely to happen. */
   1787  1.1.1.4  christos 		if (len - vallen >= sizeof (rhostname)) {
   1788      1.1  christos 			dbglog("EAP: trimming really long peer name down");
   1789      1.1  christos 			BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
   1790      1.1  christos 			rhostname[sizeof (rhostname) - 1] = '\0';
   1791      1.1  christos 		} else {
   1792      1.1  christos 			BCOPY(inp + vallen, rhostname, len - vallen);
   1793      1.1  christos 			rhostname[len - vallen] = '\0';
   1794      1.1  christos 		}
   1795      1.1  christos 
   1796      1.1  christos 		/* In case the remote doesn't give us his name. */
   1797      1.1  christos 		if (explicit_remote ||
   1798      1.1  christos 		    (remote_name[0] != '\0' && vallen == len))
   1799      1.1  christos 			strlcpy(rhostname, remote_name, sizeof (rhostname));
   1800      1.1  christos 
   1801      1.1  christos 		/*
   1802      1.1  christos 		 * Get the secret for authenticating ourselves with
   1803      1.1  christos 		 * the specified host.
   1804      1.1  christos 		 */
   1805      1.1  christos 		if (!get_secret(esp->es_unit, esp->es_client.ea_name,
   1806      1.1  christos 		    rhostname, secret, &secret_len, 0)) {
   1807      1.1  christos 			dbglog("EAP: no MD5 secret for auth to %q", rhostname);
   1808      1.1  christos 			eap_send_nak(esp, id, EAPT_SRP);
   1809      1.1  christos 			break;
   1810      1.1  christos 		}
   1811  1.1.1.5  christos 
   1812  1.1.1.5  christos 		mdctx = PPP_MD_CTX_new();
   1813  1.1.1.5  christos 		if (mdctx != NULL) {
   1814  1.1.1.5  christos 			if (PPP_DigestInit(mdctx, PPP_md5())) {
   1815  1.1.1.5  christos 				typenum = id;
   1816  1.1.1.5  christos 				if (PPP_DigestUpdate(mdctx, &typenum, 1)) {
   1817  1.1.1.5  christos 					if (PPP_DigestUpdate(mdctx, secret, secret_len)) {
   1818  1.1.1.5  christos 						BZERO(secret, sizeof(secret));
   1819  1.1.1.5  christos 						if (PPP_DigestUpdate(mdctx, inp, vallen)) {
   1820  1.1.1.5  christos 							if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
   1821  1.1.1.5  christos 								eap_chap_response(esp, id, hash, esp->es_client.ea_name,
   1822  1.1.1.5  christos 										esp->es_client.ea_namelen);
   1823  1.1.1.5  christos 								PPP_MD_CTX_free(mdctx);
   1824  1.1.1.5  christos 								break;
   1825  1.1.1.5  christos 							}
   1826  1.1.1.5  christos 						}
   1827  1.1.1.5  christos 					}
   1828  1.1.1.5  christos 				}
   1829  1.1.1.5  christos 			}
   1830  1.1.1.5  christos 			PPP_MD_CTX_free(mdctx);
   1831  1.1.1.5  christos 		}
   1832  1.1.1.5  christos 		dbglog("EAP: Invalid MD5 checksum");
   1833  1.1.1.5  christos         eap_send_nak(esp, id, EAPT_SRP);
   1834      1.1  christos 		break;
   1835      1.1  christos 
   1836  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   1837  1.1.1.4  christos 	case EAPT_TLS:
   1838  1.1.1.4  christos 
   1839  1.1.1.4  christos 		switch(esp->es_client.ea_state) {
   1840  1.1.1.4  christos 
   1841  1.1.1.4  christos 		case eapListen:
   1842  1.1.1.4  christos 
   1843  1.1.1.4  christos 			if (len < 1) {
   1844  1.1.1.4  christos 				error("EAP: received EAP-TLS Listen packet with no data");
   1845  1.1.1.4  christos 				/* Bogus request; wait for something real. */
   1846  1.1.1.4  christos 				return;
   1847  1.1.1.4  christos 			}
   1848  1.1.1.4  christos 			GETCHAR(flags, inp);
   1849  1.1.1.4  christos 			if(flags & EAP_TLS_FLAGS_START){
   1850  1.1.1.4  christos 
   1851  1.1.1.4  christos 				esp->es_client.ea_using_eaptls = 1;
   1852  1.1.1.4  christos 
   1853  1.1.1.4  christos 				if (explicit_remote){
   1854  1.1.1.4  christos 					esp->es_client.ea_peer = strdup(remote_name);
   1855  1.1.1.4  christos 					esp->es_client.ea_peerlen = strlen(remote_name);
   1856  1.1.1.4  christos 				} else
   1857  1.1.1.4  christos 					esp->es_client.ea_peer = NULL;
   1858  1.1.1.4  christos 
   1859  1.1.1.4  christos 				/* Init ssl session */
   1860  1.1.1.4  christos 				if(!eaptls_init_ssl_client(esp)) {
   1861  1.1.1.4  christos 					dbglog("cannot init ssl");
   1862  1.1.1.4  christos 					eap_send_nak(esp, id, EAPT_MSCHAPV2);
   1863  1.1.1.4  christos 					esp->es_client.ea_using_eaptls = 0;
   1864  1.1.1.4  christos 					break;
   1865  1.1.1.4  christos 				}
   1866  1.1.1.4  christos 
   1867  1.1.1.4  christos 				ets = esp->es_client.ea_session;
   1868  1.1.1.4  christos 				eap_tls_response(esp, id);
   1869  1.1.1.4  christos 				esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
   1870  1.1.1.4  christos 				break;
   1871  1.1.1.4  christos 			}
   1872  1.1.1.4  christos 
   1873  1.1.1.4  christos 			/* The server has sent a bad start packet. */
   1874  1.1.1.4  christos 			eap_send_nak(esp, id, EAPT_MSCHAPV2);
   1875  1.1.1.4  christos 			break;
   1876  1.1.1.4  christos 
   1877  1.1.1.4  christos 		case eapTlsRecvAck:
   1878  1.1.1.4  christos 			eap_tls_response(esp, id);
   1879  1.1.1.4  christos 			esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
   1880  1.1.1.4  christos 			break;
   1881  1.1.1.4  christos 
   1882  1.1.1.4  christos 		case eapTlsRecv:
   1883  1.1.1.4  christos 			if (len < 1) {
   1884  1.1.1.4  christos 				error("EAP: discarding EAP-TLS Receive packet with no data");
   1885  1.1.1.4  christos 				/* Bogus request; wait for something real. */
   1886  1.1.1.4  christos 				return;
   1887  1.1.1.4  christos 			}
   1888  1.1.1.4  christos 			eaptls_receive(ets, inp, len);
   1889  1.1.1.4  christos 
   1890  1.1.1.4  christos 			if(ets->frag) {
   1891  1.1.1.4  christos 				eap_tls_sendack(esp, id);
   1892  1.1.1.4  christos 				esp->es_client.ea_state = eapTlsRecv;
   1893  1.1.1.4  christos 				break;
   1894  1.1.1.4  christos 			}
   1895  1.1.1.4  christos 
   1896  1.1.1.4  christos 			if(ets->alert_recv) {
   1897  1.1.1.4  christos 				eap_tls_sendack(esp, id);
   1898  1.1.1.4  christos 				esp->es_client.ea_state = eapTlsRecvFailure;
   1899  1.1.1.4  christos 				break;
   1900  1.1.1.4  christos 			}
   1901  1.1.1.4  christos 
   1902  1.1.1.4  christos 			/* Check if TLS handshake is finished */
   1903  1.1.1.4  christos 			if(eaptls_is_init_finished(ets)) {
   1904  1.1.1.5  christos #ifdef PPP_WITH_MPPE
   1905  1.1.1.4  christos 				eaptls_gen_mppe_keys(ets, 1);
   1906  1.1.1.4  christos #endif
   1907  1.1.1.4  christos 				eaptls_free_session(ets);
   1908  1.1.1.4  christos 				eap_tls_sendack(esp, id);
   1909  1.1.1.4  christos 				esp->es_client.ea_state = eapTlsRecvSuccess;
   1910  1.1.1.4  christos 				break;
   1911  1.1.1.4  christos 			}
   1912  1.1.1.4  christos 
   1913  1.1.1.4  christos 			eap_tls_response(esp,id);
   1914  1.1.1.4  christos 			esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
   1915  1.1.1.4  christos 			break;
   1916  1.1.1.4  christos 
   1917  1.1.1.4  christos 		default:
   1918  1.1.1.4  christos 			eap_send_nak(esp, id, EAPT_MSCHAPV2);
   1919  1.1.1.4  christos 			esp->es_client.ea_using_eaptls = 0;
   1920  1.1.1.4  christos 			break;
   1921  1.1.1.4  christos 		}
   1922  1.1.1.4  christos 
   1923  1.1.1.4  christos 		break;
   1924  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   1925  1.1.1.4  christos 
   1926  1.1.1.5  christos #ifdef PPP_WITH_SRP
   1927      1.1  christos 	case EAPT_SRP:
   1928      1.1  christos 		if (len < 1) {
   1929      1.1  christos 			error("EAP: received empty SRP Request");
   1930      1.1  christos 			/* Bogus request; wait for something real. */
   1931      1.1  christos 			return;
   1932      1.1  christos 		}
   1933      1.1  christos 
   1934      1.1  christos 		/* Get subtype */
   1935      1.1  christos 		GETCHAR(vallen, inp);
   1936      1.1  christos 		len--;
   1937      1.1  christos 		switch (vallen) {
   1938      1.1  christos 		case EAPSRP_CHALLENGE:
   1939      1.1  christos 			tc = NULL;
   1940      1.1  christos 			if (esp->es_client.ea_session != NULL) {
   1941      1.1  christos 				tc = (struct t_client *)esp->es_client.
   1942      1.1  christos 				    ea_session;
   1943      1.1  christos 				/*
   1944      1.1  christos 				 * If this is a new challenge, then start
   1945      1.1  christos 				 * over with a new client session context.
   1946      1.1  christos 				 * Otherwise, just resend last response.
   1947      1.1  christos 				 */
   1948      1.1  christos 				if (id != esp->es_client.ea_id) {
   1949      1.1  christos 					t_clientclose(tc);
   1950      1.1  christos 					esp->es_client.ea_session = NULL;
   1951      1.1  christos 					tc = NULL;
   1952      1.1  christos 				}
   1953      1.1  christos 			}
   1954      1.1  christos 			/* No session key just yet */
   1955      1.1  christos 			esp->es_client.ea_skey = NULL;
   1956      1.1  christos 			if (tc == NULL) {
   1957      1.1  christos 				GETCHAR(vallen, inp);
   1958      1.1  christos 				len--;
   1959      1.1  christos 				if (vallen >= len) {
   1960      1.1  christos 					error("EAP: badly-formed SRP Challenge"
   1961      1.1  christos 					    " (name)");
   1962      1.1  christos 					/* Ignore badly-formed messages */
   1963      1.1  christos 					return;
   1964      1.1  christos 				}
   1965      1.1  christos 				BCOPY(inp, rhostname, vallen);
   1966      1.1  christos 				rhostname[vallen] = '\0';
   1967      1.1  christos 				INCPTR(vallen, inp);
   1968      1.1  christos 				len -= vallen;
   1969      1.1  christos 
   1970      1.1  christos 				/*
   1971      1.1  christos 				 * In case the remote doesn't give us his name,
   1972      1.1  christos 				 * use configured name.
   1973      1.1  christos 				 */
   1974      1.1  christos 				if (explicit_remote ||
   1975      1.1  christos 				    (remote_name[0] != '\0' && vallen == 0)) {
   1976      1.1  christos 					strlcpy(rhostname, remote_name,
   1977      1.1  christos 					    sizeof (rhostname));
   1978      1.1  christos 				}
   1979      1.1  christos 
   1980      1.1  christos 				if (esp->es_client.ea_peer != NULL)
   1981      1.1  christos 					free(esp->es_client.ea_peer);
   1982      1.1  christos 				esp->es_client.ea_peer = strdup(rhostname);
   1983      1.1  christos 				esp->es_client.ea_peerlen = strlen(rhostname);
   1984      1.1  christos 
   1985      1.1  christos 				GETCHAR(vallen, inp);
   1986      1.1  christos 				len--;
   1987      1.1  christos 				if (vallen >= len) {
   1988      1.1  christos 					error("EAP: badly-formed SRP Challenge"
   1989      1.1  christos 					    " (s)");
   1990      1.1  christos 					/* Ignore badly-formed messages */
   1991      1.1  christos 					return;
   1992      1.1  christos 				}
   1993      1.1  christos 				sval.data = inp;
   1994      1.1  christos 				sval.len = vallen;
   1995      1.1  christos 				INCPTR(vallen, inp);
   1996      1.1  christos 				len -= vallen;
   1997      1.1  christos 
   1998      1.1  christos 				GETCHAR(vallen, inp);
   1999      1.1  christos 				len--;
   2000      1.1  christos 				if (vallen > len) {
   2001      1.1  christos 					error("EAP: badly-formed SRP Challenge"
   2002      1.1  christos 					    " (g)");
   2003      1.1  christos 					/* Ignore badly-formed messages */
   2004      1.1  christos 					return;
   2005      1.1  christos 				}
   2006      1.1  christos 				/* If no generator present, then use value 2 */
   2007      1.1  christos 				if (vallen == 0) {
   2008      1.1  christos 					gval.data = (u_char *)"\002";
   2009      1.1  christos 					gval.len = 1;
   2010      1.1  christos 				} else {
   2011      1.1  christos 					gval.data = inp;
   2012      1.1  christos 					gval.len = vallen;
   2013      1.1  christos 				}
   2014      1.1  christos 				INCPTR(vallen, inp);
   2015      1.1  christos 				len -= vallen;
   2016      1.1  christos 
   2017      1.1  christos 				/*
   2018      1.1  christos 				 * If no modulus present, then use well-known
   2019      1.1  christos 				 * value.
   2020      1.1  christos 				 */
   2021      1.1  christos 				if (len == 0) {
   2022      1.1  christos 					Nval.data = (u_char *)wkmodulus;
   2023      1.1  christos 					Nval.len = sizeof (wkmodulus);
   2024      1.1  christos 				} else {
   2025      1.1  christos 					Nval.data = inp;
   2026      1.1  christos 					Nval.len = len;
   2027      1.1  christos 				}
   2028      1.1  christos 				tc = t_clientopen(esp->es_client.ea_name,
   2029      1.1  christos 				    &Nval, &gval, &sval);
   2030      1.1  christos 				if (tc == NULL) {
   2031      1.1  christos 					eap_send_nak(esp, id, EAPT_MD5CHAP);
   2032      1.1  christos 					break;
   2033      1.1  christos 				}
   2034      1.1  christos 				esp->es_client.ea_session = (void *)tc;
   2035      1.1  christos 
   2036      1.1  christos 				/* Add Challenge ID & type to verifier */
   2037      1.1  christos 				vals[0] = id;
   2038      1.1  christos 				vals[1] = EAPT_SRP;
   2039      1.1  christos 				t_clientaddexdata(tc, vals, 2);
   2040      1.1  christos 			}
   2041      1.1  christos 			Ap = t_clientgenexp(tc);
   2042      1.1  christos 			eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
   2043      1.1  christos 			    Ap->len);
   2044      1.1  christos 			break;
   2045      1.1  christos 
   2046      1.1  christos 		case EAPSRP_SKEY:
   2047      1.1  christos 			tc = (struct t_client *)esp->es_client.ea_session;
   2048      1.1  christos 			if (tc == NULL) {
   2049      1.1  christos 				warn("EAP: peer sent Subtype 2 without 1");
   2050      1.1  christos 				eap_send_nak(esp, id, EAPT_MD5CHAP);
   2051      1.1  christos 				break;
   2052      1.1  christos 			}
   2053      1.1  christos 			if (esp->es_client.ea_skey != NULL) {
   2054      1.1  christos 				/*
   2055      1.1  christos 				 * ID number should not change here.  Warn
   2056      1.1  christos 				 * if it does (but otherwise ignore).
   2057      1.1  christos 				 */
   2058      1.1  christos 				if (id != esp->es_client.ea_id) {
   2059      1.1  christos 					warn("EAP: ID changed from %d to %d "
   2060      1.1  christos 					    "in SRP Subtype 2 rexmit",
   2061      1.1  christos 					    esp->es_client.ea_id, id);
   2062      1.1  christos 				}
   2063      1.1  christos 			} else {
   2064      1.1  christos 				if (get_srp_secret(esp->es_unit,
   2065      1.1  christos 				    esp->es_client.ea_name,
   2066      1.1  christos 				    esp->es_client.ea_peer, secret, 0) == 0) {
   2067      1.1  christos 					/*
   2068      1.1  christos 					 * Can't work with this peer because
   2069      1.1  christos 					 * the secret is missing.  Just give
   2070      1.1  christos 					 * up.
   2071      1.1  christos 					 */
   2072      1.1  christos 					eap_send_nak(esp, id, EAPT_MD5CHAP);
   2073      1.1  christos 					break;
   2074      1.1  christos 				}
   2075      1.1  christos 				Bval.data = inp;
   2076      1.1  christos 				Bval.len = len;
   2077      1.1  christos 				t_clientpasswd(tc, secret);
   2078      1.1  christos 				BZERO(secret, sizeof (secret));
   2079      1.1  christos 				esp->es_client.ea_skey =
   2080      1.1  christos 				    t_clientgetkey(tc, &Bval);
   2081      1.1  christos 				if (esp->es_client.ea_skey == NULL) {
   2082      1.1  christos 					/* Server is rogue; stop now */
   2083      1.1  christos 					error("EAP: SRP server is rogue");
   2084      1.1  christos 					goto client_failure;
   2085      1.1  christos 				}
   2086      1.1  christos 			}
   2087      1.1  christos 			eap_srpval_response(esp, id, SRPVAL_EBIT,
   2088      1.1  christos 			    t_clientresponse(tc));
   2089      1.1  christos 			break;
   2090      1.1  christos 
   2091      1.1  christos 		case EAPSRP_SVALIDATOR:
   2092      1.1  christos 			tc = (struct t_client *)esp->es_client.ea_session;
   2093      1.1  christos 			if (tc == NULL || esp->es_client.ea_skey == NULL) {
   2094      1.1  christos 				warn("EAP: peer sent Subtype 3 without 1/2");
   2095      1.1  christos 				eap_send_nak(esp, id, EAPT_MD5CHAP);
   2096      1.1  christos 				break;
   2097      1.1  christos 			}
   2098      1.1  christos 			/*
   2099      1.1  christos 			 * If we're already open, then this ought to be a
   2100      1.1  christos 			 * duplicate.  Otherwise, check that the server is
   2101      1.1  christos 			 * who we think it is.
   2102      1.1  christos 			 */
   2103      1.1  christos 			if (esp->es_client.ea_state == eapOpen) {
   2104      1.1  christos 				if (id != esp->es_client.ea_id) {
   2105      1.1  christos 					warn("EAP: ID changed from %d to %d "
   2106      1.1  christos 					    "in SRP Subtype 3 rexmit",
   2107      1.1  christos 					    esp->es_client.ea_id, id);
   2108      1.1  christos 				}
   2109      1.1  christos 			} else {
   2110  1.1.1.5  christos 				len -= sizeof (u_int32_t) + SHA_DIGEST_LENGTH;
   2111      1.1  christos 				if (len < 0 || t_clientverify(tc, inp +
   2112      1.1  christos 					sizeof (u_int32_t)) != 0) {
   2113      1.1  christos 					error("EAP: SRP server verification "
   2114      1.1  christos 					    "failed");
   2115      1.1  christos 					goto client_failure;
   2116      1.1  christos 				}
   2117      1.1  christos 				GETLONG(esp->es_client.ea_keyflags, inp);
   2118      1.1  christos 				/* Save pseudonym if user wants it. */
   2119      1.1  christos 				if (len > 0 && esp->es_usepseudo) {
   2120  1.1.1.5  christos 					INCPTR(SHA_DIGEST_LENGTH, inp);
   2121      1.1  christos 					write_pseudonym(esp, inp, len, id);
   2122      1.1  christos 				}
   2123      1.1  christos 			}
   2124      1.1  christos 			/*
   2125      1.1  christos 			 * We've verified our peer.  We're now mostly done,
   2126      1.1  christos 			 * except for waiting on the regular EAP Success
   2127      1.1  christos 			 * message.
   2128      1.1  christos 			 */
   2129      1.1  christos 			eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
   2130      1.1  christos 			break;
   2131      1.1  christos 
   2132      1.1  christos 		case EAPSRP_LWRECHALLENGE:
   2133      1.1  christos 			if (len < 4) {
   2134      1.1  christos 				warn("EAP: malformed Lightweight rechallenge");
   2135      1.1  christos 				return;
   2136      1.1  christos 			}
   2137  1.1.1.5  christos 			ctxt = PPP_MD_CTX_new();
   2138  1.1.1.5  christos 			if (ctxt) {
   2139  1.1.1.5  christos 
   2140  1.1.1.5  christos 				vals[0] = id;
   2141  1.1.1.5  christos 				PPP_DigestInit(ctxt, PPP_sha1());
   2142  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, vals, 1);
   2143  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
   2144  1.1.1.5  christos 					SESSION_KEY_LEN);
   2145  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, inp, len);
   2146  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
   2147  1.1.1.5  christos 					esp->es_client.ea_namelen);
   2148  1.1.1.5  christos 				PPP_DigestFinal(ctxt, dig, &diglen);
   2149  1.1.1.5  christos 
   2150  1.1.1.5  christos 				PPP_MD_CTX_free(ctxt);
   2151  1.1.1.5  christos 
   2152  1.1.1.5  christos 				eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
   2153  1.1.1.5  christos 					SHA_DIGEST_LENGTH);
   2154  1.1.1.5  christos 			}
   2155      1.1  christos 			break;
   2156      1.1  christos 
   2157      1.1  christos 		default:
   2158      1.1  christos 			error("EAP: unknown SRP Subtype %d", vallen);
   2159      1.1  christos 			eap_send_nak(esp, id, EAPT_MD5CHAP);
   2160      1.1  christos 			break;
   2161      1.1  christos 		}
   2162      1.1  christos 		break;
   2163  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   2164  1.1.1.5  christos 
   2165  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
   2166  1.1.1.4  christos         case EAPT_MSCHAPV2:
   2167  1.1.1.4  christos 	    if (len < 4) {
   2168  1.1.1.4  christos 		error("EAP: received invalid MSCHAPv2 packet, too short");
   2169  1.1.1.4  christos 		return;
   2170  1.1.1.4  christos 	    }
   2171  1.1.1.4  christos 	    unsigned char opcode;
   2172  1.1.1.4  christos 	    GETCHAR(opcode, inp);
   2173  1.1.1.4  christos 	    unsigned char chapid; /* Chapv2-ID */
   2174  1.1.1.4  christos 	    GETCHAR(chapid, inp);
   2175  1.1.1.4  christos 	    short mssize;
   2176  1.1.1.4  christos 	    GETSHORT(mssize, inp);
   2177  1.1.1.4  christos 
   2178  1.1.1.4  christos 	    /* Validate the mssize field */
   2179  1.1.1.4  christos 	    if (len != mssize) {
   2180  1.1.1.4  christos 		error("EAP: received invalid MSCHAPv2 packet, invalid length");
   2181  1.1.1.4  christos 		return;
   2182  1.1.1.4  christos 	    }
   2183  1.1.1.4  christos 	    len -= 4;
   2184  1.1.1.4  christos 
   2185  1.1.1.4  christos 	    /* If MSCHAPv2 digest was not found, NAK the packet */
   2186  1.1.1.4  christos 	    if (!esp->es_client.digest) {
   2187  1.1.1.4  christos 		error("EAP MSCHAPv2 not supported");
   2188  1.1.1.4  christos 		eap_send_nak(esp, id, EAPT_SRP);
   2189  1.1.1.4  christos 		return;
   2190  1.1.1.4  christos 	    }
   2191  1.1.1.4  christos 
   2192  1.1.1.4  christos 	    switch (opcode) {
   2193  1.1.1.4  christos 	    case CHAP_CHALLENGE: {
   2194  1.1.1.4  christos 
   2195  1.1.1.4  christos 		/* make_response() expects: VLEN + VALUE */
   2196  1.1.1.4  christos 		u_char *challenge = inp;
   2197  1.1.1.4  christos 
   2198  1.1.1.4  christos 		unsigned char vsize;
   2199  1.1.1.4  christos 		GETCHAR(vsize, inp);
   2200  1.1.1.4  christos                 len -= 1;
   2201  1.1.1.4  christos 
   2202  1.1.1.4  christos 		/* Validate the VALUE field */
   2203  1.1.1.4  christos                 if (vsize != MS_CHAP2_PEER_CHAL_LEN || len < MS_CHAP2_PEER_CHAL_LEN) {
   2204  1.1.1.4  christos                     error("EAP: received invalid MSCHAPv2 packet, invalid value-length: %d", vsize);
   2205  1.1.1.4  christos                     return;
   2206  1.1.1.4  christos                 }
   2207  1.1.1.4  christos 
   2208  1.1.1.4  christos 		/* Increment past the VALUE field */
   2209  1.1.1.4  christos 		INCPTR(MS_CHAP2_PEER_CHAL_LEN, inp);
   2210  1.1.1.4  christos 		len -= MS_CHAP2_PEER_CHAL_LEN;
   2211  1.1.1.4  christos 
   2212  1.1.1.4  christos 		/* Extract the hostname */
   2213  1.1.1.4  christos 		rhostname[0] = '\0';
   2214  1.1.1.4  christos 		if (len > 0) {
   2215  1.1.1.4  christos 		    if (len >= sizeof (rhostname)) {
   2216  1.1.1.4  christos 			dbglog("EAP: trimming really long peer name down");
   2217  1.1.1.4  christos 			len = sizeof(rhostname) - 1;
   2218  1.1.1.4  christos 		    }
   2219  1.1.1.4  christos 		    BCOPY(inp, rhostname, len);
   2220  1.1.1.4  christos 		    rhostname[len] = '\0';
   2221  1.1.1.4  christos 		}
   2222  1.1.1.4  christos 
   2223  1.1.1.4  christos 		/* In case the remote doesn't give us his name. */
   2224  1.1.1.4  christos 		if (explicit_remote || (remote_name[0] != '\0' && len == 0))
   2225  1.1.1.4  christos 		    strlcpy(rhostname, remote_name, sizeof(rhostname));
   2226  1.1.1.4  christos 
   2227  1.1.1.4  christos 		/* Get the secret for authenticating ourselves with the specified host. */
   2228  1.1.1.4  christos 		if (!get_secret(esp->es_unit, esp->es_client.ea_name,
   2229  1.1.1.4  christos 		    rhostname, secret, &secret_len, 0)) {
   2230  1.1.1.4  christos 		    dbglog("EAP: no CHAP secret for auth to %q", rhostname);
   2231  1.1.1.4  christos 		    eap_send_nak(esp, id, EAPT_SRP);
   2232  1.1.1.4  christos 		    break;
   2233  1.1.1.4  christos 		}
   2234  1.1.1.5  christos 		esp->es_client.ea_namelen = strlen(esp->es_client.ea_name);
   2235  1.1.1.4  christos 
   2236  1.1.1.4  christos 		/* Create the MSCHAPv2 response (and add to cache) */
   2237  1.1.1.4  christos 		unsigned char response[MS_CHAP2_RESPONSE_LEN+1]; // VLEN + VALUE
   2238  1.1.1.4  christos 		esp->es_client.digest->make_response(response, chapid, esp->es_client.ea_name,
   2239  1.1.1.4  christos 			challenge, secret, secret_len, NULL);
   2240  1.1.1.4  christos 
   2241  1.1.1.4  christos 		eap_chapv2_response(esp, id, chapid, response, esp->es_client.ea_name, esp->es_client.ea_namelen);
   2242  1.1.1.4  christos 		break;
   2243  1.1.1.4  christos 	    }
   2244  1.1.1.4  christos 	    case CHAP_SUCCESS: {
   2245  1.1.1.4  christos 
   2246  1.1.1.4  christos 		/* Check response for mutual authentication */
   2247  1.1.1.4  christos 		u_char status = CHAP_FAILURE;
   2248  1.1.1.4  christos 		if (esp->es_client.digest->check_success(chapid, inp, len) == 1) {
   2249  1.1.1.4  christos 		     info("Chap authentication succeeded! %.*v", len, inp);
   2250  1.1.1.4  christos 		     status = CHAP_SUCCESS;
   2251  1.1.1.4  christos 		}
   2252  1.1.1.4  christos 		eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
   2253  1.1.1.4  christos 		break;
   2254  1.1.1.4  christos 	    }
   2255  1.1.1.4  christos 	    case CHAP_FAILURE: {
   2256  1.1.1.4  christos 
   2257  1.1.1.4  christos 		/* Process the failure string, and log appropriate information */
   2258  1.1.1.4  christos 		esp->es_client.digest->handle_failure(inp, len);
   2259  1.1.1.4  christos 
   2260  1.1.1.4  christos 		u_char status = CHAP_FAILURE;
   2261  1.1.1.4  christos 		eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
   2262  1.1.1.4  christos 		goto client_failure; /* force termination */
   2263  1.1.1.4  christos 	    }
   2264  1.1.1.4  christos 	    default:
   2265  1.1.1.4  christos 
   2266  1.1.1.4  christos                 error("EAP: received invalid MSCHAPv2 packet, invalid or unsupported opcode: %d", opcode);
   2267  1.1.1.4  christos 		eap_send_nak(esp, id, EAPT_SRP);
   2268  1.1.1.4  christos 	    }
   2269  1.1.1.4  christos 
   2270  1.1.1.4  christos 	    break;
   2271  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
   2272  1.1.1.5  christos #ifdef PPP_WITH_PEAP
   2273  1.1.1.5  christos 	case EAPT_PEAP:
   2274  1.1.1.5  christos 
   2275  1.1.1.5  christos 		/* Initialize the PEAP context (if not already initialized) */
   2276  1.1.1.5  christos 		if (!esp->ea_peap) {
   2277  1.1.1.5  christos 			rhostname[0] = '\0';
   2278  1.1.1.5  christos 			if (explicit_remote || (remote_name[0] != '\0')) {
   2279  1.1.1.5  christos 				strlcpy(rhostname, remote_name, sizeof (rhostname));
   2280  1.1.1.5  christos 			}
   2281  1.1.1.5  christos 			if (peap_init(&esp->ea_peap, rhostname)) {
   2282  1.1.1.5  christos 				eap_send_nak(esp, id, EAPT_TLS);
   2283  1.1.1.5  christos 				break;
   2284  1.1.1.5  christos 			}
   2285  1.1.1.5  christos 		}
   2286  1.1.1.5  christos 
   2287  1.1.1.5  christos 		/* Process the PEAP packet */
   2288  1.1.1.5  christos 		if (peap_process(esp, id, inp, len)) {
   2289  1.1.1.5  christos 			eap_send_nak(esp, id, EAPT_TLS);
   2290  1.1.1.5  christos 		}
   2291  1.1.1.5  christos 
   2292  1.1.1.5  christos 		break;
   2293  1.1.1.5  christos #endif // PPP_WITH_PEAP
   2294      1.1  christos 
   2295      1.1  christos 	default:
   2296      1.1  christos 		info("EAP: unknown authentication type %d; Naking", typenum);
   2297      1.1  christos 		eap_send_nak(esp, id, EAPT_SRP);
   2298      1.1  christos 		break;
   2299      1.1  christos 	}
   2300      1.1  christos 
   2301      1.1  christos 	if (esp->es_client.ea_timeout > 0) {
   2302      1.1  christos 		UNTIMEOUT(eap_client_timeout, (void *)esp);
   2303      1.1  christos 		TIMEOUT(eap_client_timeout, (void *)esp,
   2304      1.1  christos 		    esp->es_client.ea_timeout);
   2305      1.1  christos 	}
   2306      1.1  christos 	return;
   2307      1.1  christos 
   2308      1.1  christos client_failure:
   2309      1.1  christos 	esp->es_client.ea_state = eapBadAuth;
   2310      1.1  christos 	if (esp->es_client.ea_timeout > 0) {
   2311      1.1  christos 		UNTIMEOUT(eap_client_timeout, (void *)esp);
   2312      1.1  christos 	}
   2313      1.1  christos 	esp->es_client.ea_session = NULL;
   2314  1.1.1.5  christos #ifdef PPP_WITH_SRP
   2315      1.1  christos 	t_clientclose(tc);
   2316      1.1  christos 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
   2317  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   2318      1.1  christos }
   2319      1.1  christos 
   2320      1.1  christos /*
   2321      1.1  christos  * eap_response - Receive EAP Response message (server mode).
   2322      1.1  christos  */
   2323      1.1  christos static void
   2324  1.1.1.4  christos eap_response(eap_state *esp, u_char *inp, int id, int len)
   2325      1.1  christos {
   2326      1.1  christos 	u_char typenum;
   2327      1.1  christos 	u_char vallen;
   2328      1.1  christos 	int secret_len;
   2329      1.1  christos 	char secret[MAXSECRETLEN];
   2330      1.1  christos 	char rhostname[256];
   2331  1.1.1.5  christos 	PPP_MD_CTX *mdctx;
   2332  1.1.1.5  christos 	u_char hash[MD5_DIGEST_LENGTH];
   2333  1.1.1.5  christos 	int hashlen = MD5_DIGEST_LENGTH;
   2334  1.1.1.5  christos #ifdef PPP_WITH_SRP
   2335      1.1  christos 	struct t_server *ts;
   2336      1.1  christos 	struct t_num A;
   2337  1.1.1.5  christos 	PPP_MD_CTX *ctxt;
   2338  1.1.1.5  christos 	u_char dig[SHA_DIGEST_LENGTH];
   2339  1.1.1.5  christos 	int diglen = sizeof(dig);
   2340  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   2341      1.1  christos 
   2342  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   2343  1.1.1.4  christos 	struct eaptls_session *ets;
   2344  1.1.1.4  christos 	u_char flags;
   2345  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   2346  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
   2347  1.1.1.4  christos 	u_char opcode;
   2348  1.1.1.5  christos         chap_verify_hook_fn *chap_verifier;
   2349  1.1.1.4  christos 	char response_message[256];
   2350  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
   2351  1.1.1.4  christos 
   2352  1.1.1.4  christos 	/*
   2353  1.1.1.4  christos 	 * Ignore responses if we're not open
   2354  1.1.1.4  christos 	 */
   2355  1.1.1.4  christos 	if (esp->es_server.ea_state <= eapClosed)
   2356  1.1.1.4  christos 		return;
   2357  1.1.1.4  christos 
   2358      1.1  christos 	if (esp->es_server.ea_id != id) {
   2359      1.1  christos 		dbglog("EAP: discarding Response %d; expected ID %d", id,
   2360      1.1  christos 		    esp->es_server.ea_id);
   2361      1.1  christos 		return;
   2362      1.1  christos 	}
   2363      1.1  christos 
   2364      1.1  christos 	esp->es_server.ea_responses++;
   2365      1.1  christos 
   2366      1.1  christos 	if (len <= 0) {
   2367      1.1  christos 		error("EAP: empty Response message discarded");
   2368      1.1  christos 		return;
   2369      1.1  christos 	}
   2370      1.1  christos 
   2371      1.1  christos 	GETCHAR(typenum, inp);
   2372      1.1  christos 	len--;
   2373      1.1  christos 
   2374      1.1  christos 	switch (typenum) {
   2375      1.1  christos 	case EAPT_IDENTITY:
   2376      1.1  christos 		if (esp->es_server.ea_state != eapIdentify) {
   2377      1.1  christos 			dbglog("EAP discarding unwanted Identify \"%.q\"", len,
   2378      1.1  christos 			    inp);
   2379      1.1  christos 			break;
   2380      1.1  christos 		}
   2381      1.1  christos 		info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
   2382      1.1  christos 		if (esp->es_server.ea_peer != NULL &&
   2383      1.1  christos 		    esp->es_server.ea_peer != remote_name)
   2384      1.1  christos 			free(esp->es_server.ea_peer);
   2385      1.1  christos 		esp->es_server.ea_peer = malloc(len + 1);
   2386      1.1  christos 		if (esp->es_server.ea_peer == NULL) {
   2387      1.1  christos 			esp->es_server.ea_peerlen = 0;
   2388      1.1  christos 			eap_figure_next_state(esp, 1);
   2389      1.1  christos 			break;
   2390      1.1  christos 		}
   2391      1.1  christos 		BCOPY(inp, esp->es_server.ea_peer, len);
   2392      1.1  christos 		esp->es_server.ea_peer[len] = '\0';
   2393      1.1  christos 		esp->es_server.ea_peerlen = len;
   2394      1.1  christos 		eap_figure_next_state(esp, 0);
   2395      1.1  christos 		break;
   2396      1.1  christos 
   2397  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   2398  1.1.1.4  christos 	case EAPT_TLS:
   2399  1.1.1.4  christos 		switch(esp->es_server.ea_state) {
   2400  1.1.1.4  christos 
   2401  1.1.1.4  christos 		case eapTlsRecv:
   2402  1.1.1.4  christos 
   2403  1.1.1.4  christos 			ets = (struct eaptls_session *) esp->es_server.ea_session;
   2404  1.1.1.4  christos 
   2405  1.1.1.4  christos 			eap_figure_next_state(esp,
   2406  1.1.1.4  christos 				eaptls_receive(esp->es_server.ea_session, inp, len));
   2407  1.1.1.4  christos 
   2408  1.1.1.4  christos 			if(ets->alert_recv) {
   2409  1.1.1.4  christos 				eap_send_failure(esp);
   2410  1.1.1.4  christos 				break;
   2411  1.1.1.4  christos 			}
   2412  1.1.1.4  christos 			break;
   2413  1.1.1.4  christos 
   2414  1.1.1.4  christos 		case eapTlsRecvAck:
   2415  1.1.1.4  christos 			if(len > 1) {
   2416  1.1.1.4  christos 				dbglog("EAP-TLS ACK with extra data");
   2417  1.1.1.4  christos 			}
   2418  1.1.1.4  christos 			eap_figure_next_state(esp, 0);
   2419  1.1.1.4  christos 			break;
   2420  1.1.1.4  christos 
   2421  1.1.1.4  christos 		case eapTlsRecvClient:
   2422  1.1.1.4  christos 			/* Receive authentication response from client */
   2423  1.1.1.4  christos 			if (len > 0) {
   2424  1.1.1.4  christos 				GETCHAR(flags, inp);
   2425  1.1.1.4  christos 
   2426  1.1.1.4  christos 				if(len == 1 && !flags) {	/* Ack = ok */
   2427  1.1.1.5  christos #ifdef PPP_WITH_MPPE
   2428  1.1.1.4  christos 					eaptls_gen_mppe_keys( esp->es_server.ea_session, 0 );
   2429  1.1.1.4  christos #endif
   2430  1.1.1.4  christos 					eap_send_success(esp);
   2431  1.1.1.4  christos 				}
   2432  1.1.1.4  christos 				else {			/* failure */
   2433  1.1.1.4  christos 					warn("Server authentication failed");
   2434  1.1.1.4  christos 					eap_send_failure(esp);
   2435  1.1.1.4  christos 				}
   2436  1.1.1.4  christos 			}
   2437  1.1.1.4  christos 			else
   2438  1.1.1.4  christos 				warn("Bogus EAP-TLS packet received from client");
   2439  1.1.1.4  christos 
   2440  1.1.1.4  christos 			eaptls_free_session(esp->es_server.ea_session);
   2441  1.1.1.4  christos 
   2442  1.1.1.4  christos 			break;
   2443  1.1.1.4  christos 
   2444  1.1.1.4  christos 		case eapTlsRecvAlertAck:
   2445  1.1.1.4  christos 			eap_send_failure(esp);
   2446  1.1.1.4  christos 			break;
   2447  1.1.1.4  christos 
   2448  1.1.1.4  christos 		default:
   2449  1.1.1.4  christos 			eap_figure_next_state(esp, 1);
   2450  1.1.1.4  christos 			break;
   2451  1.1.1.4  christos 		}
   2452  1.1.1.4  christos 		break;
   2453  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   2454  1.1.1.4  christos 
   2455      1.1  christos 	case EAPT_NOTIFICATION:
   2456      1.1  christos 		dbglog("EAP unexpected Notification; response discarded");
   2457      1.1  christos 		break;
   2458      1.1  christos 
   2459      1.1  christos 	case EAPT_NAK:
   2460      1.1  christos 		if (len < 1) {
   2461      1.1  christos 			info("EAP: Nak Response with no suggested protocol");
   2462      1.1  christos 			eap_figure_next_state(esp, 1);
   2463      1.1  christos 			break;
   2464      1.1  christos 		}
   2465      1.1  christos 
   2466      1.1  christos 		GETCHAR(vallen, inp);
   2467      1.1  christos 		len--;
   2468      1.1  christos 
   2469      1.1  christos 		if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
   2470      1.1  christos 			/* Peer cannot Nak Identify Request */
   2471      1.1  christos 			eap_figure_next_state(esp, 1);
   2472      1.1  christos 			break;
   2473      1.1  christos 		}
   2474      1.1  christos 
   2475      1.1  christos 		switch (vallen) {
   2476      1.1  christos 		case EAPT_SRP:
   2477      1.1  christos 			/* Run through SRP validator selection again. */
   2478      1.1  christos 			esp->es_server.ea_state = eapIdentify;
   2479      1.1  christos 			eap_figure_next_state(esp, 0);
   2480      1.1  christos 			break;
   2481      1.1  christos 
   2482      1.1  christos 		case EAPT_MD5CHAP:
   2483      1.1  christos 			esp->es_server.ea_state = eapMD5Chall;
   2484      1.1  christos 			break;
   2485      1.1  christos 
   2486  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   2487  1.1.1.4  christos 			/* Send EAP-TLS start packet */
   2488  1.1.1.4  christos 		case EAPT_TLS:
   2489  1.1.1.4  christos 			esp->es_server.ea_state = eapTlsStart;
   2490  1.1.1.4  christos 			break;
   2491  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   2492  1.1.1.4  christos 
   2493  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
   2494  1.1.1.4  christos 		case EAPT_MSCHAPV2:
   2495  1.1.1.4  christos 			info("EAP: peer proposes MSCHAPv2");
   2496  1.1.1.5  christos 			/* If MSCHAPv2 digest was not found, NAK the packet */
   2497  1.1.1.5  christos 			if (!esp->es_server.digest) {
   2498  1.1.1.5  christos 				error("EAP MSCHAPv2 not supported");
   2499  1.1.1.5  christos 				eap_send_nak(esp, id, EAPT_SRP);
   2500  1.1.1.5  christos 				break;
   2501  1.1.1.5  christos 			}
   2502  1.1.1.4  christos 			esp->es_server.ea_state = eapMSCHAPv2Chall;
   2503  1.1.1.4  christos 			break;
   2504  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
   2505  1.1.1.4  christos 
   2506      1.1  christos 		default:
   2507      1.1  christos 			dbglog("EAP: peer requesting unknown Type %d", vallen);
   2508      1.1  christos 			switch (esp->es_server.ea_state) {
   2509      1.1  christos 			case eapSRP1:
   2510      1.1  christos 			case eapSRP2:
   2511      1.1  christos 			case eapSRP3:
   2512      1.1  christos 				esp->es_server.ea_state = eapMD5Chall;
   2513      1.1  christos 				break;
   2514      1.1  christos 			case eapMD5Chall:
   2515      1.1  christos 			case eapSRP4:
   2516      1.1  christos 				esp->es_server.ea_state = eapIdentify;
   2517      1.1  christos 				eap_figure_next_state(esp, 0);
   2518      1.1  christos 				break;
   2519      1.1  christos 			default:
   2520      1.1  christos 				break;
   2521      1.1  christos 			}
   2522      1.1  christos 			break;
   2523      1.1  christos 		}
   2524      1.1  christos 		break;
   2525      1.1  christos 
   2526      1.1  christos 	case EAPT_MD5CHAP:
   2527      1.1  christos 		if (esp->es_server.ea_state != eapMD5Chall) {
   2528      1.1  christos 			error("EAP: unexpected MD5-Response");
   2529      1.1  christos 			eap_figure_next_state(esp, 1);
   2530      1.1  christos 			break;
   2531      1.1  christos 		}
   2532      1.1  christos 		if (len < 1) {
   2533      1.1  christos 			error("EAP: received MD5-Response with no data");
   2534      1.1  christos 			eap_figure_next_state(esp, 1);
   2535      1.1  christos 			break;
   2536      1.1  christos 		}
   2537      1.1  christos 		GETCHAR(vallen, inp);
   2538      1.1  christos 		len--;
   2539      1.1  christos 		if (vallen != 16 || vallen > len) {
   2540      1.1  christos 			error("EAP: MD5-Response with bad length %d", vallen);
   2541      1.1  christos 			eap_figure_next_state(esp, 1);
   2542      1.1  christos 			break;
   2543      1.1  christos 		}
   2544      1.1  christos 
   2545      1.1  christos 		/* Not so likely to happen. */
   2546  1.1.1.4  christos 		if (len - vallen >= sizeof (rhostname)) {
   2547      1.1  christos 			dbglog("EAP: trimming really long peer name down");
   2548      1.1  christos 			BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
   2549      1.1  christos 			rhostname[sizeof (rhostname) - 1] = '\0';
   2550      1.1  christos 		} else {
   2551      1.1  christos 			BCOPY(inp + vallen, rhostname, len - vallen);
   2552      1.1  christos 			rhostname[len - vallen] = '\0';
   2553      1.1  christos 		}
   2554      1.1  christos 
   2555      1.1  christos 		/* In case the remote doesn't give us his name. */
   2556      1.1  christos 		if (explicit_remote ||
   2557      1.1  christos 		    (remote_name[0] != '\0' && vallen == len))
   2558      1.1  christos 			strlcpy(rhostname, remote_name, sizeof (rhostname));
   2559      1.1  christos 
   2560      1.1  christos 		/*
   2561      1.1  christos 		 * Get the secret for authenticating the specified
   2562      1.1  christos 		 * host.
   2563      1.1  christos 		 */
   2564      1.1  christos 		if (!get_secret(esp->es_unit, rhostname,
   2565      1.1  christos 		    esp->es_server.ea_name, secret, &secret_len, 1)) {
   2566      1.1  christos 			dbglog("EAP: no MD5 secret for auth of %q", rhostname);
   2567      1.1  christos 			eap_send_failure(esp);
   2568      1.1  christos 			break;
   2569      1.1  christos 		}
   2570  1.1.1.5  christos 
   2571  1.1.1.5  christos 		mdctx = PPP_MD_CTX_new();
   2572  1.1.1.5  christos 		if (mdctx != NULL) {
   2573  1.1.1.5  christos 
   2574  1.1.1.5  christos 			if (PPP_DigestInit(mdctx, PPP_md5())) {
   2575  1.1.1.5  christos 
   2576  1.1.1.5  christos 				if (PPP_DigestUpdate(mdctx, &esp->es_server.ea_id, 1)) {
   2577  1.1.1.5  christos 
   2578  1.1.1.5  christos 					if (PPP_DigestUpdate(mdctx, &secret, secret_len)) {
   2579  1.1.1.5  christos 
   2580  1.1.1.5  christos 						BZERO(secret, sizeof(secret));
   2581  1.1.1.5  christos 						if (PPP_DigestUpdate(mdctx, esp->es_challenge, esp->es_challen)) {
   2582  1.1.1.5  christos 
   2583  1.1.1.5  christos 							if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
   2584  1.1.1.5  christos 
   2585  1.1.1.5  christos 								if (BCMP(hash, inp, MD5_DIGEST_LENGTH) == 0) {
   2586  1.1.1.5  christos 									esp->es_server.ea_type = EAPT_MD5CHAP;
   2587  1.1.1.5  christos 									eap_send_success(esp);
   2588  1.1.1.5  christos 									eap_figure_next_state(esp, 0);
   2589  1.1.1.5  christos 
   2590  1.1.1.5  christos 									if (esp->es_rechallenge != 0) {
   2591  1.1.1.5  christos 										TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
   2592  1.1.1.5  christos 									}
   2593  1.1.1.5  christos 									PPP_MD_CTX_free(mdctx);
   2594  1.1.1.5  christos 									break;
   2595  1.1.1.5  christos 								}
   2596  1.1.1.5  christos 							}
   2597  1.1.1.5  christos 						}
   2598  1.1.1.5  christos 					}
   2599  1.1.1.5  christos 				}
   2600  1.1.1.5  christos 			}
   2601  1.1.1.5  christos 
   2602  1.1.1.5  christos 			PPP_MD_CTX_free(mdctx);
   2603      1.1  christos 		}
   2604  1.1.1.5  christos 
   2605  1.1.1.5  christos 		eap_send_failure(esp);
   2606      1.1  christos 		break;
   2607      1.1  christos 
   2608  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
   2609  1.1.1.4  christos 	case EAPT_MSCHAPV2:
   2610  1.1.1.4  christos 		if (len < 1) {
   2611  1.1.1.4  christos 			error("EAP: received MSCHAPv2 with no data");
   2612  1.1.1.4  christos 			eap_figure_next_state(esp, 1);
   2613  1.1.1.4  christos 			break;
   2614  1.1.1.4  christos 		}
   2615  1.1.1.4  christos 		GETCHAR(opcode, inp);
   2616  1.1.1.4  christos 		len--;
   2617  1.1.1.4  christos 
   2618  1.1.1.4  christos 		switch (opcode) {
   2619  1.1.1.4  christos 		case CHAP_RESPONSE:
   2620  1.1.1.4  christos 			if (esp->es_server.ea_state != eapMSCHAPv2Chall) {
   2621  1.1.1.4  christos 				error("EAP: unexpected MSCHAPv2-Response");
   2622  1.1.1.4  christos 				eap_figure_next_state(esp, 1);
   2623  1.1.1.4  christos 				break;
   2624  1.1.1.4  christos 			}
   2625  1.1.1.4  christos 			/* skip MS ID + len */
   2626  1.1.1.4  christos 			INCPTR(3, inp);
   2627  1.1.1.4  christos 			GETCHAR(vallen, inp);
   2628  1.1.1.4  christos 			len -= 4;
   2629  1.1.1.4  christos 
   2630  1.1.1.4  christos 			if (vallen != MS_CHAP2_RESPONSE_LEN || vallen > len) {
   2631  1.1.1.4  christos 				error("EAP: Invalid MSCHAPv2-Response "
   2632  1.1.1.4  christos 						"length %d", vallen);
   2633  1.1.1.4  christos 				eap_figure_next_state(esp, 1);
   2634  1.1.1.4  christos 				break;
   2635  1.1.1.4  christos 			}
   2636  1.1.1.4  christos 
   2637  1.1.1.4  christos 			/* Not so likely to happen. */
   2638  1.1.1.4  christos 			if (len - vallen >= sizeof (rhostname)) {
   2639  1.1.1.4  christos 				dbglog("EAP: trimming really long peer name down");
   2640  1.1.1.4  christos 				BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
   2641  1.1.1.4  christos 				rhostname[sizeof (rhostname) - 1] = '\0';
   2642  1.1.1.4  christos 			} else {
   2643  1.1.1.4  christos 				BCOPY(inp + vallen, rhostname, len - vallen);
   2644  1.1.1.4  christos 				rhostname[len - vallen] = '\0';
   2645  1.1.1.4  christos 			}
   2646  1.1.1.4  christos 
   2647  1.1.1.4  christos 			/* In case the remote doesn't give us his name. */
   2648  1.1.1.4  christos 			if (explicit_remote ||
   2649  1.1.1.4  christos 					(remote_name[0] != '\0' && vallen == len))
   2650  1.1.1.4  christos 				strlcpy(rhostname, remote_name, sizeof (rhostname));
   2651  1.1.1.4  christos 
   2652  1.1.1.5  christos 			/* strip the MS domain name */
   2653  1.1.1.5  christos 			if (chapms_strip_domain && strrchr(rhostname, '\\')) {
   2654  1.1.1.5  christos 				char tmp[MAXNAMELEN+1];
   2655  1.1.1.5  christos 
   2656  1.1.1.5  christos 				strcpy(tmp, strrchr(rhostname, '\\') + 1);
   2657  1.1.1.5  christos 				strlcpy(rhostname, tmp, sizeof(rhostname));
   2658  1.1.1.5  christos 			}
   2659  1.1.1.5  christos 
   2660  1.1.1.4  christos 			if (chap_verify_hook)
   2661  1.1.1.4  christos 				chap_verifier = chap_verify_hook;
   2662  1.1.1.4  christos 			else
   2663  1.1.1.4  christos 				chap_verifier = eap_chap_verify_response;
   2664  1.1.1.4  christos 
   2665  1.1.1.4  christos 			esp->es_server.ea_id += 1;
   2666  1.1.1.4  christos 			if ((*chap_verifier)(rhostname,
   2667  1.1.1.4  christos 						esp->es_server.ea_name,
   2668  1.1.1.4  christos 						id,
   2669  1.1.1.5  christos 						esp->es_server.digest,
   2670  1.1.1.4  christos 						esp->es_challenge,
   2671  1.1.1.4  christos 						inp - 1,
   2672  1.1.1.4  christos 						response_message,
   2673  1.1.1.4  christos 						sizeof(response_message)))
   2674  1.1.1.4  christos 			{
   2675  1.1.1.4  christos 				info("EAP: MSCHAPv2 success for peer %q",
   2676  1.1.1.4  christos 						rhostname);
   2677  1.1.1.4  christos 				esp->es_server.ea_type = EAPT_MSCHAPV2;
   2678  1.1.1.4  christos 				eap_chapms2_send_request(esp,
   2679  1.1.1.4  christos 						esp->es_server.ea_id,
   2680  1.1.1.4  christos 						CHAP_SUCCESS,
   2681  1.1.1.4  christos 						esp->es_server.ea_id,
   2682  1.1.1.4  christos 						response_message,
   2683  1.1.1.4  christos 						strlen(response_message));
   2684  1.1.1.4  christos 				eap_figure_next_state(esp, 0);
   2685  1.1.1.4  christos 				if (esp->es_rechallenge != 0)
   2686  1.1.1.4  christos 					TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
   2687  1.1.1.4  christos 			}
   2688  1.1.1.4  christos 			else {
   2689  1.1.1.4  christos 				warn("EAP: MSCHAPv2 failure for peer %q",
   2690  1.1.1.4  christos 						rhostname);
   2691  1.1.1.4  christos 				eap_chapms2_send_request(esp,
   2692  1.1.1.4  christos 						esp->es_server.ea_id,
   2693  1.1.1.4  christos 						CHAP_FAILURE,
   2694  1.1.1.4  christos 						esp->es_server.ea_id,
   2695  1.1.1.4  christos 						response_message,
   2696  1.1.1.4  christos 						strlen(response_message));
   2697  1.1.1.4  christos 			}
   2698  1.1.1.4  christos 			break;
   2699  1.1.1.4  christos 		case CHAP_SUCCESS:
   2700  1.1.1.4  christos 			info("EAP: MSCHAPv2 success confirmed");
   2701  1.1.1.4  christos 			break;
   2702  1.1.1.4  christos 		case CHAP_FAILURE:
   2703  1.1.1.4  christos 			info("EAP: MSCHAPv2 failure confirmed");
   2704  1.1.1.4  christos 			break;
   2705  1.1.1.4  christos 		default:
   2706  1.1.1.4  christos 			error("EAP: Unhandled MSCHAPv2 opcode %d", opcode);
   2707  1.1.1.4  christos 			eap_send_nak(esp, id, EAPT_SRP);
   2708  1.1.1.4  christos 		}
   2709  1.1.1.4  christos 
   2710  1.1.1.4  christos 		break;
   2711  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
   2712  1.1.1.4  christos 
   2713  1.1.1.5  christos #ifdef PPP_WITH_SRP
   2714      1.1  christos 	case EAPT_SRP:
   2715      1.1  christos 		if (len < 1) {
   2716      1.1  christos 			error("EAP: empty SRP Response");
   2717      1.1  christos 			eap_figure_next_state(esp, 1);
   2718      1.1  christos 			break;
   2719      1.1  christos 		}
   2720      1.1  christos 		GETCHAR(typenum, inp);
   2721      1.1  christos 		len--;
   2722      1.1  christos 		switch (typenum) {
   2723      1.1  christos 		case EAPSRP_CKEY:
   2724      1.1  christos 			if (esp->es_server.ea_state != eapSRP1) {
   2725      1.1  christos 				error("EAP: unexpected SRP Subtype 1 Response");
   2726      1.1  christos 				eap_figure_next_state(esp, 1);
   2727      1.1  christos 				break;
   2728      1.1  christos 			}
   2729      1.1  christos 			A.data = inp;
   2730      1.1  christos 			A.len = len;
   2731      1.1  christos 			ts = (struct t_server *)esp->es_server.ea_session;
   2732      1.1  christos 			assert(ts != NULL);
   2733      1.1  christos 			esp->es_server.ea_skey = t_servergetkey(ts, &A);
   2734      1.1  christos 			if (esp->es_server.ea_skey == NULL) {
   2735      1.1  christos 				/* Client's A value is bogus; terminate now */
   2736      1.1  christos 				error("EAP: bogus A value from client");
   2737      1.1  christos 				eap_send_failure(esp);
   2738      1.1  christos 			} else {
   2739      1.1  christos 				eap_figure_next_state(esp, 0);
   2740      1.1  christos 			}
   2741      1.1  christos 			break;
   2742      1.1  christos 
   2743      1.1  christos 		case EAPSRP_CVALIDATOR:
   2744      1.1  christos 			if (esp->es_server.ea_state != eapSRP2) {
   2745      1.1  christos 				error("EAP: unexpected SRP Subtype 2 Response");
   2746      1.1  christos 				eap_figure_next_state(esp, 1);
   2747      1.1  christos 				break;
   2748      1.1  christos 			}
   2749  1.1.1.5  christos 			if (len < sizeof (u_int32_t) + SHA_DIGEST_LENGTH) {
   2750      1.1  christos 				error("EAP: M1 length %d < %d", len,
   2751  1.1.1.5  christos 				    sizeof (u_int32_t) + SHA_DIGEST_LENGTH);
   2752      1.1  christos 				eap_figure_next_state(esp, 1);
   2753      1.1  christos 				break;
   2754      1.1  christos 			}
   2755      1.1  christos 			GETLONG(esp->es_server.ea_keyflags, inp);
   2756      1.1  christos 			ts = (struct t_server *)esp->es_server.ea_session;
   2757      1.1  christos 			assert(ts != NULL);
   2758      1.1  christos 			if (t_serververify(ts, inp)) {
   2759      1.1  christos 				info("EAP: unable to validate client identity");
   2760      1.1  christos 				eap_send_failure(esp);
   2761      1.1  christos 				break;
   2762      1.1  christos 			}
   2763      1.1  christos 			eap_figure_next_state(esp, 0);
   2764      1.1  christos 			break;
   2765      1.1  christos 
   2766      1.1  christos 		case EAPSRP_ACK:
   2767      1.1  christos 			if (esp->es_server.ea_state != eapSRP3) {
   2768      1.1  christos 				error("EAP: unexpected SRP Subtype 3 Response");
   2769      1.1  christos 				eap_send_failure(esp);
   2770      1.1  christos 				break;
   2771      1.1  christos 			}
   2772      1.1  christos 			esp->es_server.ea_type = EAPT_SRP;
   2773      1.1  christos 			eap_send_success(esp);
   2774      1.1  christos 			eap_figure_next_state(esp, 0);
   2775      1.1  christos 			if (esp->es_rechallenge != 0)
   2776      1.1  christos 				TIMEOUT(eap_rechallenge, esp,
   2777      1.1  christos 				    esp->es_rechallenge);
   2778      1.1  christos 			if (esp->es_lwrechallenge != 0)
   2779      1.1  christos 				TIMEOUT(srp_lwrechallenge, esp,
   2780      1.1  christos 				    esp->es_lwrechallenge);
   2781      1.1  christos 			break;
   2782      1.1  christos 
   2783      1.1  christos 		case EAPSRP_LWRECHALLENGE:
   2784      1.1  christos 			if (esp->es_server.ea_state != eapSRP4) {
   2785      1.1  christos 				info("EAP: unexpected SRP Subtype 4 Response");
   2786      1.1  christos 				return;
   2787      1.1  christos 			}
   2788  1.1.1.5  christos 			if (len != SHA_DIGEST_LENGTH) {
   2789      1.1  christos 				error("EAP: bad Lightweight rechallenge "
   2790      1.1  christos 				    "response");
   2791      1.1  christos 				return;
   2792      1.1  christos 			}
   2793  1.1.1.5  christos 			ctxt = PPP_MD_CTX_new();
   2794  1.1.1.5  christos 			if (ctxt) {
   2795  1.1.1.5  christos 				vallen = id;
   2796  1.1.1.5  christos 
   2797  1.1.1.5  christos 				PPP_DigestInit(ctxt, PPP_sha1());
   2798  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, &vallen, 1);
   2799  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
   2800  1.1.1.5  christos 					SESSION_KEY_LEN);
   2801  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, esp->es_challenge, esp->es_challen);
   2802  1.1.1.5  christos 				PPP_DigestUpdate(ctxt, esp->es_server.ea_peer,
   2803  1.1.1.5  christos 					esp->es_server.ea_peerlen);
   2804  1.1.1.5  christos 				PPP_DigestFinal(ctxt, dig, &diglen);
   2805  1.1.1.5  christos 
   2806  1.1.1.5  christos 				PPP_MD_CTX_free(ctxt);
   2807  1.1.1.5  christos 
   2808  1.1.1.5  christos 				if (BCMP(dig, inp, SHA_DIGEST_LENGTH) != 0) {
   2809  1.1.1.5  christos 					error("EAP: failed Lightweight rechallenge");
   2810  1.1.1.5  christos 					eap_send_failure(esp);
   2811  1.1.1.5  christos 					break;
   2812  1.1.1.5  christos 				}
   2813  1.1.1.5  christos 
   2814  1.1.1.5  christos 				esp->es_server.ea_state = eapOpen;
   2815  1.1.1.5  christos 				if (esp->es_lwrechallenge != 0)
   2816  1.1.1.5  christos 					TIMEOUT(srp_lwrechallenge, esp,
   2817  1.1.1.5  christos 						esp->es_lwrechallenge);
   2818      1.1  christos 			}
   2819      1.1  christos 			break;
   2820      1.1  christos 		}
   2821      1.1  christos 		break;
   2822  1.1.1.5  christos #endif /* PPP_WITH_SRP */
   2823      1.1  christos 
   2824      1.1  christos 	default:
   2825      1.1  christos 		/* This can't happen. */
   2826      1.1  christos 		error("EAP: unknown Response type %d; ignored", typenum);
   2827      1.1  christos 		return;
   2828      1.1  christos 	}
   2829      1.1  christos 
   2830      1.1  christos 	if (esp->es_server.ea_timeout > 0) {
   2831      1.1  christos 		UNTIMEOUT(eap_server_timeout, (void *)esp);
   2832      1.1  christos 	}
   2833      1.1  christos 
   2834      1.1  christos 	if (esp->es_server.ea_state != eapBadAuth &&
   2835      1.1  christos 	    esp->es_server.ea_state != eapOpen) {
   2836      1.1  christos 		esp->es_server.ea_id++;
   2837      1.1  christos 		eap_send_request(esp);
   2838      1.1  christos 	}
   2839      1.1  christos }
   2840      1.1  christos 
   2841      1.1  christos /*
   2842      1.1  christos  * eap_success - Receive EAP Success message (client mode).
   2843      1.1  christos  */
   2844      1.1  christos static void
   2845  1.1.1.4  christos eap_success(eap_state *esp, u_char *inp, int id, int len)
   2846      1.1  christos {
   2847  1.1.1.4  christos 	if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
   2848  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   2849  1.1.1.4  christos 		&& esp->es_client.ea_state != eapTlsRecvSuccess
   2850  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   2851  1.1.1.4  christos 		) {
   2852      1.1  christos 		dbglog("EAP unexpected success message in state %s (%d)",
   2853      1.1  christos 		    eap_state_name(esp->es_client.ea_state),
   2854      1.1  christos 		    esp->es_client.ea_state);
   2855      1.1  christos 		return;
   2856      1.1  christos 	}
   2857      1.1  christos 
   2858  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   2859  1.1.1.4  christos 	if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
   2860  1.1.1.4  christos 		eapTlsRecvSuccess) {
   2861  1.1.1.4  christos 		dbglog("EAP-TLS unexpected success message in state %s (%d)",
   2862  1.1.1.4  christos                     eap_state_name(esp->es_client.ea_state),
   2863  1.1.1.4  christos                     esp->es_client.ea_state);
   2864  1.1.1.4  christos 		return;
   2865  1.1.1.4  christos 	}
   2866  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   2867  1.1.1.4  christos 
   2868      1.1  christos 	if (esp->es_client.ea_timeout > 0) {
   2869      1.1  christos 		UNTIMEOUT(eap_client_timeout, (void *)esp);
   2870      1.1  christos 	}
   2871      1.1  christos 
   2872      1.1  christos 	if (len > 0) {
   2873      1.1  christos 		/* This is odd.  The spec doesn't allow for this. */
   2874      1.1  christos 		PRINTMSG(inp, len);
   2875      1.1  christos 	}
   2876      1.1  christos 
   2877  1.1.1.5  christos #ifdef PPP_WITH_PEAP
   2878  1.1.1.5  christos 	peap_finish(&esp->ea_peap);
   2879  1.1.1.5  christos #endif
   2880  1.1.1.5  christos 
   2881      1.1  christos 	esp->es_client.ea_state = eapOpen;
   2882      1.1  christos 	auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
   2883      1.1  christos }
   2884      1.1  christos 
   2885      1.1  christos /*
   2886      1.1  christos  * eap_failure - Receive EAP Failure message (client mode).
   2887      1.1  christos  */
   2888      1.1  christos static void
   2889  1.1.1.4  christos eap_failure(eap_state *esp, u_char *inp, int id, int len)
   2890      1.1  christos {
   2891  1.1.1.4  christos 	/*
   2892  1.1.1.4  christos 	 * Ignore failure messages if we're not open
   2893  1.1.1.4  christos 	 */
   2894  1.1.1.4  christos 	if (esp->es_client.ea_state <= eapClosed)
   2895  1.1.1.4  christos 		return;
   2896  1.1.1.4  christos 
   2897      1.1  christos 	if (!eap_client_active(esp)) {
   2898      1.1  christos 		dbglog("EAP unexpected failure message in state %s (%d)",
   2899      1.1  christos 		    eap_state_name(esp->es_client.ea_state),
   2900      1.1  christos 		    esp->es_client.ea_state);
   2901      1.1  christos 	}
   2902      1.1  christos 
   2903      1.1  christos 	if (esp->es_client.ea_timeout > 0) {
   2904      1.1  christos 		UNTIMEOUT(eap_client_timeout, (void *)esp);
   2905      1.1  christos 	}
   2906      1.1  christos 
   2907      1.1  christos 	if (len > 0) {
   2908      1.1  christos 		/* This is odd.  The spec doesn't allow for this. */
   2909      1.1  christos 		PRINTMSG(inp, len);
   2910      1.1  christos 	}
   2911      1.1  christos 
   2912      1.1  christos 	esp->es_client.ea_state = eapBadAuth;
   2913      1.1  christos 
   2914      1.1  christos 	error("EAP: peer reports authentication failure");
   2915  1.1.1.5  christos 
   2916  1.1.1.5  christos #ifdef PPP_WITH_PEAP
   2917  1.1.1.5  christos 	peap_finish(&esp->ea_peap);
   2918  1.1.1.5  christos #endif
   2919  1.1.1.5  christos 
   2920      1.1  christos 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
   2921      1.1  christos }
   2922      1.1  christos 
   2923      1.1  christos /*
   2924      1.1  christos  * eap_input - Handle received EAP message.
   2925      1.1  christos  */
   2926      1.1  christos static void
   2927  1.1.1.4  christos eap_input(int unit, u_char *inp, int inlen)
   2928      1.1  christos {
   2929      1.1  christos 	eap_state *esp = &eap_states[unit];
   2930      1.1  christos 	u_char code, id;
   2931      1.1  christos 	int len;
   2932      1.1  christos 
   2933      1.1  christos 	/*
   2934      1.1  christos 	 * Parse header (code, id and length).  If packet too short,
   2935      1.1  christos 	 * drop it.
   2936      1.1  christos 	 */
   2937      1.1  christos 	if (inlen < EAP_HEADERLEN) {
   2938      1.1  christos 		error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
   2939      1.1  christos 		return;
   2940      1.1  christos 	}
   2941      1.1  christos 	GETCHAR(code, inp);
   2942      1.1  christos 	GETCHAR(id, inp);
   2943      1.1  christos 	GETSHORT(len, inp);
   2944      1.1  christos 	if (len < EAP_HEADERLEN || len > inlen) {
   2945      1.1  christos 		error("EAP: packet has illegal length field %d (%d..%d)", len,
   2946      1.1  christos 		    EAP_HEADERLEN, inlen);
   2947      1.1  christos 		return;
   2948      1.1  christos 	}
   2949      1.1  christos 	len -= EAP_HEADERLEN;
   2950      1.1  christos 
   2951      1.1  christos 	/* Dispatch based on message code */
   2952      1.1  christos 	switch (code) {
   2953      1.1  christos 	case EAP_REQUEST:
   2954      1.1  christos 		eap_request(esp, inp, id, len);
   2955      1.1  christos 		break;
   2956      1.1  christos 
   2957      1.1  christos 	case EAP_RESPONSE:
   2958      1.1  christos 		eap_response(esp, inp, id, len);
   2959      1.1  christos 		break;
   2960      1.1  christos 
   2961      1.1  christos 	case EAP_SUCCESS:
   2962      1.1  christos 		eap_success(esp, inp, id, len);
   2963      1.1  christos 		break;
   2964      1.1  christos 
   2965      1.1  christos 	case EAP_FAILURE:
   2966      1.1  christos 		eap_failure(esp, inp, id, len);
   2967      1.1  christos 		break;
   2968      1.1  christos 
   2969      1.1  christos 	default:				/* XXX Need code reject */
   2970      1.1  christos 		/* Note: it's not legal to send EAP Nak here. */
   2971      1.1  christos 		warn("EAP: unknown code %d received", code);
   2972      1.1  christos 		break;
   2973      1.1  christos 	}
   2974      1.1  christos }
   2975      1.1  christos 
   2976      1.1  christos /*
   2977      1.1  christos  * eap_printpkt - print the contents of an EAP packet.
   2978      1.1  christos  */
   2979      1.1  christos static char *eap_codenames[] = {
   2980      1.1  christos 	"Request", "Response", "Success", "Failure"
   2981      1.1  christos };
   2982      1.1  christos 
   2983      1.1  christos static char *eap_typenames[] = {
   2984      1.1  christos 	"Identity", "Notification", "Nak", "MD5-Challenge",
   2985      1.1  christos 	"OTP", "Generic-Token", NULL, NULL,
   2986      1.1  christos 	"RSA", "DSS", "KEA", "KEA-Validate",
   2987      1.1  christos 	"TLS", "Defender", "Windows 2000", "Arcot",
   2988  1.1.1.4  christos 	"Cisco", "Nokia", "SRP", NULL,
   2989  1.1.1.4  christos 	"TTLS", "RAS", "AKA", "3COM", "PEAP",
   2990  1.1.1.4  christos 	"MSCHAPv2"
   2991      1.1  christos };
   2992      1.1  christos 
   2993      1.1  christos static int
   2994  1.1.1.4  christos eap_printpkt(u_char *inp, int inlen,
   2995  1.1.1.4  christos 	     void (*printer) (void *, char *, ...), void *arg)
   2996      1.1  christos {
   2997      1.1  christos 	int code, id, len, rtype, vallen;
   2998      1.1  christos 	u_char *pstart;
   2999      1.1  christos 	u_int32_t uval;
   3000  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   3001  1.1.1.4  christos 	u_char flags;
   3002  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   3003  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
   3004  1.1.1.4  christos 	u_char opcode;
   3005  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
   3006      1.1  christos 
   3007      1.1  christos 	if (inlen < EAP_HEADERLEN)
   3008      1.1  christos 		return (0);
   3009      1.1  christos 	pstart = inp;
   3010      1.1  christos 	GETCHAR(code, inp);
   3011      1.1  christos 	GETCHAR(id, inp);
   3012      1.1  christos 	GETSHORT(len, inp);
   3013      1.1  christos 	if (len < EAP_HEADERLEN || len > inlen)
   3014      1.1  christos 		return (0);
   3015      1.1  christos 
   3016      1.1  christos 	if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
   3017      1.1  christos 		printer(arg, " %s", eap_codenames[code-1]);
   3018      1.1  christos 	else
   3019      1.1  christos 		printer(arg, " code=0x%x", code);
   3020      1.1  christos 	printer(arg, " id=0x%x", id);
   3021      1.1  christos 	len -= EAP_HEADERLEN;
   3022      1.1  christos 	switch (code) {
   3023      1.1  christos 	case EAP_REQUEST:
   3024      1.1  christos 		if (len < 1) {
   3025      1.1  christos 			printer(arg, " <missing type>");
   3026      1.1  christos 			break;
   3027      1.1  christos 		}
   3028      1.1  christos 		GETCHAR(rtype, inp);
   3029      1.1  christos 		len--;
   3030      1.1  christos 		if (rtype >= 1 &&
   3031      1.1  christos 		    rtype <= sizeof (eap_typenames) / sizeof (char *))
   3032      1.1  christos 			printer(arg, " %s", eap_typenames[rtype-1]);
   3033      1.1  christos 		else
   3034      1.1  christos 			printer(arg, " type=0x%x", rtype);
   3035      1.1  christos 		switch (rtype) {
   3036      1.1  christos 		case EAPT_IDENTITY:
   3037      1.1  christos 		case EAPT_NOTIFICATION:
   3038      1.1  christos 			if (len > 0) {
   3039      1.1  christos 				printer(arg, " <Message ");
   3040      1.1  christos 				print_string((char *)inp, len, printer, arg);
   3041      1.1  christos 				printer(arg, ">");
   3042      1.1  christos 				INCPTR(len, inp);
   3043      1.1  christos 				len = 0;
   3044      1.1  christos 			} else {
   3045      1.1  christos 				printer(arg, " <No message>");
   3046      1.1  christos 			}
   3047      1.1  christos 			break;
   3048      1.1  christos 
   3049      1.1  christos 		case EAPT_MD5CHAP:
   3050      1.1  christos 			if (len <= 0)
   3051      1.1  christos 				break;
   3052      1.1  christos 			GETCHAR(vallen, inp);
   3053      1.1  christos 			len--;
   3054      1.1  christos 			if (vallen > len)
   3055      1.1  christos 				goto truncated;
   3056      1.1  christos 			printer(arg, " <Value%.*B>", vallen, inp);
   3057      1.1  christos 			INCPTR(vallen, inp);
   3058      1.1  christos 			len -= vallen;
   3059      1.1  christos 			if (len > 0) {
   3060      1.1  christos 				printer(arg, " <Name ");
   3061      1.1  christos 				print_string((char *)inp, len, printer, arg);
   3062      1.1  christos 				printer(arg, ">");
   3063      1.1  christos 				INCPTR(len, inp);
   3064      1.1  christos 				len = 0;
   3065      1.1  christos 			} else {
   3066      1.1  christos 				printer(arg, " <No name>");
   3067      1.1  christos 			}
   3068      1.1  christos 			break;
   3069      1.1  christos 
   3070  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
   3071  1.1.1.4  christos 		case EAPT_MSCHAPV2:
   3072  1.1.1.4  christos 			if (len <= 0)
   3073  1.1.1.4  christos 				break;
   3074  1.1.1.4  christos 			GETCHAR(opcode, inp);
   3075  1.1.1.4  christos 			len--;
   3076  1.1.1.4  christos 			switch (opcode) {
   3077  1.1.1.4  christos 			case CHAP_CHALLENGE:
   3078  1.1.1.4  christos 				INCPTR(3, inp);
   3079  1.1.1.4  christos 				len -= 3;
   3080  1.1.1.4  christos 				GETCHAR(vallen, inp);
   3081  1.1.1.4  christos 				len--;
   3082  1.1.1.4  christos 				if (vallen > len)
   3083  1.1.1.4  christos 					goto truncated;
   3084  1.1.1.4  christos 				len -= vallen;
   3085  1.1.1.4  christos 				printer(arg, " Challenge <");
   3086  1.1.1.4  christos 				for (; vallen > 0; --vallen) {
   3087  1.1.1.4  christos 					u_char val;
   3088  1.1.1.4  christos 					GETCHAR(val, inp);
   3089  1.1.1.4  christos 					printer(arg, "%.2x", val);
   3090  1.1.1.4  christos 				}
   3091  1.1.1.4  christos 				printer(arg, ">");
   3092  1.1.1.4  christos 				if (len > 0) {
   3093  1.1.1.4  christos 					printer(arg, ", <Name ");
   3094  1.1.1.4  christos 					print_string((char *)inp, len, printer, arg);
   3095  1.1.1.4  christos 					printer(arg, ">");
   3096  1.1.1.4  christos 					INCPTR(len, inp);
   3097  1.1.1.4  christos 					len = 0;
   3098  1.1.1.4  christos 				} else {
   3099  1.1.1.4  christos 					printer(arg, ", <No name>");
   3100  1.1.1.4  christos 				}
   3101  1.1.1.4  christos 				break;
   3102  1.1.1.4  christos 			case CHAP_SUCCESS:
   3103  1.1.1.4  christos 				INCPTR(3, inp);
   3104  1.1.1.4  christos 				len -= 3;
   3105  1.1.1.4  christos 				printer(arg, " Success <Message ");
   3106  1.1.1.4  christos 				print_string((char *)inp, len, printer, arg);
   3107  1.1.1.4  christos 				printer(arg, ">");
   3108  1.1.1.4  christos 				break;
   3109  1.1.1.4  christos 			case CHAP_FAILURE:
   3110  1.1.1.4  christos 				INCPTR(3, inp);
   3111  1.1.1.4  christos 				len -= 3;
   3112  1.1.1.4  christos 				printer(arg, " Failure <Message ");
   3113  1.1.1.4  christos 				print_string((char *)inp, len, printer, arg);
   3114  1.1.1.4  christos 				printer(arg, ">");
   3115  1.1.1.4  christos 				break;
   3116  1.1.1.4  christos 			default:
   3117  1.1.1.4  christos 				INCPTR(3, inp);
   3118  1.1.1.4  christos 				len -= 3;
   3119  1.1.1.4  christos 				printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
   3120  1.1.1.4  christos 				break;
   3121  1.1.1.4  christos 			}
   3122  1.1.1.4  christos 			break;
   3123  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
   3124  1.1.1.4  christos 
   3125  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   3126  1.1.1.4  christos 		case EAPT_TLS:
   3127  1.1.1.4  christos 			if (len < 1)
   3128  1.1.1.4  christos 				break;
   3129  1.1.1.4  christos 			GETCHAR(flags, inp);
   3130  1.1.1.4  christos 			len--;
   3131  1.1.1.4  christos 
   3132  1.1.1.4  christos                         if(flags == 0 && len == 0){
   3133  1.1.1.4  christos                                 printer(arg, " Ack");
   3134  1.1.1.4  christos                                 break;
   3135  1.1.1.4  christos                         }
   3136  1.1.1.4  christos 
   3137  1.1.1.4  christos 			printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
   3138  1.1.1.4  christos 			printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
   3139  1.1.1.4  christos 			printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
   3140  1.1.1.4  christos 			break;
   3141  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   3142  1.1.1.4  christos 
   3143  1.1.1.5  christos #ifdef PPP_WITH_SRP
   3144      1.1  christos 		case EAPT_SRP:
   3145      1.1  christos 			if (len < 3)
   3146      1.1  christos 				goto truncated;
   3147      1.1  christos 			GETCHAR(vallen, inp);
   3148      1.1  christos 			len--;
   3149      1.1  christos 			printer(arg, "-%d", vallen);
   3150      1.1  christos 			switch (vallen) {
   3151      1.1  christos 			case EAPSRP_CHALLENGE:
   3152      1.1  christos 				GETCHAR(vallen, inp);
   3153      1.1  christos 				len--;
   3154      1.1  christos 				if (vallen >= len)
   3155      1.1  christos 					goto truncated;
   3156      1.1  christos 				if (vallen > 0) {
   3157      1.1  christos 					printer(arg, " <Name ");
   3158      1.1  christos 					print_string((char *)inp, vallen, printer,
   3159      1.1  christos 					    arg);
   3160      1.1  christos 					printer(arg, ">");
   3161      1.1  christos 				} else {
   3162      1.1  christos 					printer(arg, " <No name>");
   3163      1.1  christos 				}
   3164      1.1  christos 				INCPTR(vallen, inp);
   3165      1.1  christos 				len -= vallen;
   3166      1.1  christos 				GETCHAR(vallen, inp);
   3167      1.1  christos 				len--;
   3168      1.1  christos 				if (vallen >= len)
   3169      1.1  christos 					goto truncated;
   3170      1.1  christos 				printer(arg, " <s%.*B>", vallen, inp);
   3171      1.1  christos 				INCPTR(vallen, inp);
   3172      1.1  christos 				len -= vallen;
   3173      1.1  christos 				GETCHAR(vallen, inp);
   3174      1.1  christos 				len--;
   3175      1.1  christos 				if (vallen > len)
   3176      1.1  christos 					goto truncated;
   3177      1.1  christos 				if (vallen == 0) {
   3178      1.1  christos 					printer(arg, " <Default g=2>");
   3179      1.1  christos 				} else {
   3180      1.1  christos 					printer(arg, " <g%.*B>", vallen, inp);
   3181      1.1  christos 				}
   3182      1.1  christos 				INCPTR(vallen, inp);
   3183      1.1  christos 				len -= vallen;
   3184      1.1  christos 				if (len == 0) {
   3185      1.1  christos 					printer(arg, " <Default N>");
   3186      1.1  christos 				} else {
   3187      1.1  christos 					printer(arg, " <N%.*B>", len, inp);
   3188      1.1  christos 					INCPTR(len, inp);
   3189      1.1  christos 					len = 0;
   3190      1.1  christos 				}
   3191      1.1  christos 				break;
   3192      1.1  christos 
   3193      1.1  christos 			case EAPSRP_SKEY:
   3194      1.1  christos 				printer(arg, " <B%.*B>", len, inp);
   3195      1.1  christos 				INCPTR(len, inp);
   3196      1.1  christos 				len = 0;
   3197      1.1  christos 				break;
   3198      1.1  christos 
   3199      1.1  christos 			case EAPSRP_SVALIDATOR:
   3200      1.1  christos 				if (len < sizeof (u_int32_t))
   3201      1.1  christos 					break;
   3202      1.1  christos 				GETLONG(uval, inp);
   3203      1.1  christos 				len -= sizeof (u_int32_t);
   3204      1.1  christos 				if (uval & SRPVAL_EBIT) {
   3205      1.1  christos 					printer(arg, " E");
   3206      1.1  christos 					uval &= ~SRPVAL_EBIT;
   3207      1.1  christos 				}
   3208      1.1  christos 				if (uval != 0) {
   3209      1.1  christos 					printer(arg, " f<%X>", uval);
   3210      1.1  christos 				}
   3211  1.1.1.5  christos 				if ((vallen = len) > SHA_DIGEST_LENGTH)
   3212  1.1.1.5  christos 					vallen = SHA_DIGEST_LENGTH;
   3213      1.1  christos 				printer(arg, " <M2%.*B%s>", len, inp,
   3214  1.1.1.5  christos 				    len < SHA_DIGEST_LENGTH ? "?" : "");
   3215      1.1  christos 				INCPTR(vallen, inp);
   3216      1.1  christos 				len -= vallen;
   3217      1.1  christos 				if (len > 0) {
   3218      1.1  christos 					printer(arg, " <PN%.*B>", len, inp);
   3219      1.1  christos 					INCPTR(len, inp);
   3220      1.1  christos 					len = 0;
   3221      1.1  christos 				}
   3222      1.1  christos 				break;
   3223      1.1  christos 
   3224      1.1  christos 			case EAPSRP_LWRECHALLENGE:
   3225      1.1  christos 				printer(arg, " <Challenge%.*B>", len, inp);
   3226      1.1  christos 				INCPTR(len, inp);
   3227      1.1  christos 				len = 0;
   3228      1.1  christos 				break;
   3229      1.1  christos 			}
   3230      1.1  christos 			break;
   3231  1.1.1.5  christos #endif  /* PPP_WITH_SRP */
   3232      1.1  christos 		}
   3233      1.1  christos 		break;
   3234      1.1  christos 
   3235      1.1  christos 	case EAP_RESPONSE:
   3236      1.1  christos 		if (len < 1)
   3237      1.1  christos 			break;
   3238      1.1  christos 		GETCHAR(rtype, inp);
   3239      1.1  christos 		len--;
   3240      1.1  christos 		if (rtype >= 1 &&
   3241      1.1  christos 		    rtype <= sizeof (eap_typenames) / sizeof (char *))
   3242      1.1  christos 			printer(arg, " %s", eap_typenames[rtype-1]);
   3243      1.1  christos 		else
   3244      1.1  christos 			printer(arg, " type=0x%x", rtype);
   3245      1.1  christos 		switch (rtype) {
   3246      1.1  christos 		case EAPT_IDENTITY:
   3247      1.1  christos 			if (len > 0) {
   3248      1.1  christos 				printer(arg, " <Name ");
   3249      1.1  christos 				print_string((char *)inp, len, printer, arg);
   3250      1.1  christos 				printer(arg, ">");
   3251      1.1  christos 				INCPTR(len, inp);
   3252      1.1  christos 				len = 0;
   3253      1.1  christos 			}
   3254      1.1  christos 			break;
   3255      1.1  christos 
   3256  1.1.1.5  christos #ifdef PPP_WITH_EAPTLS
   3257  1.1.1.4  christos 		case EAPT_TLS:
   3258  1.1.1.4  christos 			if (len < 1)
   3259  1.1.1.4  christos 				break;
   3260  1.1.1.4  christos 			GETCHAR(flags, inp);
   3261  1.1.1.4  christos 			len--;
   3262  1.1.1.4  christos 
   3263  1.1.1.4  christos                         if(flags == 0 && len == 0){
   3264  1.1.1.4  christos                                 printer(arg, " Ack");
   3265  1.1.1.4  christos                                 break;
   3266  1.1.1.4  christos                         }
   3267  1.1.1.4  christos 
   3268  1.1.1.4  christos 			printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
   3269  1.1.1.4  christos 			printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
   3270  1.1.1.4  christos 			printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
   3271  1.1.1.4  christos 
   3272  1.1.1.4  christos 			break;
   3273  1.1.1.5  christos #endif /* PPP_WITH_EAPTLS */
   3274  1.1.1.4  christos 
   3275      1.1  christos 		case EAPT_NAK:
   3276      1.1  christos 			if (len <= 0) {
   3277      1.1  christos 				printer(arg, " <missing hint>");
   3278      1.1  christos 				break;
   3279      1.1  christos 			}
   3280      1.1  christos 			GETCHAR(rtype, inp);
   3281      1.1  christos 			len--;
   3282      1.1  christos 			printer(arg, " <Suggested-type %02X", rtype);
   3283      1.1  christos 			if (rtype >= 1 &&
   3284  1.1.1.4  christos 			    rtype <= sizeof (eap_typenames) / sizeof (char *))
   3285      1.1  christos 				printer(arg, " (%s)", eap_typenames[rtype-1]);
   3286      1.1  christos 			printer(arg, ">");
   3287      1.1  christos 			break;
   3288      1.1  christos 
   3289      1.1  christos 		case EAPT_MD5CHAP:
   3290      1.1  christos 			if (len <= 0) {
   3291      1.1  christos 				printer(arg, " <missing length>");
   3292      1.1  christos 				break;
   3293      1.1  christos 			}
   3294      1.1  christos 			GETCHAR(vallen, inp);
   3295      1.1  christos 			len--;
   3296      1.1  christos 			if (vallen > len)
   3297      1.1  christos 				goto truncated;
   3298      1.1  christos 			printer(arg, " <Value%.*B>", vallen, inp);
   3299      1.1  christos 			INCPTR(vallen, inp);
   3300      1.1  christos 			len -= vallen;
   3301      1.1  christos 			if (len > 0) {
   3302      1.1  christos 				printer(arg, " <Name ");
   3303      1.1  christos 				print_string((char *)inp, len, printer, arg);
   3304      1.1  christos 				printer(arg, ">");
   3305      1.1  christos 				INCPTR(len, inp);
   3306      1.1  christos 				len = 0;
   3307      1.1  christos 			} else {
   3308      1.1  christos 				printer(arg, " <No name>");
   3309      1.1  christos 			}
   3310      1.1  christos 			break;
   3311      1.1  christos 
   3312  1.1.1.5  christos #ifdef PPP_WITH_CHAPMS
   3313  1.1.1.4  christos 		case EAPT_MSCHAPV2:
   3314  1.1.1.4  christos 			if (len <= 0)
   3315  1.1.1.4  christos 				break;
   3316  1.1.1.4  christos 			GETCHAR(opcode, inp);
   3317  1.1.1.4  christos 			len--;
   3318  1.1.1.4  christos 			switch (opcode) {
   3319  1.1.1.4  christos 			case CHAP_RESPONSE:
   3320  1.1.1.4  christos 				INCPTR(3, inp);
   3321  1.1.1.4  christos 				len -= 3;
   3322  1.1.1.4  christos 				GETCHAR(vallen, inp);
   3323  1.1.1.4  christos 				len--;
   3324  1.1.1.4  christos 				if (vallen > len)
   3325  1.1.1.4  christos 					goto truncated;
   3326  1.1.1.4  christos 				len -= vallen;
   3327  1.1.1.4  christos 				printer(arg, " Response <");
   3328  1.1.1.4  christos 				for (; vallen > 0; --vallen) {
   3329  1.1.1.4  christos 					u_char val;
   3330  1.1.1.4  christos 					GETCHAR(val, inp);
   3331  1.1.1.4  christos 					printer(arg, "%.2x", val);
   3332  1.1.1.4  christos 				}
   3333  1.1.1.4  christos 				printer(arg, ">");
   3334  1.1.1.4  christos 				if (len > 0) {
   3335  1.1.1.4  christos 					printer(arg, ", <Name ");
   3336  1.1.1.4  christos 					print_string((char *)inp, len, printer, arg);
   3337  1.1.1.4  christos 					printer(arg, ">");
   3338  1.1.1.4  christos 					INCPTR(len, inp);
   3339  1.1.1.4  christos 					len = 0;
   3340  1.1.1.4  christos 				} else {
   3341  1.1.1.4  christos 					printer(arg, ", <No name>");
   3342  1.1.1.4  christos 				}
   3343  1.1.1.4  christos 				break;
   3344  1.1.1.4  christos 			case CHAP_SUCCESS:
   3345  1.1.1.4  christos 				printer(arg, " Success");
   3346  1.1.1.4  christos 				break;
   3347  1.1.1.4  christos 			case CHAP_FAILURE:
   3348  1.1.1.4  christos 				printer(arg, " Failure");
   3349  1.1.1.4  christos 				break;
   3350  1.1.1.4  christos 			default:
   3351  1.1.1.4  christos 				printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
   3352  1.1.1.4  christos 				break;
   3353  1.1.1.4  christos 			}
   3354  1.1.1.4  christos 			break;
   3355  1.1.1.5  christos #endif /* PPP_WITH_CHAPMS */
   3356  1.1.1.4  christos 
   3357  1.1.1.5  christos #ifdef PPP_WITH_SRP
   3358      1.1  christos 		case EAPT_SRP:
   3359      1.1  christos 			if (len < 1)
   3360      1.1  christos 				goto truncated;
   3361      1.1  christos 			GETCHAR(vallen, inp);
   3362      1.1  christos 			len--;
   3363      1.1  christos 			printer(arg, "-%d", vallen);
   3364      1.1  christos 			switch (vallen) {
   3365      1.1  christos 			case EAPSRP_CKEY:
   3366      1.1  christos 				printer(arg, " <A%.*B>", len, inp);
   3367      1.1  christos 				INCPTR(len, inp);
   3368      1.1  christos 				len = 0;
   3369      1.1  christos 				break;
   3370      1.1  christos 
   3371      1.1  christos 			case EAPSRP_CVALIDATOR:
   3372      1.1  christos 				if (len < sizeof (u_int32_t))
   3373      1.1  christos 					break;
   3374      1.1  christos 				GETLONG(uval, inp);
   3375      1.1  christos 				len -= sizeof (u_int32_t);
   3376      1.1  christos 				if (uval & SRPVAL_EBIT) {
   3377      1.1  christos 					printer(arg, " E");
   3378      1.1  christos 					uval &= ~SRPVAL_EBIT;
   3379      1.1  christos 				}
   3380      1.1  christos 				if (uval != 0) {
   3381      1.1  christos 					printer(arg, " f<%X>", uval);
   3382      1.1  christos 				}
   3383      1.1  christos 				printer(arg, " <M1%.*B%s>", len, inp,
   3384  1.1.1.5  christos 				    len == SHA_DIGEST_LENGTH ? "" : "?");
   3385      1.1  christos 				INCPTR(len, inp);
   3386      1.1  christos 				len = 0;
   3387      1.1  christos 				break;
   3388      1.1  christos 
   3389      1.1  christos 			case EAPSRP_ACK:
   3390      1.1  christos 				break;
   3391      1.1  christos 
   3392      1.1  christos 			case EAPSRP_LWRECHALLENGE:
   3393      1.1  christos 				printer(arg, " <Response%.*B%s>", len, inp,
   3394  1.1.1.5  christos 				    len == SHA_DIGEST_LENGTH ? "" : "?");
   3395  1.1.1.5  christos 				if ((vallen = len) > SHA_DIGEST_LENGTH)
   3396  1.1.1.5  christos 					vallen = SHA_DIGEST_LENGTH;
   3397      1.1  christos 				INCPTR(vallen, inp);
   3398      1.1  christos 				len -= vallen;
   3399      1.1  christos 				break;
   3400      1.1  christos 			}
   3401      1.1  christos 			break;
   3402  1.1.1.5  christos #endif  /* PPP_WITH_SRP */
   3403      1.1  christos 		}
   3404      1.1  christos 		break;
   3405      1.1  christos 
   3406      1.1  christos 	case EAP_SUCCESS:	/* No payload expected for these! */
   3407      1.1  christos 	case EAP_FAILURE:
   3408      1.1  christos 		break;
   3409      1.1  christos 
   3410      1.1  christos 	truncated:
   3411      1.1  christos 		printer(arg, " <truncated>");
   3412      1.1  christos 		break;
   3413      1.1  christos 	}
   3414      1.1  christos 
   3415      1.1  christos 	if (len > 8)
   3416      1.1  christos 		printer(arg, "%8B...", inp);
   3417      1.1  christos 	else if (len > 0)
   3418      1.1  christos 		printer(arg, "%.*B", len, inp);
   3419      1.1  christos 	INCPTR(len, inp);
   3420      1.1  christos 
   3421      1.1  christos 	return (inp - pstart);
   3422      1.1  christos }
   3423