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