|
11 | 11 | #include <filesystem> |
12 | 12 | #include <fstream> |
13 | 13 | #include <iomanip> |
| 14 | +#include <algorithm> |
14 | 15 | #include <atomic> |
15 | 16 | #include <mutex> |
16 | 17 | #include <stdexcept> |
@@ -757,14 +758,23 @@ namespace confighttp { |
757 | 758 | pt::ptree inputTree, fileTree; |
758 | 759 |
|
759 | 760 | try { |
760 | | - // TODO: Input Validation |
761 | 761 | pt::read_json(ss, inputTree); |
762 | 762 | pt::read_json(config::stream.file_apps, fileTree); |
763 | 763 |
|
764 | 764 | auto &apps_node = fileTree.get_child("apps"s); |
765 | 765 | auto &input_apps_node = inputTree.get_child("apps"s); |
766 | 766 | auto &input_edit_node = inputTree.get_child("editApp"s); |
767 | 767 |
|
| 768 | + // Validate app name when editing a specific app |
| 769 | + if (!input_edit_node.empty()) { |
| 770 | + auto app_name = input_edit_node.get<std::string>("name", ""); |
| 771 | + if (app_name.empty() || app_name.size() > 256) { |
| 772 | + outputTree.put("status", "false"); |
| 773 | + outputTree.put("error", "App name must be 1-256 characters"); |
| 774 | + return; |
| 775 | + } |
| 776 | + } |
| 777 | + |
768 | 778 | if (input_edit_node.empty()) { |
769 | 779 | fileTree.erase("apps"); |
770 | 780 | fileTree.push_back(std::make_pair("apps", input_apps_node)); |
@@ -1163,12 +1173,24 @@ namespace confighttp { |
1163 | 1173 | pt::ptree inputTree; |
1164 | 1174 |
|
1165 | 1175 | try { |
1166 | | - // TODO: Input Validation |
1167 | 1176 | pt::read_json(ss, inputTree); |
1168 | 1177 | std::string resArray = inputTree.get<std::string>("resolutions", "[]"); |
1169 | 1178 | std::string fpsArray = inputTree.get<std::string>("fps", "[]"); |
1170 | 1179 | std::string gpu_name = inputTree.get<std::string>("adapter_name", ""); |
1171 | 1180 |
|
| 1181 | + // Validate config field lengths to prevent abuse |
| 1182 | + auto sunshine_name = inputTree.get<std::string>("sunshine_name", ""); |
| 1183 | + if (sunshine_name.size() > 256) { |
| 1184 | + outputTree.put("status", "false"); |
| 1185 | + outputTree.put("error", "sunshine_name too long (max 256)"); |
| 1186 | + return; |
| 1187 | + } |
| 1188 | + if (gpu_name.size() > 256) { |
| 1189 | + outputTree.put("status", "false"); |
| 1190 | + outputTree.put("error", "adapter_name too long (max 256)"); |
| 1191 | + return; |
| 1192 | + } |
| 1193 | + |
1172 | 1194 | saveVddSettings(resArray, fpsArray, gpu_name); |
1173 | 1195 |
|
1174 | 1196 | // 将 inputTree 转换为 std::map(保证有序) |
@@ -1249,13 +1271,25 @@ namespace confighttp { |
1249 | 1271 | }); |
1250 | 1272 |
|
1251 | 1273 | try { |
1252 | | - // TODO: Input Validation |
1253 | 1274 | pt::read_json(ss, inputTree); |
1254 | 1275 | auto username = inputTree.count("currentUsername") > 0 ? inputTree.get<std::string>("currentUsername") : ""; |
1255 | 1276 | auto newUsername = inputTree.get<std::string>("newUsername"); |
1256 | 1277 | auto password = inputTree.count("currentPassword") > 0 ? inputTree.get<std::string>("currentPassword") : ""; |
1257 | 1278 | auto newPassword = inputTree.count("newPassword") > 0 ? inputTree.get<std::string>("newPassword") : ""; |
1258 | 1279 | auto confirmPassword = inputTree.count("confirmNewPassword") > 0 ? inputTree.get<std::string>("confirmNewPassword") : ""; |
| 1280 | + |
| 1281 | + // Validate credential lengths |
| 1282 | + if (newUsername.size() > 128) { |
| 1283 | + outputTree.put("status", false); |
| 1284 | + outputTree.put("error", "Username too long (max 128)"); |
| 1285 | + return; |
| 1286 | + } |
| 1287 | + if (newPassword.size() > 256) { |
| 1288 | + outputTree.put("status", false); |
| 1289 | + outputTree.put("error", "Password too long (max 256)"); |
| 1290 | + return; |
| 1291 | + } |
| 1292 | + |
1259 | 1293 | if (newUsername.length() == 0) newUsername = username; |
1260 | 1294 | if (newUsername.length() == 0) { |
1261 | 1295 | outputTree.put("status", false); |
@@ -1306,10 +1340,23 @@ namespace confighttp { |
1306 | 1340 | }); |
1307 | 1341 |
|
1308 | 1342 | try { |
1309 | | - // TODO: Input Validation |
1310 | 1343 | pt::read_json(ss, inputTree); |
1311 | 1344 | std::string pin = inputTree.get<std::string>("pin"); |
1312 | 1345 | std::string name = inputTree.get<std::string>("name"); |
| 1346 | + |
| 1347 | + // Validate PIN: must be numeric digits only, 4-8 characters |
| 1348 | + if (pin.size() < 4 || pin.size() > 8 || !std::all_of(pin.begin(), pin.end(), ::isdigit)) { |
| 1349 | + outputTree.put("status", false); |
| 1350 | + outputTree.put("error", "PIN must be 4-8 digits"); |
| 1351 | + return; |
| 1352 | + } |
| 1353 | + // Validate client name |
| 1354 | + if (name.empty() || name.size() > 256) { |
| 1355 | + outputTree.put("status", false); |
| 1356 | + outputTree.put("error", "Client name must be 1-256 characters"); |
| 1357 | + return; |
| 1358 | + } |
| 1359 | + |
1313 | 1360 | bool pin_result = nvhttp::pin(pin, name); |
1314 | 1361 | outputTree.put("status", pin_result); |
1315 | 1362 |
|
@@ -1528,9 +1575,16 @@ namespace confighttp { |
1528 | 1575 | }); |
1529 | 1576 |
|
1530 | 1577 | try { |
1531 | | - // TODO: Input Validation |
1532 | 1578 | pt::read_json(ss, inputTree); |
1533 | 1579 | std::string uuid = inputTree.get<std::string>("uuid"); |
| 1580 | + |
| 1581 | + // Validate UUID format (hex + hyphens, reasonable length) |
| 1582 | + if (uuid.empty() || uuid.size() > 64) { |
| 1583 | + outputTree.put("status", false); |
| 1584 | + outputTree.put("error", "Invalid client UUID"); |
| 1585 | + return; |
| 1586 | + } |
| 1587 | + |
1534 | 1588 | outputTree.put("status", nvhttp::unpair_client(uuid)); |
1535 | 1589 | } |
1536 | 1590 | catch (std::exception &e) { |
|
0 commit comments