ldap_comunication.cpp
1 /** 2 * @file ldap_comunication.cpp 3 * @author Rene Ceska xceska06 (xceska06@stud.fit.vutbr.cz) 4 * @date 2023-11-19 5 */ 6 #include "inc/ldap_comunication.h" 7 #define DEBUG 8 9 BerObject *InitSearchResultEntry(BerObject *searchRequest, 10 std::vector<unsigned char> LDAPDN) { 11 std::vector<unsigned char> DNprefix = {'u', 'i', 'd', '='}; 12 DNprefix.insert(DNprefix.end(), LDAPDN.begin(), LDAPDN.end()); 13 BerSequenceObject *envelope = new BerSequenceObject(); 14 envelope->objects.push_back(new BerIntObject( 15 static_cast<BerIntObject *>( 16 static_cast<BerSequenceObject *>(searchRequest)->objects[0]) 17 ->getValue())); // copy message ID 18 BerSequenceObject *PartialAttributeList = 19 new BerSequenceObject(BER_SEARCH_RESULT_ENTRY_C); 20 envelope->objects.push_back(PartialAttributeList); 21 PartialAttributeList->objects.push_back(new BerStringObject(DNprefix)); 22 PartialAttributeList->objects.push_back(new BerSequenceObject()); 23 return envelope; 24 } 25 26 int AddToSearchResultEntry(BerObject *envelope, 27 std::vector<unsigned char> &attributeDescription, 28 std::vector<unsigned char> &attributeValue) { 29 BerSequenceObject *SearchResultEntry = 30 (BerSequenceObject *)(((BerSequenceObject *)envelope)->objects[1]); 31 BerSequenceObject *PartialAttributeList = 32 (BerSequenceObject *)(((BerSequenceObject *)SearchResultEntry) 33 ->objects[1]); 34 BerSequenceObject *attributeValueSequence = new BerSequenceObject(); 35 attributeValueSequence->objects.push_back( 36 new BerStringObject(attributeDescription)); 37 BerSetObject *attributeValueSet = new BerSetObject(); 38 attributeValueSet->objects.push_back(new BerStringObject(attributeValue)); 39 attributeValueSequence->objects.push_back(attributeValueSet); 40 41 PartialAttributeList->objects.push_back(attributeValueSequence); 42 return 0; 43 } 44 45 BerObject *CreateBindResponse(BerObject *bindRequest, int resultCode) { 46 BerSequenceObject *envelope = new BerSequenceObject(); 47 envelope->objects.push_back(((BerSequenceObject *)(bindRequest))->objects[0]); 48 BerSequenceObject *bindResponseSequence = 49 new BerSequenceObject(BER_BIND_RESPONSE_C); 50 envelope->objects.push_back(bindResponseSequence); 51 bindResponseSequence->objects.push_back(new BerEnumObject(resultCode)); 52 bindResponseSequence->objects.push_back(new BerStringObject()); 53 bindResponseSequence->objects.push_back(new BerStringObject()); 54 return envelope; 55 } 56 57 int sendSearchResultDone(BerSequenceObject *searchRequest, int comm_socket, 58 unsigned int result_code) { 59 BerSequenceObject *envelope = new BerSequenceObject(); 60 envelope->objects.push_back( 61 new BerIntObject(dynamic_cast<BerIntObject *>(searchRequest->objects[0]) 62 ->getValue())); // copy message ID 63 BerSequenceObject *searchResultDoneSequence = 64 new BerSequenceObject(BER_SEARCH_RESULT_DONE_C); 65 envelope->objects.push_back(searchResultDoneSequence); 66 searchResultDoneSequence->objects.push_back(new BerEnumObject(result_code)); 67 searchResultDoneSequence->objects.push_back(new BerStringObject("")); 68 searchResultDoneSequence->objects.push_back(new BerStringObject("")); 69 70 std::vector<unsigned char> envelopeBer = envelope->getBerRepresentation(); 71 send(comm_socket, &envelopeBer[0], envelopeBer.size(), MSG_NOSIGNAL); 72 delete envelope; 73 return 0; 74 } 75 76 int checkSearchRequest(BerObject *searchRequest) { 77 78 // use dynamic casts 79 BerSequenceObject *envelope = 80 dynamic_cast<BerSequenceObject *>(searchRequest); 81 if (envelope == nullptr) { 82 return -2; 83 } 84 // check count of object inside envelope 85 if (envelope->objects.size() != 2) { 86 return -1; 87 } 88 BerIntObject *messageID = dynamic_cast<BerIntObject *>(envelope->objects[0]); 89 if (messageID == nullptr) { 90 return -2; 91 } 92 93 BerSequenceObject *searchRequestSequence = 94 dynamic_cast<BerSequenceObject *>(envelope->objects[1]); 95 if (searchRequestSequence == nullptr) { 96 return -1; 97 } 98 // check count of object inside searchRequestSequence 99 if (searchRequestSequence->objects.size() != 8) { 100 return -1; 101 } 102 BerStringObject *baseObject = 103 dynamic_cast<BerStringObject *>(searchRequestSequence->objects[0]); 104 BerEnumObject *scope = 105 dynamic_cast<BerEnumObject *>(searchRequestSequence->objects[1]); 106 BerEnumObject *derefAliases = 107 dynamic_cast<BerEnumObject *>(searchRequestSequence->objects[2]); 108 BerIntObject *sizeLimit = 109 dynamic_cast<BerIntObject *>(searchRequestSequence->objects[3]); 110 BerIntObject *timeLimit = 111 dynamic_cast<BerIntObject *>(searchRequestSequence->objects[4]); 112 BerBoolObject *typesOnly = 113 dynamic_cast<BerBoolObject *>(searchRequestSequence->objects[5]); 114 BerUndefinedObject *filter = 115 dynamic_cast<BerUndefinedObject *>(searchRequestSequence->objects[6]); 116 BerSequenceObject *attributes = 117 dynamic_cast<BerSequenceObject *>(searchRequestSequence->objects[7]); 118 119 if (messageID == nullptr || baseObject == nullptr || scope == nullptr || 120 derefAliases == nullptr || sizeLimit == nullptr || timeLimit == nullptr || 121 typesOnly == nullptr || filter == nullptr || attributes == nullptr) { 122 return -1; 123 } 124 return 0; 125 } 126 127 int sendNoticeOfDisconnection(int comSocket, char errCode) { 128 BerSequenceObject *envelope = new BerSequenceObject(); 129 envelope->objects.push_back(new BerIntObject(0)); 130 BerSequenceObject *extendedResp = 131 new BerSequenceObject(BER_EXTENDED_RESPONSE_C); 132 envelope->objects.push_back(extendedResp); 133 extendedResp->objects.push_back(new BerEnumObject(errCode)); 134 extendedResp->objects.push_back( 135 new BerStringObject("1.3.6.1.4.1.1466.20036")); 136 extendedResp->objects.push_back(new BerStringObject("")); 137 std::vector<unsigned char> envelopeBer = envelope->getBerRepresentation(); 138 send(comSocket, &envelopeBer[0], envelopeBer.size(), MSG_NOSIGNAL); 139 return 0; 140 } 141 142 int searchRequestHandler(BerObject *searchRequest, int comm_socket, 143 const char *dbPath) { 144 145 // checks if search request is valid 146 int err = checkSearchRequest(searchRequest); 147 BerSequenceObject *envelope = 148 dynamic_cast<BerSequenceObject *>(searchRequest); 149 if (err == -2) { 150 sendNoticeOfDisconnection(comm_socket, BER_LDAP_PROTOCOL_ERROR); 151 return -1; 152 } 153 if (err == -1) { 154 sendSearchResultDone((BerSequenceObject *)envelope, comm_socket, 155 BER_LDAP_SIZE_LIMIT_EXCEEDED); 156 return -1; 157 } 158 // extracting searchRequestSequence from envelope 159 BerSequenceObject *searchRequestSequence = 160 (BerSequenceObject *)envelope->objects[1]; 161 162 // inicialization of searchRequestType 163 searchRequestType sr; 164 sr.sizeLimit = 0; 165 sr.attributes.cn = false; 166 sr.attributes.email = false; 167 sr.attributes.uid = false; 168 169 // cn 170 std::vector<unsigned char> cn = {'c', 'n'}; 171 // CommonName 172 std::vector<unsigned char> CommonName = {'c', 'o', 'm', 'm', 'o', 173 'n', 'n', 'a', 'm', 'e'}; 174 // email 175 std::vector<unsigned char> email = {'e', 'm', 'a', 'i', 'l'}; 176 // email 177 std::vector<unsigned char> mail = {'m', 'a', 'i', 'l'}; 178 // uid 179 std::vector<unsigned char> uid = {'u', 'i', 'd'}; 180 // UserID 181 std::vector<unsigned char> UserID = {'u', 's', 'e', 'r', 'i', 'd'}; 182 183 // getting size limit 184 sr.sizeLimit = 185 ((BerIntObject *)searchRequestSequence->objects[3])->getValue(); 186 // getting filters and converting them to FilterObject 187 std::vector<unsigned char> filtersBer = 188 (searchRequestSequence->objects[6])->getBerRepresentation(); 189 FilterObject *f = convertToFilterObject(filtersBer.begin(), filtersBer.end()); 190 191 // filtering database 192 std::vector<DatabaseObject> result; 193 err = 0; 194 result = filterHandler(f, &err, dbPath, sr.sizeLimit); 195 196 result = removeDuplicates(result); 197 bool sizeLimitExceeded = false; 198 if (err == 1) { 199 sizeLimitExceeded = true; 200 } 201 202 // getting attributes which should be returned 203 BerSequenceObject *attributesSequence = 204 (BerSequenceObject *)searchRequestSequence->objects[7]; 205 206 for (long unsigned int i = 0; i < attributesSequence->objects.size(); i++) { 207 208 if (ToLowerCase( 209 ((BerStringObject *)attributesSequence->objects[i])->value) == cn || 210 ToLowerCase( 211 ((BerStringObject *)attributesSequence->objects[i])->value) == 212 CommonName) { 213 sr.attributes.cn = true; 214 } 215 if (ToLowerCase( 216 ((BerStringObject *)attributesSequence->objects[i])->value) == 217 email || 218 ToLowerCase( 219 ((BerStringObject *)attributesSequence->objects[i])->value) == 220 mail) { 221 sr.attributes.email = true; 222 } 223 if (ToLowerCase( 224 ((BerStringObject *)attributesSequence->objects[i])->value) == 225 uid || 226 ToLowerCase( 227 ((BerStringObject *)attributesSequence->objects[i])->value) == 228 UserID) { 229 sr.attributes.uid = true; 230 } 231 } 232 // if no attributes specified, return all 233 if (!sr.attributes.cn && !sr.attributes.email && !sr.attributes.uid) { 234 sr.attributes.cn = true; 235 sr.attributes.email = true; 236 sr.attributes.uid = true; 237 } 238 // send search result entry for each entry in result 239 for (unsigned long int i = 0; i < result.size(); i++) { 240 BerObject *searchResultEntry = 241 InitSearchResultEntry(envelope, result[i].get_uid()); 242 243 std::vector<unsigned char> resCN = result[i].get_name(); 244 std::vector<unsigned char> resEmail = result[i].get_email(); 245 std::vector<unsigned char> resUID = result[i].get_uid(); 246 247 if (sr.attributes.cn) { 248 AddToSearchResultEntry(searchResultEntry, cn, resCN); 249 } 250 if (sr.attributes.email) { 251 AddToSearchResultEntry(searchResultEntry, email, resEmail); 252 } 253 if (sr.attributes.uid) { 254 AddToSearchResultEntry(searchResultEntry, uid, resUID); 255 } 256 257 std::vector<unsigned char> searchResultEntryBer = 258 searchResultEntry->getBerRepresentation(); 259 send(comm_socket, &searchResultEntryBer[0], searchResultEntryBer.size(), 260 MSG_NOSIGNAL); 261 delete searchResultEntry; 262 } 263 264 // send search result done 265 if (sizeLimitExceeded) { 266 267 sendSearchResultDone((BerSequenceObject *)envelope, comm_socket, 268 BER_LDAP_SIZE_LIMIT_EXCEEDED); 269 } else { 270 sendSearchResultDone((BerSequenceObject *)envelope, comm_socket, 271 BER_LDAP_SUCCESS); 272 } 273 delete f; 274 return 0; 275 } 276 277 int loadEnvelope(std::vector<unsigned char> &bindRequest, int comm_socket) { 278 unsigned char buff[1024]; 279 int lenghtOfMessage = 0; 280 int err; 281 int resNow = 0; 282 int resAll = 0; 283 for (;;) { // loads lenght of message 284 int returnCode = recv(comm_socket, buff + resNow, 1024, 0); 285 if (returnCode == 0) 286 return -1; 287 resNow += returnCode; 288 289 if (resNow >= 2) { 290 if ((buff[1] < 0x80) || 291 (buff[1] & 0x7F) <= resNow) { // checks if bytes containing lenght of 292 // message are complete 293 bindRequest.insert(bindRequest.end(), buff, buff + resNow); 294 lenghtOfMessage = 295 GetLength(bindRequest.begin() + 1, &err, bindRequest.end()) + 296 GetLengthOfLength(bindRequest.begin() + 1, &err, 297 bindRequest.end()) + 298 1; 299 break; 300 } 301 } 302 } 303 resAll = resNow; 304 for (;;) { 305 resNow = 0; 306 if (resAll < lenghtOfMessage) { 307 int returnCode = recv(comm_socket, buff, 1024, 0); 308 if (returnCode == 0) 309 return -1; 310 resNow += returnCode; 311 resAll += resNow; 312 } 313 314 if (resAll > 0) { 315 // check if message is envelope 316 if (bindRequest[0] != 0x30) { 317 sendNoticeOfDisconnection(comm_socket, BER_LDAP_PROTOCOL_ERROR); 318 err = -1; 319 break; 320 } 321 int length = 0; 322 length = buff[1]; 323 324 bindRequest.insert(bindRequest.end(), buff, buff + resNow); 325 // if whole message received, return response 326 if (resAll >= lenghtOfMessage) { 327 return length + 2; 328 } 329 } else // error or end of connection 330 break; 331 } 332 return -1; 333 }