libsmb/ntlm_check.c

ソースコードを見る。

関数

static BOOL smb_pwd_check_ntlmv1 (const DATA_BLOB *nt_response, const uchar *part_passwd, const DATA_BLOB *sec_blob, DATA_BLOB *user_sess_key)
static BOOL smb_pwd_check_ntlmv2 (const DATA_BLOB *ntv2_response, const uchar *part_passwd, const DATA_BLOB *sec_blob, const char *user, const char *domain, BOOL upper_case_domain, DATA_BLOB *user_sess_key)
NTSTATUS ntlm_password_check (TALLOC_CTX *mem_ctx, const DATA_BLOB *challenge, const DATA_BLOB *lm_response, const DATA_BLOB *nt_response, const DATA_BLOB *lm_interactive_pwd, const DATA_BLOB *nt_interactive_pwd, const char *username, const char *client_username, const char *client_domain, const uint8 *lm_pw, const uint8 *nt_pw, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key)
 Check a challenge-response password against the value of the NT or LM password hash.


関数

static BOOL smb_pwd_check_ntlmv1 ( const DATA_BLOB nt_response,
const uchar *  part_passwd,
const DATA_BLOB sec_blob,
DATA_BLOB user_sess_key 
) [static]

ntlm_check.c33 行で定義されています。

参照先 data_blob_::datadata_blob()dump_data()data_blob_::lengthSMBOWFencrypt()SMBsesskeygen_ntv1().

参照元 ntlm_password_check().

00037 {
00038         /* Finish the encryption of part_passwd. */
00039         uchar p24[24];
00040         
00041         if (part_passwd == NULL) {
00042                 DEBUG(10,("No password set - DISALLOWING access\n"));
00043                 /* No password set - always false ! */
00044                 return False;
00045         }
00046         
00047         if (sec_blob->length != 8) {
00048                 DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%lu)\n", 
00049                           (unsigned long)sec_blob->length));
00050                 return False;
00051         }
00052         
00053         if (nt_response->length != 24) {
00054                 DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%lu)\n", 
00055                           (unsigned long)nt_response->length));
00056                 return False;
00057         }
00058 
00059         SMBOWFencrypt(part_passwd, sec_blob->data, p24);
00060         if (user_sess_key != NULL) {
00061                 *user_sess_key = data_blob(NULL, 16);
00062                 SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key->data);
00063         }
00064         
00065         
00066 #ifdef DEBUG_PASSWORD
00067         DEBUG(100,("Part password (P16) was |\n"));
00068         dump_data(100, (const char *)part_passwd, 16);
00069         DEBUGADD(100,("Password from client was |\n"));
00070         dump_data(100, (const char *)nt_response->data, nt_response->length);
00071         DEBUGADD(100,("Given challenge was |\n"));
00072         dump_data(100, (const char *)sec_blob->data, sec_blob->length);
00073         DEBUGADD(100,("Value from encryption was |\n"));
00074         dump_data(100, (const char *)p24, 24);
00075 #endif
00076         return (memcmp(p24, nt_response->data, 24) == 0);
00077 }

static BOOL smb_pwd_check_ntlmv2 ( const DATA_BLOB ntv2_response,
const uchar *  part_passwd,
const DATA_BLOB sec_blob,
const char *  user,
const char *  domain,
BOOL  upper_case_domain,
DATA_BLOB user_sess_key 
) [static]

ntlm_check.c84 行で定義されています。

参照先 data_blob_::datadata_blob()data_blob_clear_free()dump_data()data_blob_::lengthntv2_owf_gen()SMBOWFencrypt_ntv2()SMBsesskeygen_ntv2().

参照元 ntlm_password_check().

