SQL Server login hibák – Error 18456, Level 14, state

(English version here)
Időnként megesik, hogy valaki nem tud belogolni egy SQL Serverbe, mert elgépeli a jelszavát, nincs joga, stb. Ez nem olyan nagy gond egészen addig, amíg tudjuk, hogy miért nem tud belogolni. De mi van, ha valaki azt mondja, hogy nem sikerült neki, 101%, hogy jó jelszóval próbálkozik, jó szerverre, jó felhasználónévvel, jó adatbázisba, minden jó, csak éppen nem tud belépni? A legegyszerűbb megoldás a nagy kedvencem, az errorlog elolvasása, már megint. Amennyiben a szerveren be van állítva a sikertelen belépési kísérletek naplózása (úgy emlékszem ez a default), akkor az errorlogba is bekerül az az üzenet, amit a kliensnek küld a szerver:

Msg 18456, Level 14, State 1, Server DEMOSQL1, Line 1
Login failed for user ‘kiscsillag’

Illetve igazából nem is ez kerül a logba, hanem valami jobb, de mielőtt ebbe belemegyek, értelmezzük az első sorát az üzenetnek, vagyis az error három numerikus argumentumát: Az első az error number, ez a hiba egyedi azonosítója, a gépek mindig jobban szeretik a számokat, mint a dumát. A második a level vagy severity, azaz mennyire gáz az adott hiba. Minél nagyobb a szám, annál rosszabb a helyzet, severity 20 és 25 között már az is kérdéses, hogy rendesen működik-e a szerver. Az utolsó elem a state, ami egy érdekes állat. Arról adhatunk itt információt, hogy honnan jött az error – például ha van egy általunk definiált hiba, amit több különböző helyen is használunk, akkor a state értékét használhatjuk annak a jelzésére, hogy honnan jött a hiba. És most nézzük azt az errorlogot!

2009-07-27 14:02:02.21 Logon     Error: 18456, Severity: 14, State: 8.
2009-07-27 14:02:02.21 Logon     Login failed for user 'kiscsillag'. [CLIENT: 10.10.10.1]

A különbség jól látható: az a bizonyos state érték eléggé más itt, mint a kliensoldalon volt, és ez nem a véletlen műve. Az SQL Server, ahogyan azt jó rendszertől elvárjuk, nem mond többet a kliensnek, mint amennyi szükséges, nehogy ezzel segítsen egy esetleges támadást. Viszont aki tényleg segítségre szorul, az megkeresheti a sysadminokat, akik a logban láthatják, hogy miért is nem sikerült az a login. A state kódok pedig a következőek:

ERRORLEÍRÁS
2, 5Érvénytelen felhasználónév
6Windows login névvel próbálkoztál SQL autentikációt használni
7Letiltott login
8Rossz jelszó
9Érvénytelen jelszó
11, 12Helyes login, de nincs szerver hozzáférés
13SQL Server service paused
16Helyes login, de nem lehetséges belépni a kért (vagy a default) adatbázisba
18Jelszót kell változtatni
23A szerver éppen leáll, nem lehet bejelentkezni (nem sysadminoknak)
27Helyes login, de a szerver nem tud meghatározni egy kezdeti adatbázist
38[2008] Nem sikerült az explicit megadott adatbázis megnyitása (16 SQL 2005-ben)
40[2008] Nem sikerült a felhasználó default adatbázisának a megnyitása (16 SQL 2005-ben)

Van néhány kód, ami nem olyan triviális, hogy mit is jelent, néhányról magam sem tudom :), úgyhogy néhány jellemzőt kiveséznék:

A state 16 (vagy 38/40 SQL 2008-ban) egyik leggyakoribb oka az auto close-os adatbázis. Azaz az SQL szerver becsukja az adatbázist, ha nem használták már egy ideje, és megint megnyitja, ha kell valakinek. Ez egy kiváló ötlet az MSDE-hez meg egyéb asztali gépes világba, de egyébként mindenkinek melegen ajánlom, hogy nézze meg, hogy van-e auto close-os adatbázisa, és ha van, kapcsolja ki ezt az opciót, mert csak szívás van vele. Hogy mi? Például a state 16: éppen be akar lépni a user, erre az SQL elkezdi megnyitni a DB-t neki, de amíg nem sikerül teljesen megnyitnia, addig ugye nem tudja beléptetni az adatbázisába a usert, és elbukik a login. Újrapróbálva valószínűleg jó lesz, mert addigra már kinyitja. A másik gagyi benne (és erről lehet messziről kiszúrni ezeket az adatbázisokat), hogy teleszemeteli az errorlogot “Starting up database XYZ” üzenetekkel.

