/ manual.md
manual.md
1 --- 2 title: ISA - LDAP server 3 author: René Češka 4 date: 19.11.2023 5 toc: true 6 numbersections: true 7 geometry: margin=2.5cm 8 urlcolor: blue 9 header-includes: | 10 \usepackage{fancyhdr} 11 \pagestyle{fancy} 12 \rfoot{Page \thepage} 13 --- 14 15 16 17 # Teorie 18 19 ## LDAP 20 21 LDAP (Lightweight Directory Access Protocol) je mechanismus pro interakci s adresářovými servery. Je často využíván k autentizaci a ukládání informací o uživatelích, skupinách a aplikacích. LDAP server se dá ale využít i pro ukládání jiných informací. [1] 22 23 Adresáře jsou ve stromových strukturách. Každá položka v adresáři má vlastní atributy, ke kterým lze přistupovat. [1] 24 25 ## BER ANS.1 26 27 LDAP používá pro komunikaci TLV kódování BER. Základní princip tohoto kódování je že každý datový typ se skládá ze tří částí. Tag, délka a data. Tag určuje typ dat, délka určuje délku dat a data jsou samotná data. 28 BER obsahuje spoustu základních typů (int, boolean, sequence, enum, atd...) a také je ho možné rozšířit o typy specifické pro vlastní aplikaci. 29 [2] 30 31 ## Komunikace 32 33 Veškeré zprávy jsou zabalené v tzv. obálce, která obsahuje MessageID. Toto MessageID slouží k identifikaci, na kterou zprávu server odpovídá, a veškeré zprávy serveru obsahují stejné MessageID jako zpráva, na kterou odpovídají. [4] 34 35 Komunikace probíhá většinou pomocí TCP protokolu, ale je možné použít i UDP. 36 37 ### LDAP princip vyhledávání 38 39 Při vyhledávání, je klientem serveru zaslán dotaz. Tento dotaz obsahuje filter, doménu, volitelně přihlašovací údaje a další parametry. 40 Server následně tento dotaz zpracuje a vrací jednotlivé položky co odpovídají dotazu. Odpověď dokončí odpovědí SearchResultDone, s kódem 0, který značí úspěšné dokončení vyhledávání, případně s jiným kódem, který značí chybu. [4] 41 42 ### LDAP princip přihlášení 43 44 Kdykoli během komunikace může klient požádat o přihlášení. Přihlášení probíhá pomocí BIND_REQUEST, který obsahuje typ přihlášení a přihlašovací údaje. Server následně zpracuje tento požadavek a vrátí odpověď BIND_RESPONSE, která obsahuje kód, který značí úspěšné přihlášení, nebo chybu. [4] 45 46 ## Filtry 47 48 V LDAP existují různé druhy filtrů, které se dají kombinovat a pomoci nich vyhledávat položky. Mezi filtry implementované v této aplikaci patří: Equality Match, Substrings, AND, OR, NOT. [4][3] 49 50 Příklady filtrů: 51 52 - Equality Match: (uid=xvesel38) - vyhledává uživatele s uid xvesel38 53 - Substrings: (uid=\*vesel\*) - vyhledává uživatele jejichž uid obsahuje vesel 54 - AND: (&(uid=xvesel38)(uid=\*vesel\*)) - vyhledává uživatele jejichž uid obsahuje vesel a je rovno xvesel38 55 - OR: (|(uid=xvesel38)(uid=xvesel40)(uid=xvesel39)) - vyhledává uživatele jejichž uid je xvesel38, xvesel40 nebo xvesel39 56 - NOT: (!(uid=xvesel38)) - vyhledává uživatele jejichž uid není xvesel38 57 58 ## CSV 59 60 CSV (Comma-separated values) je jednoduchý formát pro ukládání tabulkových dat. Jednotlivé řádky jsou odděleny znakem nového řádku a jednotlivé sloupce jsou odděleny čárkou případně jiným oddělovačem. [5] 61 62 ## TCP 63 64 TCP (Transmission Control Protocol) je spolehlivý protokol pro přenos dat. Zajišťuje, že data dorazí v pořádku a ve správném pořadí. Jedná se o proud dat. [6] 65 66 # Použití 67 68 ./isa-ldapserver {-p \<port\>} -f \<soubor\> 69 70 71 Význam parametrů a jejich hodnot: 72 73 -p \<port\>: Umožňuje specifikovat konkrétní port, na kterém začne server naslouchat požadavkům klientů. Výchozí hodnota čísla portu je 389. 74 -f \<soubor\>: Cesta k textovému soubor ve formátu CSV. 75 76 Aplikaci lze ukončit pomocí klávesové zkratky Ctrl+C (SIGINT). 77 78 ## Sestavení 79 80 Sestavení probíhá pomocí příkazu `make`. Výsledkem je spustitelný soubor `isa-ldapserver`. Veškeré zdrojové soubory jsou ve složce src, a hlavičkové soubory ve složce inc. 81 Příkaz `make clean` smaže obj soubory a binárku. 82 83 84 # Popis funkce aplikace 85 86 Hlavní smyčka aplikace je v souboru server.cpp, ve kterém se prvně nastaví poslouchání na uživatelem zadaném portu. Následně aplikace čeká dokud nepřijde požadavek od ldap klienta. Následně dojde k forku, a v dceřiném procesu se zpracuje požadavek klienta. 87 88 Na požadavek podproces reaguje dle jeho typu. Podporuje 3 druhy požadavků od klienta. Tyto požadavky jsou: 89 90 - BIND_REQUEST 91 - SEARCH_REQUEST 92 - UNBIND_REQUEST 93 94 ## BIND_REQUEST 95 96 Bind request může přijít kdykoli a nemusí být prvním požadavkem. Zde se ověřuje jestli client žádá o správný typ přihlášení. Aplikace podporuje pouze simple bind, pokud klient zažádá o jiný způsob přihlášení, je mu vrácena chyba, a komunikace ukončena. Pokud je vše v pořádku, je klientovi vrácen úspěšný BIND_RESPONSE. 97 98 ## SEARCH_REQUEST 99 100 Search request může přijít kdykoli a není třeba aby navazoval na bindrequest. Podproces následně zpracuje tento požadavek, vyhledá v databázi odpovídající záznamy a pomocí odpovědi SearchResultEntry je vrátí klientovi (na každý záznam se odesílá jedna SearchResultEntry). 101 Nakonec pošle SearchResultDone, kterým oznámí klientovi, že je vyhledávání dokončeno. 102 103 ## UNBIND_REQUEST 104 105 Jakmile příjde tento požadavek, podproces ukončí komunikaci s klientem a ukončí se. 106 107 ## Ukončení 108 109 Při zaslání SIGINT (CTRL + c) začne hlavní proces ukončovat všechny své podprocesy a následně se ukončí. 110 111 112 # Rozšíření oproti zadání 113 114 ## Výběr atributů 115 116 Aplikace podporuje možnost vybrat si jaké atributy chce uživatel vyhledat. V případě, že uživatel nevybere žádný atribut, jsou mu vráceny všechny atributy. Neexistující atributy jsou ignorovány. 117 118 ## Notice of Disconnection 119 120 Pokud dojde k chybě, která nejde oznámit přes odpovídající odpověď na požadavek, je klientovi oznámeno ukončení komunikace pomocí Notice of Disconnection. 121 122 ## Přihlášení kdykoli 123 124 Není třeba se přihlásit před bind requestem, ale je možné se přihlásit kdykoli během komunikace (LDAP3). Jelikož server podporuje jen podporuje jen simple bind, bez autentizace tak to nemá význam. Ale je možné potom velice jednoduše rozšířit aplikaci pro další typy autentizace. 125 126 # Zdrojový kód 127 128 Program byl psát v jazyku CPP s objektovým přístupem. Zdrojový kód byl dokumentován pomocí Doxygenu. Výsledná dokumentace je k dispozici v adresáři docs v souboru docs/refman.pdf. 129 130 Zde je pouze stručný popis zajímavých tříd, jejich významu a použití. 131 132 ## Popis důležitých souborů 133 134 - server.h - obsahuje ldap server 135 - ldap_comunication.h - obsahuje třídy pro komunikaci s klientem 136 - DatabaseController.h - obsahuje třídy pro práci s csv databází 137 - BerObject.h - základní objekt pro BER typy 138 - BerXObject.h - objekt pro konkrétní BER typ, dědí z BerObject 139 - FilterObject.h - základní objekt pro LDAP filtry 140 - XFilterObject.h - objekt pro konkrétní LDAP filtr, dědí z FilterObject 141 142 Podrobnější popis v souboru docs/refman.pdf. 143 144 ## Třídy 145 146 ## BerObject 147 148 Je bázovým objektem pro objekty reprezentující BER struktury. Obsahuje základní metody pro ostatní objekty. 149 150 Pomocí funkce `getBerRepresentation` lze získat reprezentaci objektu v podobě BER bajtového pole. Které lze snadno odeslat klientovy. 151 Pro deserializaci je třeba využít funkce `ParseBerObject` která vrací ukazatel na nově vytvořený objekt. 152 153 Z těchto objektů lze snadno vytvářet BER struktury a pracovat s nimy. 154 155  156 157 ## FilterObject 158 159 Je bázovým objektem pro objekty reprezentující LDAP filtry. Jeho podtřídy jsou obsahují metody pro snadnou práci s nimy. 160 161  162 163 ## DatabaseController 164 165 Třída DatabaseController slouží pro práci s csv databází. Obsahuje metody pro načítání řádků z databáze a vrací je v podobě objektů třídy DatabaseObject. 166 167 ## DatabaseObject 168 169 Třída DatabaseObject slouží pro reprezentaci řádku v databázi. Obsahuje metody pro získání hodnot atributů. 170 171 # Testování 172 173 ## Testovací prostředí 174 175 - client 176 - program ldapsearch 177 - OS Manjaro Linux 23.0.4 178 - server 179 - program isa-ldapserver 180 - OS CentOS Linux 7 181 - databáze uživatelů 182 - soubor [ldap-lidi-ascii.csv](http://nes.fit.vutbr.cz/ivesely/ldap-lidi-ascii.csv) 183 - shell 184 - zsh 5.9 185 186 ## Testovací scénáře 187 188 ## Vyhledávání 189 190 ### Vyhledávání všech uživatelů 191 192 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uid=x*)"` 193 194 - Wireshark: nehlásil chybu v komunikaci 195 196 Výsledek prošel dle očekávání a program vypsal všechny uživatele, jejichž uid začíná na x(kompletní soubor). 197 198 ### Vyhledávání uživatele pokročilejší filty 199 200 - příkaz: 201 202 ```ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(&(|(uid=xves*)(cn=*imir))(email=*stud*))"``` 203 204 - Wireshark: nehlásil chybu v komunikaci 205 206 Výsledek prošel dle očekávání a program vypsal všechny uživatele, jejichž uid začíná na xves, nebo cn obsahuje imir a email obsahuje stud. 207 208 ### forkování procesů 209 210 ### 10 klientů 211 212 - příkaz: pro jednoho client `nc merlin.fit.vutbr.cz 10013` 213 214 Výsledek prošel dle očekávání a clienti se mohli připojovat a odpojovat kdykoliv chtěli. 215 216 ### Ukončení serveru při připojení několika clientů 217 218 - příkaz: pro jednoho client `nc merlin.fit.vutbr.cz 10013` 219 220 Výsledek prošel dle očekávání a server se ukončil a všechny své podprocesy zabil. Také klientům, kteří byli ještě připojeni odeslal Notice of Disconnection s chybovým kódem unavailable. 221 222 ### IPV6 a IPV4 223 224 Toto testování proběhlo pouze na lokálním stroji(Manjaro), jelikož nemám IPV6 připojení k dispozici. 225 226 ### IPV6 227 228 - příkaz: `ldapsearch -H ldap://\[::1\]:10013 -x "(uid=xvesel38)"` 229 - Wireshark: nehlásil chybu v komunikaci 230 Výsledek prošel dle očekávání a program vypsal uživatele s uid xvesel38. 231 232 ### IPV4 233 234 - příkaz: `ldapsearch -H ldap://127.0.0.1:10013 -x "(uid=xvesel38)"` 235 - Wireshark: nehlásil chybu v komunikaci 236 237 Výsledek prošel dle očekávání a program vypsal uživatele s uid xvesel38. 238 239 240 ### Různé parametry 241 242 ### špatné argumenty při spuštění serveru 243 244 - příkaz: `./isa-ldapserver -p 10000000 -f ldap-lidi-ascii.csv` 245 - příkaz: `./isa-ldapserver -p 0 -f ldap-lidi-ascii.csv` 246 - příkaz: `./isa-ldapserver -p -f ldap-lidi-ascii.csv` 247 - příkaz: `./isa-ldapserver -f neexistujici_soubor` 248 249 Při všech těchto příkazech došlo k ukončení serveru a vypsání chybového výstupu. 250 251 ### ldapsearch bez -x (bez simple bind) 252 253 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 "(uid=xvesel38)"` 254 - Wireshark: nehlásil chybu v komunikaci 255 256 Výsledek dle očekávání vrátil `ldap_sasl_interactive_bind: No such object (32)` jelikož tato implementace ldap serveru nepodporuje presence filtry, takže ldapsearch nenašel žádný záznam o použitých technologiích k přihlášení a ukončil komunikaci, bez pokusu o přihlášení. 257 258 ### size limit 259 260 #### size limit 0 261 262 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uid=x*)" -z 0` 263 - Wireshark: nehlásil chybu v komunikaci 264 265 Výsledek dle očekávání vrátil všechny uživatele, jelikož size limit byl nastaven na 0, a tedy deaktivován. 266 267 #### size limit 1 268 269 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uid=x*)" -z 1` 270 - Wireshark: nehlásil chybu v komunikaci 271 272 Výsledek dle očekávání vrátil pouze jednoho uživatele, jelikož size limit byl nastaven na 1. 273 274 #### size limit 850 275 276 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uid=x*)" -z 850` 277 - Wireshark: nehlásil chybu v komunikaci 278 279 Výsledek dle očekávání vrátil 850 uživatelů, jelikož size limit byl nastaven na 850. 280 281 #### size limit 200000 282 283 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uid=x*)" -z 200000` 284 - Wireshark: nehlásil chybu v komunikaci 285 286 Výsledek dle očekávání vrátil všechny uživatele, jelikož size limit byl nastaven na 200000, což je více než je počet uživatelů v databázi. 287 288 ### Jednotlivé filtry 289 290 ### Equality Match 291 292 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uid=xvesel38)"` 293 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(cn=Vesely Vladimir)"` 294 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(email=xvesel38@stud.fit.vutbr.cz)` 295 296 - Wireshark: nehlásil chybu v komunikaci 297 298 Výsledek prošel dle očekávání a program vypsal u všech příkazů následující výstup: 299 300 ``` 301 # extended LDIF 302 # 303 # LDAPv3 304 # base <> (default) with scope subtree 305 # filter: (uid=xvesel38) 306 # requesting: ALL 307 # 308 309 # 310 dn: xvesel38 311 cn: Vesely Vladimir 312 email: xvesel38@stud.fit.vutbr.cz 313 uid: xvesel38 314 315 # search result 316 search: 2 317 result: 0 Success 318 319 # numResponses: 2 320 # numEntries: 1 321 322 ``` 323 324 ### Substrings 325 326 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uid=*ve*el*)"` 327 328 - Wireshark: nehlásil chybu v komunikaci 329 330 Výsledek prošel dle očekávání a program vypsal všechny uživatele, jejichž uid obsahuje `ve` a `el`. 331 332 ### AND 333 334 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(&(uid=xve*)(uid=*sel38))"` 335 336 - Wireshark: nehlásil chybu v komunikaci 337 338 Výsledek prošel dle očekávání a program vypsal všechny uživatele s uid xvesel38. 339 340 ``` 341 # extended LDIF 342 # 343 # LDAPv3 344 # base <> (default) with scope subtree 345 # filter: (&(uid=xve*)(uid=*sel38)) 346 # requesting: ALL 347 # 348 349 # 350 dn: xvesel38 351 cn: Vesely Vladimir 352 email: xvesel38@stud.fit.vutbr.cz 353 uid: xvesel38 354 355 # search result 356 search: 2 357 result: 0 Success 358 359 # numResponses: 2 360 # numEntries: 1 361 362 ``` 363 364 ### OR 365 366 - příkaz: ```ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x \"(|(uid=xvesel38)(uid=xvesel40))" ``` 367 - Wireshark: nehlásil chybu v komunikaci 368 369 Výsledek prošel dle očekávání a program vypsal 3 uživatele s uid xvesel38, xvesel40. 370 371 ``` 372 # extended LDIF 373 # 374 # LDAPv3 375 # base <> (default) with scope subtree 376 # filter: (|(uid=xvesel38)(uid=xvesel40)(uid=xvesel39)) 377 # requesting: ALL 378 # 379 380 # 381 dn: xvesel40 382 cn: Vesely Ales 383 email: xvesel40@stud.fit.vutbr.cz 384 uid: xvesel40 385 386 # 387 dn: xvesel38 388 cn: Vesely Vladimir 389 email: xvesel38@stud.fit.vutbr.cz 390 uid: xvesel38 391 392 # search result 393 search: 2 394 result: 0 Success 395 396 # numResponses: 4 397 # numEntries: 3 398 ``` 399 400 ### NOT 401 402 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(|(!(uid=x*))(uid=xvesel38))"` 403 - Wireshark: nehlásil chybu v komunikaci 404 405 Výsledek prošel dle očekávání a vypsal pouze jednoho uživatele s uid xvesel38. 406 407 ``` 408 # extended LDIF 409 # 410 # LDAPv3 411 # base <> (default) with scope subtree 412 # filter: (|(!(uid=x*))(uid=xvesel38)) 413 # requesting: ALL 414 # 415 416 # 417 dn: xvesel38 418 cn: Vesely Vladimir 419 email: xvesel38@stud.fit.vutbr.cz 420 uid: xvesel38 421 422 # search result 423 search: 2 424 result: 0 Success 425 426 # numResponses: 2 427 # numEntries: 1 428 429 ``` 430 431 ### speciální případy 432 433 ### Vyhledávání podle neexistujícího atributu 434 435 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uidd=xvesel38)"` 436 - WireShark: nehlásil chybu v komunikaci 437 438 Výsledek dle očekávání neobsahoval žádné záznamy. 439 440 ### Negace vyhledávání podle neexistujícího atributu 441 442 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(!(uidd=xvesel38))"` 443 - WireShark: nehlásil chybu v komunikaci 444 445 Výsledek dle očekávání neobsahoval žádné záznamy. 446 447 ### Dlouhý filtr 448 449 - příkaz: ```ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(|(uid=xvesel38)(uid=xvesel40))"``` 450 - pozn: (uid=xvesel38)(uid=xvesel40) se 100 x opakovalo 451 452 - WireShark: nehlásil chybu v komunikaci 453 454 Výsledek dle očekávání vypsal uživatele s uid xvesel38, xvesel40, xvesel39. 455 456 ### Dlouhý Equality Match 457 458 - příkaz: ```ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(!(uid=dlouhyretezec))"``` 459 - pozn: `dlouhyretezec` byl 1000 x znak `a` 460 - WireShark: nehlásil chybu v komunikaci 461 462 Výsledek dle očekávání obsahoval všechny uživatele. 463 464 ### Dlouhý Substrings 465 466 - příkaz: ```ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(!(uid=*dlouhyretezec))"``` 467 - pozn: `dlouhyretezec` byl 1000 x znak `a` 468 - WireShark: nehlásil chybu v komunikaci 469 470 Výsledek dle očekávání obsahoval všechny uživatele. 471 472 ## Porovnání s ldap od FIT VUT 473 474 ### Vyhledávání všech uživatelů uživatele s uid xvesel38 475 476 - příkaz: `ldapsearch -H ldap://ldap.fit.vutbr.cz:389 -x "(uid=xvesel92)" uid cn mail` 477 478 Výstup: 479 480 ``` 481 # extended LDIF 482 # 483 # LDAPv3 484 # base <> (default) with scope subtree 485 # filter: (uid=xvesel92) 486 # requesting: uid cn mail 487 # 488 489 # xvesel92, fit.vutbr.cz 490 dn: uid=xvesel92,dc=fit,dc=vutbr,dc=cz 491 cn:: VmVzZWzDvSBCb3Jpcw== 492 uid: xvesel92 493 mail: xvesel92@stud.fit.vutbr.cz 494 495 # search result 496 search: 2 497 result: 0 Success 498 499 # numResponses: 2 500 # numEntries: 1 501 502 ``` 503 504 - příkaz: `ldapsearch -H ldap://merlin.fit.vutbr.cz:10013 -x "(uid=xvesel38)"` 505 506 ``` 507 # extended LDIF 508 # 509 # LDAPv3 510 # base <> (default) with scope subtree 511 # filter: (&(uid=xvesel38)) 512 # requesting: ALL 513 # 514 515 # 516 dn: xvesel38 517 cn: Vesely Vladimir 518 email: xvesel38@stud.fit.vutbr.cz 519 uid: xvesel38 520 521 # search result 522 search: 2 523 result: 0 Success 524 525 # numResponses: 2 526 # numEntries: 1 527 ``` 528 529 # Literatura 530 531 - [1] WILSON, Neil. _LDAP_. Online. Dostupné z: [https://ldap.com/](https://ldap.com/). [cit. 2023-11-19]. 532 - [2] WILSON, Neil. _LDAPv3 Wire Protocol Reference: The ASN.1 Basic Encoding Rules_ [online]. [cit. 2023-11-19]. Dostupné z: https://ldap.com/ldapv3-wire-protocol-reference-asn1-ber/ 533 - [3] WAHL, M, T HOWES a S KILLE. Lightweight Directory Access Protocol (v3) [online]. 1997 [cit. 2023-11-19]. Dostupné z: https://datatracker.ietf.org/doc/html/rfc2251 534 - [4] WAHL, M, T HOWES a S KILLE. _RFC2251: Lightweight Directory Access Protocol (v3)_ [online]. 1997 [cit. 2023-11-19]. Dostupné z: https://datatracker.ietf.org/doc/html/rfc2251 535 - [5] SHAFRANOVICH, Y. _RFC4180: Common Format and MIME Type for Comma-Separated Values CSV Files_ [online]. 2005 [cit. 2023-11-19]. Dostupné z: https://datatracker.ietf.org/doc/html/rfc2251 536 - [6] RAY, M.D. _RFC793: TRANSMISSION CONTROL PROTOCOL_ [online]. 1997 [cit. 2023-11-19]. Dostupné z: https://tools.ietf.org/html/rfc793 537 - [7] WILSON, Neil. LDAP Filters [online]. [cit. 2023-11-19]. Dostupné z: https://ldap.com/ldap-filters/