diff options
-rw-r--r-- | source3/include/smb.h | 2 | ||||
-rw-r--r-- | source3/smbd/password.c | 37 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 75 |
3 files changed, 96 insertions, 18 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 55baf84531..2ea6633ceb 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1644,6 +1644,8 @@ typedef struct user_struct struct auth_serversupplied_info *server_info; + struct auth_ntlmssp_state *auth_ntlmssp_state; + } user_struct; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 2ee8c1232e..9ee721089c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -47,7 +47,31 @@ user_struct *get_valid_user_struct(uint16 vuid) return NULL; for (usp=validated_users;usp;usp=usp->next,count++) { - if (vuid == usp->vuid) { + if (vuid == usp->vuid && usp->server_info) { + if (count > 10) { + DLIST_PROMOTE(validated_users, usp); + } + return usp; + } + } + + return NULL; +} + +/**************************************************************************** + Get the user struct of a partial NTLMSSP login +****************************************************************************/ + +user_struct *get_partial_auth_user_struct(uint16 vuid) +{ + user_struct *usp; + int count=0; + + if (vuid == UID_FIELD_INVALID) + return NULL; + + for (usp=validated_users;usp;usp=usp->next,count++) { + if (vuid == usp->vuid && !usp->server_info) { if (count > 10) { DLIST_PROMOTE(validated_users, usp); } @@ -159,6 +183,17 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, vuser->vuid = next_vuid; + if (!server_info) { + next_vuid++; + num_validated_vuids++; + + vuser->server_info = NULL; + + DLIST_ADD(validated_users, vuser); + + return vuser->vuid; + } + /* the next functions should be done by a SID mapping system (SMS) as * the new real sam db won't have reference to unix uids or gids */ diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1ddd6256b3..8586ac1324 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -25,8 +25,6 @@ uint32 global_client_caps = 0; -static struct auth_ntlmssp_state *global_ntlmssp_state; - /* on a logon error possibly map the error to success if "map to guest" is set approriately @@ -353,6 +351,7 @@ static int reply_spnego_kerberos(connection_struct *conn, ***************************************************************************/ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, + uint16 vuid, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) { @@ -416,6 +415,8 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { auth_ntlmssp_end(auth_ntlmssp_state); + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); } return ret; @@ -428,8 +429,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out static int reply_spnego_negotiate(connection_struct *conn, char *inbuf, char *outbuf, + uint16 vuid, int length, int bufsize, - DATA_BLOB blob1) + DATA_BLOB blob1, + AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { char *OIDs[ASN1_MAX_OIDS]; DATA_BLOB secblob; @@ -442,6 +445,9 @@ static int reply_spnego_negotiate(connection_struct *conn, /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -473,25 +479,31 @@ static int reply_spnego_negotiate(connection_struct *conn, int ret = reply_spnego_kerberos(conn, inbuf, outbuf, length, bufsize, &secblob); data_blob_free(&secblob); + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ret; } #endif - if (global_ntlmssp_state) { - auth_ntlmssp_end(&global_ntlmssp_state); + if (*auth_ntlmssp_state) { + auth_ntlmssp_end(auth_ntlmssp_state); } - nt_status = auth_ntlmssp_start(&global_ntlmssp_state); + nt_status = auth_ntlmssp_start(auth_ntlmssp_state); if (!NT_STATUS_IS_OK(nt_status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ERROR_NT(nt_status); } - nt_status = auth_ntlmssp_update(global_ntlmssp_state, + nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, secblob, &chal); data_blob_free(&secblob); - reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, &chal, nt_status); data_blob_free(&chal); @@ -505,8 +517,10 @@ static int reply_spnego_negotiate(connection_struct *conn, ****************************************************************************/ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, + uint16 vuid, int length, int bufsize, - DATA_BLOB blob1) + DATA_BLOB blob1, + AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { DATA_BLOB auth, auth_reply; NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; @@ -515,20 +529,27 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, #if 0 file_save("auth.dat", blob1.data, blob1.length); #endif + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - if (!global_ntlmssp_state) { + if (!*auth_ntlmssp_state) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + /* auth before negotiatiate? */ return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - nt_status = auth_ntlmssp_update(global_ntlmssp_state, - auth, &auth_reply); + nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, + auth, &auth_reply); data_blob_free(&auth); - reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, + auth_ntlmssp_state, &auth_reply, nt_status); data_blob_free(&auth_reply); @@ -553,6 +574,8 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, char *p2; uint16 data_blob_len = SVAL(inbuf, smb_vwv7); enum remote_arch_types ra_type = get_remote_arch(); + int vuid = SVAL(inbuf,smb_uid); + user_struct *vuser = NULL; DEBUG(3,("Doing spnego session setup\n")); @@ -597,16 +620,34 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, ra_lanman_string( native_lanman ); } + vuser = get_partial_auth_user_struct(vuid); + if (!vuser) { + vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL); + if (vuid == -1) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + vuser = get_partial_auth_user_struct(vuid); + } + + if (!vuser) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + SSVAL(outbuf,smb_uid,vuid); + if (blob1.data[0] == ASN1_APPLICATION(0)) { /* its a negTokenTarg packet */ - ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1); + ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1, + &vuser->auth_ntlmssp_state); data_blob_free(&blob1); return ret; } if (blob1.data[0] == ASN1_CONTEXT(1)) { /* its a auth packet */ - ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1); + ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1, + &vuser->auth_ntlmssp_state); data_blob_free(&blob1); return ret; } @@ -682,7 +723,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { if (!global_spnego_negotiated) { DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n")); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } if (SVAL(inbuf,smb_vwv4) == 0) { @@ -843,7 +884,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */ DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } fstrcpy(sub_user, user); |