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