diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/aio.c | 45 | ||||
-rw-r--r-- | source3/smbd/notify_inotify.c | 8 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 10 | ||||
-rw-r--r-- | source3/smbd/open.c | 9 | ||||
-rw-r--r-- | source3/smbd/password.c | 4 | ||||
-rw-r--r-- | source3/smbd/reply.c | 22 | ||||
-rw-r--r-- | source3/smbd/seal.c | 20 | ||||
-rw-r--r-- | source3/smbd/server.c | 3 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 120 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 4 |
10 files changed, 175 insertions, 70 deletions
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 86fdfe31b7..2889e3c13f 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -141,21 +141,27 @@ static struct aio_extra *find_aio_ex(uint16 mid) We can have these many aio buffers in flight. *****************************************************************************/ -#define AIO_PENDING_SIZE 10 +static int aio_pending_size; static sig_atomic_t signals_received; static int outstanding_aio_calls; -static uint16 aio_pending_array[AIO_PENDING_SIZE]; +static uint16 *aio_pending_array; /**************************************************************************** Signal handler when an aio request completes. *****************************************************************************/ -static void signal_handler(int sig, siginfo_t *info, void *unused) +void aio_request_done(uint16_t mid) { - if (signals_received < AIO_PENDING_SIZE) { - aio_pending_array[signals_received] = info->si_value.sival_int; + if (signals_received < aio_pending_size) { + aio_pending_array[signals_received] = mid; signals_received++; - } /* Else signal is lost. */ + } + /* Else signal is lost. */ +} + +static void signal_handler(int sig, siginfo_t *info, void *unused) +{ + aio_request_done(info->si_value.sival_int); sys_select_signal(RT_SIGNAL_AIO); } @@ -176,6 +182,10 @@ void initialize_async_io_handler(void) { struct sigaction act; + aio_pending_size = lp_maxmux(); + aio_pending_array = SMB_MALLOC_ARRAY(uint16, aio_pending_size); + SMB_ASSERT(aio_pending_array != NULL); + ZERO_STRUCT(act); act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; @@ -202,6 +212,12 @@ bool schedule_aio_read_and_X(connection_struct *conn, size_t bufsize; size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); + if (fsp->base_fsp != NULL) { + /* No AIO on streams yet */ + DEBUG(10, ("AIO on streams not yet supported\n")); + return false; + } + if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a read for aio request. */ @@ -219,7 +235,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, return False; } - if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + if (outstanding_aio_calls >= aio_pending_size) { DEBUG(10,("schedule_aio_read_and_X: Already have %d aio " "activities outstanding.\n", outstanding_aio_calls )); @@ -285,6 +301,12 @@ bool schedule_aio_write_and_X(connection_struct *conn, bool write_through = BITSETW(req->inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); + if (fsp->base_fsp != NULL) { + /* No AIO on streams yet */ + DEBUG(10, ("AIO on streams not yet supported\n")); + return false; + } + if ((!min_aio_write_size || (numtowrite < min_aio_write_size)) && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a write for aio request. */ @@ -302,7 +324,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, return False; } - if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + if (outstanding_aio_calls >= aio_pending_size) { DEBUG(3,("schedule_aio_write_and_X: Already have %d aio " "activities outstanding.\n", outstanding_aio_calls )); @@ -351,6 +373,8 @@ bool schedule_aio_write_and_X(connection_struct *conn, return False; } + release_level_2_oplocks_on_change(fsp); + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) && fsp->aio_write_behind) { /* Lie to the client and immediately claim we finished the @@ -421,6 +445,9 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); SSVAL(smb_buf(outbuf),-2,nread); + aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread; + aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos; + DEBUG( 3, ( "handle_aio_read_complete file %s max=%d " "nread=%d\n", aio_ex->fsp->fsp_name, @@ -522,6 +549,8 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); } + + aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten; } show_msg(outbuf); diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index 73cee440d4..fa0f0ed51d 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -29,10 +29,12 @@ #include <asm/types.h> #endif +#ifndef HAVE_INOTIFY_INIT + #include <linux/inotify.h> #include <asm/unistd.h> -#ifndef HAVE_INOTIFY_INIT + /* glibc doesn't define these functions yet (as of March 2006) */ @@ -50,6 +52,10 @@ static int inotify_rm_watch(int fd, int wd) { return syscall(__NR_inotify_rm_watch, fd, wd); } +#else + +#include <sys/inotify.h> + #endif diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9381174af0..5293ca5347 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -558,7 +558,7 @@ void reply_ntcreate_and_X(struct smb_request *req) } file_len = sbuf.st_size; - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -626,7 +626,7 @@ void reply_ntcreate_and_X(struct smb_request *req) uint32 perms = 0; p += 25; if (fsp->is_directory - || can_write_to_file(conn, fname, &sbuf)) { + || can_write_to_file(conn, fsp->fsp_name, &sbuf)) { perms = FILE_GENERIC_ALL; } else { perms = FILE_GENERIC_READ|FILE_EXECUTE; @@ -1007,7 +1007,7 @@ static void call_nt_transact_create(connection_struct *conn, } file_len = sbuf.st_size; - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -1075,7 +1075,7 @@ static void call_nt_transact_create(connection_struct *conn, uint32 perms = 0; p += 25; if (fsp->is_directory - || can_write_to_file(conn, fname, &sbuf)) { + || can_write_to_file(conn, fsp->fsp_name, &sbuf)) { perms = FILE_GENERIC_ALL; } else { perms = FILE_GENERIC_READ|FILE_EXECUTE; @@ -1083,7 +1083,7 @@ static void call_nt_transact_create(connection_struct *conn, SIVAL(p,0,perms); } - DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); + DEBUG(5,("call_nt_transact_create: open name = %s\n", fsp->fsp_name)); /* Send the required number of replies */ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aa4bc48f3d..cc78503379 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2671,8 +2671,9 @@ NTSTATUS create_file_unixpath(connection_struct *conn, status = split_ntfs_stream_name(talloc_tos(), fname, &base, NULL); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("split_ntfs_stream_name failed: %s\n", - nt_errstr(status))); + DEBUG(10, ("create_file_unixpath: " + "split_ntfs_stream_name failed: %s\n", + nt_errstr(status))); goto fail; } @@ -2840,7 +2841,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, } } - DEBUG(10, ("create_file: info=%d\n", info)); + DEBUG(10, ("create_file_unixpath: info=%d\n", info)); /* * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In @@ -2867,7 +2868,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, return NT_STATUS_OK; fail: - DEBUG(10, ("create_file: %s\n", nt_errstr(status))); + DEBUG(10, ("create_file_unixpath: %s\n", nt_errstr(status))); if (fsp != NULL) { close_file(fsp, ERROR_CLOSE); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 687b67950a..80eba562c5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -121,6 +121,10 @@ void invalidate_vuid(uint16 vuid) data_blob_free(&vuser->session_key); + if (vuser->auth_ntlmssp_state) { + auth_ntlmssp_end(&vuser->auth_ntlmssp_state); + } + DLIST_REMOVE(validated_users, vuser); /* clear the vuid from the 'cache' on each connection, and diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 669dad2e3a..818ff319e4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1639,11 +1639,11 @@ void reply_open(struct smb_request *req) } size = sbuf.st_size; - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); mtime = sbuf.st_mtime; if (fattr & aDIR) { - DEBUG(3,("attempt to open a directory %s\n",fname)); + DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name)); close_file(fsp,ERROR_CLOSE); reply_doserror(req, ERRDOS,ERRnoaccess); END_PROFILE(SMBopen); @@ -1802,7 +1802,7 @@ void reply_open_and_X(struct smb_request *req) sbuf.st_size = get_allocation_size(conn,fsp,&sbuf); } - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); mtime = sbuf.st_mtime; if (fattr & aDIR) { close_file(fsp,ERROR_CLOSE); @@ -1985,7 +1985,7 @@ void reply_mknew(struct smb_request *req) } ts[0] = get_atimespec(&sbuf); /* atime. */ - file_ntimes(conn, fname, ts); + file_ntimes(conn, fsp->fsp_name, ts); reply_outbuf(req, 1, 0); SSVAL(req->outbuf,smb_vwv0,fsp->fnum); @@ -2000,9 +2000,9 @@ void reply_mknew(struct smb_request *req) CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - DEBUG( 2, ( "reply_mknew: file %s\n", fname ) ); + DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) ); DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", - fname, fsp->fh->fd, (unsigned int)fattr ) ); + fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) ); END_PROFILE(SMBcreate); return; @@ -2125,9 +2125,9 @@ void reply_ctemp(struct smb_request *req) SSVAL(req->outbuf,smb_vwv0,fsp->fnum); /* the returned filename is relative to the directory */ - s = strrchr_m(fname, '/'); + s = strrchr_m(fsp->fsp_name, '/'); if (!s) { - s = fname; + s = fsp->fsp_name; } else { s++; } @@ -2154,9 +2154,9 @@ void reply_ctemp(struct smb_request *req) CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) ); - DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd, - (unsigned int)sbuf.st_mode ) ); + DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) ); + DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name, + fsp->fh->fd, (unsigned int)sbuf.st_mode ) ); END_PROFILE(SMBctemp); return; diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index ea017e08d8..d4394e5bca 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -496,12 +496,15 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, srv_free_encryption_context(&partial_srv_trans_enc_ctx); + if (got_kerberos_mechanism) { #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); - } else +#else + /* Currently we don't SPNEGO negotiate + * back to NTLMSSP as we do in sessionsetupX. We should... */ + return NT_STATUS_LOGON_FAILURE; #endif - { + } else { status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true); } @@ -558,7 +561,16 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); data_blob_free(&auth); - response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); + /* From RFC4178. + * + * supportedMech + * + * This field SHALL only be present in the first reply from the + * target. + * So set mechOID to NULL here. + */ + + response = spnego_gen_auth_response(&auth_reply, status, NULL); data_blob_free(&auth_reply); if (NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 7116027adf..7bf11abfbd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -988,7 +988,8 @@ static bool init_structs(void ) init_dptrs(); - secrets_init(); + if (!secrets_init()) + return False; return True; } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1e4e208951..9baa02977a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -259,7 +259,7 @@ static void reply_spnego_kerberos(struct smb_request *req, fstring user; int sess_vuid = req->vuid; NTSTATUS ret = NT_STATUS_OK; - PAC_DATA *pac_data = NULL; + struct PAC_DATA *pac_data = NULL; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; DATA_BLOB session_key = data_blob_null; @@ -268,7 +268,7 @@ static void reply_spnego_kerberos(struct smb_request *req, fstring real_username; bool map_domainuser_to_guest = False; bool username_was_mapped; - PAC_LOGON_INFO *logon_info = NULL; + struct PAC_LOGON_INFO *logon_info = NULL; ZERO_STRUCT(ticket); ZERO_STRUCT(ap_rep); @@ -394,10 +394,9 @@ static void reply_spnego_kerberos(struct smb_request *req, domain = p+1; - if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) { - unistr2_to_ascii(netbios_domain_name, - &logon_info->info3.uni_logon_dom, - sizeof(netbios_domain_name)); + if (logon_info && logon_info->info3.base.domain.string) { + fstrcpy(netbios_domain_name, + logon_info->info3.base.domain.string); domain = netbios_domain_name; DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain)); @@ -620,6 +619,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req, uint16 vuid, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, + const char *OID, bool wrap) { DATA_BLOB response; @@ -680,7 +680,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req, if (wrap) { response = spnego_gen_auth_response(ntlmssp_blob, - nt_status, OID_NTLMSSP); + nt_status, OID); } else { response = *ntlmssp_blob; } @@ -745,6 +745,28 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, } /**************************************************************************** + Fall back from krb5 to NTLMSSP. +****************************************************************************/ + +static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req, + uint16 vuid) +{ + DATA_BLOB response; + + reply_outbuf(req, 4, 0); + SSVAL(req->outbuf,smb_uid,vuid); + + DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO " + "but set to downgrade to NTLMSSP\n")); + + response = spnego_gen_auth_response(NULL, + NT_STATUS_MORE_PROCESSING_REQUIRED, + OID_NTLMSSP); + reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED); + data_blob_free(&response); +} + +/**************************************************************************** Reply to a session setup spnego negotiate packet. ****************************************************************************/ @@ -789,6 +811,15 @@ static void reply_spnego_negotiate(struct smb_request *req, auth_ntlmssp_end(auth_ntlmssp_state); } + if (got_kerberos_mechanism) { + data_blob_free(&secblob); + /* The mechtoken is a krb5 ticket, but + * we need to fall back to NTLM. */ + reply_spnego_downgrade_to_ntlmssp(req, + vuid); + return; + } + status = auth_ntlmssp_start(auth_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ @@ -803,7 +834,7 @@ static void reply_spnego_negotiate(struct smb_request *req, data_blob_free(&secblob); reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state, - &chal, status, True); + &chal, status, OID_NTLMSSP, true); data_blob_free(&chal); @@ -823,7 +854,7 @@ static void reply_spnego_auth(struct smb_request *req, DATA_BLOB auth = data_blob_null; DATA_BLOB auth_reply = data_blob_null; DATA_BLOB secblob = data_blob_null; - NTSTATUS status = NT_STATUS_INVALID_PARAMETER; + NTSTATUS status = NT_STATUS_LOGON_FAILURE; if (!spnego_parse_auth(blob1, &auth)) { #if 0 @@ -833,7 +864,7 @@ static void reply_spnego_auth(struct smb_request *req, invalidate_vuid(vuid); reply_nterror(req, nt_status_squash( - NT_STATUS_INVALID_PARAMETER)); + NT_STATUS_LOGON_FAILURE)); return; } @@ -843,24 +874,43 @@ static void reply_spnego_auth(struct smb_request *req, bool got_krb5_mechanism = False; status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism); - if (NT_STATUS_IS_OK(status)) { - DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", - (unsigned long)secblob.length)); + + if (!NT_STATUS_IS_OK(status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + reply_nterror(req, nt_status_squash(status)); + return; + } + + DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", + (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || - lp_use_kerberos_keytab()) ) { - bool destroy_vuid = True; - reply_spnego_kerberos(req, &secblob, - vuid, &destroy_vuid); - data_blob_free(&secblob); - data_blob_free(&auth); - if (destroy_vuid) { - /* Kill the intermediate vuid */ - invalidate_vuid(vuid); - } - return; + if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || + lp_use_kerberos_keytab()) ) { + bool destroy_vuid = True; + reply_spnego_kerberos(req, &secblob, + vuid, &destroy_vuid); + data_blob_free(&secblob); + data_blob_free(&auth); + if (destroy_vuid) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); } + return; + } #endif + /* Can't blunder into NTLMSSP auth if we have + * a krb5 ticket. */ + + if (got_krb5_mechanism) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + DEBUG(3,("reply_spnego_auth: network " + "misconfiguration, client sent us a " + "krb5 ticket and kerberos security " + "not enabled")); + reply_nterror(req, nt_status_squash( + NT_STATUS_LOGON_FAILURE)); } } @@ -868,13 +918,13 @@ static void reply_spnego_auth(struct smb_request *req, data_blob_free(&secblob); if (!*auth_ntlmssp_state) { - /* Kill the intermediate vuid */ - invalidate_vuid(vuid); - - /* auth before negotiatiate? */ - reply_nterror(req, nt_status_squash( - NT_STATUS_INVALID_PARAMETER)); - return; + status = auth_ntlmssp_start(auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + /* Kill the intermediate vuid */ + invalidate_vuid(vuid); + reply_nterror(req, nt_status_squash(status)); + return; + } } status = auth_ntlmssp_update(*auth_ntlmssp_state, @@ -882,9 +932,11 @@ static void reply_spnego_auth(struct smb_request *req, data_blob_free(&auth); + /* Don't send the mechid as we've already sent this (RFC4178). */ + reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state, - &auth_reply, status, True); + &auth_reply, status, NULL, true); data_blob_free(&auth_reply); @@ -1251,7 +1303,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) reply_spnego_ntlmssp(req, vuid, &vuser->auth_ntlmssp_state, - &chal, status, False); + &chal, status, OID_NTLMSSP, false); data_blob_free(&chal); return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1f7af82670..dc908846b3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1017,7 +1017,7 @@ static void call_trans2open(connection_struct *conn, } size = get_file_size(sbuf); - fattr = dos_mode(conn,fname,&sbuf); + fattr = dos_mode(conn,fsp->fsp_name,&sbuf); mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fattr & aDIR) { @@ -1054,7 +1054,7 @@ static void call_trans2open(connection_struct *conn, SIVAL(params,20,inode); SSVAL(params,24,0); /* Padding. */ if (flags & 8) { - uint32 ea_size = estimate_ea_size(conn, fsp, fname); + uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name); SIVAL(params, 26, ea_size); } else { SIVAL(params, 26, 0); |