A 11-12 tipikusan a Windows loginok esete: az SQL Server kiválóan azonosítja a felhasználót, de nincs neki megfelelő login létrehozva az SQL szerveren, úgyhogy emberünk kívül marad.

A blog alapját a SQL Protocol team blogja és a nyomában kialakuló diskurzus adta, mivel nem sikerül összeszedniük az összes kódot egy táblába, és ez engem baromira zavart – úgyhogy összeszedtem.

7 Comments

  1. zsorzs:

    szia Erik!
    kapcsolódó kérdésem/problémám: Windows login vs linked szerverek. Adva van két AD-ben lévő sql 2005-ös szerver, amelyekre vki (mondjuk én) ad-s loginnal léphet be, mint sysadmin. A két szerver közt sima linked server kapcsolat van, a security ott pedig a current sec.contect-re van állítva, nincs semmiféle login mapping. SQL loginnál ez szuper, megy az openquery-s és linked srv neves átnyúlós sql parancsok végrehajtása. De az Ad-s loginnál bukta van, jön a 11-es state error a cél oldalon. Szakértők szerint valami “kerberos dual hop” varázslás kell, amit más fórumok meg RAVASZ szintű haladó átoknak jelölnek. Tudsz erről vmi gyakorlati szösszenetet írni, így az új évtizedben, ezzek kívánva buékot nekem?

  2. zsorzs:

    Ugyanez a problem nem sysadminos AD-s loginoknál, akkor ha nem dedikált egyedi ad-s userre, hanem ad-s csoportra (ou , group) építek sql logint, meg accountot. Ez lenne a b. kérdés, vagyis mi van az AD-s groupokkal linked szerverek vonzatában?

  3. Erik:

    Valami effélére gondoltál: http://blog.rollback.hu/2008/12/linked-server-es-a-security/ ? Vagy ezt már olvastad? Én ilyenkor belépek direktben az adott gépre, nem szeretem a trusted for delegation opciót. Régebben használtam, nem volt vele semmi baj, csak akkor még nem kellett többoldalas audit jegyzőkönyveket írnom félévente…

    Boldog Új Évet!

  4. zsorzs:

    Szerintem nem. Mert van egy tesztkörnyezetünk, amely egy fizikai vas, és rajta 3 named instance. Ez a gép is AD-ban van, és voltam rajta soxor mstsc-vel (-console meg anélkül is). Maga a vas ismer, sőt mondhatni szeret, mert lokál admin vagyok rajt. De mégse megy az SQL-es átnyúlás egyik instance-ről a másik instance-ra:
    Msg 18456, Level 14, State 1, Line 1
    Login failed for user ‘itt a full ad-s nevem van’.
    A “lépjnek be az AD-sok a gépre direktbe” megoldás nem jó, mert a nem IT-s üzletet is AD-s loginnal akarnám beléptetni egy nagy-nagy AD-s grouppal. A forrás szerverre belépés okés, de a célszerverre (linked server) átnyúlás továbbra is problémás. Vagy ebben az esetben is kell a trusted for delegation (ez ugye az az AD-s rádiógomb a gép properties/delegation fülén?)
    Azért köszi a gyors választ.

  5. zsorzs:

    Közben a sarokban kicsit gondolkodtam,és asszem az a baj, hogy az SQL serviceket nem domainben lévő user indítja, hanem lokál admin, és ez a baj. Na ezen a vonalaon elindulok….

  6. zsorzs:

    Igen! ez volt a gebasz oka.
    De hogy miért volt így azt egy sör mellett tudnám elmesélni

  7. Erik:

    Na, majd a kerekasztal kockáknak rendezvényen lebonyolítjuk azt is :)

Leave a comment