Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MaximInterface mbed
WebServerInterface.cpp@27:81a87d29bedd, 2016-12-16 (annotated)
- Committer:
- IanBenzMaxim
- Date:
- Fri Dec 16 20:14:05 2016 +0000
- Revision:
- 27:81a87d29bedd
- Parent:
- 25:37ea43ff81be
- Child:
- 28:e5cdaf13d299
Temporarily moved to a fork of mbed-os due to issues with the implementation of mutexes. Stripped mutex implementation for armcc which should not affect this project since it does not use RTOS features.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| IanBenzMaxim | 1:e1c7c1c636af | 1 | /******************************************************************************* |
| IanBenzMaxim | 1:e1c7c1c636af | 2 | * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. |
| IanBenzMaxim | 1:e1c7c1c636af | 3 | * |
| IanBenzMaxim | 1:e1c7c1c636af | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| IanBenzMaxim | 1:e1c7c1c636af | 5 | * copy of this software and associated documentation files (the "Software"), |
| IanBenzMaxim | 1:e1c7c1c636af | 6 | * to deal in the Software without restriction, including without limitation |
| IanBenzMaxim | 1:e1c7c1c636af | 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| IanBenzMaxim | 1:e1c7c1c636af | 8 | * and/or sell copies of the Software, and to permit persons to whom the |
| IanBenzMaxim | 1:e1c7c1c636af | 9 | * Software is furnished to do so, subject to the following conditions: |
| IanBenzMaxim | 1:e1c7c1c636af | 10 | * |
| IanBenzMaxim | 1:e1c7c1c636af | 11 | * The above copyright notice and this permission notice shall be included |
| IanBenzMaxim | 1:e1c7c1c636af | 12 | * in all copies or substantial portions of the Software. |
| IanBenzMaxim | 1:e1c7c1c636af | 13 | * |
| IanBenzMaxim | 1:e1c7c1c636af | 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| IanBenzMaxim | 1:e1c7c1c636af | 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| IanBenzMaxim | 1:e1c7c1c636af | 16 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| IanBenzMaxim | 1:e1c7c1c636af | 17 | * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES |
| IanBenzMaxim | 1:e1c7c1c636af | 18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| IanBenzMaxim | 1:e1c7c1c636af | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| IanBenzMaxim | 1:e1c7c1c636af | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
| IanBenzMaxim | 1:e1c7c1c636af | 21 | * |
| IanBenzMaxim | 1:e1c7c1c636af | 22 | * Except as contained in this notice, the name of Maxim Integrated |
| IanBenzMaxim | 1:e1c7c1c636af | 23 | * Products, Inc. shall not be used except as stated in the Maxim Integrated |
| IanBenzMaxim | 1:e1c7c1c636af | 24 | * Products, Inc. Branding Policy. |
| IanBenzMaxim | 1:e1c7c1c636af | 25 | * |
| IanBenzMaxim | 1:e1c7c1c636af | 26 | * The mere transfer of this software does not imply any licenses |
| IanBenzMaxim | 1:e1c7c1c636af | 27 | * of trade secrets, proprietary technology, copyrights, patents, |
| IanBenzMaxim | 1:e1c7c1c636af | 28 | * trademarks, maskwork rights, or any other form of intellectual |
| IanBenzMaxim | 1:e1c7c1c636af | 29 | * property whatsoever. Maxim Integrated Products, Inc. retains all |
| IanBenzMaxim | 1:e1c7c1c636af | 30 | * ownership rights. |
| IanBenzMaxim | 1:e1c7c1c636af | 31 | ******************************************************************************* |
| IanBenzMaxim | 1:e1c7c1c636af | 32 | */ |
| IanBenzMaxim | 1:e1c7c1c636af | 33 | |
| IanBenzMaxim | 1:e1c7c1c636af | 34 | #include <vector> |
| IanBenzMaxim | 1:e1c7c1c636af | 35 | #include "WebServerInterface.hpp" |
| IanBenzMaxim | 1:e1c7c1c636af | 36 | #include "ESP8266.hpp" |
| IanBenzMaxim | 16:6bce01c1dd90 | 37 | #include "Slaves/Authenticators/ISha256MacCoproc.h" |
| IanBenzMaxim | 25:37ea43ff81be | 38 | #include "SensorData.hpp" |
| IanBenzMaxim | 25:37ea43ff81be | 39 | #include "HexConversions.hpp" |
| IanBenzMaxim | 6:b6bafd0a7013 | 40 | #include "Serial.h" |
| IanBenzMaxim | 6:b6bafd0a7013 | 41 | #include "wait_api.h" |
| IanBenzMaxim | 6:b6bafd0a7013 | 42 | |
| IanBenzMaxim | 8:594529956266 | 43 | using OneWire::ISha256MacCoproc; |
| IanBenzMaxim | 1:e1c7c1c636af | 44 | |
| IanBenzMaxim | 27:81a87d29bedd | 45 | const char WebServerInterface::wifiSsid[] = "WifiSsid"; |
| IanBenzMaxim | 27:81a87d29bedd | 46 | const char WebServerInterface::wifiPassword[] = "WifiPassword"; |
| IanBenzMaxim | 12:5f8727ba1493 | 47 | const char WebServerInterface::serverAddress[] = "www.mxim-security.us"; |
| IanBenzMaxim | 3:ac723be395d9 | 48 | const unsigned int WebServerInterface::serverPort = 80; |
| IanBenzMaxim | 1:e1c7c1c636af | 49 | const char WebServerInterface::serverPostPath[] = "/post.php"; |
| IanBenzMaxim | 1:e1c7c1c636af | 50 | const char WebServerInterface::serverChallengePath[] = "/challenge.php"; |
| IanBenzMaxim | 1:e1c7c1c636af | 51 | |
| IanBenzMaxim | 1:e1c7c1c636af | 52 | // HTTP formatting constants |
| IanBenzMaxim | 1:e1c7c1c636af | 53 | static const char keyValSeparator = '='; |
| IanBenzMaxim | 1:e1c7c1c636af | 54 | static const char fieldSeparator = '&'; |
| IanBenzMaxim | 1:e1c7c1c636af | 55 | static const std::string newline = "\r\n"; |
| IanBenzMaxim | 1:e1c7c1c636af | 56 | static const char sessionIdKey[] = "SessionId"; |
| IanBenzMaxim | 1:e1c7c1c636af | 57 | |
| IanBenzMaxim | 1:e1c7c1c636af | 58 | // Authentication MAC constants |
| IanBenzMaxim | 6:b6bafd0a7013 | 59 | static const size_t challengeLen = 32; |
| IanBenzMaxim | 6:b6bafd0a7013 | 60 | static const uint8_t defaultPaddingByte = 0x00; |
| IanBenzMaxim | 1:e1c7c1c636af | 61 | |
| IanBenzMaxim | 1:e1c7c1c636af | 62 | /// Select the Transport Secret for the web server in the Controller. |
| IanBenzMaxim | 1:e1c7c1c636af | 63 | /// @returns True on success. |
| IanBenzMaxim | 25:37ea43ff81be | 64 | static bool setHttpPostSecret(ISha256MacCoproc & MacCoproc, const OneWire::RomId & sessionId) |
| IanBenzMaxim | 1:e1c7c1c636af | 65 | { |
| IanBenzMaxim | 25:37ea43ff81be | 66 | ISha256MacCoproc::DevicePage fillData; |
| IanBenzMaxim | 25:37ea43ff81be | 67 | fillData.fill(defaultPaddingByte); |
| IanBenzMaxim | 25:37ea43ff81be | 68 | ISha256MacCoproc::SlaveSecretData secretData; |
| IanBenzMaxim | 25:37ea43ff81be | 69 | secretData.fill(defaultPaddingByte); |
| IanBenzMaxim | 25:37ea43ff81be | 70 | std::copy(sessionId.buffer.begin(), sessionId.buffer.end(), secretData.begin()); |
| IanBenzMaxim | 25:37ea43ff81be | 71 | return (MacCoproc.computeSlaveSecret(fillData, fillData, secretData) == ISha256MacCoproc::Success); |
| IanBenzMaxim | 1:e1c7c1c636af | 72 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 73 | |
| IanBenzMaxim | 1:e1c7c1c636af | 74 | WebServerInterface::WebServerInterface(ESP8266 & esp8266, mbed::Serial * pc) |
| IanBenzMaxim | 1:e1c7c1c636af | 75 | : esp8266(esp8266), pc(pc) |
| IanBenzMaxim | 1:e1c7c1c636af | 76 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 77 | |
| IanBenzMaxim | 1:e1c7c1c636af | 78 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 79 | |
| IanBenzMaxim | 1:e1c7c1c636af | 80 | bool WebServerInterface::initialize() |
| IanBenzMaxim | 1:e1c7c1c636af | 81 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 82 | esp8266.setPowered(true); |
| IanBenzMaxim | 1:e1c7c1c636af | 83 | esp8266.reset(); |
| IanBenzMaxim | 1:e1c7c1c636af | 84 | bool result = (esp8266.performSelfTest() == ESP8266::AT_OK); |
| IanBenzMaxim | 25:37ea43ff81be | 85 | if (result) |
| IanBenzMaxim | 1:e1c7c1c636af | 86 | { |
| IanBenzMaxim | 25:37ea43ff81be | 87 | result = (esp8266.setCurrentWifiMode(ESP8266::softAP_station_mode) == ESP8266::AT_OK); |
| IanBenzMaxim | 1:e1c7c1c636af | 88 | } |
| IanBenzMaxim | 25:37ea43ff81be | 89 | if (result) |
| IanBenzMaxim | 1:e1c7c1c636af | 90 | { |
| IanBenzMaxim | 25:37ea43ff81be | 91 | result = (esp8266.setMaxRFTXPower(10) == ESP8266::AT_OK); |
| IanBenzMaxim | 1:e1c7c1c636af | 92 | } |
| IanBenzMaxim | 25:37ea43ff81be | 93 | if (result) |
| IanBenzMaxim | 1:e1c7c1c636af | 94 | { |
| IanBenzMaxim | 25:37ea43ff81be | 95 | result = (esp8266.joinCurrentAccessPoint(wifiSsid, wifiPassword) == ESP8266::AT_OK); |
| IanBenzMaxim | 1:e1c7c1c636af | 96 | } |
| IanBenzMaxim | 25:37ea43ff81be | 97 | return result; |
| IanBenzMaxim | 1:e1c7c1c636af | 98 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 99 | |
| IanBenzMaxim | 1:e1c7c1c636af | 100 | /// Format an HTTP GET request as a string for transmission. |
| IanBenzMaxim | 1:e1c7c1c636af | 101 | /// @param host Web server address. |
| IanBenzMaxim | 1:e1c7c1c636af | 102 | /// @param path Web server location to retrieve. |
| IanBenzMaxim | 1:e1c7c1c636af | 103 | /// @param sessionId Session ID used to identify this controller. |
| IanBenzMaxim | 1:e1c7c1c636af | 104 | /// @returns GET request string. |
| IanBenzMaxim | 1:e1c7c1c636af | 105 | static std::string formatHttpGet(const std::string & host, const std::string & path, const std::string & sessionId) |
| IanBenzMaxim | 1:e1c7c1c636af | 106 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 107 | std::ostringstream httpGetStream; |
| IanBenzMaxim | 1:e1c7c1c636af | 108 | httpGetStream << "GET " << path; |
| IanBenzMaxim | 1:e1c7c1c636af | 109 | if (sessionId.length() > 0) |
| IanBenzMaxim | 1:e1c7c1c636af | 110 | httpGetStream << '?' << sessionIdKey << keyValSeparator << sessionId; |
| IanBenzMaxim | 1:e1c7c1c636af | 111 | httpGetStream << " HTTP/1.1" << newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 112 | httpGetStream << "Host: " << host << newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 113 | httpGetStream << newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 114 | return httpGetStream.str(); |
| IanBenzMaxim | 1:e1c7c1c636af | 115 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 116 | |
| IanBenzMaxim | 1:e1c7c1c636af | 117 | /// Computes a MAC using the Transport Secret to sign HTTP POST requests. |
| IanBenzMaxim | 1:e1c7c1c636af | 118 | /// @param macCoproc Coprocessor such as the DS2465 used to calculate the authentication MAC. |
| IanBenzMaxim | 1:e1c7c1c636af | 119 | /// @param input Message array used for MAC calculation. |
| IanBenzMaxim | 1:e1c7c1c636af | 120 | /// @param ilen Length of array input. |
| IanBenzMaxim | 1:e1c7c1c636af | 121 | /// @param output Calculated MAC output. |
| IanBenzMaxim | 6:b6bafd0a7013 | 122 | static void calculateHttpPostMac(const ISha256MacCoproc & macCoproc, const uint8_t * input, size_t ilen, ISha256MacCoproc::Mac & output) |
| IanBenzMaxim | 1:e1c7c1c636af | 123 | { |
| IanBenzMaxim | 6:b6bafd0a7013 | 124 | ISha256MacCoproc::DeviceScratchpad block; |
| IanBenzMaxim | 6:b6bafd0a7013 | 125 | size_t index = 0; |
| IanBenzMaxim | 6:b6bafd0a7013 | 126 | ISha256MacCoproc::AuthMacData padding; |
| IanBenzMaxim | 25:37ea43ff81be | 127 | padding.fill(defaultPaddingByte); |
| IanBenzMaxim | 25:37ea43ff81be | 128 | output.fill(defaultPaddingByte); // Set initial hash value |
| IanBenzMaxim | 1:e1c7c1c636af | 129 | while (index < ilen) |
| IanBenzMaxim | 1:e1c7c1c636af | 130 | { |
| IanBenzMaxim | 25:37ea43ff81be | 131 | if ((index + block.size()) <= ilen) // Full block |
| IanBenzMaxim | 1:e1c7c1c636af | 132 | { |
| IanBenzMaxim | 25:37ea43ff81be | 133 | std::memcpy(block.data(), &input[index], block.size()); |
| IanBenzMaxim | 25:37ea43ff81be | 134 | index += block.size(); |
| IanBenzMaxim | 1:e1c7c1c636af | 135 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 136 | else // Partial block with padding |
| IanBenzMaxim | 1:e1c7c1c636af | 137 | { |
| IanBenzMaxim | 25:37ea43ff81be | 138 | std::memcpy(block.data(), &input[index], ilen - index); |
| IanBenzMaxim | 25:37ea43ff81be | 139 | std::memset(&block[ilen - index], defaultPaddingByte, block.size() - (ilen - index)); |
| IanBenzMaxim | 1:e1c7c1c636af | 140 | index = ilen; |
| IanBenzMaxim | 1:e1c7c1c636af | 141 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 142 | // Write data to coprocessor and hash block |
| IanBenzMaxim | 1:e1c7c1c636af | 143 | macCoproc.computeAuthMac(output, block, padding, output); |
| IanBenzMaxim | 1:e1c7c1c636af | 144 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 145 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 146 | |
| IanBenzMaxim | 1:e1c7c1c636af | 147 | /// Format an HTTP POST request as a string for transmission. |
| IanBenzMaxim | 1:e1c7c1c636af | 148 | /// @param host Web server address. |
| IanBenzMaxim | 1:e1c7c1c636af | 149 | /// @param path Web server location to receive POST. |
| IanBenzMaxim | 1:e1c7c1c636af | 150 | /// @param sessionId Session ID used to identify this Controller. |
| IanBenzMaxim | 1:e1c7c1c636af | 151 | /// @param macCoproc Coprocessor such as the DS2465 used to calculate the authentication MAC. |
| IanBenzMaxim | 1:e1c7c1c636af | 152 | /// @param event Event message type. |
| IanBenzMaxim | 1:e1c7c1c636af | 153 | /// @param initialPostBody Message body as determined by the event message type. |
| IanBenzMaxim | 1:e1c7c1c636af | 154 | /// @param challenge Challenge previously received from web server for use in authentication MAC. |
| IanBenzMaxim | 1:e1c7c1c636af | 155 | /// @returns POST request string. |
| IanBenzMaxim | 1:e1c7c1c636af | 156 | static std::string formatHttpPost(const std::string & host, const std::string & path, const std::string & sessionId, |
| IanBenzMaxim | 6:b6bafd0a7013 | 157 | const ISha256MacCoproc & macCoproc, PostEvent event, const std::string & initialPostBody, |
| IanBenzMaxim | 6:b6bafd0a7013 | 158 | const uint8_t (&challenge)[challengeLen]) |
| IanBenzMaxim | 1:e1c7c1c636af | 159 | { |
| IanBenzMaxim | 6:b6bafd0a7013 | 160 | const size_t headerReserve = 115, bodyReserve = 200; |
| IanBenzMaxim | 1:e1c7c1c636af | 161 | |
| IanBenzMaxim | 1:e1c7c1c636af | 162 | std::string httpPost; |
| IanBenzMaxim | 1:e1c7c1c636af | 163 | httpPost.reserve(initialPostBody.length() + headerReserve + bodyReserve); |
| IanBenzMaxim | 1:e1c7c1c636af | 164 | |
| IanBenzMaxim | 1:e1c7c1c636af | 165 | // Add session ID to post body |
| IanBenzMaxim | 1:e1c7c1c636af | 166 | if (sessionId.length() > 0) |
| IanBenzMaxim | 1:e1c7c1c636af | 167 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 168 | httpPost += sessionIdKey; |
| IanBenzMaxim | 1:e1c7c1c636af | 169 | httpPost += keyValSeparator; |
| IanBenzMaxim | 1:e1c7c1c636af | 170 | httpPost += sessionId; |
| IanBenzMaxim | 1:e1c7c1c636af | 171 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 172 | |
| IanBenzMaxim | 1:e1c7c1c636af | 173 | // Add event to post body |
| IanBenzMaxim | 1:e1c7c1c636af | 174 | std::string eventString; |
| IanBenzMaxim | 1:e1c7c1c636af | 175 | switch (event) |
| IanBenzMaxim | 1:e1c7c1c636af | 176 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 177 | case SensorDataEvent: |
| IanBenzMaxim | 1:e1c7c1c636af | 178 | eventString = "SensorData"; |
| IanBenzMaxim | 1:e1c7c1c636af | 179 | break; |
| IanBenzMaxim | 1:e1c7c1c636af | 180 | |
| IanBenzMaxim | 1:e1c7c1c636af | 181 | case InvalidSensorEvent: |
| IanBenzMaxim | 1:e1c7c1c636af | 182 | eventString = "InvalidSensor"; |
| IanBenzMaxim | 1:e1c7c1c636af | 183 | break; |
| IanBenzMaxim | 1:e1c7c1c636af | 184 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 185 | if (eventString.length() > 0) |
| IanBenzMaxim | 1:e1c7c1c636af | 186 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 187 | if (httpPost.length() > 0) |
| IanBenzMaxim | 1:e1c7c1c636af | 188 | httpPost += fieldSeparator; |
| IanBenzMaxim | 1:e1c7c1c636af | 189 | httpPost += "Event"; |
| IanBenzMaxim | 1:e1c7c1c636af | 190 | httpPost += keyValSeparator; |
| IanBenzMaxim | 1:e1c7c1c636af | 191 | httpPost += eventString; |
| IanBenzMaxim | 1:e1c7c1c636af | 192 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 193 | |
| IanBenzMaxim | 1:e1c7c1c636af | 194 | // Add initial post body |
| IanBenzMaxim | 1:e1c7c1c636af | 195 | if (initialPostBody.length() > 0) |
| IanBenzMaxim | 1:e1c7c1c636af | 196 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 197 | if (httpPost.length() > 0) |
| IanBenzMaxim | 1:e1c7c1c636af | 198 | httpPost += fieldSeparator; |
| IanBenzMaxim | 1:e1c7c1c636af | 199 | httpPost += initialPostBody; |
| IanBenzMaxim | 1:e1c7c1c636af | 200 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 201 | |
| IanBenzMaxim | 1:e1c7c1c636af | 202 | // Combine initial post body with initial secret and hash |
| IanBenzMaxim | 6:b6bafd0a7013 | 203 | std::vector<uint8_t> hashInput; |
| IanBenzMaxim | 1:e1c7c1c636af | 204 | hashInput.reserve(challengeLen + httpPost.length()); |
| IanBenzMaxim | 25:37ea43ff81be | 205 | hashInput.assign(challenge, challenge + challengeLen); |
| IanBenzMaxim | 1:e1c7c1c636af | 206 | hashInput.insert(hashInput.end(), httpPost.begin(), httpPost.end()); |
| IanBenzMaxim | 6:b6bafd0a7013 | 207 | ISha256MacCoproc::Mac mac; |
| IanBenzMaxim | 1:e1c7c1c636af | 208 | calculateHttpPostMac(macCoproc, &hashInput[0], hashInput.size(), mac); |
| IanBenzMaxim | 1:e1c7c1c636af | 209 | |
| IanBenzMaxim | 1:e1c7c1c636af | 210 | char contentLen[5]; |
| IanBenzMaxim | 25:37ea43ff81be | 211 | snprintf(contentLen, sizeof(contentLen) / sizeof(contentLen[0]), "%u", (hashInput.size() - challengeLen) + (mac.size() * charsPerByte) + 5 /* &MAC= */); |
| IanBenzMaxim | 1:e1c7c1c636af | 212 | |
| IanBenzMaxim | 1:e1c7c1c636af | 213 | // Construct full post request |
| IanBenzMaxim | 1:e1c7c1c636af | 214 | httpPost = ""; |
| IanBenzMaxim | 1:e1c7c1c636af | 215 | httpPost += "POST "; |
| IanBenzMaxim | 1:e1c7c1c636af | 216 | httpPost += path; |
| IanBenzMaxim | 1:e1c7c1c636af | 217 | httpPost += " HTTP/1.1"; |
| IanBenzMaxim | 1:e1c7c1c636af | 218 | httpPost += newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 219 | httpPost += "Host: "; |
| IanBenzMaxim | 1:e1c7c1c636af | 220 | httpPost += host; |
| IanBenzMaxim | 1:e1c7c1c636af | 221 | httpPost += newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 222 | httpPost += "Accept: */*"; |
| IanBenzMaxim | 1:e1c7c1c636af | 223 | httpPost += newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 224 | httpPost += "Content-Length: "; |
| IanBenzMaxim | 1:e1c7c1c636af | 225 | httpPost += contentLen; |
| IanBenzMaxim | 1:e1c7c1c636af | 226 | httpPost += newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 227 | httpPost += "Content-Type: application/x-www-form-urlencoded"; |
| IanBenzMaxim | 1:e1c7c1c636af | 228 | httpPost += newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 229 | httpPost += newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 230 | // Add post body |
| IanBenzMaxim | 1:e1c7c1c636af | 231 | httpPost.append(reinterpret_cast<char *>(&hashInput[challengeLen]), hashInput.size() - challengeLen); |
| IanBenzMaxim | 1:e1c7c1c636af | 232 | // Convert hash to hex string and add to post body |
| IanBenzMaxim | 1:e1c7c1c636af | 233 | httpPost += fieldSeparator; |
| IanBenzMaxim | 1:e1c7c1c636af | 234 | httpPost += "MAC"; |
| IanBenzMaxim | 1:e1c7c1c636af | 235 | httpPost += keyValSeparator; |
| IanBenzMaxim | 25:37ea43ff81be | 236 | byteArrayToHexString(mac.data(), mac.size(), httpPost); |
| IanBenzMaxim | 1:e1c7c1c636af | 237 | httpPost += newline; |
| IanBenzMaxim | 1:e1c7c1c636af | 238 | |
| IanBenzMaxim | 1:e1c7c1c636af | 239 | return httpPost; |
| IanBenzMaxim | 1:e1c7c1c636af | 240 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 241 | |
| IanBenzMaxim | 6:b6bafd0a7013 | 242 | bool WebServerInterface::authPostHttpEvent(ISha256MacCoproc & macCoproc, PostEvent event, const std::string & postData, bool setSecret) |
| IanBenzMaxim | 1:e1c7c1c636af | 243 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 244 | const std::string challengeSearch(newline + newline); |
| IanBenzMaxim | 1:e1c7c1c636af | 245 | bool result; |
| IanBenzMaxim | 6:b6bafd0a7013 | 246 | uint8_t challenge[challengeLen]; |
| IanBenzMaxim | 1:e1c7c1c636af | 247 | std::string response; |
| IanBenzMaxim | 1:e1c7c1c636af | 248 | |
| IanBenzMaxim | 1:e1c7c1c636af | 249 | std::memset(challenge, defaultPaddingByte, challengeLen); |
| IanBenzMaxim | 1:e1c7c1c636af | 250 | response.reserve(300); |
| IanBenzMaxim | 1:e1c7c1c636af | 251 | |
| IanBenzMaxim | 1:e1c7c1c636af | 252 | if (setSecret) |
| IanBenzMaxim | 1:e1c7c1c636af | 253 | { |
| IanBenzMaxim | 25:37ea43ff81be | 254 | result = setHttpPostSecret(macCoproc, m_sessionId); |
| IanBenzMaxim | 1:e1c7c1c636af | 255 | if (!result) |
| IanBenzMaxim | 1:e1c7c1c636af | 256 | return result; |
| IanBenzMaxim | 1:e1c7c1c636af | 257 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 258 | |
| IanBenzMaxim | 1:e1c7c1c636af | 259 | // Open connection |
| IanBenzMaxim | 1:e1c7c1c636af | 260 | esp8266.clearRecvData(); // Clear received data buffer |
| IanBenzMaxim | 1:e1c7c1c636af | 261 | result = (esp8266.openConnection(ESP8266::TCP, serverAddress, 80) == ESP8266::AT_OK); |
| IanBenzMaxim | 1:e1c7c1c636af | 262 | if (result) |
| IanBenzMaxim | 1:e1c7c1c636af | 263 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 264 | // Request challenge |
| IanBenzMaxim | 25:37ea43ff81be | 265 | result = (esp8266.sendData(formatHttpGet(serverAddress, serverChallengePath, m_sessionIdString)) == ESP8266::AT_OK); |
| IanBenzMaxim | 1:e1c7c1c636af | 266 | if (result) |
| IanBenzMaxim | 1:e1c7c1c636af | 267 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 268 | // Receive server response |
| IanBenzMaxim | 1:e1c7c1c636af | 269 | for (int i = 0; i < 10; i++) |
| IanBenzMaxim | 1:e1c7c1c636af | 270 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 271 | while (esp8266.recvIpDataReadable()) |
| IanBenzMaxim | 1:e1c7c1c636af | 272 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 273 | char read = esp8266.getcRecvIpData(); |
| IanBenzMaxim | 1:e1c7c1c636af | 274 | if (pc != NULL) |
| IanBenzMaxim | 1:e1c7c1c636af | 275 | pc->putc(read); |
| IanBenzMaxim | 1:e1c7c1c636af | 276 | if (response.length() < response.capacity()) |
| IanBenzMaxim | 1:e1c7c1c636af | 277 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 278 | response += read; |
| IanBenzMaxim | 1:e1c7c1c636af | 279 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 280 | else |
| IanBenzMaxim | 1:e1c7c1c636af | 281 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 282 | wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time |
| IanBenzMaxim | 1:e1c7c1c636af | 283 | goto close_get_connection; |
| IanBenzMaxim | 1:e1c7c1c636af | 284 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 285 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 286 | wait_ms(100); |
| IanBenzMaxim | 1:e1c7c1c636af | 287 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 288 | // Close connection |
| IanBenzMaxim | 1:e1c7c1c636af | 289 | close_get_connection: |
| IanBenzMaxim | 1:e1c7c1c636af | 290 | esp8266.closeConnection(); |
| IanBenzMaxim | 1:e1c7c1c636af | 291 | |
| IanBenzMaxim | 1:e1c7c1c636af | 292 | // Parse challenge from response |
| IanBenzMaxim | 6:b6bafd0a7013 | 293 | size_t challengePos = response.find(challengeSearch); |
| IanBenzMaxim | 1:e1c7c1c636af | 294 | if ((challengePos != std::string::npos) && ((challengePos + challengeSearch.length() + (challengeLen * charsPerByte)) <= response.length())) |
| IanBenzMaxim | 1:e1c7c1c636af | 295 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 296 | challengePos += challengeSearch.length(); |
| IanBenzMaxim | 6:b6bafd0a7013 | 297 | for (size_t i = 0; i < challengeLen; i++) |
| IanBenzMaxim | 1:e1c7c1c636af | 298 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 299 | std::sscanf(response.substr(challengePos + (i * charsPerByte), charsPerByte).c_str(), "%2hhx", &challenge[i]); |
| IanBenzMaxim | 1:e1c7c1c636af | 300 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 301 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 302 | |
| IanBenzMaxim | 1:e1c7c1c636af | 303 | // Post sensor data |
| IanBenzMaxim | 3:ac723be395d9 | 304 | result = (esp8266.openConnection(ESP8266::TCP, serverAddress, serverPort) == ESP8266::AT_OK); |
| IanBenzMaxim | 1:e1c7c1c636af | 305 | if (result) |
| IanBenzMaxim | 1:e1c7c1c636af | 306 | { |
| IanBenzMaxim | 25:37ea43ff81be | 307 | result = (esp8266.sendData(formatHttpPost(serverAddress, serverPostPath, m_sessionIdString, macCoproc, event, postData, challenge)) == ESP8266::AT_OK); |
| IanBenzMaxim | 1:e1c7c1c636af | 308 | wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time |
| IanBenzMaxim | 1:e1c7c1c636af | 309 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 310 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 311 | |
| IanBenzMaxim | 1:e1c7c1c636af | 312 | // Close connection |
| IanBenzMaxim | 1:e1c7c1c636af | 313 | esp8266.closeConnection(); |
| IanBenzMaxim | 1:e1c7c1c636af | 314 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 315 | |
| IanBenzMaxim | 1:e1c7c1c636af | 316 | return result; |
| IanBenzMaxim | 1:e1c7c1c636af | 317 | } |
| IanBenzMaxim | 1:e1c7c1c636af | 318 | |
| IanBenzMaxim | 1:e1c7c1c636af | 319 | std::string WebServerInterface::formatSensorDataPostBody(const SensorData & sensorData) |
| IanBenzMaxim | 1:e1c7c1c636af | 320 | { |
| IanBenzMaxim | 1:e1c7c1c636af | 321 | // Create initial post body string from input data |
| IanBenzMaxim | 1:e1c7c1c636af | 322 | std::ostringstream postBodyStream; |
| IanBenzMaxim | 1:e1c7c1c636af | 323 | postBodyStream << "Temp" << keyValSeparator << static_cast<int>(sensorData.temp); |
| IanBenzMaxim | 1:e1c7c1c636af | 324 | postBodyStream << fieldSeparator; |
| IanBenzMaxim | 1:e1c7c1c636af | 325 | postBodyStream << "FilterLife" << keyValSeparator << static_cast<unsigned>(sensorData.filterLife); |
| IanBenzMaxim | 1:e1c7c1c636af | 326 | postBodyStream << fieldSeparator; |
| IanBenzMaxim | 1:e1c7c1c636af | 327 | postBodyStream << "TempAlarm" << keyValSeparator << (sensorData.tempAlarm() ? "true" : "false"); |
| IanBenzMaxim | 1:e1c7c1c636af | 328 | postBodyStream << fieldSeparator; |
| IanBenzMaxim | 1:e1c7c1c636af | 329 | postBodyStream << "FilterLifeAlarm" << keyValSeparator << (sensorData.filterLifeAlarm() ? "true" : "false"); |
| IanBenzMaxim | 1:e1c7c1c636af | 330 | return postBodyStream.str(); |
| IanBenzMaxim | 25:37ea43ff81be | 331 | } |
| IanBenzMaxim | 25:37ea43ff81be | 332 | |
| IanBenzMaxim | 25:37ea43ff81be | 333 | void WebServerInterface::setSessionId(const OneWire::RomId & sessionId) |
| IanBenzMaxim | 25:37ea43ff81be | 334 | { |
| IanBenzMaxim | 25:37ea43ff81be | 335 | m_sessionIdString = byteArrayToHexString(sessionId.buffer.data(), sessionId.buffer.size()); |
| IanBenzMaxim | 25:37ea43ff81be | 336 | m_sessionId = sessionId; |
| IanBenzMaxim | 1:e1c7c1c636af | 337 | } |
MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification