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