00090 {
00091         /* Finish the encryption of part_passwd. */
00092         uchar kr[16];
00093         uchar value_from_encryption[16];
00094         uchar client_response[16];
00095         DATA_BLOB client_key_data;
00096         BOOL res;
00097 
00098         if (part_passwd == NULL) {
00099                 DEBUG(10,("No password set - DISALLOWING access\n"));
00100                 /* No password set - always False */
00101                 return False;
00102         }
00103 
00104         if (sec_blob->length != 8) {
00105                 DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect challenge size (%lu)\n", 
00106                           (unsigned long)sec_blob->length));
00107                 return False;
00108         }
00109         
00110         if (ntv2_response->length < 24) {
00111                 /* We MUST have more than 16 bytes, or the stuff below will go
00112                    crazy.  No known implementation sends less than the 24 bytes
00113                    for LMv2, let alone NTLMv2. */
00114                 DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%lu)\n", 
00115                           (unsigned long)ntv2_response->length));
00116                 return False;
00117         }
00118 
00119         client_key_data = data_blob(ntv2_response->data+16, ntv2_response->length-16);
00120         /* 
00121            todo:  should we be checking this for anything?  We can't for LMv2, 
00122            but for NTLMv2 it is meant to contain the current time etc.
00123         */
00124 
00125         memcpy(client_response, ntv2_response->data, sizeof(client_response));
00126 
00127         if (!ntv2_owf_gen(part_passwd, user, domain, upper_case_domain, kr)) {
00128                 return False;
00129         }
00130 
00131         SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption);
00132         if (user_sess_key != NULL) {
00133                 *user_sess_key = data_blob(NULL, 16);
00134                 SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data);
00135         }
00136 
00137 #if DEBUG_PASSWORD
00138         DEBUG(100,("Part password (P16) was |\n"));
00139         dump_data(100, (const char *)part_passwd, 16);
00140         DEBUGADD(100,("Password from client was |\n"));
00141         dump_data(100, (const char *)ntv2_response->data, ntv2_response->length);
00142         DEBUGADD(100,("Variable data from client was |\n"));
00143         dump_data(100, (const char *)client_key_data.data, client_key_data.length);
00144         DEBUGADD(100,("Given challenge was |\n"));
00145         dump_data(100, (const char *)sec_blob->data, sec_blob->length);
00146         DEBUGADD(100,("Value from encryption was |\n"));
00147         dump_data(100, (const char *)value_from_encryption, 16);
00148 #endif
00149         data_blob_clear_free(&client_key_data);
00150         res = (memcmp(value_from_encryption, client_response, 16) == 0);
00151         if ((!res) && (user_sess_key != NULL))
00152                 data_blob_clear_free(user_sess_key);
00153         return res;
00154 }

NTSTATUS ntlm_password_check ( TALLOC_CTX mem_ctx,
const DATA_BLOB challenge,
const DATA_BLOB lm_response,
const DATA_BLOB nt_response,
const DATA_BLOB lm_interactive_pwd,
const DATA_BLOB nt_interactive_pwd,
const char *  username,
const char *  client_username,
const char *  client_domain,
const uint8 *  lm_pw,
const uint8 *  nt_pw,
DATA_BLOB user_sess_key,
DATA_BLOB lm_sess_key 
)

Check a challenge-response password against the value of the NT or LM password hash.

引数:
mem_ctx talloc context
challenge 8-byte challenge. If all zero, forces plaintext comparison
nt_response 'unicode' NT response to the challenge, or unicode password
lm_response ASCII or LANMAN response to the challenge, or password in DOS code page
username internal Samba username, for log messages
client_username username the client used
client_domain domain name the client used (may be mapped)
nt_pw MD4 unicode password from our passdb or similar
lm_pw LANMAN ASCII password from our passdb or similar
user_sess_key User session key
lm_sess_key LM session key (first 8 bytes of the LM hash)

ntlm_check.c173 行で定義されています。

参照先 data_blob_::datadata_blob()E_P16()data_blob_::lengthmdfour()smb_pwd_check_ntlmv1()smb_pwd_check_ntlmv2()SMBsesskeygen_ntv1().

参照元 local_pw_check()sam_password_ok().

