Ошибка ldap при смене пароля

Ozzy

Ozzy

Случайный прохожий


  • #1

Всем привет! Подскажите как пофиксить проблему. Пользователи подключаются к чекпойнту через endpoint security vpn по логину и паролю. Если у пользователя просрочен пароль то клиент предлагает его сменить или обновить, но это сделать не удается. Появляется ошибка: Failed to modify password, LDAP Error
Где искать правду ?

1.png

Последнее редактирование:

  • #5

Такое ощущение что как будто нет разрешений на смену пароля в AD

А если к примеру домен админ будет так пытаться пароль поменять через gaia или через endpoint security VPN?

  • #10

По моему опыту оно вообще через раз работает. И работоспособность сильно зависит от версии клиента.

I currently try to change passwords in our Active Directory Envoirenment via LDAP on Linux since the users in question do not have access to a windows-machine and we want to keep it that way.
In order to change the password I am currently stuck figuring out how to use ldapmodify to do so. After a lot of reading on different sites/forums/newsgroups I am much more confused than before

However:
I try the following command to do so:

ldapmodify -f ldif.example -H ldaps://lab01-dc01.example.com -D 'CN=test,CN=users,DC=lab01,DC=example,DC=com' -x -W

The contents of the ldif.example:

dn: CN=test,CN=Users,DC=lab01,DC=example,DC=com
changetype: modify
delete: unicodePwd
unicodePwd:: V3VQdXV1STEyLg==
-
add: unicodePwd
unicodePwd:: QmxhVVVraTEyLg==
-

(Don’t worry — those passwords are not used anywhere and it is not a production envoirenment)

Now — every time I execute the command I get the following error:

modifying entry CN=test,CN=Users,DC=lab01,DC=example,DC=com"
ldapmodify: Constraint violation (19)
 additional info: 0000216C: AtrErr: DSID-03190EB0, #1:
 0: 0000216C: DSID-03190EB0, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 9005a (unicodePwd)

Now, after what I read the reason for this error is either that the password is badly formatted or that the password policy doesn’t allow the password I used. I checked the policy — multiple times now — and the new password definetly complies to the policy by all the criteria. If I set the password using a Windows-machine it also works well (of course I changed the «oldpassword» and «newpassword» afterwards since I am not allowed by the policy to change to an earlier password). The password I enter after passing the «-W» option to ldapmodify is also definetly right, otherwise the error spit out by ldapmodify is that I used invalid credentials instead of a constraint violation.
So — the sole reason I can think of is indeed a bad formatted password — but I can’t figure out where the bad formatting should come from since I use the normal base64 algorythm to encode the password.

Has anyone an idea what is going on?
Can anyone push me in the right direction?

Help is very appreciated and I thank you in advance.

Edit:
Something which bugs me:
When I run the base encoded strings through base64 it keeps telling me «Invalid Input». Now — I went ahead and just re-coded the passwords with the use of base64 on the linux machine — but when I run the generated string through the decode function again, base64 keeps telling me «Invalid Input»… The strings however slightly changed between the windows-base64 encoded string and the linux encoded string. But base64 just says «Invalid input» no matter what I put in there.

Edit2:
Nevermind — reading the purpose of the function I gather that it throws this error because of the dots and the exclamation mark in the password.

I am doing the c# code to change a ldap user’s password by either user himself, or the admin.
I can successfully authenticate the users. However, I get the following error message when I try to invoke a ChangePassword or SetPassword behavior:

InnerException: The directory property cannot be found in the cache.

My code is as follows:

LDAPPath = "LDAP://10.29.0.1:50405/DC=DCServerName,DC=local"
LDAPAdminDN = "CN=useradmin,OU=SystemAccounts,DC=DCServerName,DC=local"
LDAPAdminPwd = "S8kf5t3!"
username = "user1"
password = "oldPassword1"
npassword = "newPassword1"

DirectoryEntry root = new DirectoryEntry(
LDAPPath,
LDAPAdminDN,
LDAPAdminPwd,
AuthenticationTypes.None
);

