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