00185 {
00186         static const unsigned char zeros[8] = { 0, };
00187         if (nt_pw == NULL) {
00188                 DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", 
00189                          username));
00190         }
00191 
00192         if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) { 
00193                 if (nt_interactive_pwd->length != 16) {
00194                         DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length,
00195                                  username));
00196                         return NT_STATUS_WRONG_PASSWORD;
00197                 }
00198 
00199                 if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) {
00200                         if (user_sess_key) {
00201                                 *user_sess_key = data_blob(NULL, 16);
00202                                 SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data);
00203                         }
00204                         return NT_STATUS_OK;
00205                 } else {
00206                         DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n",
00207                                  username));
00208                         return NT_STATUS_WRONG_PASSWORD;
00209                 }
00210 
00211         } else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) { 
00212                 if (lm_interactive_pwd->length != 16) {
00213                         DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length,
00214                                  username));
00215                         return NT_STATUS_WRONG_PASSWORD;
00216                 }
00217 
00218                 if (!lp_lanman_auth()) {
00219                         DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n",
00220                                  username));
00221                         return NT_STATUS_WRONG_PASSWORD;
00222                 }
00223 
00224                 if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) {
00225                         return NT_STATUS_OK;
00226                 } else {
00227                         DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n",
00228                                  username));
00229                         return NT_STATUS_WRONG_PASSWORD;
00230                 }
00231         }
00232 
00233         /* Check for cleartext netlogon. Used by Exchange 5.5. */
00234         if (challenge->length == sizeof(zeros) && 
00235             (memcmp(challenge->data, zeros, challenge->length) == 0 )) {
00236 
00237                 DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n",
00238                          username));
00239                 if (nt_pw && nt_response->length) {
00240                         unsigned char pwhash[16];
00241                         mdfour(pwhash, nt_response->data, nt_response->length);
00242                         if (memcmp(pwhash, nt_pw, sizeof(pwhash)) == 0) {
00243                                 return NT_STATUS_OK;
00244                         } else {
00245                                 DEBUG(3,("ntlm_password_check: NT (Unicode) plaintext password check failed for user %s\n",
00246                                          username));
00247                                 return NT_STATUS_WRONG_PASSWORD;
00248                         }
00249 
00250                 } else if (!lp_lanman_auth()) {
00251                         DEBUG(3,("ntlm_password_check: (plaintext password check) LANMAN passwords NOT PERMITTED for user %s\n",
00252                                  username));
00253 
00254                 } else if (lm_pw && lm_response->length) {
00255                         uchar dospwd[14]; 
00256                         uchar p16[16]; 
00257                         ZERO_STRUCT(dospwd);
00258                         
00259                         memcpy(dospwd, lm_response->data, MIN(lm_response->length, sizeof(dospwd)));
00260                         /* Only the fisrt 14 chars are considered, password need not be null terminated. */
00261 
00262                         /* we *might* need to upper-case the string here */
00263                         E_P16((const unsigned char *)dospwd, p16);
00264 
00265                         if (memcmp(p16, lm_pw, sizeof(p16)) == 0) {
00266                                 return NT_STATUS_OK;
00267                         } else {
00268                                 DEBUG(3,("ntlm_password_check: LANMAN (ASCII) plaintext password check failed for user %s\n",
00269                                          username));
00270                                 return NT_STATUS_WRONG_PASSWORD;
00271                         }
00272                 } else {
00273                         DEBUG(3, ("Plaintext authentication for user %s attempted, but neither NT nor LM passwords available\n", username));
00274                         return NT_STATUS_WRONG_PASSWORD;
00275                 }
00276         }
00277 
00278         if (nt_response->length != 0 && nt_response->length < 24) {
00279                 DEBUG(2,("ntlm_password_check: invalid NT password length (%lu) for user %s\n", 
00280                          (unsigned long)nt_response->length, username));                
00281         }
00282         
00283         if (nt_response->length >= 24 && nt_pw) {
00284                 if (nt_response->length > 24) {
00285                         /* We have the NT MD4 hash challenge available - see if we can
00286                            use it 
00287                         */
00288                         DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain));
00289                         if (smb_pwd_check_ntlmv2( nt_response, 
00290                                                   nt_pw, challenge, 
00291                                                   client_username, 
00292                                                   client_domain,
00293                                                   False,
00294                                                   user_sess_key)) {
00295                                 return NT_STATUS_OK;
00296                         }
00297                         
00298                         DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain));
00299                         if (smb_pwd_check_ntlmv2( nt_response, 
00300                                                   nt_pw, challenge, 
00301                                                   client_username, 
00302                                                   client_domain,
00303                                                   True,
00304                                                   user_sess_key)) {
00305                                 return NT_STATUS_OK;
00306                         }
00307                         
00308                         DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n"));
00309                         if (smb_pwd_check_ntlmv2( nt_response, 
00310                                                   nt_pw, challenge, 
00311                                                   client_username, 
00312                                                   "",
00313                                                   False,
00314                                                   user_sess_key)) {
00315                                 return NT_STATUS_OK;
00316                         } else {
00317                                 DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n"));
00318                                 return NT_STATUS_WRONG_PASSWORD;
00319                         }
00320                 }
00321 
00322                 if (lp_ntlm_auth()) {           
00323                         /* We have the NT MD4 hash challenge available - see if we can
00324                            use it (ie. does it exist in the smbpasswd file).
00325                         */
00326                         DEBUG(4,("ntlm_password_check: Checking NT MD4 password\n"));
00327                         if (smb_pwd_check_ntlmv1(nt_response, 
00328                                                  nt_pw, challenge,
00329                                                  user_sess_key)) {
00330                                 /* The LM session key for this response is not very secure, 
00331                                    so use it only if we otherwise allow LM authentication */
00332 
00333                                 if (lp_lanman_auth() && lm_pw) {
00334                                         uint8 first_8_lm_hash[16];
00335                                         memcpy(first_8_lm_hash, lm_pw, 8);
00336                                         memset(first_8_lm_hash + 8, '\0', 8);
00337                                         if (lm_sess_key) {
00338                                                 *lm_sess_key = data_blob(first_8_lm_hash, 16);
00339                                         }
00340                                 }
00341                                 return NT_STATUS_OK;
00342                         } else {
00343                                 DEBUG(3,("ntlm_password_check: NT MD4 password check failed for user %s\n",
00344                                          username));
00345                                 return NT_STATUS_WRONG_PASSWORD;
00346                         }
00347                 } else {
00348                         DEBUG(2,("ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s\n",
00349                                  username));                    
00350                         /* no return, becouse we might pick up LMv2 in the LM field */
00351                 }
00352         }
00353         
00354         if (lm_response->length == 0) {
00355                 DEBUG(3,("ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s\n",
00356                          username));
00357                 return NT_STATUS_WRONG_PASSWORD;
00358         }
00359         
00360         if (lm_response->length < 24) {
00361                 DEBUG(2,("ntlm_password_check: invalid LanMan password length (%lu) for user %s\n", 
00362                          (unsigned long)nt_response->length, username));                
00363                 return NT_STATUS_WRONG_PASSWORD;
00364         }
00365                 
00366         if (!lp_lanman_auth()) {
00367                 DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n",
00368                          username));
00369         } else if (!lm_pw) {
00370                 DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n",
00371                          username));
00372         } else {
00373                 DEBUG(4,("ntlm_password_check: Checking LM password\n"));
00374                 if (smb_pwd_check_ntlmv1(lm_response, 
00375                                          lm_pw, challenge,
00376                                          NULL)) {
00377                         uint8 first_8_lm_hash[16];
00378                         memcpy(first_8_lm_hash, lm_pw, 8);
00379                         memset(first_8_lm_hash + 8, '\0', 8);
00380                         if (user_sess_key) {
00381                                 *user_sess_key = data_blob(first_8_lm_hash, 16);
00382                         }
00383 
00384                         if (lm_sess_key) {
00385                                 *lm_sess_key = data_blob(first_8_lm_hash, 16);
00386                         }
00387                         return NT_STATUS_OK;
00388                 }
00389         }
00390         
00391         if (!nt_pw) {
00392                 DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username));
00393                 return NT_STATUS_WRONG_PASSWORD;
00394         }
00395         
00396         /* This is for 'LMv2' authentication.  almost NTLMv2 but limited to 24 bytes.
00397            - related to Win9X, legacy NAS pass-though authentication
00398         */
00399         DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n", client_domain));
00400         if (smb_pwd_check_ntlmv2( lm_response, 
00401                                   nt_pw, challenge, 
00402                                   client_username,
00403                                   client_domain,
00404                                   False,
00405                                   NULL)) {
00406                 return NT_STATUS_OK;
00407         }
00408         
00409         DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", client_domain));
00410         if (smb_pwd_check_ntlmv2( lm_response, 
00411                                   nt_pw, challenge, 
00412                                   client_username,
00413                                   client_domain,
00414                                   True,
00415                                   NULL)) {
00416                 return NT_STATUS_OK;
00417         }
00418         
00419         DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n"));
00420         if (smb_pwd_check_ntlmv2( lm_response, 
00421                                   nt_pw, challenge, 
00422                                   client_username,
00423                                   "",
00424                                   False,
00425                                   NULL)) {
00426                 return NT_STATUS_OK;
00427         }
00428 
00429         /* Apparently NT accepts NT responses in the LM field
00430            - I think this is related to Win9X pass-though authentication
00431         */
00432         DEBUG(4,("ntlm_password_check: Checking NT MD4 password in LM field\n"));
00433         if (lp_ntlm_auth()) {
00434                 if (smb_pwd_check_ntlmv1(lm_response, 
00435                                          nt_pw, challenge,
00436                                          NULL)) {
00437                         /* The session key for this response is still very odd.  
00438                            It not very secure, so use it only if we otherwise 
00439                            allow LM authentication */
00440 
00441                         if (lp_lanman_auth() && lm_pw) {
00442                                 uint8 first_8_lm_hash[16];
00443                                 memcpy(first_8_lm_hash, lm_pw, 8);
00444                                 memset(first_8_lm_hash + 8, '\0', 8);
00445                                 if (user_sess_key) {
00446                                         *user_sess_key = data_blob(first_8_lm_hash, 16);
00447                                 }
00448 
00449                                 if (lm_sess_key) {
00450                                         *lm_sess_key = data_blob(first_8_lm_hash, 16);
00451                                 }
00452                         }
00453                         return NT_STATUS_OK;
00454                 }
00455                 DEBUG(3,("ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",username));
00456         } else {
00457                 DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username));
00458         }
00459         return NT_STATUS_WRONG_PASSWORD;
00460 }


Sambaに対してSat Aug 29 21:23:49 2009に生成されました。  doxygen 1.4.7