/** Called by the low layer protocol to copy some data in socket send buffer starting from the specific offset to a buffer provided by the caller. @param Sock Pointer to the socket. @param Offset The start point of the data to be copied. @param Len The length of the data to be copied. @param Dest Pointer to the destination to copy the data. @return The data size copied. **/ UINT32 SockGetDataToSend ( IN SOCKET *Sock, IN UINT32 Offset, IN UINT32 Len, IN UINT8 *Dest ) { ASSERT ((Sock != NULL) && SockStream == Sock->Type); return NetbufQueCopy ( Sock->SndBuffer.DataQueue, Offset, Len, Dest ); }
/** Copy data from socket buffer to an application provided receive buffer. @param[in] Sock Pointer to the socket. @param[in] TcpRxData Pointer to the application provided receive buffer. @param[in] RcvdBytes The maximum length of the data can be copied. @param[in] IsUrg If TRUE the data is Out of Bound, FALSE the data is normal. **/ VOID SockSetTcpRxData ( IN SOCKET *Sock, IN VOID *TcpRxData, IN UINT32 RcvdBytes, IN BOOLEAN IsUrg ) { UINT32 Index; UINT32 CopyBytes; UINT32 OffSet; EFI_TCP4_RECEIVE_DATA *RxData; EFI_TCP4_FRAGMENT_DATA *Fragment; RxData = (EFI_TCP4_RECEIVE_DATA *) TcpRxData; OffSet = 0; ASSERT (RxData->DataLength >= RcvdBytes); RxData->DataLength = RcvdBytes; RxData->UrgentFlag = IsUrg; // // Copy the CopyBytes data from socket receive buffer to RxData. // for (Index = 0; (Index < RxData->FragmentCount) && (RcvdBytes > 0); Index++) { Fragment = &RxData->FragmentTable[Index]; CopyBytes = MIN ((UINT32) (Fragment->FragmentLength), RcvdBytes); NetbufQueCopy ( Sock->RcvBuffer.DataQueue, OffSet, CopyBytes, Fragment->FragmentBuffer ); Fragment->FragmentLength = CopyBytes; RcvdBytes -= CopyBytes; OffSet += CopyBytes; } }
/** This function checks the received iSCSI Login Response during the security negotiation stage. @param[in] Conn The iSCSI connection. @retval EFI_SUCCESS The Login Response passed the CHAP validation. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_PROTOCOL_ERROR Some kind of protocol error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS IScsiCHAPOnRspReceived ( IN ISCSI_CONNECTION *Conn ) { EFI_STATUS Status; ISCSI_SESSION *Session; ISCSI_CHAP_AUTH_DATA *AuthData; CHAR8 *Value; UINT8 *Data; UINT32 Len; LIST_ENTRY *KeyValueList; UINTN Algorithm; CHAR8 *Identifier; CHAR8 *Challenge; CHAR8 *Name; CHAR8 *Response; UINT8 TargetRsp[ISCSI_CHAP_RSP_LEN]; UINT32 RspLen; UINTN Result; ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION); ASSERT (Conn->RspQue.BufNum != 0); Session = Conn->Session; AuthData = &Session->AuthData.CHAP; Len = Conn->RspQue.BufSize; Data = AllocateZeroPool (Len); if (Data == NULL) { return EFI_OUT_OF_RESOURCES; } // // Copy the data in case the data spans over multiple PDUs. // NetbufQueCopy (&Conn->RspQue, 0, Len, Data); // // Build the key-value list from the data segment of the Login Response. // KeyValueList = IScsiBuildKeyValueList ((CHAR8 *) Data, Len); if (KeyValueList == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Status = EFI_PROTOCOL_ERROR; switch (Conn->AuthStep) { case ISCSI_AUTH_INITIAL: // // The first Login Response. // Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_PORTAL_GROUP_TAG); if (Value == NULL) { goto ON_EXIT; } Result = IScsiNetNtoi (Value); if (Result > 0xFFFF) { goto ON_EXIT; } Session->TargetPortalGroupTag = (UINT16) Result; Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_AUTH_METHOD); if (Value == NULL) { goto ON_EXIT; } // // Initiator mandates CHAP authentication but target replies without "CHAP", or // initiator suggets "None" but target replies with some kind of auth method. // if (Session->AuthType == ISCSI_AUTH_TYPE_NONE) { if (AsciiStrCmp (Value, ISCSI_KEY_VALUE_NONE) != 0) { goto ON_EXIT; } } else if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) { if (AsciiStrCmp (Value, ISCSI_AUTH_METHOD_CHAP) != 0) { goto ON_EXIT; } } else { goto ON_EXIT; } // // Transit to CHAP step one. // Conn->AuthStep = ISCSI_CHAP_STEP_ONE; Status = EFI_SUCCESS; break; case ISCSI_CHAP_STEP_TWO: // // The Target replies with CHAP_A=<A> CHAP_I=<I> CHAP_C=<C> // Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_ALGORITHM); if (Value == NULL) { goto ON_EXIT; } Algorithm = IScsiNetNtoi (Value); if (Algorithm != ISCSI_CHAP_ALGORITHM_MD5) { // // Unsupported algorithm is chosen by target. // goto ON_EXIT; } Identifier = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_IDENTIFIER); if (Identifier == NULL) { goto ON_EXIT; } Challenge = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_CHALLENGE); if (Challenge == NULL) { goto ON_EXIT; } // // Process the CHAP identifier and CHAP Challenge from Target. // Calculate Response value. // Result = IScsiNetNtoi (Identifier); if (Result > 0xFF) { goto ON_EXIT; } AuthData->InIdentifier = (UINT32) Result; AuthData->InChallengeLength = ISCSI_CHAP_AUTH_MAX_LEN; IScsiHexToBin ((UINT8 *) AuthData->InChallenge, &AuthData->InChallengeLength, Challenge); Status = IScsiCHAPCalculateResponse ( AuthData->InIdentifier, AuthData->AuthConfig->CHAPSecret, (UINT32) AsciiStrLen (AuthData->AuthConfig->CHAPSecret), AuthData->InChallenge, AuthData->InChallengeLength, AuthData->CHAPResponse ); // // Transit to next step. // Conn->AuthStep = ISCSI_CHAP_STEP_THREE; break; case ISCSI_CHAP_STEP_THREE: // // One way CHAP authentication and the target would like to // authenticate us. // Status = EFI_SUCCESS; break; case ISCSI_CHAP_STEP_FOUR: ASSERT (AuthData->AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL); // // The forth step, CHAP_N=<N> CHAP_R=<R> is received from Target. // Name = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_NAME); if (Name == NULL) { goto ON_EXIT; } Response = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_RESPONSE); if (Response == NULL) { goto ON_EXIT; } RspLen = ISCSI_CHAP_RSP_LEN; IScsiHexToBin (TargetRsp, &RspLen, Response); // // Check the CHAP Name and Response replied by Target. // Status = IScsiCHAPAuthTarget (AuthData, TargetRsp); break; default: break; } ON_EXIT: if (KeyValueList != NULL) { IScsiFreeKeyValueList (KeyValueList); } FreePool (Data); return Status; }