summaryrefslogtreecommitdiff
path: root/source3/smbd/sesssetup.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/sesssetup.c')
-rw-r--r--source3/smbd/sesssetup.c122
1 files changed, 79 insertions, 43 deletions
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 22ad43ff75..e63511c368 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -249,8 +249,8 @@ static void reply_spnego_kerberos(connection_struct *conn,
fstring netbios_domain_name;
struct passwd *pw;
fstring user;
- int sess_vuid;
- NTSTATUS ret;
+ int sess_vuid = SVAL(req->inbuf, smb_uid);
+ NTSTATUS ret = NT_STATUS_OK;
PAC_DATA *pac_data;
DATA_BLOB ap_rep, ap_rep_wrapped, response;
auth_serversupplied_info *server_info = NULL;
@@ -535,18 +535,28 @@ static void reply_spnego_kerberos(connection_struct *conn,
}
}
- /* register_vuid keeps the server info */
- /* register_vuid takes ownership of session_key, no need to free after this.
- A better interface would copy it.... */
- sess_vuid = register_vuid(server_info, session_key, nullblob, client);
+ /* register_existing_vuid keeps the server info */
+ /* register_existing_vuid takes ownership of session_key on success,
+ * no need to free after this on success. A better interface would copy
+ * it.... */
+
+ if (!is_partial_auth_vuid(sess_vuid)) {
+ sess_vuid = register_initial_vuid();
+ }
+ sess_vuid = register_existing_vuid(sess_vuid,
+ server_info,
+ session_key,
+ nullblob,
+ client);
SAFE_FREE(client);
reply_outbuf(req, 4, 0);
- SSVAL(req->outbuf,smb_uid,vuid);
+ SSVAL(req->outbuf,smb_uid,sess_vuid);
if (sess_vuid == UID_FIELD_INVALID ) {
ret = NT_STATUS_LOGON_FAILURE;
+ data_blob_free(&session_key);
} else {
/* current_user_info is changed on new vuid */
reload_services( True );
@@ -560,6 +570,8 @@ static void reply_spnego_kerberos(connection_struct *conn,
SSVAL(req->outbuf, smb_uid, sess_vuid);
sessionsetup_start_signing_engine(server_info, req->inbuf);
+ /* Successful logon. Keep this vuid. */
+ *p_invalidate_vuid = False;
}
/* wrap that up in a nice GSS-API wrapping */
@@ -611,33 +623,43 @@ static void reply_spnego_ntlmssp(connection_struct *conn,
SSVAL(req->outbuf, smb_uid, vuid);
if (NT_STATUS_IS_OK(nt_status)) {
- int sess_vuid;
DATA_BLOB nullblob = data_blob_null;
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, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
+ if (!is_partial_auth_vuid(vuid)) {
+ data_blob_free(&session_key);
+ nt_status = NT_STATUS_LOGON_FAILURE;
+ goto out;
+ }
+ /* register_existing_vuid keeps the server info */
+ if (register_existing_vuid(vuid,
+ server_info,
+ session_key, nullblob,
+ (*auth_ntlmssp_state)->ntlmssp_state->user) !=
+ vuid) {
+ data_blob_free(&session_key);
+ nt_status = NT_STATUS_LOGON_FAILURE;
+ goto out;
+ }
+
(*auth_ntlmssp_state)->server_info = NULL;
- if (sess_vuid == UID_FIELD_INVALID ) {
- nt_status = NT_STATUS_LOGON_FAILURE;
- } else {
-
- /* current_user_info is changed on new vuid */
- reload_services( True );
+ /* current_user_info is changed on new vuid */
+ reload_services( True );
- SSVAL(req->outbuf, smb_vwv3, 0);
-
- if (server_info->guest) {
- SSVAL(req->outbuf,smb_vwv2,1);
- }
-
- SSVAL(req->outbuf,smb_uid,sess_vuid);
+ SSVAL(req->outbuf, smb_vwv3, 0);
- sessionsetup_start_signing_engine(server_info, req->inbuf);
+ if (server_info->guest) {
+ SSVAL(req->outbuf,smb_vwv2,1);
}
+
+ SSVAL(req->outbuf,smb_uid,vuid);
+
+ sessionsetup_start_signing_engine(server_info, req->inbuf);
}
+ out:
+
if (wrap) {
response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
} else {
@@ -655,8 +677,10 @@ static void reply_spnego_ntlmssp(connection_struct *conn,
if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
/* NB. This is *NOT* an error case. JRA */
auth_ntlmssp_end(auth_ntlmssp_state);
- /* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ }
}
}
@@ -1111,36 +1135,36 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn,
}
}
- vuser = get_partial_auth_user_struct(vuid);
- if (!vuser) {
+ /* Did we get a valid vuid ? */
+ if (!is_partial_auth_vuid(vuid)) {
+ /* No, then try and see if this is an intermediate sessionsetup
+ * for a large SPNEGO packet. */
struct pending_auth_data *pad = get_pending_auth_data(smbpid);
if (pad) {
DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
(unsigned int)pad->vuid ));
vuid = pad->vuid;
- vuser = get_partial_auth_user_struct(vuid);
}
}
- if (!vuser) {
- vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL);
- if (vuid == UID_FIELD_INVALID ) {
+ /* Do we have a valid vuid now ? */
+ if (!is_partial_auth_vuid(vuid)) {
+ /* No, start a new authentication setup. */
+ vuid = register_initial_vuid();
+ if (vuid == UID_FIELD_INVALID) {
data_blob_free(&blob1);
reply_nterror(req, nt_status_squash(
NT_STATUS_INVALID_PARAMETER));
return;
}
-
- vuser = get_partial_auth_user_struct(vuid);
}
+ vuser = get_partial_auth_user_struct(vuid);
+ /* This MUST be valid. */
if (!vuser) {
- data_blob_free(&blob1);
- reply_nterror(req, nt_status_squash(
- NT_STATUS_INVALID_PARAMETER));
- return;
+ smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
}
-
+
/* Large (greater than 4k) SPNEGO blobs are split into multiple
* sessionsetup requests as the Windows limit on the security blob
* field is 4k. Bug #4400. JRA.
@@ -1617,13 +1641,25 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req)
data_blob_free(&session_key);
TALLOC_FREE(server_info);
} else {
- /* register_vuid keeps the server info */
- sess_vuid = register_vuid(server_info, session_key,
- nt_resp.data ? nt_resp : lm_resp,
- sub_user);
+ /* Ignore the initial vuid. */
+ sess_vuid = register_initial_vuid();
if (sess_vuid == UID_FIELD_INVALID) {
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
+ data_blob_free(&session_key);
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
+ }
+ /* register_existing_vuid keeps the server info */
+ sess_vuid = register_existing_vuid(sess_vuid,
+ server_info,
+ session_key,
+ nt_resp.data ? nt_resp : lm_resp,
+ sub_user);
+ if (sess_vuid == UID_FIELD_INVALID) {
+ data_blob_free(&nt_resp);
+ data_blob_free(&lm_resp);
+ data_blob_free(&session_key);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
return;