diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/password.c | 23 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 32 |
2 files changed, 40 insertions, 15 deletions
diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 958ed663e6..494d9ecd43 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -77,6 +77,8 @@ void invalidate_vuid(uint16 vuid) free_server_info(&vuser->server_info); + data_blob_free(&vuser->session_key); + DLIST_REMOVE(validated_users, vuser); /* clear the vuid from the 'cache' on each connection, and @@ -109,25 +111,36 @@ void invalidate_all_vuids(void) * @param server_info The token returned from the authentication process. * (now 'owned' by register_vuid) * + * @param session_key The User session key for the login session (now also 'owned' by register_vuid) + * + * @param respose_blob The NT challenge-response, if available. (May be freed after this call) + * + * @param smb_name The untranslated name of the user + * * @return Newly allocated vuid, biased by an offset. (This allows us to * tell random client vuid's (normally zero) from valid vuids.) * */ -int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name) +int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name) { user_struct *vuser = NULL; /* Ensure no vuid gets registered in share level security. */ - if(lp_security() == SEC_SHARE) + if(lp_security() == SEC_SHARE) { + data_blob_free(&session_key); return UID_FIELD_INVALID; + } /* Limit allowed vuids to 16bits - VUID_OFFSET. */ - if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) + if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) { + data_blob_free(&session_key); return UID_FIELD_INVALID; + } if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) { DEBUG(0,("Failed to malloc users struct!\n")); + data_blob_free(&session_key); return UID_FIELD_INVALID; } @@ -156,6 +169,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob if (vuser->n_groups) { if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) { DEBUG(0,("register_vuid: failed to memdup vuser->groups\n")); + data_blob_free(&session_key); free(vuser); free_server_info(&server_info); return UID_FIELD_INVALID; @@ -197,7 +211,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob } } - memcpy(vuser->session_key, server_info->session_key, sizeof(vuser->session_key)); + vuser->session_key = session_key; DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->uid, @@ -211,6 +225,7 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob } else { DEBUG(1, ("server_info does not contain a user_token - cannot continue\n")); free_server_info(&server_info); + data_blob_free(&session_key); SAFE_FREE(vuser->homedir); SAFE_FREE(vuser->unix_homedir); SAFE_FREE(vuser->logon_script); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 314ffbb4a9..64c25db2ab 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -149,7 +149,7 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB auth_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; - uint8 session_key[16]; + DATA_BLOB session_key; uint8 tok_id[2]; BOOL foreign = False; DATA_BLOB nullblob = data_blob(NULL, 0); @@ -164,7 +164,7 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, session_key); + ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key); data_blob_free(&ticket); @@ -223,11 +223,8 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(ret); } - /* Copy out the session key from the AP_REQ. */ - memcpy(server_info->session_key, session_key, sizeof(session_key)); - /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, nullblob, user); + sess_vuid = register_vuid(server_info, session_key, nullblob, user); free(user); @@ -297,9 +294,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out if (NT_STATUS_IS_OK(nt_status)) { int sess_vuid; DATA_BLOB nullblob = data_blob(NULL, 0); + DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length); /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); + sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); (*auth_ntlmssp_state)->server_info = NULL; if (sess_vuid == -1) { @@ -566,6 +564,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, NTSTATUS nt_status; BOOL doencrypt = global_encrypted_passwords_negotiated; + + DATA_BLOB session_key; START_PROFILE(SMBsesssetupX); @@ -766,18 +766,28 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, free_user_info(&user_info); - data_blob_free(&lm_resp); - data_blob_clear_free(&plaintext_password); - if (!NT_STATUS_IS_OK(nt_status)) { nt_status = do_map_to_guest(nt_status, &server_info, user, domain); } if (!NT_STATUS_IS_OK(nt_status)) { data_blob_free(&nt_resp); + data_blob_free(&lm_resp); + data_blob_clear_free(&plaintext_password); return ERROR_NT(nt_status_squash(nt_status)); } + if (server_info->nt_session_key.data) { + session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length); + } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) { + session_key = data_blob(NULL, 16); + SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data, + session_key.data); + } + + data_blob_free(&lm_resp); + data_blob_clear_free(&plaintext_password); + /* it's ok - setup a reply */ set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { @@ -795,7 +805,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, to a uid can get through without a password, on the same VC */ /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, nt_resp, sub_user); + sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user); data_blob_free(&nt_resp); if (sess_vuid == -1) { |