using (root)
{
    DirectorySearcher searcher = new DirectorySearcher(root,
        string.Format("(CN={0})", username)
        );
    var result = searcher.FindOne();
    if (result != null)
    {
        var user = result.GetDirectoryEntry();
        try
        {
            user.Invoke("ChangePassword", new object[] { password, npassword });
            user.Properties["LockOutTime"].Value = 0; 
            //user.Invoke("SetPassword", new object[] { npassword });
            user.CommitChanges();
        }
        catch (Exception e)
        {
            string innerMsg = e.InnerException.Message;
            return false;
        }
    }

I am wondering how to resolve this problem to change the password successfully. Thank you guys

Update:
I tried several options as below but all of them don’t work:
One:

int intPort = 50405;
user.Invoke("SetOption", new object[] { ADS_OPTION_PASSWORD_PORTNUMBER, intPort });
user.Invoke("SetOption", new object[] { ADS_OPTION_PASSWORD_METHOD, ADS_PASSWORD_ENCODE_CLEAR });

Two:

user.UsePropertyCache = true;

They all get error of 0x80072020

My IT guy enabled «change password on nonSSL», I am not sure any settings matter in AD LDS part.

Question:
Am I right to use an admin account to change a user’s password in this way instead of using any impersonate code?

I currently try to change passwords in our Active Directory Envoirenment via LDAP on Linux since the users in question do not have access to a windows-machine and we want to keep it that way.
In order to change the password I am currently stuck figuring out how to use ldapmodify to do so. After a lot of reading on different sites/forums/newsgroups I am much more confused than before

However:
I try the following command to do so:

ldapmodify -f ldif.example -H ldaps://lab01-dc01.example.com -D 'CN=test,CN=users,DC=lab01,DC=example,DC=com' -x -W

The contents of the ldif.example:

dn: CN=test,CN=Users,DC=lab01,DC=example,DC=com
changetype: modify
delete: unicodePwd
unicodePwd:: V3VQdXV1STEyLg==
-
add: unicodePwd
unicodePwd:: QmxhVVVraTEyLg==
-

(Don’t worry — those passwords are not used anywhere and it is not a production envoirenment)

Now — every time I execute the command I get the following error:

modifying entry CN=test,CN=Users,DC=lab01,DC=example,DC=com"
ldapmodify: Constraint violation (19)
 additional info: 0000216C: AtrErr: DSID-03190EB0, #1:
 0: 0000216C: DSID-03190EB0, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 9005a (unicodePwd)

Now, after what I read the reason for this error is either that the password is badly formatted or that the password policy doesn’t allow the password I used. I checked the policy — multiple times now — and the new password definetly complies to the policy by all the criteria. If I set the password using a Windows-machine it also works well (of course I changed the «oldpassword» and «newpassword» afterwards since I am not allowed by the policy to change to an earlier password). The password I enter after passing the «-W» option to ldapmodify is also definetly right, otherwise the error spit out by ldapmodify is that I used invalid credentials instead of a constraint violation.
So — the sole reason I can think of is indeed a bad formatted password — but I can’t figure out where the bad formatting should come from since I use the normal base64 algorythm to encode the password.

Has anyone an idea what is going on?
Can anyone push me in the right direction?

Help is very appreciated and I thank you in advance.

Edit:
Something which bugs me:
When I run the base encoded strings through base64 it keeps telling me «Invalid Input». Now — I went ahead and just re-coded the passwords with the use of base64 on the linux machine — but when I run the generated string through the decode function again, base64 keeps telling me «Invalid Input»… The strings however slightly changed between the windows-base64 encoded string and the linux encoded string. But base64 just says «Invalid input» no matter what I put in there.

Edit2:
Nevermind — reading the purpose of the function I gather that it throws this error because of the dots and the exclamation mark in the password.

в настоящее время я проверять подлинность пользователей против некоторых ad, используя следующий код:

DirectoryEntry entry = new DirectoryEntry(_path, username, pwd);

try
{
    // Bind to the native AdsObject to force authentication.
    Object obj = entry.NativeObject;

    DirectorySearcher search = new DirectorySearcher(entry) { Filter = "(sAMAccountName=" + username + ")" };
    search.PropertiesToLoad.Add("cn");
    SearchResult result = search.FindOne();
    if (result == null)
    {
        return false;
    }
    // Update the new path to the user in the directory
    _path = result.Path;
    _filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
    throw new Exception("Error authenticating user. " + ex.Message);
}

это отлично работает для проверки пароля против имени пользователя.

проблема заключается в том, что родовые ошибки всегда возвращается «ошибка входа в систему: неизвестное имя пользователя или неверный пароль.»когда аутентификация не выполняется.

однако аутентификация также может завершиться ошибкой, если учетная запись заблокирована.

Как бы я узнал, если он терпит неудачу из-за того, что он заперто?

я наткнулся на статьи, в которых говорится, что вы можете использовать:

Convert.ToBoolean(entry.InvokeGet("IsAccountLocked"))

или сделать что-то вроде объяснил здесь

проблема в том, что всякий раз, когда вы пытаетесь получить доступ к любому свойству на DirectoryEntry, будет вызвана та же ошибка.

любое другое предложение о том, как добраться до фактической причины сбоя аутентификации? (учетная запись заблокирована / пароль истек / etc.)

рекламу я подключиться не может скорее быть сервер Windows.

4 ответов


немного поздно, но я оставлю это там.

Если вы хотите действительно иметь возможность определить конкретную причину, по которой учетная запись не проходит проверку подлинности (есть еще много причин, кроме неправильного пароля, истекшего срока действия, блокировки и т. д.), вы можете использовать Windows API LogonUser. Не пугайтесь этого — это легче, чем кажется. Вы просто вызываете LogonUser, и если это не удается, вы смотрите на Маршала.GetLastWin32Error (), который даст вам код возврата, указывающий (очень) конкретная причина сбоя входа в систему.

однако вы не сможете вызвать это в контексте пользователя, которого вы аутентифицируете; вам понадобится учетная запись priveleged-я считаю, что требование SE_TCB_NAME (aka SeTcbPrivilege) — учетная запись пользователя, которая имеет право «действовать как часть операционной системы».

//Your new authenticate code snippet:
        try
        {
            if (!LogonUser(user, domain, pass, LogonTypes.Network, LogonProviders.Default, out token))
            {
                errorCode = Marshal.GetLastWin32Error();
                success = false;
            }
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            CloseHandle(token);    
        }            
        success = true;

если это не удается, вы получите один из кодов возврата (есть больше, что вы можете посмотреть, но это важно из них:

 //See http://support.microsoft.com/kb/155012
    const int ERROR_PASSWORD_MUST_CHANGE = 1907;
    const int ERROR_LOGON_FAILURE = 1326;
    const int ERROR_ACCOUNT_RESTRICTION = 1327;
    const int ERROR_ACCOUNT_DISABLED = 1331;
    const int ERROR_INVALID_LOGON_HOURS = 1328;
    const int ERROR_NO_LOGON_SERVERS = 1311;
    const int ERROR_INVALID_WORKSTATION = 1329;
    const int ERROR_ACCOUNT_LOCKED_OUT = 1909;      //It gives this error if the account is locked, REGARDLESS OF WHETHER VALID CREDENTIALS WERE PROVIDED!!!
    const int ERROR_ACCOUNT_EXPIRED = 1793;
    const int ERROR_PASSWORD_EXPIRED = 1330;  

остальное просто скопируйте / вставьте, чтобы получить DLLImports и значения для передачи в

  //here are enums
    enum LogonTypes : uint
        {
            Interactive = 2,
            Network =3,
            Batch = 4,
            Service = 5,
            Unlock = 7,
            NetworkCleartext = 8,
            NewCredentials = 9
        }
        enum LogonProviders : uint
        {
            Default = 0, // default for platform (use this!)
            WinNT35,     // sends smoke signals to authority
            WinNT40,     // uses NTLM
            WinNT50      // negotiates Kerb or NTLM
        }

//Paste these DLLImports

[DllImport("advapi32.dll", SetLastError = true)]
        static extern bool LogonUser(
         string principal,
         string authority,
         string password,
         LogonTypes logonType,
         LogonProviders logonProvider,
         out IntPtr token);

[DllImport("kernel32.dll", SetLastError = true)]
        static extern bool CloseHandle(IntPtr handle);

Я знаю, что этот ответ опоздал на несколько лет, но мы просто столкнулись с той же ситуацией, что и оригинальный плакат. К сожалению, в нашей среде мы не можем использовать LogonUser — нам нужно чистое решение LDAP. Оказывается, есть способ получить расширенный код ошибки из операции привязки. Это немного уродливо, но это работает:

catch(DirectoryServicesCOMException exc)
{
    if((uint)exc.ExtendedError == 0x80090308)
    {
        LDAPErrors errCode = 0;

        try
        {
            // Unfortunately, the only place to get the LDAP bind error code is in the "data" field of the 
            // extended error message, which is in this format:
            // 80090308: LdapErr: DSID-0C09030B, comment: AcceptSecurityContext error, data 52e, v893
            if(!string.IsNullOrEmpty(exc.ExtendedErrorMessage))
            {
                Match match = Regex.Match(exc.ExtendedErrorMessage, @" data (?<errCode>[0-9A-Fa-f]+),");
                if(match.Success)
                {
                    string errCodeHex = match.Groups["errCode"].Value;
                    errCode = (LDAPErrors)Convert.ToInt32(errCodeHex, fromBase: 16);
                }
            }
        }
        catch { }

        switch(errCode)
        {
            case LDAPErrors.ERROR_PASSWORD_EXPIRED:
            case LDAPErrors.ERROR_PASSWORD_MUST_CHANGE:
                throw new Exception("Your password has expired and must be changed.");

            // Add any other special error handling here (account disabled, locked out, etc...).
        }
    }

    // If the extended error handling doesn't work out, just throw the original exception.
    throw;
}

и вам понадобятся определения для кодов ошибок (их намного больше на http://www.lifeasbob.com/code/errorcodes.aspx):

private enum LDAPErrors
{
    ERROR_INVALID_PASSWORD = 0x56,
    ERROR_PASSWORD_RESTRICTION = 0x52D,
    ERROR_LOGON_FAILURE = 0x52e,
    ERROR_ACCOUNT_RESTRICTION = 0x52f,
    ERROR_INVALID_LOGON_HOURS = 0x530,
    ERROR_INVALID_WORKSTATION = 0x531,
    ERROR_PASSWORD_EXPIRED = 0x532,
    ERROR_ACCOUNT_DISABLED = 0x533,
    ERROR_ACCOUNT_EXPIRED = 0x701,
    ERROR_PASSWORD_MUST_CHANGE = 0x773,
    ERROR_ACCOUNT_LOCKED_OUT = 0x775,
    ERROR_ENTRY_EXISTS = 0x2071,
}

Я не мог найти эту информацию в другом месте-все просто говорят, что вы должны использовать LogonUser. Если есть лучшее решение, я с удовольствием его выслушаю. Если нет, я надеюсь, что это поможет другим людям, которые не могут позвонить LogonUser.


проверка «пароль истекает» относительно проста — по крайней мере, в Windows (не уверен, как другие системы справляются с этим): когда значение Int64 «pwdLastSet» равно 0, пользователю придется изменить свой пароль при следующем входе в систему. Самый простой способ проверить это-включить это свойство в DirectorySearcher:

DirectorySearcher search = new DirectorySearcher(entry)
      { Filter = "(sAMAccountName=" + username + ")" };
search.PropertiesToLoad.Add("cn");
search.PropertiesToLoad.Add("pwdLastSet");

SearchResult result = search.FindOne();
if (result == null)
{
    return false;
}

Int64 pwdLastSetValue = (Int64)result.Properties["pwdLastSet"][0];

что касается проверки» учетная запись заблокирована » — сначала это кажется легким, но это не так…. Флаг» UF_Lockout » на «userAccountControl» не выполняет свою работу надежно.

начиная с Windows 2003 AD, есть новый вычисляемый атрибут, который вы можете проверить:msDS-User-Account-Control-Computed.

дали класс directoryentry user, вы можете сделать:

string attribName = "msDS-User-Account-Control-Computed";
user.RefreshCache(new string[] { attribName });

const int UF_LOCKOUT = 0x0010;

int userFlags = (int)user.Properties[attribName].Value;

if(userFlags & UF_LOCKOUT == UF_LOCKOUT) 
{
   // if this is the case, the account is locked out
}

если вы можете использовать .NET 3.5, все стало намного проще-проверьте статья MSDN о том, как обращаться с пользователями и группами в .NET 3.5 с помощью System.DirectoryServices.AccountManagement пространство имен. Е. Г. теперь у вас есть собственность IsAccountLockedOut на классе UserPrincipal который надежно говорит вам является ли учетная запись заблокирована.

надеюсь, что это помогает!

Марк


вот атрибуты ad LDAP, которые изменяются для пользователя, когда пароль заблокирован (первое значение) против, когда пароль не заблокирован (второе значение). badPwdCount и lockoutTime, очевидно, наиболее актуальна. Я не уверен, должны ли uSNChanged и whenChanged обновляться вручную или нет.

$ diff LockedOut.ldif NotLockedOut.ldif:

< badPwdCount: 3
> badPwdCount: 0

< lockoutTime: 129144318210315776
> lockoutTime: 0

< uSNChanged: 8064871
> uSNChanged: 8065084

< whenChanged: 20100330141028.0Z
> whenChanged: 20100330141932.0Z

Долго бился над проблемой корректного обновления паролей для авторизуемых через LDAP пользователей.

Настройки умолчанию позволяли корректно логинится и изменять себе пароль без проблем, но в случае истекания срока действия пароля начинались странности —
все необходимые атрибуты проверялись успешно и при логине система корректно рапортовала о необходимости обновления пароля:

You are required to change you LDAP password immediately.

,но после столь обнадеживающей фразы процесс смены пароля заканчивался печально

Authentication failed.

Поиск ничего путного не выдавал по данной проблеме, пришлось дебажить и исправлять самостоятельно.

Ищем проблему

Сначала подозрение пало на некорректно настроенные права доступа в OpenLDAP. Включил полный доступ на запись всем, ситуация не изменилась. При таком поведении, подозрения с LDAP’а были сняты, оставался PAM.

PAM

Просмотрев бегло исходники модуля pam_ldap, и не обнаружив ничего подозрительного начал экспериментировать с общими настройками в /etc/pam.d/common-*
В качестве средства дебага, я воспользовался модулем pam_echo для вывода трейсовых сообщений.

В результате проблема локализовалась в account части, ответственной за проверку «протухания» пароля. После того как она отрабатывала для ldap аккаунтов, передача управления в password не происходило.

Решение

Исходный конфиг для common-account при работе unix и ldap аккаунтов в Ubuntu Server выглядит так:

account [success=2 new_authtok_reqd=done default=ignore] pam_unix.so
account [success=1 default=die] pam_ldap.so
account requisite pam_deny.so
account required pam_permit.so

В результате экспериментов оказалось, что некорректо были настроены секция контрольных флагов (contol-flags) для модуля pam_ldap. Для правильной обработки истекшего пароля необходимо, как и в секции pam_unix, добавить указание для обработки new_authtok_reqd

account [success=1 new_authtok_reqd=done default=die] pam_ldap.so

При внесении данной правки, при попытке залогиниться пользователем с истекшим паролем, форма логина будет радовать нас предложением ввести новый пароль.
Стоит отметить что использование стандартной директивы sufficient вместо детального указания отдельных флагов тоже исправляет проблему с передачей управления дальше.

Проблема и её решение работают и в других дистрибутивах. Так в ALT Легкий и в ПСПО настройки по умолчанию также не позволяют менять пароль при его «протухании» и исправляются аналогичным образом.

Problem Description:

I currently try to change passwords in our Active Directory Envoirenment via LDAP on Linux since the users in question do not have access to a windows-machine and we want to keep it that way.
In order to change the password I am currently stuck figuring out how to use ldapmodify to do so. After a lot of reading on different sites/forums/newsgroups I am much more confused than before

However:
I try the following command to do so:

ldapmodify -f ldif.example -H ldaps://lab01-dc01.example.com -D 'CN=test,CN=users,DC=lab01,DC=example,DC=com' -x -W

The contents of the ldif.example:

dn: CN=test,CN=Users,DC=lab01,DC=example,DC=com
changetype: modify
delete: unicodePwd
unicodePwd:: V3VQdXV1STEyLg==
-
add: unicodePwd
unicodePwd:: QmxhVVVraTEyLg==
-

(Don’t worry – those passwords are not used anywhere and it is not a production envoirenment)

Now – every time I execute the command I get the following error:

modifying entry CN=test,CN=Users,DC=lab01,DC=example,DC=com"
ldapmodify: Constraint violation (19)
 additional info: 0000216C: AtrErr: DSID-03190EB0, #1:
 0: 0000216C: DSID-03190EB0, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 9005a (unicodePwd)

Now, after what I read the reason for this error is either that the password is badly formatted or that the password policy doesn’t allow the password I used. I checked the policy – multiple times now – and the new password definetly complies to the policy by all the criteria. If I set the password using a Windows-machine it also works well (of course I changed the “oldpassword” and “newpassword” afterwards since I am not allowed by the policy to change to an earlier password). The password I enter after passing the “-W” option to ldapmodify is also definetly right, otherwise the error spit out by ldapmodify is that I used invalid credentials instead of a constraint violation.
So – the sole reason I can think of is indeed a bad formatted password – but I can’t figure out where the bad formatting should come from since I use the normal base64 algorythm to encode the password.

Has anyone an idea what is going on?
Can anyone push me in the right direction?

Help is very appreciated and I thank you in advance.

Edit:
Something which bugs me:
When I run the base encoded strings through base64 it keeps telling me “Invalid Input”. Now – I went ahead and just re-coded the passwords with the use of base64 on the linux machine – but when I run the generated string through the decode function again, base64 keeps telling me “Invalid Input”… The strings however slightly changed between the windows-base64 encoded string and the linux encoded string. But base64 just says “Invalid input” no matter what I put in there.

Edit2:
Nevermind – reading the purpose of the function I gather that it throws this error because of the dots and the exclamation mark in the password.

Solution – 1

What about fetching an existsing, working password from a different user and try to include that in your ldif?

This way you will be sure that your password is working.

Second, do not use delete/add use replace instead in the ldif. Maybe the delete will cause an objectclass violation errror.

Third, you only need to base64 encode an attribute if it is contain non-printable or special characters. There is an empty row in the end of the ldif file.

dn: CN=test,CN=Users,DC=lab01,DC=example,DC=com
changetype: modify
replace: unicodePwd
unicodePwd: BlaUUki12.

Regards,

Solution – 2

For future reference, if anyone should encounter similiar problems:
The simple solution? Just use smbpasswd instead of ldap to change the password – that works flawless! I am really grumped that I didn’t think of it before 😀

However – the way to change your password in the active directory using samba (using CentOS):

~#yum install samba
~#smbpasswd -r domaincontroller.example.com -U testuser1
Old SMB password:
New SMB password:
Retype new SMB password:
Password changed for user testuser1 on domaincontroller.example.com

And then you can login using the new password. Easy as that, really.

Solution – 3

yum install samba didn’t work for me as it installed smbpasswd program from samba version 3.6.9.

What worked was yum install samba4-client. This installs smbpasswd program for Samba 4 and this version of smbpasswd actualy can change password on Windows Server 2008 R2 Domain Controller. I used samba4-client as I don’t need the Samba server only it’s client utilities.

The syntax for the smbpasswd command is the same:

smbpasswd -r domaincontroller.example.com -U testuser1    

Hope this helps.

Solution – 4

Constraint error could mean you use an old password that does not conform to the policy of, say, cannot use the last 24 passwords.

For future reference:
Connect to AD server (bind):

  • as Admin: you can change and reset passwords for everyone. There is a difference between change and reset. Change = AD will enforce the password policy. Reset = does not.

  • as a User: you may change your password but are not allowed to reset it. Change = AD will enforce the password policy.

Hope it helps though it’s a little late!

Solution – 5

When setting the password, it needs to be UTF-16LE and Base64 encoded. In Java, it could be done with:

String source = ""car"";
String utf16base64 = new String(Base64.getEncoder().encode(source.getBytes("UTF-16LE")));

UTF-16LE has to be used, UTF-16 is not enough.

Changing ‘unicodePwd’ over LDAP requires that the new password is a Unicode string with double quotes. It means when you want to set a new password(Password01!) convert the password with double quotes("Password01!") into Base64.

An online tool can be used – http://www5.rptea.com/base64/ (select UTF-16).

Details about unicodePwd are there – https://technet.microsoft.com/en-us/magazine/ff848710.aspx .

Понравилась статья? Поделить с друзьями:
  • Ошибка ldap invalid credentials 49
  • Ошибка err 165
  • Ошибка oracle 302000
  • Ошибка kernel auto boost invalid lock release
  • Ошибка oracle 2291