1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 // 5 // Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de 6 //--------------------------------------------------------------------- 7 8 #include "_KPPPAuthenticationHandler.h" 9 10 #include <KPPPConfigurePacket.h> 11 #include <KPPPDevice.h> 12 13 #include <netinet/in.h> 14 15 #define AUTHENTICATION_TYPE 0x3 16 #define AUTHENTICATOR_TYPE_STRING "Authenticator" 17 18 typedef struct authentication_item { 19 uint8 type; 20 uint8 length; 21 uint16 protocol; 22 } authentication_item; 23 24 25 _PPPAuthenticationHandler::_PPPAuthenticationHandler(PPPInterface& interface) 26 : PPPOptionHandler("Authentication Handler", AUTHENTICATION_TYPE, interface, NULL), 27 fLocalIndex(-1), 28 fPeerIndex(-1), 29 fSuggestedLocalIndex(-1), 30 fSuggestedPeerIndex(-1), 31 fPeerAuthenticatorRejected(false) 32 { 33 } 34 35 36 int32 37 _PPPAuthenticationHandler::NextAuthenticator(int32 start, ppp_side side) 38 { 39 // find the next authenticator for side, beginning at start 40 41 PPPProtocol *protocol; 42 for(int32 index = start; index < Interface().CountProtocols(); index++) { 43 protocol = Interface().ProtocolAt(index); 44 if(protocol && !strcasecmp(protocol->Type(), AUTHENTICATOR_TYPE_STRING) 45 && protocol->OptionHandler() 46 && protocol->Side() == side) 47 return index; 48 } 49 50 return -1; 51 } 52 53 54 status_t 55 _PPPAuthenticationHandler::AddToRequest(PPPConfigurePacket& request) 56 { 57 // AddToRequest(): Check if peer must authenticate itself and 58 // add an authentication request if needed. This request is added 59 // by the authenticator's OptionHandler. 60 61 int32 index; 62 PPPProtocol *protocol; 63 if(fPeerIndex != -1 && (protocol = Interface().ProtocolAt(fPeerIndex))) 64 protocol->SetEnabled(false); 65 if(fSuggestedPeerIndex != -1 66 && (protocol = Interface().ProtocolAt(fSuggestedPeerIndex))) 67 protocol->SetEnabled(false); 68 69 if(fPeerAuthenticatorRejected) { 70 if(fSuggestedPeerIndex == -1) { 71 // This happens when the protocol is rejected, but no alternative 72 // protocol is supplied to us or the suggested protocol is not supported. 73 // We can use this chance to increase fPeerIndex to the next authenticator. 74 index = NextAuthenticator(fPeerIndex + 1, PPP_PEER_SIDE); 75 } else 76 index = fSuggestedPeerIndex; 77 78 fPeerAuthenticatorRejected = false; 79 } else { 80 if(fPeerIndex == -1) { 81 // there is no authenticator selected, so find one for us 82 index = NextAuthenticator(fPeerIndex + 1, PPP_PEER_SIDE); 83 } else 84 index = fPeerIndex; 85 } 86 87 // check if all authenticators were rejected or if no authentication needed 88 if(index == -1) { 89 if(fPeerIndex == -1) 90 return B_OK; 91 // no peer authentication needed 92 else 93 return B_ERROR; 94 // all authenticators were denied 95 } 96 97 protocol = Interface().ProtocolAt(index); 98 if(!protocol || !protocol->OptionHandler()) 99 return B_ERROR; 100 101 fPeerIndex = index; 102 // this could omit some authenticators when we get a suggestion, but that is 103 // no problem because the suggested authenticator will be accepted (hopefully) 104 105 protocol->SetEnabled(true); 106 return protocol->OptionHandler()->AddToRequest(request); 107 // let protocol add its request 108 } 109 110 111 status_t 112 _PPPAuthenticationHandler::ParseNak(const PPPConfigurePacket& nak) 113 { 114 // The authenticator's OptionHandler is not notified. 115 116 authentication_item *item = 117 (authentication_item*) nak.ItemWithType(AUTHENTICATION_TYPE); 118 119 if(!item) 120 return B_OK; 121 // the request was not rejected 122 if(item->length < 4) 123 return B_ERROR; 124 125 PPPProtocol *protocol; 126 if(fSuggestedPeerIndex != -1 127 && (protocol = Interface().ProtocolAt(fSuggestedPeerIndex))) { 128 protocol->SetEnabled(false); 129 // if no alternative protocol is supplied we will choose a new one in 130 // AddToRequest() 131 if(ntohs(item->protocol) == protocol->Protocol()) { 132 fSuggestedPeerIndex = -1; 133 return B_OK; 134 } 135 } 136 137 fPeerAuthenticatorRejected = true; 138 int32 index = 0; 139 if((protocol = Interface().ProtocolFor(ntohs(item->protocol), &index)) 140 && !strcasecmp(protocol->Type(), AUTHENTICATOR_TYPE_STRING) 141 && protocol->OptionHandler()) 142 fSuggestedPeerIndex = index; 143 else 144 fSuggestedPeerIndex = -1; 145 146 return B_OK; 147 } 148 149 150 status_t 151 _PPPAuthenticationHandler::ParseReject(const PPPConfigurePacket& reject) 152 { 153 // an authentication request must not be rejected! 154 if(reject.ItemWithType(AUTHENTICATION_TYPE)) 155 return B_ERROR; 156 157 return B_OK; 158 } 159 160 161 status_t 162 _PPPAuthenticationHandler::ParseAck(const PPPConfigurePacket& ack) 163 { 164 authentication_item *item = 165 (authentication_item*) ack.ItemWithType(AUTHENTICATION_TYPE); 166 167 PPPProtocol *protocol = Interface().ProtocolAt(fPeerIndex); 168 if(fPeerIndex != -1 && !protocol) 169 return B_ERROR; 170 // could not find the protocol 171 172 if(!item) { 173 if(fPeerIndex != -1) 174 return B_ERROR; 175 // the ack does not contain our request 176 } else if(fPeerIndex == -1 || ntohs(item->protocol) != protocol->Protocol()) 177 return B_ERROR; 178 // this item was never requested 179 180 return protocol->OptionHandler()->ParseAck(ack); 181 // this should enable the authenticator 182 } 183 184 185 status_t 186 _PPPAuthenticationHandler::ParseRequest(const PPPConfigurePacket& request, 187 int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject) 188 { 189 PPPProtocol *protocol; 190 if(fLocalIndex != -1 && (protocol = Interface().ProtocolAt(fLocalIndex))) 191 protocol->SetEnabled(false); 192 193 authentication_item *item = (authentication_item*) request.ItemAt(index); 194 if(!item) 195 return B_OK; 196 // no authentication requested by peer 197 198 // try to find the requested protocol and select it by saving it in fLocalIndex 199 fLocalIndex = 0; 200 protocol = Interface().ProtocolFor(ntohs(item->protocol), &fLocalIndex); 201 if(protocol && !strcasecmp(protocol->Type(), AUTHENTICATOR_TYPE_STRING) 202 && protocol->OptionHandler()) 203 return protocol->OptionHandler()->ParseRequest(request, index, nak, reject); 204 205 // suggest another authentication protocol 206 int32 nextIndex = NextAuthenticator(fSuggestedLocalIndex + 1, PPP_LOCAL_SIDE); 207 208 if(nextIndex == -1) { 209 if(fSuggestedLocalIndex == -1) { 210 // reject the complete authentication option 211 reject.AddItem((ppp_configure_item*) item); 212 return B_OK; 213 } else 214 nextIndex = fSuggestedLocalIndex; 215 // try the old one again as it was not rejected until now 216 } 217 218 protocol = Interface().ProtocolAt(nextIndex); 219 if(!protocol) 220 return B_ERROR; 221 222 fSuggestedLocalIndex = nextIndex; 223 fLocalIndex = -1; 224 // no authenticator selected 225 226 // nak this authenticator and suggest an alternative 227 authentication_item suggestion; 228 suggestion.type = AUTHENTICATION_TYPE; 229 suggestion.length = 4; 230 suggestion.protocol = htons(protocol->Protocol()); 231 return nak.AddItem((ppp_configure_item*) &suggestion) ? B_OK : B_ERROR; 232 } 233 234 235 status_t 236 _PPPAuthenticationHandler::SendingAck(const PPPConfigurePacket& ack) 237 { 238 // do not insist on authenticating our side of the link ;) 239 240 authentication_item *item = 241 (authentication_item*) ack.ItemWithType(AUTHENTICATION_TYPE); 242 243 if(!item) 244 return B_OK; 245 // no authentication needed 246 247 fSuggestedLocalIndex = -1; 248 249 if(fLocalIndex == -1) 250 return B_ERROR; 251 // no authenticator selected (our suggestions must be requested, too) 252 253 PPPProtocol *protocol = Interface().ProtocolAt(fLocalIndex); 254 if(!protocol) 255 return B_ERROR; 256 257 protocol->SetEnabled(true); 258 return protocol->OptionHandler()->SendingAck(ack); 259 // this should enable the authenticator 260 } 261 262 263 void 264 _PPPAuthenticationHandler::Reset() 265 { 266 PPPProtocol *protocol = NULL; 267 if(fLocalIndex != -1 && (protocol = Interface().ProtocolAt(fLocalIndex))) { 268 protocol->SetEnabled(false); 269 protocol->OptionHandler()->Reset(); 270 } 271 if(fPeerIndex != -1 && (protocol = Interface().ProtocolAt(fPeerIndex))) { 272 protocol->SetEnabled(false); 273 protocol->OptionHandler()->Reset(); 274 } 275 if(fSuggestedPeerIndex != -1 276 && (protocol = Interface().ProtocolAt(fSuggestedPeerIndex))) { 277 protocol->SetEnabled(false); 278 protocol->OptionHandler()->Reset(); 279 } 280 281 fLocalIndex = fPeerIndex = fSuggestedLocalIndex = fSuggestedPeerIndex = -1; 282 fPeerAuthenticatorRejected = false; 283 } 284