xref: /haiku/src/add-ons/kernel/network/ppp/pap/Protocol.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
1 /*
2  * Copyright 2003-2006, Waldemar Kornewald <wkornew@gmx.net>
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "Protocol.h"
7 #include <KPPPConfigurePacket.h>
8 #include <KPPPInterface.h>
9 
10 #include <cstring>
11 #include <netinet/in.h>
12 #include <core_funcs.h>
13 #include <sys/sockio.h>
14 
15 
16 static const bigtime_t kPAPTimeout = 3000000;
17 	// 3 seconds
18 
19 // PAPHandler
20 static const uint8 kAuthenticationType = 0x3;
21 static const char *kAuthenticatorTypeString = "Authenticator";
22 
23 typedef struct authentication_item {
24 	uint8 type;
25 	uint8 length;
26 	uint16 protocolNumber;
27 } _PACKED authentication_item;
28 
29 
30 PAPHandler::PAPHandler(PAP& owner, KPPPInterface& interface)
31 	: KPPPOptionHandler("PAP", kAuthenticationType, interface, NULL),
32 	fOwner(owner)
33 {
34 }
35 
36 
37 status_t
38 PAPHandler::AddToRequest(KPPPConfigurePacket& request)
39 {
40 	// only local authenticators send requests to peer
41 	if(Owner().Side() != PPP_PEER_SIDE)
42 		return B_OK;
43 
44 	authentication_item item;
45 	item.type = kAuthenticationType;
46 	item.length = sizeof(item);
47 	item.protocolNumber = htons(PAP_PROTOCOL);
48 
49 	request.AddItem((ppp_configure_item*) &item);
50 
51 	return B_OK;
52 }
53 
54 
55 status_t
56 PAPHandler::ParseRequest(const KPPPConfigurePacket& request,
57 	int32 index, KPPPConfigurePacket& nak, KPPPConfigurePacket& reject)
58 {
59 	// only local authenticators handle requests from peer
60 	if(Owner().Side() != PPP_LOCAL_SIDE)
61 		return B_OK;
62 
63 	// we merely check if the values are correct
64 	authentication_item *item = (authentication_item*) request.ItemAt(index);
65 	if(item->type != kAuthenticationType
66 			|| item->length != 4 || ntohs(item->protocolNumber) != PAP_PROTOCOL)
67 		return B_ERROR;
68 
69 	return B_OK;
70 }
71 
72 
73 // PAP
74 PAP::PAP(KPPPInterface& interface, driver_parameter *settings)
75 	: KPPPProtocol("PAP", PPP_AUTHENTICATION_PHASE, PAP_PROTOCOL, PPP_PROTOCOL_LEVEL,
76 		AF_UNSPEC, 0, interface, settings, PPP_ALWAYS_ALLOWED,
77 		kAuthenticatorTypeString, new PAPHandler(*this, interface)),
78 	fState(INITIAL),
79 	fID(system_time() & 0xFF),
80 	fMaxRequest(3),
81 	fRequestID(0),
82 	fNextTimeout(0)
83 {
84 }
85 
86 
87 PAP::~PAP()
88 {
89 }
90 
91 
92 status_t
93 PAP::InitCheck() const
94 {
95 	if(Side() != PPP_LOCAL_SIDE && Side() != PPP_PEER_SIDE)
96 		return B_ERROR;
97 
98 	return KPPPProtocol::InitCheck();
99 }
100 
101 
102 bool
103 PAP::Up()
104 {
105 	TRACE("PAP: Up() state=%d\n", State());
106 
107 	switch(State()) {
108 		case INITIAL:
109 			if(Side() == PPP_LOCAL_SIDE) {
110 				NewState(REQ_SENT);
111 				InitializeRestartCount();
112 				SendRequest();
113 			} else if(Side() == PPP_PEER_SIDE) {
114 				NewState(WAITING_FOR_REQ);
115 				InitializeRestartCount();
116 				fNextTimeout = system_time() + kPAPTimeout;
117 			} else {
118 				UpFailedEvent();
119 				return false;
120 			}
121 		break;
122 
123 		default:
124 			;
125 	}
126 
127 	return true;
128 }
129 
130 
131 bool
132 PAP::Down()
133 {
134 	TRACE("PAP: Down() state=%d\n", State());
135 
136 	switch(Interface().Phase()) {
137 		case PPP_DOWN_PHASE:
138 			// interface finished terminating
139 		case PPP_ESTABLISHED_PHASE:
140 			// terminate this NCP individually (block until we finished terminating)
141 			NewState(INITIAL);
142 			DownEvent();
143 		break;
144 
145 /*		case PPP_TERMINATION_PHASE:
146 			// interface is terminating
147 		break;
148 
149 		case PPP_ESTABLISHMENT_PHASE:
150 			// interface is reconfiguring
151 		break;
152 */
153 		default:
154 			;
155 	}
156 
157 	return true;
158 }
159 
160 
161 status_t
162 PAP::Send(struct mbuf *packet, uint16 protocolNumber)
163 {
164 	// we do not encapsulate PAP packets
165 	m_freem(packet);
166 	return B_ERROR;
167 }
168 
169 
170 status_t
171 PAP::Receive(struct mbuf *packet, uint16 protocolNumber)
172 {
173 	if(!packet)
174 		return B_ERROR;
175 
176 	if(protocolNumber != PAP_PROTOCOL)
177 		return PPP_UNHANDLED;
178 
179 	ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*);
180 
181 	// check if the packet is meant for us:
182 	// only peer authenticators handle requests
183 	if(data->code == PPP_CONFIGURE_REQUEST && Side() != PPP_PEER_SIDE)
184 		return PPP_UNHANDLED;
185 	// only local authenticators handle acks and naks
186 	if((data->code == PPP_CONFIGURE_ACK || data->code == PPP_CONFIGURE_NAK)
187 			&& Side() != PPP_LOCAL_SIDE)
188 		return PPP_UNHANDLED;
189 
190 	// remove padding
191 	int32 length = packet->m_len;
192 	if(packet->m_flags & M_PKTHDR)
193 		length = packet->m_pkthdr.len;
194 	length -= ntohs(data->length);
195 	if(length)
196 		m_adj(packet, -length);
197 
198 	if(ntohs(data->length) < 4)
199 		return B_ERROR;
200 
201 	// packet is freed by event methods
202 	// code values are the same as for LCP (but very reduced)
203 	switch(data->code) {
204 		case PPP_CONFIGURE_REQUEST:
205 			RREvent(packet);
206 		break;
207 
208 		case PPP_CONFIGURE_ACK:
209 			RAEvent(packet);
210 		break;
211 
212 		case PPP_CONFIGURE_NAK:
213 			RNEvent(packet);
214 		break;
215 
216 		default:
217 			return PPP_UNHANDLED;
218 	}
219 
220 	return B_OK;
221 }
222 
223 
224 void
225 PAP::Pulse()
226 {
227 	if(fNextTimeout == 0 || fNextTimeout > system_time())
228 		return;
229 	fNextTimeout = 0;
230 
231 	switch(State()) {
232 		case REQ_SENT:
233 		case WAITING_FOR_REQ:
234 			if(fRequestCounter <= 0)
235 				TOBadEvent();
236 			else
237 				TOGoodEvent();
238 		break;
239 
240 		default:
241 			;
242 	}
243 }
244 
245 
246 uint8
247 PAP::NextID()
248 {
249 	return (uint8) atomic_add(&fID, 1);
250 }
251 
252 
253 void
254 PAP::NewState(pap_state next)
255 {
256 	TRACE("PAP: NewState(%d) state=%d\n", next, State());
257 
258 	//  state changes
259 	if(State() == INITIAL && next != State()) {
260 		if(Side() == PPP_LOCAL_SIDE)
261 			Interface().StateMachine().LocalAuthenticationRequested();
262 		else if(Side() == PPP_PEER_SIDE)
263 			Interface().StateMachine().PeerAuthenticationRequested();
264 
265 		UpStarted();
266 	} else if(State() == ACCEPTED && next != State())
267 		DownStarted();
268 
269 	// maybe we do not need the timer anymore
270 	if(next == INITIAL || next == ACCEPTED)
271 		fNextTimeout = 0;
272 
273 	fState = next;
274 }
275 
276 
277 void
278 PAP::TOGoodEvent()
279 {
280 	TRACE("PAP: TOGoodEvent() state=%d\n", State());
281 
282 	switch(State()) {
283 		case REQ_SENT:
284 			SendRequest();
285 		break;
286 
287 		case WAITING_FOR_REQ:
288 			fNextTimeout = system_time() + kPAPTimeout;
289 		break;
290 
291 		default:
292 			;
293 	}
294 }
295 
296 
297 void
298 PAP::TOBadEvent()
299 {
300 	TRACE("PAP: TOBadEvent() state=%d\n", State());
301 
302 	switch(State()) {
303 		case REQ_SENT:
304 		case WAITING_FOR_REQ:
305 			NewState(INITIAL);
306 			if(State() == REQ_SENT)
307 				Interface().StateMachine().LocalAuthenticationDenied(
308 					Interface().Username());
309 			else
310 				Interface().StateMachine().PeerAuthenticationDenied(
311 					Interface().Username());
312 
313 			UpFailedEvent();
314 		break;
315 
316 		default:
317 			;
318 	}
319 }
320 
321 
322 void
323 PAP::RREvent(struct mbuf *packet)
324 {
325 	TRACE("PAP: RREvent() state=%d\n", State());
326 
327 	ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
328 	int32 length = ntohs(request->length);
329 	uint8 *data = request->data;
330 	uint8 *userLength = data;
331 	uint8 *passwordLength = data + 1 + data[0];
332 
333 	// make sure the length values are all okay
334 	if(6 + *userLength + *passwordLength > length) {
335 		m_freem(packet);
336 		return;
337 	}
338 
339 	char *peerUsername = (char*) userLength + 1,
340 		*peerPassword = (char*) passwordLength + 1;
341 	const char *username = Interface().Username(), *password = Interface().Password();
342 
343 	if(*userLength == strlen(username) && *passwordLength == strlen(password)
344 			&& !strncmp(peerUsername, username, *userLength)
345 			&& !strncmp(peerPassword, password, *passwordLength)) {
346 		NewState(ACCEPTED);
347 		Interface().StateMachine().PeerAuthenticationAccepted(username);
348 		UpEvent();
349 		SendAck(packet);
350 	} else {
351 		NewState(INITIAL);
352 		Interface().StateMachine().PeerAuthenticationDenied(username);
353 		UpFailedEvent();
354 		SendNak(packet);
355 	}
356 }
357 
358 
359 void
360 PAP::RAEvent(struct mbuf *packet)
361 {
362 	TRACE("PAP: RAEvent() state=%d\n", State());
363 
364 	if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) {
365 		// this packet is not a reply to our request
366 
367 		// TODO: log this event
368 		m_freem(packet);
369 		return;
370 	}
371 
372 	switch(State()) {
373 		case REQ_SENT:
374 			NewState(ACCEPTED);
375 			Interface().StateMachine().LocalAuthenticationAccepted(
376 				Interface().Username());
377 			UpEvent();
378 		break;
379 
380 		default:
381 			;
382 	}
383 
384 	m_freem(packet);
385 }
386 
387 
388 void
389 PAP::RNEvent(struct mbuf *packet)
390 {
391 	TRACE("PAP: RNEvent() state=%d\n", State());
392 
393 	if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) {
394 		// this packet is not a reply to our request
395 
396 		// TODO: log this event
397 		m_freem(packet);
398 		return;
399 	}
400 
401 	switch(State()) {
402 		case REQ_SENT:
403 			NewState(INITIAL);
404 			Interface().StateMachine().LocalAuthenticationDenied(
405 				Interface().Username());
406 			UpFailedEvent();
407 		break;
408 
409 		default:
410 			;
411 	}
412 
413 	m_freem(packet);
414 }
415 
416 
417 void
418 PAP::InitializeRestartCount()
419 {
420 	fRequestCounter = fMaxRequest;
421 }
422 
423 
424 bool
425 PAP::SendRequest()
426 {
427 	TRACE("PAP: SendRequest() state=%d\n", State());
428 
429 	--fRequestCounter;
430 	fNextTimeout = system_time() + kPAPTimeout;
431 
432 	struct mbuf *packet = m_gethdr(MT_DATA);
433 	if(!packet)
434 		return false;
435 
436 	const char *username = Interface().Username(), *password = Interface().Password();
437 
438 	packet->m_pkthdr.len = packet->m_len = 6 + strlen(username) + strlen(password);
439 
440 	// reserve some space for overhead (we are lazy and reserve too much)
441 	packet->m_data += Interface().PacketOverhead();
442 
443 	ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
444 	request->code = PPP_CONFIGURE_REQUEST;
445 	request->id = fRequestID = NextID();
446 	request->length = htons(packet->m_len);
447 	uint8 *data = request->data;
448 	data[0] = strlen(username);
449 	memcpy(data + 1, username, strlen(username));
450 	data[1 + data[0]] = strlen(password);
451 	memcpy(data + 2 + data[0], password, strlen(password));
452 
453 	return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
454 }
455 
456 
457 bool
458 PAP::SendAck(struct mbuf *packet)
459 {
460 	TRACE("PAP: SendAck() state=%d\n", State());
461 
462 	if(!packet)
463 		return false;
464 
465 	ppp_lcp_packet *ack = mtod(packet, ppp_lcp_packet*);
466 	ack->code = PPP_CONFIGURE_ACK;
467 	packet->m_len = 5;
468 	if(packet->m_flags & M_PKTHDR)
469 		packet->m_pkthdr.len = 5;
470 	ack->length = htons(packet->m_len);
471 
472 	ack->data[0] = 0;
473 
474 	return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
475 }
476 
477 
478 bool
479 PAP::SendNak(struct mbuf *packet)
480 {
481 	TRACE("PAP: SendNak() state=%d\n", State());
482 
483 	if(!packet)
484 		return false;
485 
486 	ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*);
487 	nak->code = PPP_CONFIGURE_NAK;
488 	packet->m_len = 5;
489 	if(packet->m_flags & M_PKTHDR)
490 		packet->m_pkthdr.len = 5;
491 	nak->length = htons(packet->m_len);
492 
493 	nak->data[0] = 0;
494 
495 	return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
496 }
497