| Lewanczyk, Dawid | 88d16c9 | 2018-02-02 14:51:09 +0100 | [diff] [blame] | 1 | /* | 
|  | 2 | // Copyright (c) 2018 Intel Corporation | 
|  | 3 | // | 
|  | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | // you may not use this file except in compliance with the License. | 
|  | 6 | // You may obtain a copy of the License at | 
|  | 7 | // | 
|  | 8 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | // | 
|  | 10 | // Unless required by applicable law or agreed to in writing, software | 
|  | 11 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | // See the License for the specific language governing permissions and | 
|  | 14 | // limitations under the License. | 
|  | 15 | */ | 
|  | 16 | #pragma once | 
| Lewanczyk, Dawid | 88d16c9 | 2018-02-02 14:51:09 +0100 | [diff] [blame] | 17 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 18 | #include <app.hpp> | 
| Ratan Gupta | 24c8542 | 2019-01-30 19:41:24 +0530 | [diff] [blame] | 19 | #include <dbus_utility.hpp> | 
| Ed Tanous | 65b0dc3 | 2018-09-19 16:04:03 -0700 | [diff] [blame] | 20 | #include <error_messages.hpp> | 
| Ed Tanous | b9b2e0b | 2018-09-13 13:47:50 -0700 | [diff] [blame] | 21 | #include <openbmc_dbus_rest.hpp> | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 22 | #include <persistent_data.hpp> | 
| Ed Tanous | 45ca1b8 | 2022-03-25 13:07:27 -0700 | [diff] [blame] | 23 | #include <query.hpp> | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame] | 24 | #include <registries/privilege_registry.hpp> | 
| Jonathan Doman | 1e1e598 | 2021-06-11 09:36:17 -0700 | [diff] [blame] | 25 | #include <sdbusplus/asio/property.hpp> | 
| Ed Tanous | a840879 | 2018-09-05 16:08:38 -0700 | [diff] [blame] | 26 | #include <utils/json_utils.hpp> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 27 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 28 | namespace redfish | 
|  | 29 | { | 
| Lewanczyk, Dawid | 88d16c9 | 2018-02-02 14:51:09 +0100 | [diff] [blame] | 30 |  | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 31 | constexpr const char* ldapConfigObjectName = | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 32 | "/xyz/openbmc_project/user/ldap/openldap"; | 
| Ed Tanous | 2c70f80 | 2020-09-28 14:29:23 -0700 | [diff] [blame] | 33 | constexpr const char* adConfigObject = | 
| Ratan Gupta | ab828d7 | 2019-04-22 14:18:33 +0530 | [diff] [blame] | 34 | "/xyz/openbmc_project/user/ldap/active_directory"; | 
|  | 35 |  | 
| P Dheeraj Srujan Kumar | b477fd4 | 2021-12-16 07:17:51 +0530 | [diff] [blame] | 36 | constexpr const char* rootUserDbusPath = "/xyz/openbmc_project/user/"; | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 37 | constexpr const char* ldapRootObject = "/xyz/openbmc_project/user/ldap"; | 
|  | 38 | constexpr const char* ldapDbusService = "xyz.openbmc_project.Ldap.Config"; | 
|  | 39 | constexpr const char* ldapConfigInterface = | 
|  | 40 | "xyz.openbmc_project.User.Ldap.Config"; | 
|  | 41 | constexpr const char* ldapCreateInterface = | 
|  | 42 | "xyz.openbmc_project.User.Ldap.Create"; | 
|  | 43 | constexpr const char* ldapEnableInterface = "xyz.openbmc_project.Object.Enable"; | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 44 | constexpr const char* ldapPrivMapperInterface = | 
|  | 45 | "xyz.openbmc_project.User.PrivilegeMapper"; | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 46 | constexpr const char* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; | 
|  | 47 | constexpr const char* propertyInterface = "org.freedesktop.DBus.Properties"; | 
|  | 48 | constexpr const char* mapperBusName = "xyz.openbmc_project.ObjectMapper"; | 
|  | 49 | constexpr const char* mapperObjectPath = "/xyz/openbmc_project/object_mapper"; | 
|  | 50 | constexpr const char* mapperIntf = "xyz.openbmc_project.ObjectMapper"; | 
|  | 51 |  | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 52 | struct LDAPRoleMapData | 
|  | 53 | { | 
|  | 54 | std::string groupName; | 
|  | 55 | std::string privilege; | 
|  | 56 | }; | 
|  | 57 |  | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 58 | struct LDAPConfigData | 
|  | 59 | { | 
|  | 60 | std::string uri{}; | 
|  | 61 | std::string bindDN{}; | 
|  | 62 | std::string baseDN{}; | 
|  | 63 | std::string searchScope{}; | 
|  | 64 | std::string serverType{}; | 
|  | 65 | bool serviceEnabled = false; | 
|  | 66 | std::string userNameAttribute{}; | 
|  | 67 | std::string groupAttribute{}; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 68 | std::vector<std::pair<std::string, LDAPRoleMapData>> groupRoleList; | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 69 | }; | 
|  | 70 |  | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 71 | inline std::string getRoleIdFromPrivilege(std::string_view role) | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 72 | { | 
|  | 73 | if (role == "priv-admin") | 
|  | 74 | { | 
|  | 75 | return "Administrator"; | 
|  | 76 | } | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 77 | if (role == "priv-user") | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 78 | { | 
| AppaRao Puli | c80fee5 | 2019-10-16 14:49:36 +0530 | [diff] [blame] | 79 | return "ReadOnly"; | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 80 | } | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 81 | if (role == "priv-operator") | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 82 | { | 
|  | 83 | return "Operator"; | 
|  | 84 | } | 
| Ed Tanous | 26f6976 | 2022-01-25 09:49:11 -0800 | [diff] [blame] | 85 | if (role.empty() || (role == "priv-noaccess")) | 
| jayaprakash Mutyala | e9e6d24 | 2019-07-29 11:59:08 +0000 | [diff] [blame] | 86 | { | 
|  | 87 | return "NoAccess"; | 
|  | 88 | } | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 89 | return ""; | 
|  | 90 | } | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 91 | inline std::string getPrivilegeFromRoleId(std::string_view role) | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 92 | { | 
|  | 93 | if (role == "Administrator") | 
|  | 94 | { | 
|  | 95 | return "priv-admin"; | 
|  | 96 | } | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 97 | if (role == "ReadOnly") | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 98 | { | 
|  | 99 | return "priv-user"; | 
|  | 100 | } | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 101 | if (role == "Operator") | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 102 | { | 
|  | 103 | return "priv-operator"; | 
|  | 104 | } | 
| Ed Tanous | 26f6976 | 2022-01-25 09:49:11 -0800 | [diff] [blame] | 105 | if ((role == "NoAccess") || (role.empty())) | 
| jayaprakash Mutyala | e9e6d24 | 2019-07-29 11:59:08 +0000 | [diff] [blame] | 106 | { | 
|  | 107 | return "priv-noaccess"; | 
|  | 108 | } | 
| AppaRao Puli | 84e12cb | 2018-10-11 01:28:15 +0530 | [diff] [blame] | 109 | return ""; | 
|  | 110 | } | 
| Ed Tanous | b9b2e0b | 2018-09-13 13:47:50 -0700 | [diff] [blame] | 111 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 112 | inline void userErrorMessageHandler( | 
|  | 113 | const sd_bus_error* e, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 114 | const std::string& newUser, const std::string& username) | 
| jayaprakash Mutyala | 66b5ca7 | 2019-08-07 20:26:37 +0000 | [diff] [blame] | 115 | { | 
| jayaprakash Mutyala | 66b5ca7 | 2019-08-07 20:26:37 +0000 | [diff] [blame] | 116 | if (e == nullptr) | 
|  | 117 | { | 
|  | 118 | messages::internalError(asyncResp->res); | 
|  | 119 | return; | 
|  | 120 | } | 
|  | 121 |  | 
| Manojkiran Eda | 055806b | 2020-11-03 09:36:28 +0530 | [diff] [blame] | 122 | const char* errorMessage = e->name; | 
| jayaprakash Mutyala | 66b5ca7 | 2019-08-07 20:26:37 +0000 | [diff] [blame] | 123 | if (strcmp(errorMessage, | 
|  | 124 | "xyz.openbmc_project.User.Common.Error.UserNameExists") == 0) | 
|  | 125 | { | 
|  | 126 | messages::resourceAlreadyExists(asyncResp->res, | 
| Gunnar Mills | 8114bd4 | 2020-06-11 20:55:21 -0500 | [diff] [blame] | 127 | "#ManagerAccount.v1_4_0.ManagerAccount", | 
| jayaprakash Mutyala | 66b5ca7 | 2019-08-07 20:26:37 +0000 | [diff] [blame] | 128 | "UserName", newUser); | 
|  | 129 | } | 
|  | 130 | else if (strcmp(errorMessage, "xyz.openbmc_project.User.Common.Error." | 
|  | 131 | "UserNameDoesNotExist") == 0) | 
|  | 132 | { | 
|  | 133 | messages::resourceNotFound( | 
| Gunnar Mills | 8114bd4 | 2020-06-11 20:55:21 -0500 | [diff] [blame] | 134 | asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", username); | 
| jayaprakash Mutyala | 66b5ca7 | 2019-08-07 20:26:37 +0000 | [diff] [blame] | 135 | } | 
| Ed Tanous | d4d2579 | 2020-09-29 15:15:03 -0700 | [diff] [blame] | 136 | else if ((strcmp(errorMessage, | 
|  | 137 | "xyz.openbmc_project.Common.Error.InvalidArgument") == | 
|  | 138 | 0) || | 
| George Liu | 0fda0f1 | 2021-11-16 10:06:17 +0800 | [diff] [blame] | 139 | (strcmp( | 
|  | 140 | errorMessage, | 
|  | 141 | "xyz.openbmc_project.User.Common.Error.UserNameGroupFail") == | 
|  | 142 | 0)) | 
| jayaprakash Mutyala | 66b5ca7 | 2019-08-07 20:26:37 +0000 | [diff] [blame] | 143 | { | 
|  | 144 | messages::propertyValueFormatError(asyncResp->res, newUser, "UserName"); | 
|  | 145 | } | 
|  | 146 | else if (strcmp(errorMessage, | 
|  | 147 | "xyz.openbmc_project.User.Common.Error.NoResource") == 0) | 
|  | 148 | { | 
|  | 149 | messages::createLimitReachedForResource(asyncResp->res); | 
|  | 150 | } | 
| jayaprakash Mutyala | 66b5ca7 | 2019-08-07 20:26:37 +0000 | [diff] [blame] | 151 | else | 
|  | 152 | { | 
|  | 153 | messages::internalError(asyncResp->res); | 
|  | 154 | } | 
| jayaprakash Mutyala | 66b5ca7 | 2019-08-07 20:26:37 +0000 | [diff] [blame] | 155 | } | 
|  | 156 |  | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 157 | inline void parseLDAPConfigData(nlohmann::json& jsonResponse, | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 158 | const LDAPConfigData& confData, | 
|  | 159 | const std::string& ldapType) | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 160 | { | 
| Ratan Gupta | ab828d7 | 2019-04-22 14:18:33 +0530 | [diff] [blame] | 161 | std::string service = | 
|  | 162 | (ldapType == "LDAP") ? "LDAPService" : "ActiveDirectoryService"; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 163 |  | 
| Ed Tanous | 1476687 | 2022-03-15 10:44:42 -0700 | [diff] [blame] | 164 | nlohmann::json& ldap = jsonResponse[ldapType]; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 165 |  | 
| Ed Tanous | 1476687 | 2022-03-15 10:44:42 -0700 | [diff] [blame] | 166 | ldap["ServiceEnabled"] = confData.serviceEnabled; | 
|  | 167 | ldap["ServiceAddresses"] = nlohmann::json::array({confData.uri}); | 
|  | 168 | ldap["Authentication"]["AuthenticationType"] = "UsernameAndPassword"; | 
|  | 169 | ldap["Authentication"]["Username"] = confData.bindDN; | 
|  | 170 | ldap["Authentication"]["Password"] = nullptr; | 
|  | 171 |  | 
|  | 172 | ldap["LDAPService"]["SearchSettings"]["BaseDistinguishedNames"] = | 
|  | 173 | nlohmann::json::array({confData.baseDN}); | 
|  | 174 | ldap["LDAPService"]["SearchSettings"]["UsernameAttribute"] = | 
|  | 175 | confData.userNameAttribute; | 
|  | 176 | ldap["LDAPService"]["SearchSettings"]["GroupsAttribute"] = | 
|  | 177 | confData.groupAttribute; | 
|  | 178 |  | 
|  | 179 | nlohmann::json& roleMapArray = ldap["RemoteRoleMapping"]; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 180 | roleMapArray = nlohmann::json::array(); | 
| Ed Tanous | 9eb808c | 2022-01-25 10:19:23 -0800 | [diff] [blame] | 181 | for (const auto& obj : confData.groupRoleList) | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 182 | { | 
|  | 183 | BMCWEB_LOG_DEBUG << "Pushing the data groupName=" | 
|  | 184 | << obj.second.groupName << "\n"; | 
|  | 185 | roleMapArray.push_back( | 
|  | 186 | {nlohmann::json::array({"RemoteGroup", obj.second.groupName}), | 
|  | 187 | nlohmann::json::array( | 
|  | 188 | {"LocalRole", getRoleIdFromPrivilege(obj.second.privilege)})}); | 
|  | 189 | } | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 190 | } | 
|  | 191 |  | 
|  | 192 | /** | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 193 | *  @brief validates given JSON input and then calls appropriate method to | 
|  | 194 | * create, to delete or to set Rolemapping object based on the given input. | 
|  | 195 | * | 
|  | 196 | */ | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 197 | inline void handleRoleMapPatch( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 198 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 199 | const std::vector<std::pair<std::string, LDAPRoleMapData>>& roleMapObjData, | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 200 | const std::string& serverType, const std::vector<nlohmann::json>& input) | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 201 | { | 
|  | 202 | for (size_t index = 0; index < input.size(); index++) | 
|  | 203 | { | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 204 | const nlohmann::json& thisJson = input[index]; | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 205 |  | 
|  | 206 | if (thisJson.is_null()) | 
|  | 207 | { | 
|  | 208 | // delete the existing object | 
|  | 209 | if (index < roleMapObjData.size()) | 
|  | 210 | { | 
|  | 211 | crow::connections::systemBus->async_method_call( | 
|  | 212 | [asyncResp, roleMapObjData, serverType, | 
|  | 213 | index](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 214 | if (ec) | 
|  | 215 | { | 
|  | 216 | BMCWEB_LOG_ERROR << "DBUS response error: " << ec; | 
|  | 217 | messages::internalError(asyncResp->res); | 
|  | 218 | return; | 
|  | 219 | } | 
|  | 220 | asyncResp->res | 
|  | 221 | .jsonValue[serverType]["RemoteRoleMapping"][index] = | 
|  | 222 | nullptr; | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 223 | }, | 
|  | 224 | ldapDbusService, roleMapObjData[index].first, | 
|  | 225 | "xyz.openbmc_project.Object.Delete", "Delete"); | 
|  | 226 | } | 
|  | 227 | else | 
|  | 228 | { | 
|  | 229 | BMCWEB_LOG_ERROR << "Can't delete the object"; | 
|  | 230 | messages::propertyValueTypeError( | 
| Ed Tanous | 71f52d9 | 2021-02-19 08:51:17 -0800 | [diff] [blame] | 231 | asyncResp->res, | 
|  | 232 | thisJson.dump(2, ' ', true, | 
|  | 233 | nlohmann::json::error_handler_t::replace), | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 234 | "RemoteRoleMapping/" + std::to_string(index)); | 
|  | 235 | return; | 
|  | 236 | } | 
|  | 237 | } | 
|  | 238 | else if (thisJson.empty()) | 
|  | 239 | { | 
|  | 240 | // Don't do anything for the empty objects,parse next json | 
|  | 241 | // eg {"RemoteRoleMapping",[{}]} | 
|  | 242 | } | 
|  | 243 | else | 
|  | 244 | { | 
|  | 245 | // update/create the object | 
|  | 246 | std::optional<std::string> remoteGroup; | 
|  | 247 | std::optional<std::string> localRole; | 
|  | 248 |  | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 249 | // This is a copy, but it's required in this case because of how | 
|  | 250 | // readJson is structured | 
|  | 251 | nlohmann::json thisJsonCopy = thisJson; | 
|  | 252 | if (!json_util::readJson(thisJsonCopy, asyncResp->res, | 
|  | 253 | "RemoteGroup", remoteGroup, "LocalRole", | 
|  | 254 | localRole)) | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 255 | { | 
|  | 256 | continue; | 
|  | 257 | } | 
|  | 258 |  | 
|  | 259 | // Update existing RoleMapping Object | 
|  | 260 | if (index < roleMapObjData.size()) | 
|  | 261 | { | 
|  | 262 | BMCWEB_LOG_DEBUG << "Update Role Map Object"; | 
|  | 263 | // If "RemoteGroup" info is provided | 
|  | 264 | if (remoteGroup) | 
|  | 265 | { | 
|  | 266 | crow::connections::systemBus->async_method_call( | 
|  | 267 | [asyncResp, roleMapObjData, serverType, index, | 
|  | 268 | remoteGroup](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 269 | if (ec) | 
|  | 270 | { | 
|  | 271 | BMCWEB_LOG_ERROR << "DBUS response error: " << ec; | 
|  | 272 | messages::internalError(asyncResp->res); | 
|  | 273 | return; | 
|  | 274 | } | 
|  | 275 | asyncResp->res | 
|  | 276 | .jsonValue[serverType]["RemoteRoleMapping"][index] | 
|  | 277 | ["RemoteGroup"] = *remoteGroup; | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 278 | }, | 
|  | 279 | ldapDbusService, roleMapObjData[index].first, | 
|  | 280 | propertyInterface, "Set", | 
|  | 281 | "xyz.openbmc_project.User.PrivilegeMapperEntry", | 
|  | 282 | "GroupName", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 283 | dbus::utility::DbusVariantType( | 
|  | 284 | std::move(*remoteGroup))); | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 285 | } | 
|  | 286 |  | 
|  | 287 | // If "LocalRole" info is provided | 
|  | 288 | if (localRole) | 
|  | 289 | { | 
|  | 290 | crow::connections::systemBus->async_method_call( | 
|  | 291 | [asyncResp, roleMapObjData, serverType, index, | 
|  | 292 | localRole](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 293 | if (ec) | 
|  | 294 | { | 
|  | 295 | BMCWEB_LOG_ERROR << "DBUS response error: " << ec; | 
|  | 296 | messages::internalError(asyncResp->res); | 
|  | 297 | return; | 
|  | 298 | } | 
|  | 299 | asyncResp->res | 
|  | 300 | .jsonValue[serverType]["RemoteRoleMapping"][index] | 
|  | 301 | ["LocalRole"] = *localRole; | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 302 | }, | 
|  | 303 | ldapDbusService, roleMapObjData[index].first, | 
|  | 304 | propertyInterface, "Set", | 
|  | 305 | "xyz.openbmc_project.User.PrivilegeMapperEntry", | 
|  | 306 | "Privilege", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 307 | dbus::utility::DbusVariantType( | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 308 | getPrivilegeFromRoleId(std::move(*localRole)))); | 
|  | 309 | } | 
|  | 310 | } | 
|  | 311 | // Create a new RoleMapping Object. | 
|  | 312 | else | 
|  | 313 | { | 
|  | 314 | BMCWEB_LOG_DEBUG | 
|  | 315 | << "setRoleMappingProperties: Creating new Object"; | 
|  | 316 | std::string pathString = | 
|  | 317 | "RemoteRoleMapping/" + std::to_string(index); | 
|  | 318 |  | 
|  | 319 | if (!localRole) | 
|  | 320 | { | 
|  | 321 | messages::propertyMissing(asyncResp->res, | 
|  | 322 | pathString + "/LocalRole"); | 
|  | 323 | continue; | 
|  | 324 | } | 
|  | 325 | if (!remoteGroup) | 
|  | 326 | { | 
|  | 327 | messages::propertyMissing(asyncResp->res, | 
|  | 328 | pathString + "/RemoteGroup"); | 
|  | 329 | continue; | 
|  | 330 | } | 
|  | 331 |  | 
|  | 332 | std::string dbusObjectPath; | 
|  | 333 | if (serverType == "ActiveDirectory") | 
|  | 334 | { | 
| Ed Tanous | 2c70f80 | 2020-09-28 14:29:23 -0700 | [diff] [blame] | 335 | dbusObjectPath = adConfigObject; | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 336 | } | 
|  | 337 | else if (serverType == "LDAP") | 
|  | 338 | { | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 339 | dbusObjectPath = ldapConfigObjectName; | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 340 | } | 
|  | 341 |  | 
|  | 342 | BMCWEB_LOG_DEBUG << "Remote Group=" << *remoteGroup | 
|  | 343 | << ",LocalRole=" << *localRole; | 
|  | 344 |  | 
|  | 345 | crow::connections::systemBus->async_method_call( | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 346 | [asyncResp, serverType, localRole, | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 347 | remoteGroup](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 348 | if (ec) | 
|  | 349 | { | 
|  | 350 | BMCWEB_LOG_ERROR << "DBUS response error: " << ec; | 
|  | 351 | messages::internalError(asyncResp->res); | 
|  | 352 | return; | 
|  | 353 | } | 
|  | 354 | nlohmann::json& remoteRoleJson = | 
|  | 355 | asyncResp->res | 
|  | 356 | .jsonValue[serverType]["RemoteRoleMapping"]; | 
|  | 357 | nlohmann::json::object_t roleMapEntry; | 
|  | 358 | roleMapEntry["LocalRole"] = *localRole; | 
|  | 359 | roleMapEntry["RemoteGroup"] = *remoteGroup; | 
|  | 360 | remoteRoleJson.push_back(std::move(roleMapEntry)); | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 361 | }, | 
|  | 362 | ldapDbusService, dbusObjectPath, ldapPrivMapperInterface, | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 363 | "Create", *remoteGroup, | 
| Ratan Gupta | 0678524 | 2019-07-26 22:30:16 +0530 | [diff] [blame] | 364 | getPrivilegeFromRoleId(std::move(*localRole))); | 
|  | 365 | } | 
|  | 366 | } | 
|  | 367 | } | 
|  | 368 | } | 
|  | 369 |  | 
|  | 370 | /** | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 371 | * Function that retrieves all properties for LDAP config object | 
|  | 372 | * into JSON | 
|  | 373 | */ | 
|  | 374 | template <typename CallbackFunc> | 
|  | 375 | inline void getLDAPConfigData(const std::string& ldapType, | 
|  | 376 | CallbackFunc&& callback) | 
|  | 377 | { | 
| Ratan Gupta | ab828d7 | 2019-04-22 14:18:33 +0530 | [diff] [blame] | 378 |  | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 379 | const std::array<const char*, 2> interfaces = {ldapEnableInterface, | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 380 | ldapConfigInterface}; | 
|  | 381 |  | 
|  | 382 | crow::connections::systemBus->async_method_call( | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 383 | [callback, ldapType](const boost::system::error_code ec, | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 384 | const dbus::utility::MapperGetObject& resp) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 385 | if (ec || resp.empty()) | 
|  | 386 | { | 
|  | 387 | BMCWEB_LOG_ERROR | 
|  | 388 | << "DBUS response error during getting of service name: " << ec; | 
|  | 389 | LDAPConfigData empty{}; | 
|  | 390 | callback(false, empty, ldapType); | 
|  | 391 | return; | 
|  | 392 | } | 
|  | 393 | std::string service = resp.begin()->first; | 
|  | 394 | crow::connections::systemBus->async_method_call( | 
|  | 395 | [callback, | 
|  | 396 | ldapType](const boost::system::error_code errorCode, | 
|  | 397 | const dbus::utility::ManagedObjectType& ldapObjects) { | 
|  | 398 | LDAPConfigData confData{}; | 
|  | 399 | if (errorCode) | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 400 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 401 | callback(false, confData, ldapType); | 
|  | 402 | BMCWEB_LOG_ERROR << "D-Bus responses error: " << errorCode; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 403 | return; | 
|  | 404 | } | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 405 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 406 | std::string ldapDbusType; | 
|  | 407 | std::string searchString; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 408 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 409 | if (ldapType == "LDAP") | 
|  | 410 | { | 
|  | 411 | ldapDbusType = | 
|  | 412 | "xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap"; | 
|  | 413 | searchString = "openldap"; | 
|  | 414 | } | 
|  | 415 | else if (ldapType == "ActiveDirectory") | 
|  | 416 | { | 
|  | 417 | ldapDbusType = | 
|  | 418 | "xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory"; | 
|  | 419 | searchString = "active_directory"; | 
|  | 420 | } | 
|  | 421 | else | 
|  | 422 | { | 
|  | 423 | BMCWEB_LOG_ERROR << "Can't get the DbusType for the given type=" | 
|  | 424 | << ldapType; | 
|  | 425 | callback(false, confData, ldapType); | 
|  | 426 | return; | 
|  | 427 | } | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 428 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 429 | std::string ldapEnableInterfaceStr = ldapEnableInterface; | 
|  | 430 | std::string ldapConfigInterfaceStr = ldapConfigInterface; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 431 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 432 | for (const auto& object : ldapObjects) | 
|  | 433 | { | 
|  | 434 | // let's find the object whose ldap type is equal to the | 
|  | 435 | // given type | 
|  | 436 | if (object.first.str.find(searchString) == std::string::npos) | 
|  | 437 | { | 
|  | 438 | continue; | 
|  | 439 | } | 
|  | 440 |  | 
|  | 441 | for (const auto& interface : object.second) | 
|  | 442 | { | 
|  | 443 | if (interface.first == ldapEnableInterfaceStr) | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 444 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 445 | // rest of the properties are string. | 
|  | 446 | for (const auto& property : interface.second) | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 447 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 448 | if (property.first == "Enabled") | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 449 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 450 | const bool* value = | 
|  | 451 | std::get_if<bool>(&property.second); | 
|  | 452 | if (value == nullptr) | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 453 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 454 | continue; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 455 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 456 | confData.serviceEnabled = *value; | 
|  | 457 | break; | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 458 | } | 
|  | 459 | } | 
|  | 460 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 461 | else if (interface.first == ldapConfigInterfaceStr) | 
|  | 462 | { | 
|  | 463 |  | 
|  | 464 | for (const auto& property : interface.second) | 
|  | 465 | { | 
|  | 466 | const std::string* strValue = | 
|  | 467 | std::get_if<std::string>(&property.second); | 
|  | 468 | if (strValue == nullptr) | 
|  | 469 | { | 
|  | 470 | continue; | 
|  | 471 | } | 
|  | 472 | if (property.first == "LDAPServerURI") | 
|  | 473 | { | 
|  | 474 | confData.uri = *strValue; | 
|  | 475 | } | 
|  | 476 | else if (property.first == "LDAPBindDN") | 
|  | 477 | { | 
|  | 478 | confData.bindDN = *strValue; | 
|  | 479 | } | 
|  | 480 | else if (property.first == "LDAPBaseDN") | 
|  | 481 | { | 
|  | 482 | confData.baseDN = *strValue; | 
|  | 483 | } | 
|  | 484 | else if (property.first == "LDAPSearchScope") | 
|  | 485 | { | 
|  | 486 | confData.searchScope = *strValue; | 
|  | 487 | } | 
|  | 488 | else if (property.first == "GroupNameAttribute") | 
|  | 489 | { | 
|  | 490 | confData.groupAttribute = *strValue; | 
|  | 491 | } | 
|  | 492 | else if (property.first == "UserNameAttribute") | 
|  | 493 | { | 
|  | 494 | confData.userNameAttribute = *strValue; | 
|  | 495 | } | 
|  | 496 | else if (property.first == "LDAPType") | 
|  | 497 | { | 
|  | 498 | confData.serverType = *strValue; | 
|  | 499 | } | 
|  | 500 | } | 
|  | 501 | } | 
|  | 502 | else if (interface.first == | 
|  | 503 | "xyz.openbmc_project.User.PrivilegeMapperEntry") | 
|  | 504 | { | 
|  | 505 | LDAPRoleMapData roleMapData{}; | 
|  | 506 | for (const auto& property : interface.second) | 
|  | 507 | { | 
|  | 508 | const std::string* strValue = | 
|  | 509 | std::get_if<std::string>(&property.second); | 
|  | 510 |  | 
|  | 511 | if (strValue == nullptr) | 
|  | 512 | { | 
|  | 513 | continue; | 
|  | 514 | } | 
|  | 515 |  | 
|  | 516 | if (property.first == "GroupName") | 
|  | 517 | { | 
|  | 518 | roleMapData.groupName = *strValue; | 
|  | 519 | } | 
|  | 520 | else if (property.first == "Privilege") | 
|  | 521 | { | 
|  | 522 | roleMapData.privilege = *strValue; | 
|  | 523 | } | 
|  | 524 | } | 
|  | 525 |  | 
|  | 526 | confData.groupRoleList.emplace_back(object.first.str, | 
|  | 527 | roleMapData); | 
|  | 528 | } | 
|  | 529 | } | 
|  | 530 | } | 
|  | 531 | callback(true, confData, ldapType); | 
|  | 532 | }, | 
|  | 533 | service, ldapRootObject, dbusObjManagerIntf, "GetManagedObjects"); | 
| Nagaraju Goruganti | 54fc587 | 2019-01-30 05:11:00 -0600 | [diff] [blame] | 534 | }, | 
|  | 535 | mapperBusName, mapperObjectPath, mapperIntf, "GetObject", | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 536 | ldapConfigObjectName, interfaces); | 
| Ratan Gupta | 6973a58 | 2018-12-13 18:25:44 +0530 | [diff] [blame] | 537 | } | 
|  | 538 |  | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 539 | /** | 
|  | 540 | * @brief parses the authentication section under the LDAP | 
|  | 541 | * @param input JSON data | 
|  | 542 | * @param asyncResp pointer to the JSON response | 
|  | 543 | * @param userName  userName to be filled from the given JSON. | 
|  | 544 | * @param password  password to be filled from the given JSON. | 
|  | 545 | */ | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 546 | inline void parseLDAPAuthenticationJson( | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 547 | nlohmann::json input, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 548 | std::optional<std::string>& username, std::optional<std::string>& password) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 549 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 550 | std::optional<std::string> authType; | 
|  | 551 |  | 
|  | 552 | if (!json_util::readJson(input, asyncResp->res, "AuthenticationType", | 
|  | 553 | authType, "Username", username, "Password", | 
|  | 554 | password)) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 555 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 556 | return; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 557 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 558 | if (!authType) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 559 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 560 | return; | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 561 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 562 | if (*authType != "UsernameAndPassword") | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 563 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 564 | messages::propertyValueNotInList(asyncResp->res, *authType, | 
|  | 565 | "AuthenticationType"); | 
|  | 566 | return; | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 567 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 568 | } | 
|  | 569 | /** | 
|  | 570 | * @brief parses the LDAPService section under the LDAP | 
|  | 571 | * @param input JSON data | 
|  | 572 | * @param asyncResp pointer to the JSON response | 
|  | 573 | * @param baseDNList baseDN to be filled from the given JSON. | 
|  | 574 | * @param userNameAttribute  userName to be filled from the given JSON. | 
|  | 575 | * @param groupaAttribute  password to be filled from the given JSON. | 
|  | 576 | */ | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 577 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 578 | inline void | 
|  | 579 | parseLDAPServiceJson(nlohmann::json input, | 
|  | 580 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 581 | std::optional<std::vector<std::string>>& baseDNList, | 
|  | 582 | std::optional<std::string>& userNameAttribute, | 
|  | 583 | std::optional<std::string>& groupsAttribute) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 584 | { | 
|  | 585 | std::optional<nlohmann::json> searchSettings; | 
|  | 586 |  | 
|  | 587 | if (!json_util::readJson(input, asyncResp->res, "SearchSettings", | 
|  | 588 | searchSettings)) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 589 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 590 | return; | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 591 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 592 | if (!searchSettings) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 593 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 594 | return; | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 595 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 596 | if (!json_util::readJson(*searchSettings, asyncResp->res, | 
|  | 597 | "BaseDistinguishedNames", baseDNList, | 
|  | 598 | "UsernameAttribute", userNameAttribute, | 
|  | 599 | "GroupsAttribute", groupsAttribute)) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 600 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 601 | return; | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 602 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 603 | } | 
|  | 604 | /** | 
|  | 605 | * @brief updates the LDAP server address and updates the | 
|  | 606 | json response with the new value. | 
|  | 607 | * @param serviceAddressList address to be updated. | 
|  | 608 | * @param asyncResp pointer to the JSON response | 
|  | 609 | * @param ldapServerElementName Type of LDAP | 
|  | 610 | server(openLDAP/ActiveDirectory) | 
|  | 611 | */ | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 612 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 613 | inline void handleServiceAddressPatch( | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 614 | const std::vector<std::string>& serviceAddressList, | 
|  | 615 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 616 | const std::string& ldapServerElementName, | 
|  | 617 | const std::string& ldapConfigObject) | 
|  | 618 | { | 
|  | 619 | crow::connections::systemBus->async_method_call( | 
|  | 620 | [asyncResp, ldapServerElementName, | 
|  | 621 | serviceAddressList](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 622 | if (ec) | 
|  | 623 | { | 
|  | 624 | BMCWEB_LOG_DEBUG | 
|  | 625 | << "Error Occurred in updating the service address"; | 
|  | 626 | messages::internalError(asyncResp->res); | 
|  | 627 | return; | 
|  | 628 | } | 
|  | 629 | std::vector<std::string> modifiedserviceAddressList = { | 
|  | 630 | serviceAddressList.front()}; | 
|  | 631 | asyncResp->res.jsonValue[ldapServerElementName]["ServiceAddresses"] = | 
|  | 632 | modifiedserviceAddressList; | 
|  | 633 | if ((serviceAddressList).size() > 1) | 
|  | 634 | { | 
|  | 635 | messages::propertyValueModified(asyncResp->res, "ServiceAddresses", | 
|  | 636 | serviceAddressList.front()); | 
|  | 637 | } | 
|  | 638 | BMCWEB_LOG_DEBUG << "Updated the service address"; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 639 | }, | 
|  | 640 | ldapDbusService, ldapConfigObject, propertyInterface, "Set", | 
|  | 641 | ldapConfigInterface, "LDAPServerURI", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 642 | dbus::utility::DbusVariantType(serviceAddressList.front())); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 643 | } | 
|  | 644 | /** | 
|  | 645 | * @brief updates the LDAP Bind DN and updates the | 
|  | 646 | json response with the new value. | 
|  | 647 | * @param username name of the user which needs to be updated. | 
|  | 648 | * @param asyncResp pointer to the JSON response | 
|  | 649 | * @param ldapServerElementName Type of LDAP | 
|  | 650 | server(openLDAP/ActiveDirectory) | 
|  | 651 | */ | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 652 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 653 | inline void | 
|  | 654 | handleUserNamePatch(const std::string& username, | 
|  | 655 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 656 | const std::string& ldapServerElementName, | 
|  | 657 | const std::string& ldapConfigObject) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 658 | { | 
|  | 659 | crow::connections::systemBus->async_method_call( | 
|  | 660 | [asyncResp, username, | 
|  | 661 | ldapServerElementName](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 662 | if (ec) | 
|  | 663 | { | 
|  | 664 | BMCWEB_LOG_DEBUG << "Error occurred in updating the username"; | 
|  | 665 | messages::internalError(asyncResp->res); | 
|  | 666 | return; | 
|  | 667 | } | 
|  | 668 | asyncResp->res | 
|  | 669 | .jsonValue[ldapServerElementName]["Authentication"]["Username"] = | 
|  | 670 | username; | 
|  | 671 | BMCWEB_LOG_DEBUG << "Updated the username"; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 672 | }, | 
|  | 673 | ldapDbusService, ldapConfigObject, propertyInterface, "Set", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 674 | ldapConfigInterface, "LDAPBindDN", | 
|  | 675 | dbus::utility::DbusVariantType(username)); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 676 | } | 
|  | 677 |  | 
|  | 678 | /** | 
|  | 679 | * @brief updates the LDAP password | 
|  | 680 | * @param password : ldap password which needs to be updated. | 
|  | 681 | * @param asyncResp pointer to the JSON response | 
|  | 682 | * @param ldapServerElementName Type of LDAP | 
|  | 683 | *        server(openLDAP/ActiveDirectory) | 
|  | 684 | */ | 
|  | 685 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 686 | inline void | 
|  | 687 | handlePasswordPatch(const std::string& password, | 
|  | 688 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 689 | const std::string& ldapServerElementName, | 
|  | 690 | const std::string& ldapConfigObject) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 691 | { | 
|  | 692 | crow::connections::systemBus->async_method_call( | 
|  | 693 | [asyncResp, password, | 
|  | 694 | ldapServerElementName](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 695 | if (ec) | 
|  | 696 | { | 
|  | 697 | BMCWEB_LOG_DEBUG << "Error occurred in updating the password"; | 
|  | 698 | messages::internalError(asyncResp->res); | 
|  | 699 | return; | 
|  | 700 | } | 
|  | 701 | asyncResp->res | 
|  | 702 | .jsonValue[ldapServerElementName]["Authentication"]["Password"] = | 
|  | 703 | ""; | 
|  | 704 | BMCWEB_LOG_DEBUG << "Updated the password"; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 705 | }, | 
|  | 706 | ldapDbusService, ldapConfigObject, propertyInterface, "Set", | 
|  | 707 | ldapConfigInterface, "LDAPBindDNPassword", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 708 | dbus::utility::DbusVariantType(password)); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 709 | } | 
|  | 710 |  | 
|  | 711 | /** | 
|  | 712 | * @brief updates the LDAP BaseDN and updates the | 
|  | 713 | json response with the new value. | 
|  | 714 | * @param baseDNList baseDN list which needs to be updated. | 
|  | 715 | * @param asyncResp pointer to the JSON response | 
|  | 716 | * @param ldapServerElementName Type of LDAP | 
|  | 717 | server(openLDAP/ActiveDirectory) | 
|  | 718 | */ | 
|  | 719 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 720 | inline void | 
|  | 721 | handleBaseDNPatch(const std::vector<std::string>& baseDNList, | 
|  | 722 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 723 | const std::string& ldapServerElementName, | 
|  | 724 | const std::string& ldapConfigObject) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 725 | { | 
|  | 726 | crow::connections::systemBus->async_method_call( | 
|  | 727 | [asyncResp, baseDNList, | 
|  | 728 | ldapServerElementName](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 729 | if (ec) | 
|  | 730 | { | 
|  | 731 | BMCWEB_LOG_DEBUG << "Error Occurred in Updating the base DN"; | 
|  | 732 | messages::internalError(asyncResp->res); | 
|  | 733 | return; | 
|  | 734 | } | 
|  | 735 | auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName]; | 
|  | 736 | auto& searchSettingsJson = | 
|  | 737 | serverTypeJson["LDAPService"]["SearchSettings"]; | 
|  | 738 | std::vector<std::string> modifiedBaseDNList = {baseDNList.front()}; | 
|  | 739 | searchSettingsJson["BaseDistinguishedNames"] = modifiedBaseDNList; | 
|  | 740 | if (baseDNList.size() > 1) | 
|  | 741 | { | 
|  | 742 | messages::propertyValueModified( | 
|  | 743 | asyncResp->res, "BaseDistinguishedNames", baseDNList.front()); | 
|  | 744 | } | 
|  | 745 | BMCWEB_LOG_DEBUG << "Updated the base DN"; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 746 | }, | 
|  | 747 | ldapDbusService, ldapConfigObject, propertyInterface, "Set", | 
|  | 748 | ldapConfigInterface, "LDAPBaseDN", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 749 | dbus::utility::DbusVariantType(baseDNList.front())); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 750 | } | 
|  | 751 | /** | 
|  | 752 | * @brief updates the LDAP user name attribute and updates the | 
|  | 753 | json response with the new value. | 
|  | 754 | * @param userNameAttribute attribute to be updated. | 
|  | 755 | * @param asyncResp pointer to the JSON response | 
|  | 756 | * @param ldapServerElementName Type of LDAP | 
|  | 757 | server(openLDAP/ActiveDirectory) | 
|  | 758 | */ | 
|  | 759 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 760 | inline void | 
|  | 761 | handleUserNameAttrPatch(const std::string& userNameAttribute, | 
|  | 762 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 763 | const std::string& ldapServerElementName, | 
|  | 764 | const std::string& ldapConfigObject) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 765 | { | 
|  | 766 | crow::connections::systemBus->async_method_call( | 
|  | 767 | [asyncResp, userNameAttribute, | 
|  | 768 | ldapServerElementName](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 769 | if (ec) | 
|  | 770 | { | 
|  | 771 | BMCWEB_LOG_DEBUG << "Error Occurred in Updating the " | 
|  | 772 | "username attribute"; | 
|  | 773 | messages::internalError(asyncResp->res); | 
|  | 774 | return; | 
|  | 775 | } | 
|  | 776 | auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName]; | 
|  | 777 | auto& searchSettingsJson = | 
|  | 778 | serverTypeJson["LDAPService"]["SearchSettings"]; | 
|  | 779 | searchSettingsJson["UsernameAttribute"] = userNameAttribute; | 
|  | 780 | BMCWEB_LOG_DEBUG << "Updated the user name attr."; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 781 | }, | 
|  | 782 | ldapDbusService, ldapConfigObject, propertyInterface, "Set", | 
|  | 783 | ldapConfigInterface, "UserNameAttribute", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 784 | dbus::utility::DbusVariantType(userNameAttribute)); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 785 | } | 
|  | 786 | /** | 
|  | 787 | * @brief updates the LDAP group attribute and updates the | 
|  | 788 | json response with the new value. | 
|  | 789 | * @param groupsAttribute attribute to be updated. | 
|  | 790 | * @param asyncResp pointer to the JSON response | 
|  | 791 | * @param ldapServerElementName Type of LDAP | 
|  | 792 | server(openLDAP/ActiveDirectory) | 
|  | 793 | */ | 
|  | 794 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 795 | inline void handleGroupNameAttrPatch( | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 796 | const std::string& groupsAttribute, | 
|  | 797 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 798 | const std::string& ldapServerElementName, | 
|  | 799 | const std::string& ldapConfigObject) | 
|  | 800 | { | 
|  | 801 | crow::connections::systemBus->async_method_call( | 
|  | 802 | [asyncResp, groupsAttribute, | 
|  | 803 | ldapServerElementName](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 804 | if (ec) | 
|  | 805 | { | 
|  | 806 | BMCWEB_LOG_DEBUG << "Error Occurred in Updating the " | 
|  | 807 | "groupname attribute"; | 
|  | 808 | messages::internalError(asyncResp->res); | 
|  | 809 | return; | 
|  | 810 | } | 
|  | 811 | auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName]; | 
|  | 812 | auto& searchSettingsJson = | 
|  | 813 | serverTypeJson["LDAPService"]["SearchSettings"]; | 
|  | 814 | searchSettingsJson["GroupsAttribute"] = groupsAttribute; | 
|  | 815 | BMCWEB_LOG_DEBUG << "Updated the groupname attr"; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 816 | }, | 
|  | 817 | ldapDbusService, ldapConfigObject, propertyInterface, "Set", | 
|  | 818 | ldapConfigInterface, "GroupNameAttribute", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 819 | dbus::utility::DbusVariantType(groupsAttribute)); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 820 | } | 
|  | 821 | /** | 
|  | 822 | * @brief updates the LDAP service enable and updates the | 
|  | 823 | json response with the new value. | 
|  | 824 | * @param input JSON data. | 
|  | 825 | * @param asyncResp pointer to the JSON response | 
|  | 826 | * @param ldapServerElementName Type of LDAP | 
|  | 827 | server(openLDAP/ActiveDirectory) | 
|  | 828 | */ | 
|  | 829 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 830 | inline void handleServiceEnablePatch( | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 831 | bool serviceEnabled, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 832 | const std::string& ldapServerElementName, | 
|  | 833 | const std::string& ldapConfigObject) | 
|  | 834 | { | 
|  | 835 | crow::connections::systemBus->async_method_call( | 
|  | 836 | [asyncResp, serviceEnabled, | 
|  | 837 | ldapServerElementName](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 838 | if (ec) | 
|  | 839 | { | 
|  | 840 | BMCWEB_LOG_DEBUG << "Error Occurred in Updating the service enable"; | 
|  | 841 | messages::internalError(asyncResp->res); | 
|  | 842 | return; | 
|  | 843 | } | 
|  | 844 | asyncResp->res.jsonValue[ldapServerElementName]["ServiceEnabled"] = | 
|  | 845 | serviceEnabled; | 
|  | 846 | BMCWEB_LOG_DEBUG << "Updated Service enable = " << serviceEnabled; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 847 | }, | 
|  | 848 | ldapDbusService, ldapConfigObject, propertyInterface, "Set", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 849 | ldapEnableInterface, "Enabled", | 
|  | 850 | dbus::utility::DbusVariantType(serviceEnabled)); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 851 | } | 
|  | 852 |  | 
| Ed Tanous | 4f48d5f | 2021-06-21 08:27:45 -0700 | [diff] [blame] | 853 | inline void | 
|  | 854 | handleAuthMethodsPatch(nlohmann::json& input, | 
|  | 855 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 856 | { | 
|  | 857 | std::optional<bool> basicAuth; | 
|  | 858 | std::optional<bool> cookie; | 
|  | 859 | std::optional<bool> sessionToken; | 
|  | 860 | std::optional<bool> xToken; | 
|  | 861 | std::optional<bool> tls; | 
|  | 862 |  | 
|  | 863 | if (!json_util::readJson(input, asyncResp->res, "BasicAuth", basicAuth, | 
|  | 864 | "Cookie", cookie, "SessionToken", sessionToken, | 
|  | 865 | "XToken", xToken, "TLS", tls)) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 866 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 867 | BMCWEB_LOG_ERROR << "Cannot read values from AuthMethod tag"; | 
|  | 868 | return; | 
|  | 869 | } | 
|  | 870 |  | 
|  | 871 | // Make a copy of methods configuration | 
|  | 872 | persistent_data::AuthConfigMethods authMethodsConfig = | 
|  | 873 | persistent_data::SessionStore::getInstance().getAuthMethodsConfig(); | 
|  | 874 |  | 
|  | 875 | if (basicAuth) | 
|  | 876 | { | 
|  | 877 | #ifndef BMCWEB_ENABLE_BASIC_AUTHENTICATION | 
|  | 878 | messages::actionNotSupported( | 
| George Liu | 0fda0f1 | 2021-11-16 10:06:17 +0800 | [diff] [blame] | 879 | asyncResp->res, | 
|  | 880 | "Setting BasicAuth when basic-auth feature is disabled"); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 881 | return; | 
|  | 882 | #endif | 
|  | 883 | authMethodsConfig.basic = *basicAuth; | 
|  | 884 | } | 
|  | 885 |  | 
|  | 886 | if (cookie) | 
|  | 887 | { | 
|  | 888 | #ifndef BMCWEB_ENABLE_COOKIE_AUTHENTICATION | 
| George Liu | 0fda0f1 | 2021-11-16 10:06:17 +0800 | [diff] [blame] | 889 | messages::actionNotSupported( | 
|  | 890 | asyncResp->res, | 
|  | 891 | "Setting Cookie when cookie-auth feature is disabled"); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 892 | return; | 
|  | 893 | #endif | 
|  | 894 | authMethodsConfig.cookie = *cookie; | 
|  | 895 | } | 
|  | 896 |  | 
|  | 897 | if (sessionToken) | 
|  | 898 | { | 
|  | 899 | #ifndef BMCWEB_ENABLE_SESSION_AUTHENTICATION | 
|  | 900 | messages::actionNotSupported( | 
| George Liu | 0fda0f1 | 2021-11-16 10:06:17 +0800 | [diff] [blame] | 901 | asyncResp->res, | 
|  | 902 | "Setting SessionToken when session-auth feature is disabled"); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 903 | return; | 
|  | 904 | #endif | 
|  | 905 | authMethodsConfig.sessionToken = *sessionToken; | 
|  | 906 | } | 
|  | 907 |  | 
|  | 908 | if (xToken) | 
|  | 909 | { | 
|  | 910 | #ifndef BMCWEB_ENABLE_XTOKEN_AUTHENTICATION | 
| George Liu | 0fda0f1 | 2021-11-16 10:06:17 +0800 | [diff] [blame] | 911 | messages::actionNotSupported( | 
|  | 912 | asyncResp->res, | 
|  | 913 | "Setting XToken when xtoken-auth feature is disabled"); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 914 | return; | 
|  | 915 | #endif | 
|  | 916 | authMethodsConfig.xtoken = *xToken; | 
|  | 917 | } | 
|  | 918 |  | 
|  | 919 | if (tls) | 
|  | 920 | { | 
|  | 921 | #ifndef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION | 
| George Liu | 0fda0f1 | 2021-11-16 10:06:17 +0800 | [diff] [blame] | 922 | messages::actionNotSupported( | 
|  | 923 | asyncResp->res, | 
|  | 924 | "Setting TLS when mutual-tls-auth feature is disabled"); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 925 | return; | 
|  | 926 | #endif | 
|  | 927 | authMethodsConfig.tls = *tls; | 
|  | 928 | } | 
|  | 929 |  | 
|  | 930 | if (!authMethodsConfig.basic && !authMethodsConfig.cookie && | 
|  | 931 | !authMethodsConfig.sessionToken && !authMethodsConfig.xtoken && | 
|  | 932 | !authMethodsConfig.tls) | 
|  | 933 | { | 
|  | 934 | // Do not allow user to disable everything | 
|  | 935 | messages::actionNotSupported(asyncResp->res, | 
|  | 936 | "of disabling all available methods"); | 
|  | 937 | return; | 
|  | 938 | } | 
|  | 939 |  | 
|  | 940 | persistent_data::SessionStore::getInstance().updateAuthMethodsConfig( | 
|  | 941 | authMethodsConfig); | 
|  | 942 | // Save configuration immediately | 
|  | 943 | persistent_data::getConfig().writeData(); | 
|  | 944 |  | 
|  | 945 | messages::success(asyncResp->res); | 
|  | 946 | } | 
|  | 947 |  | 
|  | 948 | /** | 
|  | 949 | * @brief Get the required values from the given JSON, validates the | 
|  | 950 | *        value and create the LDAP config object. | 
|  | 951 | * @param input JSON data | 
|  | 952 | * @param asyncResp pointer to the JSON response | 
|  | 953 | * @param serverType Type of LDAP server(openLDAP/ActiveDirectory) | 
|  | 954 | */ | 
|  | 955 |  | 
|  | 956 | inline void handleLDAPPatch(nlohmann::json& input, | 
|  | 957 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 958 | const std::string& serverType) | 
|  | 959 | { | 
|  | 960 | std::string dbusObjectPath; | 
|  | 961 | if (serverType == "ActiveDirectory") | 
|  | 962 | { | 
|  | 963 | dbusObjectPath = adConfigObject; | 
|  | 964 | } | 
|  | 965 | else if (serverType == "LDAP") | 
|  | 966 | { | 
|  | 967 | dbusObjectPath = ldapConfigObjectName; | 
|  | 968 | } | 
|  | 969 | else | 
|  | 970 | { | 
|  | 971 | return; | 
|  | 972 | } | 
|  | 973 |  | 
|  | 974 | std::optional<nlohmann::json> authentication; | 
|  | 975 | std::optional<nlohmann::json> ldapService; | 
|  | 976 | std::optional<std::vector<std::string>> serviceAddressList; | 
|  | 977 | std::optional<bool> serviceEnabled; | 
|  | 978 | std::optional<std::vector<std::string>> baseDNList; | 
|  | 979 | std::optional<std::string> userNameAttribute; | 
|  | 980 | std::optional<std::string> groupsAttribute; | 
|  | 981 | std::optional<std::string> userName; | 
|  | 982 | std::optional<std::string> password; | 
|  | 983 | std::optional<std::vector<nlohmann::json>> remoteRoleMapData; | 
|  | 984 |  | 
|  | 985 | if (!json_util::readJson(input, asyncResp->res, "Authentication", | 
|  | 986 | authentication, "LDAPService", ldapService, | 
|  | 987 | "ServiceAddresses", serviceAddressList, | 
|  | 988 | "ServiceEnabled", serviceEnabled, | 
|  | 989 | "RemoteRoleMapping", remoteRoleMapData)) | 
|  | 990 | { | 
|  | 991 | return; | 
|  | 992 | } | 
|  | 993 |  | 
|  | 994 | if (authentication) | 
|  | 995 | { | 
|  | 996 | parseLDAPAuthenticationJson(*authentication, asyncResp, userName, | 
|  | 997 | password); | 
|  | 998 | } | 
|  | 999 | if (ldapService) | 
|  | 1000 | { | 
|  | 1001 | parseLDAPServiceJson(*ldapService, asyncResp, baseDNList, | 
|  | 1002 | userNameAttribute, groupsAttribute); | 
|  | 1003 | } | 
|  | 1004 | if (serviceAddressList) | 
|  | 1005 | { | 
| Ed Tanous | 26f6976 | 2022-01-25 09:49:11 -0800 | [diff] [blame] | 1006 | if (serviceAddressList->empty()) | 
| Ratan Gupta | eb2bbe5 | 2019-04-22 14:27:01 +0530 | [diff] [blame] | 1007 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1008 | messages::propertyValueNotInList(asyncResp->res, "[]", | 
|  | 1009 | "ServiceAddress"); | 
| Ed Tanous | cb13a39 | 2020-07-25 19:02:03 +0000 | [diff] [blame] | 1010 | return; | 
|  | 1011 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1012 | } | 
|  | 1013 | if (baseDNList) | 
|  | 1014 | { | 
| Ed Tanous | 26f6976 | 2022-01-25 09:49:11 -0800 | [diff] [blame] | 1015 | if (baseDNList->empty()) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1016 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1017 | messages::propertyValueNotInList(asyncResp->res, "[]", | 
|  | 1018 | "BaseDistinguishedNames"); | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1019 | return; | 
|  | 1020 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1021 | } | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1022 |  | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1023 | // nothing to update, then return | 
|  | 1024 | if (!userName && !password && !serviceAddressList && !baseDNList && | 
|  | 1025 | !userNameAttribute && !groupsAttribute && !serviceEnabled && | 
|  | 1026 | !remoteRoleMapData) | 
|  | 1027 | { | 
|  | 1028 | return; | 
|  | 1029 | } | 
|  | 1030 |  | 
|  | 1031 | // Get the existing resource first then keep modifying | 
|  | 1032 | // whenever any property gets updated. | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1033 | getLDAPConfigData( | 
|  | 1034 | serverType, | 
|  | 1035 | [asyncResp, userName, password, baseDNList, userNameAttribute, | 
|  | 1036 | groupsAttribute, serviceAddressList, serviceEnabled, dbusObjectPath, | 
|  | 1037 | remoteRoleMapData](bool success, const LDAPConfigData& confData, | 
|  | 1038 | const std::string& serverT) { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1039 | if (!success) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1040 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1041 | messages::internalError(asyncResp->res); | 
|  | 1042 | return; | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1043 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1044 | parseLDAPConfigData(asyncResp->res.jsonValue, confData, serverT); | 
|  | 1045 | if (confData.serviceEnabled) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1046 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1047 | // Disable the service first and update the rest of | 
|  | 1048 | // the properties. | 
|  | 1049 | handleServiceEnablePatch(false, asyncResp, serverT, dbusObjectPath); | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1050 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1051 |  | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1052 | if (serviceAddressList) | 
|  | 1053 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1054 | handleServiceAddressPatch(*serviceAddressList, asyncResp, serverT, | 
|  | 1055 | dbusObjectPath); | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1056 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1057 | if (userName) | 
|  | 1058 | { | 
|  | 1059 | handleUserNamePatch(*userName, asyncResp, serverT, dbusObjectPath); | 
|  | 1060 | } | 
|  | 1061 | if (password) | 
|  | 1062 | { | 
|  | 1063 | handlePasswordPatch(*password, asyncResp, serverT, dbusObjectPath); | 
|  | 1064 | } | 
|  | 1065 |  | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1066 | if (baseDNList) | 
|  | 1067 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1068 | handleBaseDNPatch(*baseDNList, asyncResp, serverT, dbusObjectPath); | 
|  | 1069 | } | 
|  | 1070 | if (userNameAttribute) | 
|  | 1071 | { | 
|  | 1072 | handleUserNameAttrPatch(*userNameAttribute, asyncResp, serverT, | 
|  | 1073 | dbusObjectPath); | 
|  | 1074 | } | 
|  | 1075 | if (groupsAttribute) | 
|  | 1076 | { | 
|  | 1077 | handleGroupNameAttrPatch(*groupsAttribute, asyncResp, serverT, | 
|  | 1078 | dbusObjectPath); | 
|  | 1079 | } | 
|  | 1080 | if (serviceEnabled) | 
|  | 1081 | { | 
|  | 1082 | // if user has given the value as true then enable | 
|  | 1083 | // the service. if user has given false then no-op | 
|  | 1084 | // as service is already stopped. | 
|  | 1085 | if (*serviceEnabled) | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1086 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1087 | handleServiceEnablePatch(*serviceEnabled, asyncResp, serverT, | 
|  | 1088 | dbusObjectPath); | 
| Ratan Gupta | 8a07d28 | 2019-03-16 08:33:47 +0530 | [diff] [blame] | 1089 | } | 
|  | 1090 | } | 
| jayaprakash Mutyala | 9620060 | 2020-04-08 11:09:10 +0000 | [diff] [blame] | 1091 | else | 
|  | 1092 | { | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1093 | // if user has not given the service enabled value | 
|  | 1094 | // then revert it to the same state as it was | 
|  | 1095 | // before. | 
|  | 1096 | handleServiceEnablePatch(confData.serviceEnabled, asyncResp, | 
|  | 1097 | serverT, dbusObjectPath); | 
| jayaprakash Mutyala | 9620060 | 2020-04-08 11:09:10 +0000 | [diff] [blame] | 1098 | } | 
| Ed Tanous | 04ae99e | 2018-09-20 15:54:36 -0700 | [diff] [blame] | 1099 |  | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1100 | if (remoteRoleMapData) | 
|  | 1101 | { | 
|  | 1102 | handleRoleMapPatch(asyncResp, confData.groupRoleList, serverT, | 
|  | 1103 | *remoteRoleMapData); | 
|  | 1104 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1105 | }); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1106 | } | 
|  | 1107 |  | 
|  | 1108 | inline void updateUserProperties(std::shared_ptr<bmcweb::AsyncResp> asyncResp, | 
|  | 1109 | const std::string& username, | 
|  | 1110 | std::optional<std::string> password, | 
|  | 1111 | std::optional<bool> enabled, | 
|  | 1112 | std::optional<std::string> roleId, | 
|  | 1113 | std::optional<bool> locked) | 
|  | 1114 | { | 
| P Dheeraj Srujan Kumar | b477fd4 | 2021-12-16 07:17:51 +0530 | [diff] [blame] | 1115 | sdbusplus::message::object_path tempObjPath(rootUserDbusPath); | 
|  | 1116 | tempObjPath /= username; | 
|  | 1117 | std::string dbusObjectPath(tempObjPath); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1118 |  | 
|  | 1119 | dbus::utility::checkDbusPathExists( | 
|  | 1120 | dbusObjectPath, | 
| Ed Tanous | 1106333 | 2021-09-24 11:55:44 -0700 | [diff] [blame] | 1121 | [dbusObjectPath, username, password(std::move(password)), | 
|  | 1122 | roleId(std::move(roleId)), enabled, locked, | 
|  | 1123 | asyncResp{std::move(asyncResp)}](int rc) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1124 | if (rc <= 0) | 
|  | 1125 | { | 
|  | 1126 | messages::resourceNotFound(asyncResp->res, | 
|  | 1127 | "#ManagerAccount.v1_4_0.ManagerAccount", | 
|  | 1128 | username); | 
|  | 1129 | return; | 
|  | 1130 | } | 
|  | 1131 |  | 
|  | 1132 | if (password) | 
|  | 1133 | { | 
|  | 1134 | int retval = pamUpdatePassword(username, *password); | 
|  | 1135 |  | 
|  | 1136 | if (retval == PAM_USER_UNKNOWN) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1137 | { | 
|  | 1138 | messages::resourceNotFound( | 
|  | 1139 | asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", | 
|  | 1140 | username); | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1141 | } | 
|  | 1142 | else if (retval == PAM_AUTHTOK_ERR) | 
|  | 1143 | { | 
|  | 1144 | // If password is invalid | 
|  | 1145 | messages::propertyValueFormatError(asyncResp->res, *password, | 
|  | 1146 | "Password"); | 
|  | 1147 | BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; | 
|  | 1148 | } | 
|  | 1149 | else if (retval != PAM_SUCCESS) | 
|  | 1150 | { | 
|  | 1151 | messages::internalError(asyncResp->res); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1152 | return; | 
|  | 1153 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1154 | else | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1155 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1156 | messages::success(asyncResp->res); | 
|  | 1157 | } | 
|  | 1158 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1159 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1160 | if (enabled) | 
|  | 1161 | { | 
|  | 1162 | crow::connections::systemBus->async_method_call( | 
|  | 1163 | [asyncResp](const boost::system::error_code ec) { | 
|  | 1164 | if (ec) | 
| Ed Tanous | 04ae99e | 2018-09-20 15:54:36 -0700 | [diff] [blame] | 1165 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1166 | BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; | 
| Ayushi Smriti | 599c71d | 2019-08-23 17:43:18 +0000 | [diff] [blame] | 1167 | messages::internalError(asyncResp->res); | 
| Ed Tanous | 04ae99e | 2018-09-20 15:54:36 -0700 | [diff] [blame] | 1168 | return; | 
|  | 1169 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1170 | messages::success(asyncResp->res); | 
|  | 1171 | return; | 
|  | 1172 | }, | 
|  | 1173 | "xyz.openbmc_project.User.Manager", dbusObjectPath, | 
|  | 1174 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 1175 | "xyz.openbmc_project.User.Attributes", "UserEnabled", | 
|  | 1176 | dbus::utility::DbusVariantType{*enabled}); | 
|  | 1177 | } | 
|  | 1178 |  | 
|  | 1179 | if (roleId) | 
|  | 1180 | { | 
|  | 1181 | std::string priv = getPrivilegeFromRoleId(*roleId); | 
|  | 1182 | if (priv.empty()) | 
|  | 1183 | { | 
|  | 1184 | messages::propertyValueNotInList(asyncResp->res, *roleId, | 
|  | 1185 | "RoleId"); | 
|  | 1186 | return; | 
|  | 1187 | } | 
|  | 1188 | if (priv == "priv-noaccess") | 
|  | 1189 | { | 
|  | 1190 | priv = ""; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1191 | } | 
| Ed Tanous | 04ae99e | 2018-09-20 15:54:36 -0700 | [diff] [blame] | 1192 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1193 | crow::connections::systemBus->async_method_call( | 
|  | 1194 | [asyncResp](const boost::system::error_code ec) { | 
|  | 1195 | if (ec) | 
| Ed Tanous | 04ae99e | 2018-09-20 15:54:36 -0700 | [diff] [blame] | 1196 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1197 | BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; | 
|  | 1198 | messages::internalError(asyncResp->res); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1199 | return; | 
|  | 1200 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1201 | messages::success(asyncResp->res); | 
|  | 1202 | }, | 
|  | 1203 | "xyz.openbmc_project.User.Manager", dbusObjectPath, | 
|  | 1204 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 1205 | "xyz.openbmc_project.User.Attributes", "UserPrivilege", | 
|  | 1206 | dbus::utility::DbusVariantType{priv}); | 
|  | 1207 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1208 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1209 | if (locked) | 
|  | 1210 | { | 
|  | 1211 | // admin can unlock the account which is locked by | 
|  | 1212 | // successive authentication failures but admin should | 
|  | 1213 | // not be allowed to lock an account. | 
|  | 1214 | if (*locked) | 
|  | 1215 | { | 
|  | 1216 | messages::propertyValueNotInList(asyncResp->res, "true", | 
|  | 1217 | "Locked"); | 
|  | 1218 | return; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1219 | } | 
|  | 1220 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1221 | crow::connections::systemBus->async_method_call( | 
|  | 1222 | [asyncResp](const boost::system::error_code ec) { | 
|  | 1223 | if (ec) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1224 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1225 | BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; | 
|  | 1226 | messages::internalError(asyncResp->res); | 
| Ed Tanous | 04ae99e | 2018-09-20 15:54:36 -0700 | [diff] [blame] | 1227 | return; | 
|  | 1228 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1229 | messages::success(asyncResp->res); | 
|  | 1230 | return; | 
|  | 1231 | }, | 
|  | 1232 | "xyz.openbmc_project.User.Manager", dbusObjectPath, | 
|  | 1233 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 1234 | "xyz.openbmc_project.User.Attributes", | 
|  | 1235 | "UserLockedForFailedAttempt", | 
|  | 1236 | dbus::utility::DbusVariantType{*locked}); | 
|  | 1237 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1238 | }); | 
|  | 1239 | } | 
| Ed Tanous | b9b2e0b | 2018-09-13 13:47:50 -0700 | [diff] [blame] | 1240 |  | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1241 | inline void requestAccountServiceRoutes(App& app) | 
| Ed Tanous | b9b2e0b | 2018-09-13 13:47:50 -0700 | [diff] [blame] | 1242 | { | 
| Ed Tanous | b9b2e0b | 2018-09-13 13:47:50 -0700 | [diff] [blame] | 1243 |  | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1244 | BMCWEB_ROUTE(app, "/redfish/v1/AccountService/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame] | 1245 | .privileges(redfish::privileges::getAccountService) | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1246 | .methods(boost::beast::http::verb::get)( | 
|  | 1247 | [&app]( | 
|  | 1248 | const crow::Request& req, | 
|  | 1249 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) -> void { | 
|  | 1250 | if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1251 | { | 
|  | 1252 | return; | 
|  | 1253 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1254 | const persistent_data::AuthConfigMethods& authMethodsConfig = | 
|  | 1255 | persistent_data::SessionStore::getInstance() | 
|  | 1256 | .getAuthMethodsConfig(); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1257 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1258 | nlohmann::json& json = asyncResp->res.jsonValue; | 
|  | 1259 | json["@odata.id"] = "/redfish/v1/AccountService"; | 
|  | 1260 | json["@odata.type"] = "#AccountService." | 
|  | 1261 | "v1_10_0.AccountService"; | 
|  | 1262 | json["Id"] = "AccountService"; | 
|  | 1263 | json["Name"] = "Account Service"; | 
|  | 1264 | json["Description"] = "Account Service"; | 
|  | 1265 | json["ServiceEnabled"] = true; | 
|  | 1266 | json["MaxPasswordLength"] = 20; | 
|  | 1267 | json["Accounts"]["@odata.id"] = | 
|  | 1268 | "/redfish/v1/AccountService/Accounts"; | 
|  | 1269 | json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles"; | 
|  | 1270 | json["Oem"]["OpenBMC"]["@odata.type"] = | 
|  | 1271 | "#OemAccountService.v1_0_0.AccountService"; | 
|  | 1272 | json["Oem"]["OpenBMC"]["@odata.id"] = | 
|  | 1273 | "/redfish/v1/AccountService#/Oem/OpenBMC"; | 
|  | 1274 | json["Oem"]["OpenBMC"]["AuthMethods"]["BasicAuth"] = | 
|  | 1275 | authMethodsConfig.basic; | 
|  | 1276 | json["Oem"]["OpenBMC"]["AuthMethods"]["SessionToken"] = | 
|  | 1277 | authMethodsConfig.sessionToken; | 
|  | 1278 | json["Oem"]["OpenBMC"]["AuthMethods"]["XToken"] = | 
|  | 1279 | authMethodsConfig.xtoken; | 
|  | 1280 | json["Oem"]["OpenBMC"]["AuthMethods"]["Cookie"] = | 
|  | 1281 | authMethodsConfig.cookie; | 
|  | 1282 | json["Oem"]["OpenBMC"]["AuthMethods"]["TLS"] = | 
|  | 1283 | authMethodsConfig.tls; | 
|  | 1284 |  | 
|  | 1285 | // /redfish/v1/AccountService/LDAP/Certificates is something | 
|  | 1286 | // only ConfigureManager can access then only display when the | 
|  | 1287 | // user has permissions ConfigureManager | 
|  | 1288 | Privileges effectiveUserPrivileges = | 
|  | 1289 | redfish::getUserPrivileges(req.userRole); | 
|  | 1290 |  | 
|  | 1291 | if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, | 
|  | 1292 | effectiveUserPrivileges)) | 
|  | 1293 | { | 
|  | 1294 | asyncResp->res | 
|  | 1295 | .jsonValue["LDAP"]["Certificates"]["@odata.id"] = | 
|  | 1296 | "/redfish/v1/AccountService/LDAP/Certificates"; | 
|  | 1297 | } | 
|  | 1298 | crow::connections::systemBus->async_method_call( | 
|  | 1299 | [asyncResp](const boost::system::error_code ec, | 
|  | 1300 | const dbus::utility::DBusPropertiesMap& | 
|  | 1301 | propertiesList) { | 
|  | 1302 | if (ec) | 
|  | 1303 | { | 
|  | 1304 | messages::internalError(asyncResp->res); | 
|  | 1305 | return; | 
|  | 1306 | } | 
|  | 1307 | BMCWEB_LOG_DEBUG << "Got " << propertiesList.size() | 
|  | 1308 | << "properties for AccountService"; | 
|  | 1309 | for (const std::pair<std::string, dbus::utility::DbusVariantType>& | 
|  | 1310 | property : propertiesList) | 
|  | 1311 | { | 
|  | 1312 | if (property.first == "MinPasswordLength") | 
|  | 1313 | { | 
|  | 1314 | const uint8_t* value = | 
|  | 1315 | std::get_if<uint8_t>(&property.second); | 
|  | 1316 | if (value != nullptr) | 
|  | 1317 | { | 
|  | 1318 | asyncResp->res.jsonValue["MinPasswordLength"] = *value; | 
|  | 1319 | } | 
|  | 1320 | } | 
|  | 1321 | if (property.first == "AccountUnlockTimeout") | 
|  | 1322 | { | 
|  | 1323 | const uint32_t* value = | 
|  | 1324 | std::get_if<uint32_t>(&property.second); | 
|  | 1325 | if (value != nullptr) | 
|  | 1326 | { | 
|  | 1327 | asyncResp->res.jsonValue["AccountLockoutDuration"] = | 
|  | 1328 | *value; | 
|  | 1329 | } | 
|  | 1330 | } | 
|  | 1331 | if (property.first == "MaxLoginAttemptBeforeLockout") | 
|  | 1332 | { | 
|  | 1333 | const uint16_t* value = | 
|  | 1334 | std::get_if<uint16_t>(&property.second); | 
|  | 1335 | if (value != nullptr) | 
|  | 1336 | { | 
|  | 1337 | asyncResp->res.jsonValue["AccountLockoutThreshold"] = | 
|  | 1338 | *value; | 
|  | 1339 | } | 
|  | 1340 | } | 
|  | 1341 | } | 
|  | 1342 | }, | 
|  | 1343 | "xyz.openbmc_project.User.Manager", | 
|  | 1344 | "/xyz/openbmc_project/user", | 
|  | 1345 | "org.freedesktop.DBus.Properties", "GetAll", | 
|  | 1346 | "xyz.openbmc_project.User.AccountPolicy"); | 
|  | 1347 |  | 
|  | 1348 | auto callback = | 
|  | 1349 | [asyncResp](bool success, LDAPConfigData& confData, | 
|  | 1350 | const std::string& ldapType) { | 
|  | 1351 | if (!success) | 
|  | 1352 | { | 
|  | 1353 | return; | 
|  | 1354 | } | 
|  | 1355 | parseLDAPConfigData(asyncResp->res.jsonValue, confData, ldapType); | 
|  | 1356 | }; | 
|  | 1357 |  | 
|  | 1358 | getLDAPConfigData("LDAP", callback); | 
|  | 1359 | getLDAPConfigData("ActiveDirectory", callback); | 
|  | 1360 | }); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1361 |  | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1362 | BMCWEB_ROUTE(app, "/redfish/v1/AccountService/") | 
| Gunnar Mills | 1ec43ee | 2022-01-04 15:39:52 -0600 | [diff] [blame] | 1363 | .privileges(redfish::privileges::patchAccountService) | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1364 | .methods(boost::beast::http::verb::patch)( | 
| Ed Tanous | 45ca1b8 | 2022-03-25 13:07:27 -0700 | [diff] [blame] | 1365 | [&app]( | 
|  | 1366 | const crow::Request& req, | 
|  | 1367 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) -> void { | 
|  | 1368 | if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) | 
|  | 1369 | { | 
|  | 1370 | return; | 
|  | 1371 | } | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1372 | std::optional<uint32_t> unlockTimeout; | 
|  | 1373 | std::optional<uint16_t> lockoutThreshold; | 
| Paul Fertser | ef73ad0 | 2022-01-21 19:44:40 +0000 | [diff] [blame] | 1374 | std::optional<uint8_t> minPasswordLength; | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1375 | std::optional<uint16_t> maxPasswordLength; | 
|  | 1376 | std::optional<nlohmann::json> ldapObject; | 
|  | 1377 | std::optional<nlohmann::json> activeDirectoryObject; | 
|  | 1378 | std::optional<nlohmann::json> oemObject; | 
|  | 1379 |  | 
| Willy Tu | 15ed678 | 2021-12-14 11:03:16 -0800 | [diff] [blame] | 1380 | if (!json_util::readJsonPatch( | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1381 | req, asyncResp->res, "AccountLockoutDuration", | 
|  | 1382 | unlockTimeout, "AccountLockoutThreshold", | 
|  | 1383 | lockoutThreshold, "MaxPasswordLength", | 
|  | 1384 | maxPasswordLength, "MinPasswordLength", | 
|  | 1385 | minPasswordLength, "LDAP", ldapObject, | 
|  | 1386 | "ActiveDirectory", activeDirectoryObject, "Oem", | 
|  | 1387 | oemObject)) | 
|  | 1388 | { | 
|  | 1389 | return; | 
|  | 1390 | } | 
|  | 1391 |  | 
|  | 1392 | if (minPasswordLength) | 
|  | 1393 | { | 
| Paul Fertser | ef73ad0 | 2022-01-21 19:44:40 +0000 | [diff] [blame] | 1394 | crow::connections::systemBus->async_method_call( | 
|  | 1395 | [asyncResp](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1396 | if (ec) | 
|  | 1397 | { | 
|  | 1398 | messages::internalError(asyncResp->res); | 
|  | 1399 | return; | 
|  | 1400 | } | 
|  | 1401 | messages::success(asyncResp->res); | 
| Paul Fertser | ef73ad0 | 2022-01-21 19:44:40 +0000 | [diff] [blame] | 1402 | }, | 
|  | 1403 | "xyz.openbmc_project.User.Manager", | 
|  | 1404 | "/xyz/openbmc_project/user", | 
|  | 1405 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 1406 | "xyz.openbmc_project.User.AccountPolicy", | 
|  | 1407 | "MinPasswordLength", | 
|  | 1408 | dbus::utility::DbusVariantType(*minPasswordLength)); | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1409 | } | 
|  | 1410 |  | 
|  | 1411 | if (maxPasswordLength) | 
|  | 1412 | { | 
|  | 1413 | messages::propertyNotWritable(asyncResp->res, | 
|  | 1414 | "MaxPasswordLength"); | 
|  | 1415 | } | 
|  | 1416 |  | 
|  | 1417 | if (ldapObject) | 
|  | 1418 | { | 
|  | 1419 | handleLDAPPatch(*ldapObject, asyncResp, "LDAP"); | 
|  | 1420 | } | 
|  | 1421 |  | 
|  | 1422 | if (std::optional<nlohmann::json> oemOpenBMCObject; | 
|  | 1423 | oemObject && | 
|  | 1424 | json_util::readJson(*oemObject, asyncResp->res, "OpenBMC", | 
|  | 1425 | oemOpenBMCObject)) | 
|  | 1426 | { | 
|  | 1427 | if (std::optional<nlohmann::json> authMethodsObject; | 
|  | 1428 | oemOpenBMCObject && | 
|  | 1429 | json_util::readJson(*oemOpenBMCObject, asyncResp->res, | 
|  | 1430 | "AuthMethods", authMethodsObject)) | 
|  | 1431 | { | 
|  | 1432 | if (authMethodsObject) | 
|  | 1433 | { | 
|  | 1434 | handleAuthMethodsPatch(*authMethodsObject, | 
|  | 1435 | asyncResp); | 
|  | 1436 | } | 
|  | 1437 | } | 
|  | 1438 | } | 
|  | 1439 |  | 
|  | 1440 | if (activeDirectoryObject) | 
|  | 1441 | { | 
|  | 1442 | handleLDAPPatch(*activeDirectoryObject, asyncResp, | 
|  | 1443 | "ActiveDirectory"); | 
|  | 1444 | } | 
|  | 1445 |  | 
|  | 1446 | if (unlockTimeout) | 
|  | 1447 | { | 
|  | 1448 | crow::connections::systemBus->async_method_call( | 
|  | 1449 | [asyncResp](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1450 | if (ec) | 
|  | 1451 | { | 
|  | 1452 | messages::internalError(asyncResp->res); | 
|  | 1453 | return; | 
|  | 1454 | } | 
|  | 1455 | messages::success(asyncResp->res); | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1456 | }, | 
|  | 1457 | "xyz.openbmc_project.User.Manager", | 
|  | 1458 | "/xyz/openbmc_project/user", | 
|  | 1459 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 1460 | "xyz.openbmc_project.User.AccountPolicy", | 
|  | 1461 | "AccountUnlockTimeout", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 1462 | dbus::utility::DbusVariantType(*unlockTimeout)); | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1463 | } | 
|  | 1464 | if (lockoutThreshold) | 
|  | 1465 | { | 
|  | 1466 | crow::connections::systemBus->async_method_call( | 
|  | 1467 | [asyncResp](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1468 | if (ec) | 
|  | 1469 | { | 
|  | 1470 | messages::internalError(asyncResp->res); | 
|  | 1471 | return; | 
|  | 1472 | } | 
|  | 1473 | messages::success(asyncResp->res); | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1474 | }, | 
|  | 1475 | "xyz.openbmc_project.User.Manager", | 
|  | 1476 | "/xyz/openbmc_project/user", | 
|  | 1477 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 1478 | "xyz.openbmc_project.User.AccountPolicy", | 
|  | 1479 | "MaxLoginAttemptBeforeLockout", | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 1480 | dbus::utility::DbusVariantType(*lockoutThreshold)); | 
| Ed Tanous | f5ffd80 | 2021-07-19 10:55:33 -0700 | [diff] [blame] | 1481 | } | 
|  | 1482 | }); | 
|  | 1483 |  | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1484 | BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame] | 1485 | .privileges(redfish::privileges::getManagerAccountCollection) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1486 | .methods(boost::beast::http::verb::get)( | 
| Ed Tanous | 45ca1b8 | 2022-03-25 13:07:27 -0700 | [diff] [blame] | 1487 | [&app]( | 
|  | 1488 | const crow::Request& req, | 
|  | 1489 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) -> void { | 
|  | 1490 | if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) | 
|  | 1491 | { | 
|  | 1492 | return; | 
|  | 1493 | } | 
| Ed Tanous | 1476687 | 2022-03-15 10:44:42 -0700 | [diff] [blame] | 1494 |  | 
|  | 1495 | asyncResp->res.jsonValue["@odata.id"] = | 
|  | 1496 | "/redfish/v1/AccountService/Accounts"; | 
|  | 1497 | asyncResp->res.jsonValue["@odata.type"] = | 
|  | 1498 | "#ManagerAccountCollection." | 
|  | 1499 | "ManagerAccountCollection"; | 
|  | 1500 | asyncResp->res.jsonValue["Name"] = "Accounts Collection"; | 
|  | 1501 | asyncResp->res.jsonValue["Description"] = "BMC User Accounts"; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1502 |  | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1503 | Privileges effectiveUserPrivileges = | 
|  | 1504 | redfish::getUserPrivileges(req.userRole); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1505 |  | 
| JunLin Chen | f5e29f3 | 2021-12-08 16:47:04 +0800 | [diff] [blame] | 1506 | std::string thisUser; | 
|  | 1507 | if (req.session) | 
|  | 1508 | { | 
|  | 1509 | thisUser = req.session->username; | 
|  | 1510 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1511 | crow::connections::systemBus->async_method_call( | 
| Ed Tanous | cef1ddf | 2021-06-03 13:45:10 -0700 | [diff] [blame] | 1512 | [asyncResp, thisUser, effectiveUserPrivileges]( | 
|  | 1513 | const boost::system::error_code ec, | 
| Ed Tanous | 711ac7a | 2021-12-20 09:34:41 -0800 | [diff] [blame] | 1514 | const dbus::utility::ManagedObjectType& users) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1515 | if (ec) | 
|  | 1516 | { | 
|  | 1517 | messages::internalError(asyncResp->res); | 
|  | 1518 | return; | 
|  | 1519 | } | 
| Ed Tanous | 9712f8a | 2018-09-21 13:38:49 -0700 | [diff] [blame] | 1520 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1521 | bool userCanSeeAllAccounts = | 
|  | 1522 | effectiveUserPrivileges.isSupersetOf({"ConfigureUsers"}); | 
| Ed Tanous | cef1ddf | 2021-06-03 13:45:10 -0700 | [diff] [blame] | 1523 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1524 | bool userCanSeeSelf = | 
|  | 1525 | effectiveUserPrivileges.isSupersetOf({"ConfigureSelf"}); | 
| Ed Tanous | cef1ddf | 2021-06-03 13:45:10 -0700 | [diff] [blame] | 1526 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1527 | nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"]; | 
|  | 1528 | memberArray = nlohmann::json::array(); | 
| Ratan Gupta | 24c8542 | 2019-01-30 19:41:24 +0530 | [diff] [blame] | 1529 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1530 | for (const auto& userpath : users) | 
|  | 1531 | { | 
|  | 1532 | std::string user = userpath.first.filename(); | 
|  | 1533 | if (user.empty()) | 
|  | 1534 | { | 
|  | 1535 | messages::internalError(asyncResp->res); | 
|  | 1536 | BMCWEB_LOG_ERROR << "Invalid firmware ID"; | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1537 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1538 | return; | 
|  | 1539 | } | 
| Ratan Gupta | 24c8542 | 2019-01-30 19:41:24 +0530 | [diff] [blame] | 1540 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1541 | // As clarified by Redfish here: | 
|  | 1542 | // https://redfishforum.com/thread/281/manageraccountcollection-change-allows-account-enumeration | 
|  | 1543 | // Users without ConfigureUsers, only see their own | 
|  | 1544 | // account. Users with ConfigureUsers, see all | 
|  | 1545 | // accounts. | 
|  | 1546 | if (userCanSeeAllAccounts || | 
|  | 1547 | (thisUser == user && userCanSeeSelf)) | 
|  | 1548 | { | 
|  | 1549 | nlohmann::json::object_t member; | 
|  | 1550 | member["@odata.id"] = | 
|  | 1551 | "/redfish/v1/AccountService/Accounts/" + user; | 
|  | 1552 | memberArray.push_back(std::move(member)); | 
|  | 1553 | } | 
|  | 1554 | } | 
|  | 1555 | asyncResp->res.jsonValue["Members@odata.count"] = | 
|  | 1556 | memberArray.size(); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1557 | }, | 
|  | 1558 | "xyz.openbmc_project.User.Manager", | 
|  | 1559 | "/xyz/openbmc_project/user", | 
|  | 1560 | "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); | 
| Ratan Gupta | 24c8542 | 2019-01-30 19:41:24 +0530 | [diff] [blame] | 1561 | }); | 
| Ed Tanous | 06e086d | 2018-09-19 17:19:52 -0700 | [diff] [blame] | 1562 |  | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1563 | BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame] | 1564 | .privileges(redfish::privileges::postManagerAccountCollection) | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1565 | .methods(boost::beast::http::verb::post)( | 
|  | 1566 | [&app]( | 
|  | 1567 | const crow::Request& req, | 
|  | 1568 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) -> void { | 
|  | 1569 | if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) | 
|  | 1570 | { | 
|  | 1571 | return; | 
|  | 1572 | } | 
|  | 1573 | std::string username; | 
|  | 1574 | std::string password; | 
|  | 1575 | std::optional<std::string> roleId("User"); | 
|  | 1576 | std::optional<bool> enabled = true; | 
|  | 1577 | if (!json_util::readJsonPatch( | 
|  | 1578 | req, asyncResp->res, "UserName", username, "Password", | 
|  | 1579 | password, "RoleId", roleId, "Enabled", enabled)) | 
|  | 1580 | { | 
|  | 1581 | return; | 
|  | 1582 | } | 
|  | 1583 |  | 
|  | 1584 | std::string priv = getPrivilegeFromRoleId(*roleId); | 
|  | 1585 | if (priv.empty()) | 
|  | 1586 | { | 
|  | 1587 | messages::propertyValueNotInList(asyncResp->res, *roleId, | 
|  | 1588 | "RoleId"); | 
|  | 1589 | return; | 
|  | 1590 | } | 
|  | 1591 | // TODO: Following override will be reverted once support in | 
|  | 1592 | // phosphor-user-manager is added. In order to avoid dependency | 
|  | 1593 | // issues, this is added in bmcweb, which will removed, once | 
|  | 1594 | // phosphor-user-manager supports priv-noaccess. | 
|  | 1595 | if (priv == "priv-noaccess") | 
|  | 1596 | { | 
|  | 1597 | roleId = ""; | 
|  | 1598 | } | 
|  | 1599 | else | 
|  | 1600 | { | 
|  | 1601 | roleId = priv; | 
|  | 1602 | } | 
|  | 1603 |  | 
|  | 1604 | // Reading AllGroups property | 
|  | 1605 | sdbusplus::asio::getProperty<std::vector<std::string>>( | 
|  | 1606 | *crow::connections::systemBus, | 
|  | 1607 | "xyz.openbmc_project.User.Manager", | 
|  | 1608 | "/xyz/openbmc_project/user", | 
|  | 1609 | "xyz.openbmc_project.User.Manager", "AllGroups", | 
|  | 1610 | [asyncResp, username, password{std::move(password)}, roleId, | 
|  | 1611 | enabled](const boost::system::error_code ec, | 
|  | 1612 | const std::vector<std::string>& allGroupsList) { | 
|  | 1613 | if (ec) | 
| Ed Tanous | 45ca1b8 | 2022-03-25 13:07:27 -0700 | [diff] [blame] | 1614 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1615 | BMCWEB_LOG_DEBUG << "ERROR with async_method_call"; | 
|  | 1616 | messages::internalError(asyncResp->res); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1617 | return; | 
|  | 1618 | } | 
| Ed Tanous | 06e086d | 2018-09-19 17:19:52 -0700 | [diff] [blame] | 1619 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1620 | if (allGroupsList.empty()) | 
| JunLin Chen | 031514f | 2021-12-14 14:33:49 +0800 | [diff] [blame] | 1621 | { | 
|  | 1622 | messages::internalError(asyncResp->res); | 
|  | 1623 | return; | 
|  | 1624 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1625 |  | 
|  | 1626 | crow::connections::systemBus->async_method_call( | 
|  | 1627 | [asyncResp, username, | 
|  | 1628 | password](const boost::system::error_code ec2, | 
|  | 1629 | sdbusplus::message::message& m) { | 
|  | 1630 | if (ec2) | 
| Ed Tanous | 06e086d | 2018-09-19 17:19:52 -0700 | [diff] [blame] | 1631 | { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1632 | userErrorMessageHandler(m.get_error(), asyncResp, username, | 
|  | 1633 | ""); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1634 | return; | 
|  | 1635 | } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1636 |  | 
|  | 1637 | if (pamUpdatePassword(username, password) != PAM_SUCCESS) | 
|  | 1638 | { | 
|  | 1639 | // At this point we have a user that's been | 
|  | 1640 | // created, but the password set | 
|  | 1641 | // failed.Something is wrong, so delete the user | 
|  | 1642 | // that we've already created | 
|  | 1643 | sdbusplus::message::object_path tempObjPath( | 
|  | 1644 | rootUserDbusPath); | 
|  | 1645 | tempObjPath /= username; | 
|  | 1646 | const std::string userPath(tempObjPath); | 
|  | 1647 |  | 
|  | 1648 | crow::connections::systemBus->async_method_call( | 
|  | 1649 | [asyncResp, | 
|  | 1650 | password](const boost::system::error_code ec3) { | 
|  | 1651 | if (ec3) | 
|  | 1652 | { | 
|  | 1653 | messages::internalError(asyncResp->res); | 
|  | 1654 | return; | 
|  | 1655 | } | 
|  | 1656 |  | 
|  | 1657 | // If password is invalid | 
|  | 1658 | messages::propertyValueFormatError( | 
|  | 1659 | asyncResp->res, password, "Password"); | 
|  | 1660 | }, | 
|  | 1661 | "xyz.openbmc_project.User.Manager", userPath, | 
|  | 1662 | "xyz.openbmc_project.Object.Delete", "Delete"); | 
|  | 1663 |  | 
|  | 1664 | BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; | 
|  | 1665 | return; | 
|  | 1666 | } | 
|  | 1667 |  | 
|  | 1668 | messages::created(asyncResp->res); | 
|  | 1669 | asyncResp->res.addHeader( | 
|  | 1670 | "Location", | 
|  | 1671 | "/redfish/v1/AccountService/Accounts/" + username); | 
|  | 1672 | }, | 
|  | 1673 | "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", | 
|  | 1674 | "xyz.openbmc_project.User.Manager", "CreateUser", username, | 
|  | 1675 | allGroupsList, *roleId, *enabled); | 
|  | 1676 | }); | 
|  | 1677 | }); | 
|  | 1678 |  | 
|  | 1679 | BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/") | 
|  | 1680 | .privileges(redfish::privileges::getManagerAccount) | 
|  | 1681 | .methods(boost::beast::http::verb::get)( | 
|  | 1682 | [&app]([[maybe_unused]] const crow::Request& req, | 
|  | 1683 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 1684 | const std::string& accountName) -> void { | 
|  | 1685 | if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) | 
|  | 1686 | { | 
|  | 1687 | return; | 
|  | 1688 | } | 
|  | 1689 | #ifdef BMCWEB_INSECURE_DISABLE_AUTHX | 
|  | 1690 | // If authentication is disabled, there are no user accounts | 
|  | 1691 | messages::resourceNotFound( | 
|  | 1692 | asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", | 
|  | 1693 | accountName); | 
|  | 1694 | return; | 
|  | 1695 |  | 
|  | 1696 | #endif // BMCWEB_INSECURE_DISABLE_AUTHX | 
|  | 1697 | if (req.session == nullptr) | 
|  | 1698 | { | 
|  | 1699 | messages::internalError(asyncResp->res); | 
|  | 1700 | return; | 
|  | 1701 | } | 
|  | 1702 | if (req.session->username != accountName) | 
|  | 1703 | { | 
|  | 1704 | // At this point we've determined that the user is trying to | 
|  | 1705 | // modify a user that isn't them.  We need to verify that | 
|  | 1706 | // they have permissions to modify other users, so re-run | 
|  | 1707 | // the auth check with the same permissions, minus | 
|  | 1708 | // ConfigureSelf. | 
|  | 1709 | Privileges effectiveUserPrivileges = | 
|  | 1710 | redfish::getUserPrivileges(req.userRole); | 
|  | 1711 | Privileges requiredPermissionsToChangeNonSelf = { | 
|  | 1712 | "ConfigureUsers", "ConfigureManager"}; | 
|  | 1713 | if (!effectiveUserPrivileges.isSupersetOf( | 
|  | 1714 | requiredPermissionsToChangeNonSelf)) | 
|  | 1715 | { | 
|  | 1716 | BMCWEB_LOG_DEBUG << "GET Account denied access"; | 
|  | 1717 | messages::insufficientPrivilege(asyncResp->res); | 
|  | 1718 | return; | 
|  | 1719 | } | 
|  | 1720 | } | 
|  | 1721 |  | 
|  | 1722 | crow::connections::systemBus->async_method_call( | 
|  | 1723 | [asyncResp, accountName]( | 
|  | 1724 | const boost::system::error_code ec, | 
|  | 1725 | const dbus::utility::ManagedObjectType& users) { | 
|  | 1726 | if (ec) | 
|  | 1727 | { | 
|  | 1728 | messages::internalError(asyncResp->res); | 
|  | 1729 | return; | 
|  | 1730 | } | 
|  | 1731 | const auto userIt = std::find_if( | 
|  | 1732 | users.begin(), users.end(), | 
|  | 1733 | [accountName]( | 
|  | 1734 | const std::pair<sdbusplus::message::object_path, | 
|  | 1735 | dbus::utility::DBusInteracesMap>& user) { | 
|  | 1736 | return accountName == user.first.filename(); | 
|  | 1737 | }); | 
|  | 1738 |  | 
|  | 1739 | if (userIt == users.end()) | 
|  | 1740 | { | 
|  | 1741 | messages::resourceNotFound(asyncResp->res, "ManagerAccount", | 
|  | 1742 | accountName); | 
|  | 1743 | return; | 
|  | 1744 | } | 
|  | 1745 |  | 
|  | 1746 | asyncResp->res.jsonValue["@odata.type"] = | 
|  | 1747 | "#ManagerAccount.v1_4_0.ManagerAccount"; | 
|  | 1748 | asyncResp->res.jsonValue["Name"] = "User Account"; | 
|  | 1749 | asyncResp->res.jsonValue["Description"] = "User Account"; | 
|  | 1750 | asyncResp->res.jsonValue["Password"] = nullptr; | 
|  | 1751 | asyncResp->res.jsonValue["AccountTypes"] = {"Redfish"}; | 
|  | 1752 |  | 
|  | 1753 | for (const auto& interface : userIt->second) | 
|  | 1754 | { | 
|  | 1755 | if (interface.first == "xyz.openbmc_project.User.Attributes") | 
|  | 1756 | { | 
|  | 1757 | for (const auto& property : interface.second) | 
|  | 1758 | { | 
|  | 1759 | if (property.first == "UserEnabled") | 
|  | 1760 | { | 
|  | 1761 | const bool* userEnabled = | 
|  | 1762 | std::get_if<bool>(&property.second); | 
|  | 1763 | if (userEnabled == nullptr) | 
|  | 1764 | { | 
|  | 1765 | BMCWEB_LOG_ERROR << "UserEnabled wasn't a bool"; | 
|  | 1766 | messages::internalError(asyncResp->res); | 
|  | 1767 | return; | 
|  | 1768 | } | 
|  | 1769 | asyncResp->res.jsonValue["Enabled"] = *userEnabled; | 
|  | 1770 | } | 
|  | 1771 | else if (property.first == "UserLockedForFailedAttempt") | 
|  | 1772 | { | 
|  | 1773 | const bool* userLocked = | 
|  | 1774 | std::get_if<bool>(&property.second); | 
|  | 1775 | if (userLocked == nullptr) | 
|  | 1776 | { | 
|  | 1777 | BMCWEB_LOG_ERROR << "UserLockedForF" | 
|  | 1778 | "ailedAttempt " | 
|  | 1779 | "wasn't a bool"; | 
|  | 1780 | messages::internalError(asyncResp->res); | 
|  | 1781 | return; | 
|  | 1782 | } | 
|  | 1783 | asyncResp->res.jsonValue["Locked"] = *userLocked; | 
|  | 1784 | asyncResp->res | 
|  | 1785 | .jsonValue["Locked@Redfish.AllowableValues"] = { | 
|  | 1786 | "false"}; // can only unlock accounts | 
|  | 1787 | } | 
|  | 1788 | else if (property.first == "UserPrivilege") | 
|  | 1789 | { | 
|  | 1790 | const std::string* userPrivPtr = | 
|  | 1791 | std::get_if<std::string>(&property.second); | 
|  | 1792 | if (userPrivPtr == nullptr) | 
|  | 1793 | { | 
|  | 1794 | BMCWEB_LOG_ERROR << "UserPrivilege wasn't a " | 
|  | 1795 | "string"; | 
|  | 1796 | messages::internalError(asyncResp->res); | 
|  | 1797 | return; | 
|  | 1798 | } | 
|  | 1799 | std::string role = | 
|  | 1800 | getRoleIdFromPrivilege(*userPrivPtr); | 
|  | 1801 | if (role.empty()) | 
|  | 1802 | { | 
|  | 1803 | BMCWEB_LOG_ERROR << "Invalid user role"; | 
|  | 1804 | messages::internalError(asyncResp->res); | 
|  | 1805 | return; | 
|  | 1806 | } | 
|  | 1807 | asyncResp->res.jsonValue["RoleId"] = role; | 
|  | 1808 |  | 
|  | 1809 | nlohmann::json& roleEntry = | 
|  | 1810 | asyncResp->res.jsonValue["Links"]["Role"]; | 
|  | 1811 | roleEntry["@odata.id"] = | 
|  | 1812 | "/redfish/v1/AccountService/Roles/" + role; | 
|  | 1813 | } | 
|  | 1814 | else if (property.first == "UserPasswordExpired") | 
|  | 1815 | { | 
|  | 1816 | const bool* userPasswordExpired = | 
|  | 1817 | std::get_if<bool>(&property.second); | 
|  | 1818 | if (userPasswordExpired == nullptr) | 
|  | 1819 | { | 
|  | 1820 | BMCWEB_LOG_ERROR | 
|  | 1821 | << "UserPasswordExpired wasn't a bool"; | 
|  | 1822 | messages::internalError(asyncResp->res); | 
|  | 1823 | return; | 
|  | 1824 | } | 
|  | 1825 | asyncResp->res.jsonValue["PasswordChangeRequired"] = | 
|  | 1826 | *userPasswordExpired; | 
|  | 1827 | } | 
|  | 1828 | } | 
|  | 1829 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1830 | } | 
|  | 1831 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1832 | asyncResp->res.jsonValue["@odata.id"] = | 
|  | 1833 | "/redfish/v1/AccountService/Accounts/" + accountName; | 
|  | 1834 | asyncResp->res.jsonValue["Id"] = accountName; | 
|  | 1835 | asyncResp->res.jsonValue["UserName"] = accountName; | 
|  | 1836 | }, | 
|  | 1837 | "xyz.openbmc_project.User.Manager", | 
|  | 1838 | "/xyz/openbmc_project/user", | 
|  | 1839 | "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); | 
|  | 1840 | }); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1841 |  | 
|  | 1842 | BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame] | 1843 | // TODO this privilege should be using the generated endpoints, but | 
|  | 1844 | // because of the special handling of ConfigureSelf, it's not able to | 
|  | 1845 | // yet | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1846 | .privileges({{"ConfigureUsers"}, {"ConfigureSelf"}}) | 
|  | 1847 | .methods(boost::beast::http::verb::patch)( | 
| Ed Tanous | 45ca1b8 | 2022-03-25 13:07:27 -0700 | [diff] [blame] | 1848 | [&app](const crow::Request& req, | 
|  | 1849 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 1850 | const std::string& username) -> void { | 
|  | 1851 | if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) | 
|  | 1852 | { | 
|  | 1853 | return; | 
|  | 1854 | } | 
| Nan Zhou | a43ea82 | 2022-05-27 00:42:44 +0000 | [diff] [blame] | 1855 | #ifdef BMCWEB_INSECURE_DISABLE_AUTHX | 
| JunLin Chen | 031514f | 2021-12-14 14:33:49 +0800 | [diff] [blame] | 1856 | // If authentication is disabled, there are no user accounts | 
|  | 1857 | messages::resourceNotFound( | 
|  | 1858 | asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", | 
|  | 1859 | username); | 
|  | 1860 | return; | 
|  | 1861 |  | 
| Nan Zhou | a43ea82 | 2022-05-27 00:42:44 +0000 | [diff] [blame] | 1862 | #endif // BMCWEB_INSECURE_DISABLE_AUTHX | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1863 | std::optional<std::string> newUserName; | 
|  | 1864 | std::optional<std::string> password; | 
|  | 1865 | std::optional<bool> enabled; | 
|  | 1866 | std::optional<std::string> roleId; | 
|  | 1867 | std::optional<bool> locked; | 
| Ed Tanous | e9cc517 | 2021-11-03 14:13:19 +0800 | [diff] [blame] | 1868 |  | 
| JunLin Chen | 031514f | 2021-12-14 14:33:49 +0800 | [diff] [blame] | 1869 | if (req.session == nullptr) | 
|  | 1870 | { | 
|  | 1871 | messages::internalError(asyncResp->res); | 
|  | 1872 | return; | 
|  | 1873 | } | 
|  | 1874 |  | 
| Ed Tanous | e9cc517 | 2021-11-03 14:13:19 +0800 | [diff] [blame] | 1875 | Privileges effectiveUserPrivileges = | 
|  | 1876 | redfish::getUserPrivileges(req.userRole); | 
|  | 1877 | Privileges configureUsers = {"ConfigureUsers"}; | 
|  | 1878 | bool userHasConfigureUsers = | 
|  | 1879 | effectiveUserPrivileges.isSupersetOf(configureUsers); | 
|  | 1880 | if (userHasConfigureUsers) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1881 | { | 
| Ed Tanous | e9cc517 | 2021-11-03 14:13:19 +0800 | [diff] [blame] | 1882 | // Users with ConfigureUsers can modify for all users | 
| Willy Tu | 15ed678 | 2021-12-14 11:03:16 -0800 | [diff] [blame] | 1883 | if (!json_util::readJsonPatch( | 
|  | 1884 | req, asyncResp->res, "UserName", newUserName, | 
|  | 1885 | "Password", password, "RoleId", roleId, "Enabled", | 
|  | 1886 | enabled, "Locked", locked)) | 
| Ed Tanous | e9cc517 | 2021-11-03 14:13:19 +0800 | [diff] [blame] | 1887 | { | 
|  | 1888 | return; | 
|  | 1889 | } | 
| Ed Tanous | 06e086d | 2018-09-19 17:19:52 -0700 | [diff] [blame] | 1890 | } | 
| Ed Tanous | e9cc517 | 2021-11-03 14:13:19 +0800 | [diff] [blame] | 1891 | else | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1892 | { | 
| Ed Tanous | e9cc517 | 2021-11-03 14:13:19 +0800 | [diff] [blame] | 1893 | // ConfigureSelf accounts can only modify their own account | 
|  | 1894 | if (username != req.session->username) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1895 | { | 
|  | 1896 | messages::insufficientPrivilege(asyncResp->res); | 
|  | 1897 | return; | 
|  | 1898 | } | 
| JunLin Chen | 031514f | 2021-12-14 14:33:49 +0800 | [diff] [blame] | 1899 |  | 
| Ed Tanous | e9cc517 | 2021-11-03 14:13:19 +0800 | [diff] [blame] | 1900 | // ConfigureSelf accounts can only modify their password | 
| Willy Tu | 15ed678 | 2021-12-14 11:03:16 -0800 | [diff] [blame] | 1901 | if (!json_util::readJsonPatch(req, asyncResp->res, | 
|  | 1902 | "Password", password)) | 
| Ed Tanous | e9cc517 | 2021-11-03 14:13:19 +0800 | [diff] [blame] | 1903 | { | 
|  | 1904 | return; | 
|  | 1905 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1906 | } | 
|  | 1907 |  | 
|  | 1908 | // if user name is not provided in the patch method or if it | 
|  | 1909 | // matches the user name in the URI, then we are treating it as | 
|  | 1910 | // updating user properties other then username. If username | 
|  | 1911 | // provided doesn't match the URI, then we are treating this as | 
|  | 1912 | // user rename request. | 
|  | 1913 | if (!newUserName || (newUserName.value() == username)) | 
|  | 1914 | { | 
|  | 1915 | updateUserProperties(asyncResp, username, password, enabled, | 
|  | 1916 | roleId, locked); | 
|  | 1917 | return; | 
|  | 1918 | } | 
|  | 1919 | crow::connections::systemBus->async_method_call( | 
|  | 1920 | [asyncResp, username, password(std::move(password)), | 
|  | 1921 | roleId(std::move(roleId)), enabled, | 
|  | 1922 | newUser{std::string(*newUserName)}, | 
|  | 1923 | locked](const boost::system::error_code ec, | 
|  | 1924 | sdbusplus::message::message& m) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1925 | if (ec) | 
|  | 1926 | { | 
|  | 1927 | userErrorMessageHandler(m.get_error(), asyncResp, newUser, | 
|  | 1928 | username); | 
|  | 1929 | return; | 
|  | 1930 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1931 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1932 | updateUserProperties(asyncResp, newUser, password, enabled, roleId, | 
|  | 1933 | locked); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1934 | }, | 
|  | 1935 | "xyz.openbmc_project.User.Manager", | 
|  | 1936 | "/xyz/openbmc_project/user", | 
|  | 1937 | "xyz.openbmc_project.User.Manager", "RenameUser", username, | 
|  | 1938 | *newUserName); | 
|  | 1939 | }); | 
|  | 1940 |  | 
|  | 1941 | BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame] | 1942 | .privileges(redfish::privileges::deleteManagerAccount) | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1943 | .methods(boost::beast::http::verb::delete_)( | 
| Ed Tanous | 45ca1b8 | 2022-03-25 13:07:27 -0700 | [diff] [blame] | 1944 | [&app](const crow::Request& req, | 
|  | 1945 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 1946 | const std::string& username) -> void { | 
|  | 1947 | if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) | 
|  | 1948 | { | 
|  | 1949 | return; | 
|  | 1950 | } | 
| JunLin Chen | 031514f | 2021-12-14 14:33:49 +0800 | [diff] [blame] | 1951 |  | 
| Nan Zhou | a43ea82 | 2022-05-27 00:42:44 +0000 | [diff] [blame] | 1952 | #ifdef BMCWEB_INSECURE_DISABLE_AUTHX | 
| JunLin Chen | 031514f | 2021-12-14 14:33:49 +0800 | [diff] [blame] | 1953 | // If authentication is disabled, there are no user accounts | 
|  | 1954 | messages::resourceNotFound( | 
|  | 1955 | asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", | 
|  | 1956 | username); | 
|  | 1957 | return; | 
|  | 1958 |  | 
| Nan Zhou | a43ea82 | 2022-05-27 00:42:44 +0000 | [diff] [blame] | 1959 | #endif // BMCWEB_INSECURE_DISABLE_AUTHX | 
| P Dheeraj Srujan Kumar | b477fd4 | 2021-12-16 07:17:51 +0530 | [diff] [blame] | 1960 | sdbusplus::message::object_path tempObjPath(rootUserDbusPath); | 
|  | 1961 | tempObjPath /= username; | 
|  | 1962 | const std::string userPath(tempObjPath); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1963 |  | 
|  | 1964 | crow::connections::systemBus->async_method_call( | 
|  | 1965 | [asyncResp, username](const boost::system::error_code ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1966 | if (ec) | 
|  | 1967 | { | 
|  | 1968 | messages::resourceNotFound( | 
|  | 1969 | asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", | 
|  | 1970 | username); | 
|  | 1971 | return; | 
|  | 1972 | } | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1973 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame^] | 1974 | messages::accountRemoved(asyncResp->res); | 
| Ed Tanous | 6c51eab | 2021-06-03 12:30:29 -0700 | [diff] [blame] | 1975 | }, | 
|  | 1976 | "xyz.openbmc_project.User.Manager", userPath, | 
|  | 1977 | "xyz.openbmc_project.Object.Delete", "Delete"); | 
|  | 1978 | }); | 
|  | 1979 | } | 
| Lewanczyk, Dawid | 88d16c9 | 2018-02-02 14:51:09 +0100 | [diff] [blame] | 1980 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1981 | } // namespace redfish |