diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/sesssetup.c | 82 |
1 files changed, 55 insertions, 27 deletions
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7f125de583..e36760c148 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1998-2001 Copyright (C) Andrew Bartlett 2001 Copyright (C) Jim McDonough 2002 + Copyright (C) Luke Howard 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,16 +39,14 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { DEBUG(3,("No such user %s [%s] - using guest account\n", user, domain)); - make_server_info_guest(server_info); - status = NT_STATUS_OK; + status = make_server_info_guest(server_info); } } if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) { if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { DEBUG(3,("Registered username %s for guest access\n",user)); - make_server_info_guest(server_info); - status = NT_STATUS_OK; + status = make_server_info_guest(server_info); } } @@ -146,11 +145,14 @@ static int reply_spnego_kerberos(connection_struct *conn, int sess_vuid; NTSTATUS ret; DATA_BLOB auth_data; + DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; ADS_STRUCT *ads; + uint8 session_key[16]; + uint8 tok_id[2]; BOOL foreign = False; - if (!spnego_parse_krb5_wrap(*secblob, &ticket)) { + if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -162,7 +164,7 @@ static int reply_spnego_kerberos(connection_struct *conn, ads->auth.realm = strdup(lp_realm()); - ret = ads_verify_ticket(ads, &ticket, &client, &auth_data); + ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, &ap_rep, session_key); if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,("Failed to verify incoming ticket!\n")); ads_destroy(&ads); @@ -177,6 +179,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!p) { DEBUG(3,("Doesn't look like a valid principal\n")); ads_destroy(&ads); + data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -184,6 +187,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (strcasecmp(p+1, ads->auth.realm) != 0) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { + data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } foreign = True; @@ -209,31 +213,51 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); + data_blob_free(&ap_rep); return ERROR_NT(NT_STATUS_NO_SUCH_USER); } if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { DEBUG(1,("make_server_info_from_pw failed!\n")); + data_blob_free(&ap_rep); 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, user); free(user); if (sess_vuid == -1) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + ret = NT_STATUS_LOGON_FAILURE; + } else { + set_message(outbuf,4,0,True); + SSVAL(outbuf, smb_vwv3, 0); + + if (server_info->guest) { + SSVAL(outbuf,smb_vwv2,1); + } + + SSVAL(outbuf, smb_uid, sess_vuid); } - set_message(outbuf,4,0,True); - SSVAL(outbuf, smb_vwv3, 0); - add_signature(outbuf); - - SSVAL(outbuf,smb_uid,sess_vuid); - SSVAL(inbuf,smb_uid,sess_vuid); - - return chain_reply(inbuf,outbuf,length,bufsize); + /* wrap that up in a nice GSS-API wrapping */ + if (NT_STATUS_IS_OK(ret)) { + ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP); + } else { + ap_rep_wrapped = data_blob(NULL, 0); + } + response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); + reply_sesssetup_blob(conn, outbuf, response, ret); + + data_blob_free(&ap_rep); + data_blob_free(&ap_rep_wrapped); + data_blob_free(&response); + + return -1; /* already replied */ } #endif @@ -249,10 +273,11 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, { BOOL ret; DATA_BLOB response; - struct auth_serversupplied_info *server_info; - server_info = (*auth_ntlmssp_state)->server_info; + struct auth_serversupplied_info *server_info = NULL; - if (!NT_STATUS_IS_OK(nt_status)) { + if (NT_STATUS_IS_OK(nt_status)) { + server_info = (*auth_ntlmssp_state)->server_info; + } else { nt_status = do_map_to_guest(nt_status, &server_info, (*auth_ntlmssp_state)->ntlmssp_state->user, @@ -280,7 +305,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, } } - response = spnego_gen_auth_response(ntlmssp_blob, nt_status); + response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP); ret = reply_sesssetup_blob(conn, outbuf, response, nt_status); data_blob_free(&response); @@ -363,19 +388,22 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, DATA_BLOB blob1) { DATA_BLOB auth, auth_reply; - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; if (!spnego_parse_auth(blob1, &auth)) { #if 0 file_save("auth.dat", blob1.data, blob1.length); #endif - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - - if ( global_ntlmssp_state ) { - nt_status = auth_ntlmssp_update(global_ntlmssp_state, - auth, &auth_reply); + + if (!global_ntlmssp_state) { + /* auth before negotiatiate? */ + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } + + nt_status = auth_ntlmssp_update(global_ntlmssp_state, + auth, &auth_reply); data_blob_free(&auth); @@ -545,7 +573,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, set_remote_arch( RA_WIN95); } } - + if (!doencrypt) { /* both Win95 and WinNT stuff up the password lengths for non-encrypting systems. Uggh. |