diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/process.c | 12 | ||||
-rw-r--r-- | source3/smbd/server.c | 5 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 338 |
3 files changed, 249 insertions, 106 deletions
diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 98ec6ce184..8018d5f6f6 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1314,17 +1314,5 @@ void smbd_process(void) last_timeout_processing_time = new_check_time; /* Reset time. */ } } - - /* The timeout_processing function isn't run nearly - often enough to implement 'max log size' without - overrunning the size of the file by many megabytes. - This is especially true if we are running at debug - level 10. Checking every 50 SMBs is a nice - tradeoff of performance vs log file size overrun. */ - - if ((num_smbs % 50) == 0 && need_to_check_log_size()) { - change_to_root_user(); - check_log_size(); - } } } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 194f9f2300..1d1061f6d8 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -377,10 +377,6 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ return False; } - /* Load DSO's */ - if(lp_modules()) - smb_load_modules(lp_modules()); - return True; } /* The parent doesn't need this socket */ @@ -870,7 +866,6 @@ static BOOL init_structs(void ) smbd_process(); uni_group_cache_shutdown(); - namecache_shutdown(); exit_server("normal exit"); return(0); } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 23a44d8df7..f8e8e017e0 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,8 +23,7 @@ #include "includes.h" uint32 global_client_caps = 0; - -static struct auth_ntlmssp_state *global_ntlmssp_state; +static struct auth_context *ntlmssp_auth_context = NULL; /* on a logon error possibly map the error to success if "map to guest" @@ -213,7 +212,7 @@ static int reply_spnego_kerberos(connection_struct *conn, send a security blob via a session setup reply ****************************************************************************/ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, - DATA_BLOB blob, NTSTATUS nt_status) + DATA_BLOB blob, uint32 errcode) { char *p; @@ -222,69 +221,21 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end that we aren't finished yet */ - nt_status = nt_status_squash(nt_status); - SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status)); + SIVAL(outbuf, smb_rcls, errcode); SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */ SSVAL(outbuf, smb_vwv3, blob.length); p = smb_buf(outbuf); memcpy(p, blob.data, blob.length); - - add_signature(outbuf); + p += blob.length; + p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE); + p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE); + set_message_end(outbuf,p); return send_smb(smbd_server_fd(),outbuf); } /**************************************************************************** - send a session setup reply, wrapped in SPNEGO. - get vuid and check first. - end the NTLMSSP exchange context if we are OK/complete fail -***************************************************************************/ -static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, - AUTH_NTLMSSP_STATE **auth_ntlmssp_state, - DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) -{ - DATA_BLOB response; - struct auth_serversupplied_info *server_info; - server_info = (*auth_ntlmssp_state)->server_info; - - if (!NT_STATUS_IS_OK(nt_status)) { - nt_status = do_map_to_guest(nt_status, - &server_info, - (*auth_ntlmssp_state)->ntlmssp_state->user, - (*auth_ntlmssp_state)->ntlmssp_state->domain); - } - - if (NT_STATUS_IS_OK(nt_status)) { - int sess_vuid; - sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user /* check this for weird */); - - if (sess_vuid == -1) { - nt_status = NT_STATUS_LOGON_FAILURE; - } else { - - set_message(outbuf,4,0,True); - SSVAL(outbuf, smb_vwv3, 0); - - if ((*auth_ntlmssp_state)->server_info->guest) { - SSVAL(outbuf,smb_vwv2,1); - } - - SSVAL(outbuf,smb_uid,sess_vuid); - } - } - - response = spnego_gen_auth_response(ntlmssp_blob, nt_status); - reply_sesssetup_blob(conn, outbuf, response, nt_status); - data_blob_free(&response); - - if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - auth_ntlmssp_end(&global_ntlmssp_state); - } - - return True; -} - -/**************************************************************************** reply to a session setup spnego negotiate packet ****************************************************************************/ static int reply_spnego_negotiate(connection_struct *conn, @@ -296,9 +247,12 @@ static int reply_spnego_negotiate(connection_struct *conn, char *OIDs[ASN1_MAX_OIDS]; DATA_BLOB secblob; int i; - DATA_BLOB chal; + uint32 ntlmssp_command, neg_flags, chal_flags; + DATA_BLOB chal, spnego_chal; + const uint8 *cryptkey; BOOL got_kerberos = False; NTSTATUS nt_status; + char *cliname=NULL, *domname=NULL; /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { @@ -324,26 +278,95 @@ static int reply_spnego_negotiate(connection_struct *conn, } #endif - if (global_ntlmssp_state) { - auth_ntlmssp_end(&global_ntlmssp_state); + /* parse the NTLMSSP packet */ +#if 0 + file_save("secblob.dat", secblob.data, secblob.length); +#endif + + if (!msrpc_parse(&secblob, "CddAA", + "NTLMSSP", + &ntlmssp_command, + &neg_flags, + &cliname, + &domname)) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + + data_blob_free(&secblob); - nt_status = auth_ntlmssp_start(&global_ntlmssp_state); - if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status); + if (ntlmssp_command != NTLMSSP_NEGOTIATE) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - nt_status = auth_ntlmssp_update(global_ntlmssp_state, - secblob, &chal); + debug_ntlmssp_flags(neg_flags); - data_blob_free(&secblob); + if (ntlmssp_auth_context) { + (ntlmssp_auth_context->free)(&ntlmssp_auth_context); + } + + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) { + return ERROR_NT(nt_status); + } + + cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context); - reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, - &chal, nt_status); + /* Give them the challenge. For now, ignore neg_flags and just + return the flags we want. Obviously this is not correct */ + + chal_flags = NTLMSSP_NEGOTIATE_UNICODE | + NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_CHAL_TARGET_INFO; + + { + DATA_BLOB domain_blob, struct_blob; + fstring dnsname, dnsdomname; + msrpc_gen(&domain_blob, + "U", + lp_workgroup()); + + fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():""); + strlower(dnsdomname); + + fstrcpy(dnsname, global_myname()); + fstrcat(dnsname, "."); + fstrcat(dnsname, dnsdomname); + strlower(dnsname); + + msrpc_gen(&struct_blob, "aaaaa", + 2, lp_workgroup(), + 1, global_myname(), + 4, dnsdomname, + 3, dnsname, + 0, ""); + + msrpc_gen(&chal, "CdUdbddB", + "NTLMSSP", + NTLMSSP_CHALLENGE, + lp_workgroup(), + chal_flags, + cryptkey, 8, + 0, 0, + struct_blob.data, struct_blob.length); + + data_blob_free(&domain_blob); + data_blob_free(&struct_blob); + } + + if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) { + DEBUG(3,("Failed to generate challenge\n")); + data_blob_free(&chal); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + /* now tell the client to send the auth packet */ + reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)); + data_blob_free(&chal); + data_blob_free(&spnego_chal); - /* already replied */ + /* and tell smbd that we have already replied to this packet */ return -1; } @@ -355,8 +378,23 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, DATA_BLOB blob1) { - DATA_BLOB auth, auth_reply; + DATA_BLOB auth, response; + char *workgroup = NULL, *user = NULL, *machine = NULL; + DATA_BLOB lmhash, nthash, sess_key; + DATA_BLOB plaintext_password = data_blob(NULL, 0); + uint32 ntlmssp_command, neg_flags; NTSTATUS nt_status; + int sess_vuid; + BOOL as_guest; + uint32 auth_flags = AUTH_FLAG_NONE; + auth_usersupplied_info *user_info = NULL; + auth_serversupplied_info *server_info = NULL; + + /* we must have setup the auth context by now */ + if (!ntlmssp_auth_context) { + DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n")); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } if (!spnego_parse_auth(blob1, &auth)) { #if 0 @@ -365,15 +403,107 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - nt_status = auth_ntlmssp_update(global_ntlmssp_state, - auth, &auth_reply); + /* now the NTLMSSP encoded auth hashes */ + if (!msrpc_parse(&auth, "CdBBUUUBd", + "NTLMSSP", + &ntlmssp_command, + &lmhash, + &nthash, + &workgroup, + &user, + &machine, + &sess_key, + &neg_flags)) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } data_blob_free(&auth); + data_blob_free(&sess_key); + + DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n", + user, workgroup, machine, lmhash.length, nthash.length)); - reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, - &auth_reply, nt_status); - - data_blob_free(&auth_reply); + /* the client has given us its machine name (which we otherwise would not get on port 445). + we need to possibly reload smb.conf if smb.conf includes depend on the machine name */ + + set_remote_machine_name(machine); + + /* setup the string used by %U */ + sub_set_smb_name(user); + + reload_services(True); + +#if 0 + file_save("nthash1.dat", nthash.data, nthash.length); + file_save("lmhash1.dat", lmhash.data, lmhash.length); +#endif + + if (lmhash.length) { + auth_flags |= AUTH_FLAG_LM_RESP; + } + + if (nthash.length == 24) { + auth_flags |= AUTH_FLAG_NTLM_RESP; + } else if (nthash.length > 24) { + auth_flags |= AUTH_FLAG_NTLMv2_RESP; + }; + + nt_status = make_user_info_map(&user_info, user, workgroup, machine, + lmhash, nthash, plaintext_password, + auth_flags, True); + + /* it looks a bit weird, but this function returns int type... */ + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info); + + if (!NT_STATUS_IS_OK(nt_status)) { + nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup); + } + + SAFE_FREE(workgroup); + SAFE_FREE(machine); + + (ntlmssp_auth_context->free)(&ntlmssp_auth_context); + + free_user_info(&user_info); + + data_blob_free(&lmhash); + + data_blob_free(&nthash); + + if (!NT_STATUS_IS_OK(nt_status)) { + SAFE_FREE(user); + return ERROR_NT(nt_status_squash(nt_status)); + } + + as_guest = server_info->guest; + + sess_vuid = register_vuid(server_info, user); + free_server_info(&server_info); + + SAFE_FREE(user); + + if (sess_vuid == -1) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + set_message(outbuf,4,0,True); + SSVAL(outbuf, smb_vwv3, 0); + + if (as_guest) { + SSVAL(outbuf,smb_vwv2,1); + } + + add_signature(outbuf); + + SSVAL(outbuf,smb_uid,sess_vuid); + SSVAL(inbuf,smb_uid,sess_vuid); + + response = spnego_gen_auth_response(); + reply_sesssetup_blob(conn, outbuf, response, 0); /* and tell smbd that we have already replied to this packet */ return -1; @@ -381,16 +511,49 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, /**************************************************************************** +reply to a session setup spnego anonymous packet +****************************************************************************/ +static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf, + int length, int bufsize) +{ + int sess_vuid; + auth_serversupplied_info *server_info = NULL; + NTSTATUS nt_status; + + nt_status = check_guest_password(&server_info); + + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status_squash(nt_status)); + } + + sess_vuid = register_vuid(server_info, lp_guestaccount()); + + free_server_info(&server_info); + + if (sess_vuid == -1) { + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + + 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); +} + + +/**************************************************************************** reply to a session setup command ****************************************************************************/ -static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, - char *outbuf, +static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf, int length,int bufsize) { uint8 *p; DATA_BLOB blob1; int ret; - size_t bufrem; DEBUG(3,("Doing spnego session setup\n")); @@ -401,13 +564,12 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, p = (uint8 *)smb_buf(inbuf); if (SVAL(inbuf, smb_vwv7) == 0) { - /* an invalid request */ - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + /* an anonymous request */ + return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize); } - bufrem = smb_bufrem(inbuf, p); /* pull the spnego blob */ - blob1 = data_blob(p, MIN(bufrem, SVAL(inbuf, smb_vwv7))); + blob1 = data_blob(p, SVAL(inbuf, smb_vwv7)); #if 0 file_save("negotiate.dat", blob1.data, blob1.length); @@ -624,10 +786,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, nt_status = check_guest_password(&server_info); } else if (doencrypt) { - if (!negprot_global_auth_context) { - DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } nt_status = make_user_info_for_reply_enc(&user_info, user, domain, lm_resp, nt_resp); if (NT_STATUS_IS_OK(nt_status)) { @@ -672,8 +830,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } /* it's ok - setup a reply */ - set_message(outbuf,3,0,True); - if (Protocol == PROTOCOL_NT1) { + if (Protocol < PROTOCOL_NT1) { + set_message(outbuf,3,0,True); + } else { + set_message(outbuf,3,0,True); add_signature(outbuf); /* perhaps grab OS version here?? */ } |