diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/aio.c | 181 | ||||
-rw-r--r-- | source3/smbd/close.c | 20 | ||||
-rw-r--r-- | source3/smbd/conn.c | 1 | ||||
-rw-r--r-- | source3/smbd/connection.c | 32 | ||||
-rw-r--r-- | source3/smbd/error.c | 8 | ||||
-rw-r--r-- | source3/smbd/files.c | 1 | ||||
-rw-r--r-- | source3/smbd/notify.c | 7 | ||||
-rw-r--r-- | source3/smbd/open.c | 4 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 2 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 2 | ||||
-rw-r--r-- | source3/smbd/process.c | 29 | ||||
-rw-r--r-- | source3/smbd/reply.c | 28 | ||||
-rw-r--r-- | source3/smbd/seal.c | 703 | ||||
-rw-r--r-- | source3/smbd/server.c | 246 | ||||
-rw-r--r-- | source3/smbd/service.c | 18 | ||||
-rw-r--r-- | source3/smbd/session.c | 5 | ||||
-rw-r--r-- | source3/smbd/sockinit.c | 211 | ||||
-rw-r--r-- | source3/smbd/srvstr.c | 2 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 49 | ||||
-rw-r--r-- | source3/smbd/utmp.c | 4 |
20 files changed, 389 insertions, 1164 deletions
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 49855796b7..6ee0fe16e1 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -48,10 +48,8 @@ static struct aio_extra *aio_list_head; of the aio_read call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_read(files_struct *fsp, - size_t buflen, - uint16 mid, - const uint8 *inbuf) +static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, + uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -67,14 +65,6 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, SAFE_FREE(aio_ex); return NULL; } - /* Save the first 8 bytes of inbuf for possible enc data. */ - aio_ex->inbuf = SMB_MALLOC_ARRAY(char, 8); - if (!aio_ex->inbuf) { - SAFE_FREE(aio_ex->outbuf); - SAFE_FREE(aio_ex); - return NULL; - } - memcpy(aio_ex->inbuf, inbuf, 8); DLIST_ADD(aio_list_head, aio_ex); aio_ex->fsp = fsp; aio_ex->read_req = True; @@ -240,14 +230,13 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, bufsize = smb_size + 12 * 2 + smb_maxcnt; - if (!(aio_ex = create_aio_ex_read(fsp, bufsize, req->mid, - req->inbuf))) { + if ((aio_ex = create_aio_ex_read(fsp, bufsize, req->mid)) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } construct_reply_common((char *)req->inbuf, aio_ex->outbuf); - set_message((char *)req->inbuf, aio_ex->outbuf, 12, 0, True); + set_message(aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -292,6 +281,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; size_t inbufsize, outbufsize; + BOOL write_through = BITSETW(req->inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { @@ -359,7 +349,22 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } - srv_defer_sign_response(aio_ex->mid); + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) + && fsp->aio_write_behind) { + /* Lie to the client and immediately claim we finished the + * write. */ + SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); + SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); + show_msg(aio_ex->outbuf); + if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { + exit_server_cleanly("handle_aio_write: send_smb " + "failed."); + } + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " + "behind for file %s\n", fsp->fsp_name )); + } else { + srv_defer_sign_response(aio_ex->mid); + } outstanding_aio_calls++; DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " @@ -382,7 +387,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; - char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -406,7 +410,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; } else { - outsize = set_message(inbuf,outbuf,12,nread,False); + outsize = set_message(outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -419,7 +423,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(inbuf,outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " @@ -444,10 +448,34 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; - char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); + if (fsp->aio_write_behind) { + if (nwritten != numtowrite) { + if (nwritten == -1) { + DEBUG(5,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Error %s\n", + fsp->fsp_name, strerror(errno) )); + ret = errno; + } else { + DEBUG(0,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Wanted %u bytes but " + "only wrote %d\n", fsp->fsp_name, + (unsigned int)numtowrite, + (int)nwritten )); + ret = EIO; + } + } else { + DEBUG(10,("handle_aio_write_complete: " + "aio_write_behind completed for file %s\n", + fsp->fsp_name )); + } + return 0; + } + /* We don't need outsize or set_message here as we've already set the fixed size length when we set up the aio call. */ @@ -590,6 +618,115 @@ int process_aio_queue(void) } /**************************************************************************** + We're doing write behind and the client closed the file. Wait up to 30 + seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes + completed, errno to return if not. +*****************************************************************************/ + +#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 + +int wait_for_aio_completion(files_struct *fsp) +{ + struct aio_extra *aio_ex; + const SMB_STRUCT_AIOCB **aiocb_list; + int aio_completion_count = 0; + time_t start_time = time(NULL); + int seconds_left; + + for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; + seconds_left >= 0;) { + int err = 0; + int i; + struct timespec ts; + + aio_completion_count = 0; + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aio_completion_count++; + } + } + + if (!aio_completion_count) { + return 0; + } + + DEBUG(3,("wait_for_aio_completion: waiting for %d aio events " + "to complete.\n", aio_completion_count )); + + aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, + aio_completion_count); + if (!aiocb_list) { + return ENOMEM; + } + + for( i = 0, aio_ex = aio_list_head; + aio_ex; + aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aiocb_list[i++] = &aio_ex->acb; + } + } + + /* Now wait up to seconds_left for completion. */ + ts.tv_sec = seconds_left; + ts.tv_nsec = 0; + + DEBUG(10,("wait_for_aio_completion: %d events, doing a wait " + "of %d seconds.\n", + aio_completion_count, seconds_left )); + + err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, + aio_completion_count, &ts); + + DEBUG(10,("wait_for_aio_completion: returned err = %d, " + "errno = %s\n", err, strerror(errno) )); + + if (err == -1 && errno == EAGAIN) { + DEBUG(0,("wait_for_aio_completion: aio_suspend timed " + "out waiting for %d events after a wait of " + "%d seconds\n", aio_completion_count, + seconds_left)); + /* Timeout. */ + cancel_aio_by_fsp(fsp); + SAFE_FREE(aiocb_list); + return EIO; + } + + /* One or more events might have completed - process them if + * so. */ + for( i = 0; i < aio_completion_count; i++) { + uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; + + aio_ex = find_aio_ex(mid); + + if (!aio_ex) { + DEBUG(0, ("wait_for_aio_completion: mid %u " + "doesn't match an aio record\n", + (unsigned int)mid )); + continue; + } + + if (!handle_aio_completed(aio_ex, &err)) { + continue; + } + delete_aio_ex(aio_ex); + } + + SAFE_FREE(aiocb_list); + seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT + - (time(NULL) - start_time); + } + + /* We timed out - we don't know why. Return ret if already an error, + * else EIO. */ + DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting " + "for %d events\n", + aio_completion_count)); + + return EIO; +} + +/**************************************************************************** Cancel any outstanding aio requests. The client doesn't care about the reply. *****************************************************************************/ @@ -645,4 +782,8 @@ void cancel_aio_by_fsp(files_struct *fsp) { } +BOOL wait_for_aio_completion(files_struct *fsp) +{ + return True; +} #endif diff --git a/source3/smbd/close.c b/source3/smbd/close.c index aee1c92f7b..ae45aaa6da 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -345,16 +345,28 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ NTSTATUS status = NT_STATUS_OK; NTSTATUS saved_status1 = NT_STATUS_OK; NTSTATUS saved_status2 = NT_STATUS_OK; + NTSTATUS saved_status3 = NT_STATUS_OK; connection_struct *conn = fsp->conn; - cancel_aio_by_fsp(fsp); + if (fsp->aio_write_behind) { + /* + * If we're finishing write behind on a close we can get a write + * error here, we must remember this. + */ + int ret = wait_for_aio_completion(fsp); + if (ret) { + saved_status1 = map_nt_error_from_unix(ret); + } + } else { + cancel_aio_by_fsp(fsp); + } /* * If we're flushing on a close we can get a write * error here, we must remember this. */ - saved_status1 = close_filestruct(fsp); + saved_status2 = close_filestruct(fsp); if (fsp->print_file) { print_fsp_end(fsp, close_type); @@ -368,7 +380,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ if (fsp->fh->ref_count == 1) { /* Should we return on error here... ? */ - saved_status2 = close_remove_share_mode(fsp, close_type); + saved_status3 = close_remove_share_mode(fsp, close_type); } if(fsp->oplock_type) { @@ -399,6 +411,8 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ status = saved_status1; } else if (!NT_STATUS_IS_OK(saved_status2)) { status = saved_status2; + } else if (!NT_STATUS_IS_OK(saved_status3)) { + status = saved_status3; } } diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index f9befb84d2..50a71edf9d 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -285,6 +285,7 @@ void conn_free_internal(connection_struct *conn) free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); + free_namearray(conn->aio_write_behind_list); string_free(&conn->user); string_free(&conn->dirpath); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 4b807f7b90..65b7c352c5 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -83,19 +83,9 @@ static int count_fn(struct db_record *rec, } return 0; } - - if (cs->name) { - /* We are counting all the connections to a given share. */ - if (strequal(crec->servicename, cs->name)) { - cs->curr_connections++; - } - } else { - /* We are counting all the connections. Static registrations - * like the lpq backgroud process and the smbd daemon process - * have a cnum of -1, so won't be counted here. - */ + + if (strequal(crec->servicename, cs->name)) cs->curr_connections++; - } return 0; } @@ -121,29 +111,13 @@ int count_current_connections( const char *sharename, BOOL clear ) if (connections_forall(count_fn, &cs) == -1) { DEBUG(0,("count_current_connections: traverse of " "connections.tdb failed\n")); - DEBUGADD(0, ("count_current_connections: connection count of %d might not be accurate", - cs.curr_connections)); + return False; } - /* If the traverse failed part-way through, we at least return - * as many connections as we had already counted. If it failed - * right at the start, we will return 0, which is about all we - * can do anywway. - */ - return cs.curr_connections; } /**************************************************************************** - Count the number of connections open across all shares. -****************************************************************************/ - -int count_all_current_connections(void) -{ - return count_current_connections(NULL, True /* clear stale entries */); -} - -/**************************************************************************** Claim an entry in the connections database. ****************************************************************************/ diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 143417dce3..6cb63f0c49 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -28,7 +28,7 @@ extern uint32 global_client_caps; Create an error packet from errno. ****************************************************************************/ -int unix_error_packet(const char *inbuf,char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) +int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) { int eclass=def_class; int ecode=def_code; @@ -49,7 +49,7 @@ int unix_error_packet(const char *inbuf,char *outbuf,int def_class,uint32 def_co } } - return error_packet(inbuf,outbuf,eclass,ecode,ntstatus,line,file); + return error_packet(outbuf,eclass,ecode,ntstatus,line,file); } BOOL use_nt_status(void) @@ -109,9 +109,9 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu } } -int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) +int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { - int outsize = set_message(inbuf,outbuf,0,0,True); + int outsize = set_message(outbuf,0,0,True); error_packet_set(outbuf, eclass, ecode, ntstatus, line, file); return outsize; } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index f3740da328..179963dae9 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -558,6 +558,7 @@ NTSTATUS dup_file_fsp(files_struct *fsp, dup_fsp->modified = fsp->modified; dup_fsp->is_directory = fsp->is_directory; dup_fsp->is_stat = fsp->is_stat; + dup_fsp->aio_write_behind = fsp->aio_write_behind; string_set(&dup_fsp->fsp_name,fsp->fsp_name); *result = dup_fsp; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index da80c25407..b8c5085b41 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -131,11 +131,10 @@ static BOOL notify_marshall_changes(int num_changes, static void change_notify_reply_packet(const uint8 *request_buf, NTSTATUS error_code) { - const char *inbuf = (char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + construct_reply_common((char *)request_buf, outbuf); ERROR_NT(error_code); @@ -143,7 +142,7 @@ static void change_notify_reply_packet(const uint8 *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - set_message(inbuf,outbuf,18,0,False); + set_message(outbuf,18,0,False); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) @@ -187,7 +186,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, * We're only interested in the header fields here */ - smb_setlen(NULL, (char *)tmp_request, smb_size); + smb_setlen((char *)tmp_request, smb_size); SCVAL(tmp_request, smb_wct, 0); init_smb_request(req, tmp_request); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c2d7807158..fbc6f9ab64 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -387,6 +387,10 @@ static NTSTATUS open_file(files_struct *fsp, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; + if (conn->aio_write_behind_list && + is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) { + fsp->aio_write_behind = True; + } string_set(&fsp->fsp_name, path); fsp->wcp = NULL; /* Write cache pointer. */ diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index a5f74b89d0..9ac9d76284 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -253,7 +253,7 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx, } memset(result,'\0',smb_size); - set_message(NULL,result,8,0,True); + set_message(result,8,0,True); SCVAL(result,smb_com,SMBlockingX); SSVAL(result,smb_tid,fsp->conn->cnum); SSVAL(result,smb_pid,0xFFFF); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 9906bfb45b..da43a29767 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -291,7 +291,7 @@ void reply_pipe_read_and_X(struct smb_request *req) return; } - set_message(NULL, (char *)req->outbuf, 12, nread, False); + set_message((char *)req->outbuf, 12, nread, False); SSVAL(req->outbuf,smb_vwv5,nread); SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 29b942de81..7faf26af25 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -91,8 +91,8 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf) static struct pending_message_list *deferred_open_queue; /**************************************************************************** - Function to push a message onto the tail of a linked list of smb messages - ready for processing. + Function to push a message onto the tail of a linked list of smb messages ready + for processing. ****************************************************************************/ static BOOL push_queued_message(struct smb_request *req, @@ -148,7 +148,7 @@ void remove_deferred_open_smb_message(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { if (mid == SVAL(pml->buf.data,smb_mid)) { - DEBUG(10,("remove_deferred_open_smb_message: " + DEBUG(10,("remove_sharing_violation_open_smb_message: " "deleting mid %u len %u\n", (unsigned int)mid, (unsigned int)pml->buf.length )); @@ -171,11 +171,11 @@ void schedule_deferred_open_smb_message(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { uint16 msg_mid = SVAL(pml->buf.data,smb_mid); - DEBUG(10, ("schedule_deferred_open_smb_message: [%d] " - "msg_mid = %u\n", i++, (unsigned int)msg_mid )); + DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++, + (unsigned int)msg_mid )); if (mid == msg_mid) { - DEBUG(10, ("schedule_deferred_open_smb_message: " - "scheduling mid %u\n", mid)); + DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n", + mid )); pml->end_time.tv_sec = 0; pml->end_time.tv_usec = 0; DLIST_PROMOTE(deferred_open_queue, pml); @@ -183,8 +183,8 @@ void schedule_deferred_open_smb_message(uint16 mid) } } - DEBUG(10, ("schedule_deferred_open_smb_message: failed to find " - "message mid %u\n", mid )); + DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n", + mid )); } /**************************************************************************** @@ -932,8 +932,7 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) } construct_reply_common((char *)req->inbuf, (char *)req->outbuf); - set_message((char *)req->inbuf, (char *)req->outbuf, - num_words, num_bytes, False); + set_message((char *)req->outbuf, num_words, num_bytes, False); /* * Zero out the word area, the caller has to take care of the bcc area * himself @@ -1226,8 +1225,8 @@ void remove_from_common_flags2(uint32 v) void construct_reply_common(const char *inbuf, char *outbuf) { - set_message(inbuf,outbuf,0,0,False); - + set_message(outbuf,0,0,False); + SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); SIVAL(outbuf,smb_rcls,0); SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); @@ -1341,7 +1340,7 @@ void chain_reply(struct smb_request *req) } /* And set it in the header. */ - smb_setlen(inbuf, inbuf2, new_size - 4); + smb_setlen(inbuf2, new_size - 4); DEBUG(3,("Chained message\n")); show_msg(inbuf2); @@ -1428,7 +1427,7 @@ void chain_reply(struct smb_request *req) memset(outbuf + outsize, 0, outsize_padded - outsize); } - smb_setlen(NULL, outbuf, outsize2 + chain_size - 4); + smb_setlen(outbuf, outsize2 + chain_size - 4); /* * restore the saved data, being careful not to overwrite any data diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e27272f0dd..7c44216aea 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -402,7 +402,7 @@ void reply_special(char *inbuf) memset(outbuf, '\0', sizeof(outbuf)); - smb_setlen(inbuf,outbuf,0); + smb_setlen(outbuf,0); switch (msg_type) { case 0x81: /* session request */ @@ -1645,8 +1645,8 @@ void reply_open(connection_struct *conn, struct smb_request *req) if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { - END_PROFILE(SMBopen); /* We have re-scheduled this call. */ + END_PROFILE(SMBopen); return; } reply_openerror(req, status); @@ -2040,7 +2040,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req) /* We have re-scheduled this call. */ return; } - reply_nterror(req, status); + reply_openerror(req, status); return; } @@ -3017,7 +3017,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return; } - set_message(NULL, (char *)req->outbuf, 5, nread+3, False); + set_message((char *)req->outbuf, 5, nread+3, False); SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); @@ -3104,7 +3104,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", return; } - set_message(NULL, (char *)req->outbuf, 5, nread+3, False); + set_message((char *)req->outbuf, 5, nread+3, False); SSVAL(req->outbuf,smb_vwv0,nread); SSVAL(req->outbuf,smb_vwv5,nread+3); @@ -3122,14 +3122,12 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Setup readX header. ****************************************************************************/ -static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf, - size_t smb_maxcnt) +static int setup_readX_header(char *outbuf, size_t smb_maxcnt) { int outsize; char *data; - outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt, - False); + outsize = set_message(outbuf,12,smb_maxcnt,False); data = smb_buf(outbuf); memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */ @@ -3192,7 +3190,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, header = data_blob_const(headerbuf, sizeof(headerbuf)); construct_reply_common((char *)req->inbuf, (char *)headerbuf); - setup_readX_header(req->inbuf, headerbuf, smb_maxcnt); + setup_readX_header((char *)headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ @@ -3243,7 +3241,7 @@ normal_read: uint8 headerbuf[smb_size + 2*12]; construct_reply_common((char *)req->inbuf, (char *)headerbuf); - setup_readX_header(req->inbuf, headerbuf, smb_maxcnt); + setup_readX_header((char *)headerbuf, smb_maxcnt); /* Send out the header. */ if (write_data(smbd_server_fd(), (char *)headerbuf, @@ -3270,7 +3268,7 @@ normal_read: return; } - setup_readX_header(req->inbuf, req->outbuf, nread); + setup_readX_header((char *)req->outbuf, nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); @@ -3334,8 +3332,8 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req) END_PROFILE(SMBreadX); return; } - /* We currently don't do this on signed or sealed data. */ - if (srv_is_signing_active() || srv_encryption_on()) { + /* We currently don't do this on signed data. */ + if (srv_is_signing_active()) { reply_nterror(req, NT_STATUS_NOT_SUPPORTED); END_PROFILE(SMBreadX); return; @@ -3526,7 +3524,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) * it to send more bytes */ memcpy(buf, req->inbuf, smb_size); - outsize = set_message(NULL,buf, + outsize = set_message(buf, Protocol>PROTOCOL_COREPLUS?1:0,0,True); SCVAL(buf,smb_com,SMBwritebraw); SSVALS(buf,smb_vwv0,0xFFFF); diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c deleted file mode 100644 index 0276e34002..0000000000 --- a/source3/smbd/seal.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB Transport encryption (sealing) code - server code. - Copyright (C) Jeremy Allison 2007. - - 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 - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -/****************************************************************************** - Server side encryption. -******************************************************************************/ - -/****************************************************************************** - Global server state. -******************************************************************************/ - -struct smb_srv_trans_enc_ctx { - struct smb_trans_enc_state *es; - AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */ -}; - -static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; -static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; - -/****************************************************************************** - Is server encryption on ? -******************************************************************************/ - -BOOL srv_encryption_on(void) -{ - if (srv_trans_enc_ctx) { - return common_encryption_on(srv_trans_enc_ctx->es); - } - return False; -} - -/****************************************************************************** - Create an auth_ntlmssp_state and ensure pointer copy is correct. -******************************************************************************/ - -static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) -{ - NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - - /* - * We must remember to update the pointer copy for the common - * functions after any auth_ntlmssp_start/auth_ntlmssp_end. - */ - ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; - return status; -} - -/****************************************************************************** - Destroy an auth_ntlmssp_state and ensure pointer copy is correct. -******************************************************************************/ - -static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) -{ - /* - * We must remember to update the pointer copy for the common - * functions after any auth_ntlmssp_start/auth_ntlmssp_end. - */ - - if (ec->auth_ntlmssp_state) { - auth_ntlmssp_end(&ec->auth_ntlmssp_state); - /* The auth_ntlmssp_end killed this already. */ - ec->es->s.ntlmssp_state = NULL; - } -} - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - -/****************************************************************************** - Import a name. -******************************************************************************/ - -static NTSTATUS get_srv_gss_creds(const char *service, - const char *name, - gss_cred_usage_t cred_type, - gss_cred_id_t *p_srv_cred) -{ - OM_uint32 ret; - OM_uint32 min; - gss_name_t srv_name; - gss_buffer_desc input_name; - char *host_princ_s = NULL; - NTSTATUS status = NT_STATUS_OK; - - gss_OID_desc nt_hostbased_service = - {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; - - asprintf(&host_princ_s, "%s@%s", service, name); - if (host_princ_s == NULL) { - return NT_STATUS_NO_MEMORY; - } - - input_name.value = host_princ_s; - input_name.length = strlen(host_princ_s) + 1; - - ret = gss_import_name(&min, - &input_name, - &nt_hostbased_service, - &srv_name); - - DEBUG(10,("get_srv_gss_creds: imported name %s\n", - host_princ_s )); - - if (ret != GSS_S_COMPLETE) { - SAFE_FREE(host_princ_s); - return map_nt_error_from_gss(ret, min); - } - - /* - * We're accessing the krb5.keytab file here. - * ensure we have permissions to do so. - */ - become_root(); - - ret = gss_acquire_cred(&min, - srv_name, - GSS_C_INDEFINITE, - GSS_C_NULL_OID_SET, - cred_type, - p_srv_cred, - NULL, - NULL); - unbecome_root(); - - if (ret != GSS_S_COMPLETE) { - ADS_STATUS adss = ADS_ERROR_GSS(ret, min); - DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n", - ads_errstr(adss))); - status = map_nt_error_from_gss(ret, min); - } - - SAFE_FREE(host_princ_s); - gss_release_name(&min, &srv_name); - return status; -} - -/****************************************************************************** - Create a gss state. - Try and get the cifs/server@realm principal first, then fall back to - host/server@realm. -******************************************************************************/ - -static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) -{ - NTSTATUS status; - gss_cred_id_t srv_cred; - fstring fqdn; - - name_to_fqdn(fqdn, global_myname()); - strlower_m(fqdn); - - status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); - if (!NT_STATUS_IS_OK(status)) { - status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - } - - ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); - if (!ec->es->s.gss_state) { - OM_uint32 min; - gss_release_cred(&min, &srv_cred); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(ec->es->s.gss_state); - ec->es->s.gss_state->creds = srv_cred; - - /* No context yet. */ - ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT; - - return NT_STATUS_OK; -} -#endif - -/****************************************************************************** - Shutdown a server encryption context. -******************************************************************************/ - -static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) -{ - struct smb_srv_trans_enc_ctx *ec = *pp_ec; - - if (!ec) { - return; - } - - if (ec->es) { - switch (ec->es->smb_enc_type) { - case SMB_TRANS_ENC_NTLM: - destroy_auth_ntlmssp(ec); - break; -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - case SMB_TRANS_ENC_GSS: - break; -#endif - } - common_free_encryption_state(&ec->es); - } - - SAFE_FREE(ec); - *pp_ec = NULL; -} - -/****************************************************************************** - Create a server encryption context. -******************************************************************************/ - -static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec) -{ - struct smb_srv_trans_enc_ctx *ec; - - *pp_ec = NULL; - - ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); - if (!ec) { - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(partial_srv_trans_enc_ctx); - ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); - if (!ec->es) { - SAFE_FREE(ec); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(ec->es); - ec->es->smb_enc_type = smb_enc_type; - switch (smb_enc_type) { - case SMB_TRANS_ENC_NTLM: - { - NTSTATUS status = make_auth_ntlmssp(ec); - if (!NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&ec); - return status; - } - } - break; - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - case SMB_TRANS_ENC_GSS: - /* Acquire our credentials by calling gss_acquire_cred here. */ - { - NTSTATUS status = make_auth_gss(ec); - if (!NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&ec); - return status; - } - } - break; -#endif - default: - srv_free_encryption_context(&ec); - return NT_STATUS_INVALID_PARAMETER; - } - *pp_ec = ec; - return NT_STATUS_OK; -} - -/****************************************************************************** - Free an encryption-allocated buffer. -******************************************************************************/ - -void srv_free_enc_buffer(char *buf) -{ - /* We know this is an smb buffer, and we - * didn't malloc, only copy, for a keepalive, - * so ignore session keepalives. */ - - if(CVAL(buf,0) == SMBkeepalive) { - return; - } - - if (srv_trans_enc_ctx) { - common_free_enc_buffer(srv_trans_enc_ctx->es, buf); - } -} - -/****************************************************************************** - Decrypt an incoming buffer. -******************************************************************************/ - -NTSTATUS srv_decrypt_buffer(char *buf) -{ - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { - return NT_STATUS_OK; - } - - if (srv_trans_enc_ctx) { - return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); - } - - return NT_STATUS_OK; -} - -/****************************************************************************** - Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. -******************************************************************************/ - -NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) -{ - *buf_out = buf; - - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { - return NT_STATUS_OK; - } - - if (srv_trans_enc_ctx) { - return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out); - } - /* Not encrypting. */ - return NT_STATUS_OK; -} - -/****************************************************************************** - Do the gss encryption negotiation. Parameters are in/out. - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) -static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) -{ - OM_uint32 ret; - OM_uint32 min; - OM_uint32 flags = 0; - gss_buffer_desc in_buf, out_buf; - struct smb_tran_enc_state_gss *gss_state; - DATA_BLOB auth_reply = data_blob_null; - DATA_BLOB response = data_blob_null; - NTSTATUS status; - - if (!partial_srv_trans_enc_ctx) { - status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } - - gss_state = partial_srv_trans_enc_ctx->es->s.gss_state; - - in_buf.value = secblob.data; - in_buf.length = secblob.length; - - out_buf.value = NULL; - out_buf.length = 0; - - become_root(); - - ret = gss_accept_sec_context(&min, - &gss_state->gss_ctx, - gss_state->creds, - &in_buf, - GSS_C_NO_CHANNEL_BINDINGS, - NULL, - NULL, /* Ignore oids. */ - &out_buf, /* To return. */ - &flags, - NULL, /* Ingore time. */ - NULL); /* Ignore delegated creds. */ - unbecome_root(); - - status = gss_err_to_ntstatus(ret, min); - if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { - return status; - } - - /* Ensure we've got sign+seal available. */ - if (ret == GSS_S_COMPLETE) { - if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) != - (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) { - DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough " - "for SMB sealing.\n")); - gss_release_buffer(&min, &out_buf); - return NT_STATUS_ACCESS_DENIED; - } - } - - auth_reply = data_blob(out_buf.value, out_buf.length); - gss_release_buffer(&min, &out_buf); - - /* Wrap in SPNEGO. */ - response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5); - data_blob_free(&auth_reply); - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - - return status; -} -#endif - -/****************************************************************************** - Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out. - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap) -{ - NTSTATUS status; - DATA_BLOB chal = data_blob_null; - DATA_BLOB response = data_blob_null; - - status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); - - /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED - * for success ... */ - - if (spnego_wrap) { - response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); - data_blob_free(&chal); - } else { - /* Return the raw blob. */ - response = chal; - } - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Do the SPNEGO encryption negotiation. Parameters are in/out. - Based off code in smbd/sesssionsetup.c - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_null; - DATA_BLOB secblob = data_blob_null; - BOOL got_kerberos_mechanism = False; - - blob = data_blob_const(*ppdata, *p_data_size); - - status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - - /* We should have no partial context at this point. */ - - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - -#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 -#endif - { - status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, True); - } - - data_blob_free(&secblob); - - if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return nt_status_squash(status); - } - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); - *p_param_size = 2; - } - - return status; -} - -/****************************************************************************** - Complete a SPNEGO encryption negotiation. Parameters are in/out. - We only get this for a NTLM auth second stage. -******************************************************************************/ - -static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_null; - DATA_BLOB auth = data_blob_null; - DATA_BLOB auth_reply = data_blob_null; - DATA_BLOB response = data_blob_null; - struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; - - /* We must have a partial context here. */ - - if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - blob = data_blob_const(*ppdata, *p_data_size); - if (!spnego_parse_auth(blob, &auth)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - 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); - data_blob_free(&auth_reply); - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,ec->es->enc_ctx_num); - *p_param_size = 2; - } - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Raw NTLM encryption negotiation. Parameters are in/out. - This function does both steps. -******************************************************************************/ - -static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); - DATA_BLOB response = data_blob_null; - struct smb_srv_trans_enc_ctx *ec; - - if (!partial_srv_trans_enc_ctx) { - /* This is the initial step. */ - status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False); - if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return nt_status_squash(status); - } - return status; - } - - ec = partial_srv_trans_enc_ctx; - if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - /* Second step. */ - status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,ec->es->enc_ctx_num); - *p_param_size = 2; - } - - /* Return the raw blob. */ - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Do the SPNEGO encryption negotiation. Parameters are in/out. -******************************************************************************/ - -NTSTATUS srv_request_encryption_setup(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - unsigned char *pdata = *ppdata; - - SAFE_FREE(*pparam); - *p_param_size = 0; - - if (*p_data_size < 1) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (pdata[0] == ASN1_APPLICATION(0)) { - /* its a negTokenTarg packet */ - return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size); - } - - if (pdata[0] == ASN1_CONTEXT(1)) { - /* It's an auth packet */ - return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); - } - - /* Maybe it's a raw unwrapped auth ? */ - if (*p_data_size < 7) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { - return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); - } - - DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); - - return NT_STATUS_LOGON_FAILURE; -} - -/****************************************************************************** - Negotiation was successful - turn on server-side encryption. -******************************************************************************/ - -static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) -{ - if (!ec || !ec->es) { - return NT_STATUS_LOGON_FAILURE; - } - - if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != - (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { - return NT_STATUS_INVALID_PARAMETER; - } - } - /* Todo - check gssapi case. */ - - return NT_STATUS_OK; -} - -/****************************************************************************** - Negotiation was successful - turn on server-side encryption. -******************************************************************************/ - -NTSTATUS srv_encryption_start(connection_struct *conn) -{ - NTSTATUS status; - - /* Check that we are really doing sign+seal. */ - status = check_enc_good(partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* Throw away the context we're using currently (if any). */ - srv_free_encryption_context(&srv_trans_enc_ctx); - - /* Steal the partial pointer. Deliberate shallow copy. */ - srv_trans_enc_ctx = partial_srv_trans_enc_ctx; - srv_trans_enc_ctx->es->enc_on = True; - - partial_srv_trans_enc_ctx = NULL; - return NT_STATUS_OK; -} - -/****************************************************************************** - Shutdown all server contexts. -******************************************************************************/ - -void server_encryption_shutdown(void) -{ - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - srv_free_encryption_context(&srv_trans_enc_ctx); -} diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 72eeb7ee6a..0f47a550e9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -4,7 +4,6 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 Copyright (C) Jelmer Vernooij 2002-2003 - Copyright (C) James Peach 2007 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 @@ -294,33 +293,25 @@ static BOOL allowable_number_of_smbd_processes(void) } /**************************************************************************** - Are we idle enough that we could safely exit? -****************************************************************************/ - -static BOOL smbd_is_idle(void) -{ - /* Currently we define "idle" as having no client connections. */ - return count_all_current_connections() == 0; -} - -/**************************************************************************** Open the socket communication. ****************************************************************************/ -static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ports) +static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports) { + int num_interfaces = iface_count(); int num_sockets = 0; int fd_listenset[FD_SETSIZE]; fd_set listen_set; int s; int maxfd = 0; int i; - struct timeval idle_timeout = timeval_zero(); + char *ports; - if (server_mode == SERVER_MODE_INETD) { + if (!is_daemon) { return open_sockets_inetd(); } + #ifdef HAVE_ATEXIT { static int atexit_set; @@ -333,21 +324,116 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ /* Stop zombies */ CatchSignal(SIGCLD, sig_cld); - + FD_ZERO(&listen_set); - /* At this point, it doesn't matter what daemon mode we are in, we - * need some sockets to listen on. - */ - num_sockets = smbd_sockinit(smb_ports, fd_listenset, &idle_timeout); - if (num_sockets == 0) { - return False; + /* use a reasonable default set of ports - listing on 445 and 139 */ + if (!smb_ports) { + ports = lp_smb_ports(); + if (!ports || !*ports) { + ports = smb_xstrdup(SMB_PORTS); + } else { + ports = smb_xstrdup(ports); + } + } else { + ports = smb_xstrdup(smb_ports); } - for (i = 0; i < num_sockets; ++i) { - FD_SET(fd_listenset[i], &listen_set); - maxfd = MAX(maxfd, fd_listenset[i]); - } + if (lp_interfaces() && lp_bind_interfaces_only()) { + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ + + /* Now open a listen socket for each of the + interfaces. */ + for(i = 0; i < num_interfaces; i++) { + struct in_addr *ifip = iface_n_ip(i); + fstring tok; + const char *ptr; + + if(ifip == NULL) { + DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); + continue; + } + + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0 || port > 0xffff) { + continue; + } + s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); + if(s == -1) + return False; + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("listen: %s\n",strerror(errno))); + close(s); + return False; + } + FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); + + num_sockets++; + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } + } + } + } else { + /* Just bind to 0.0.0.0 - accept connections + from anywhere. */ + + fstring tok; + const char *ptr; + + num_interfaces = 1; + + for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { + unsigned port = atoi(tok); + if (port == 0 || port > 0xffff) continue; + /* open an incoming socket */ + s = open_socket_in(SOCK_STREAM, port, 0, + interpret_addr(lp_socket_address()),True); + if (s == -1) + return(False); + + /* ready to listen */ + set_socket_options(s,"SO_KEEPALIVE"); + set_socket_options(s,user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("open_sockets_smbd: listen: %s\n", + strerror(errno))); + close(s); + return False; + } + + fd_listenset[num_sockets] = s; + FD_SET(s,&listen_set); + maxfd = MAX( maxfd, s); + + num_sockets++; + + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } + } + } + + SAFE_FREE(ports); /* Setup the main smbd so that we can get messages. Note that @@ -380,7 +466,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ for each incoming connection */ DEBUG(2,("waiting for a connection\n")); while (1) { - struct timeval now; + struct timeval now, idle_timeout; fd_set r_fds, w_fds; int num; @@ -396,6 +482,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ } } + idle_timeout = timeval_zero(); + memcpy((char *)&r_fds, (char *)&listen_set, sizeof(listen_set)); FD_ZERO(&w_fds); @@ -405,21 +493,9 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ &r_fds, &w_fds, &idle_timeout, &maxfd); - if (timeval_is_zero(&idle_timeout)) { - num = sys_select(maxfd + 1, &r_fds, &w_fds, - NULL, NULL); - } else { - num = sys_select(maxfd + 1, &r_fds, &w_fds, - NULL, &idle_timeout); - - /* If the idle timeout fired and we are idle, exit - * gracefully. We expect to be running under a process - * controller that will restart us if necessry. - */ - if (num == 0 && smbd_is_idle()) { - exit_server_cleanly("idle timeout"); - } - } + num = sys_select(maxfd+1,&r_fds,&w_fds,NULL, + timeval_is_zero(&idle_timeout) ? + NULL : &idle_timeout); if (num == -1 && errno == EINTR) { if (got_sig_term) { @@ -436,7 +512,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ continue; } - + if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { continue; } @@ -476,13 +552,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ /* Ensure child is set to blocking mode */ set_blocking(smbd_server_fd(),True); - /* In interactive mode, return with a connected socket. - * Foreground and daemon modes should fork worker - * processes. - */ - if (server_mode == SERVER_MODE_INTERACTIVE) { + if (smbd_server_fd() != -1 && interactive) return True; - } if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && @@ -694,8 +765,6 @@ static void exit_server_common(enum server_exit_reason how, locking_end(); printing_end(); - server_encryption_shutdown(); - if (how != SERVER_EXIT_NORMAL) { int oldlevel = DEBUGLEVEL; @@ -804,26 +873,23 @@ extern void build_options(BOOL screen); int main(int argc,const char *argv[]) { /* shall I run as a daemon */ - BOOL no_process_group = False; - BOOL log_stdout = False; - const char *ports = NULL; - const char *profile_level = NULL; + static BOOL is_daemon = False; + static BOOL interactive = False; + static BOOL Fork = True; + static BOOL no_process_group = False; + static BOOL log_stdout = False; + static char *ports = NULL; + static char *profile_level = NULL; int opt; poptContext pc; BOOL print_build_options = False; - enum smb_server_mode server_mode = SERVER_MODE_DAEMON; - struct poptOption long_options[] = { POPT_AUTOHELP - {"daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON, - "Become a daemon (default)" }, - {"interactive", 'i', POPT_ARG_VAL, &server_mode, SERVER_MODE_INTERACTIVE, - "Run interactive (not a daemon)"}, - {"foreground", 'F', POPT_ARG_VAL, &server_mode, SERVER_MODE_FOREGROUND, - "Run daemon in foreground (for daemontools, etc.)" }, - {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, - "Don't create a new process group" }, + {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, + {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, + {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc.)" }, + {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, @@ -870,14 +936,16 @@ extern void build_options(BOOL screen); set_remote_machine_name("smbd", False); - if (server_mode == SERVER_MODE_INTERACTIVE) { + if (interactive) { + Fork = False; log_stdout = True; - if (DEBUGLEVEL >= 9) { - talloc_enable_leak_report(); - } } - if (log_stdout && server_mode == SERVER_MODE_DAEMON) { + if (interactive && (DEBUGLEVEL >= 9)) { + talloc_enable_leak_report(); + } + + if (log_stdout && Fork) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } @@ -967,19 +1035,21 @@ extern void build_options(BOOL screen); DEBUG(3,( "loaded services\n")); - if (is_a_socket(0)) { - if (server_mode == SERVER_MODE_DAEMON) { - DEBUG(0,("standard input is a socket, " - "assuming -F option\n")); - } - server_mode = SERVER_MODE_INETD; + if (!is_daemon && !is_a_socket(0)) { + if (!interactive) + DEBUG(0,("standard input is not a socket, assuming -D option\n")); + + /* + * Setting is_daemon here prevents us from eventually calling + * the open_sockets_inetd() + */ + + is_daemon = True; } - if (server_mode == SERVER_MODE_DAEMON) { + if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(True, no_process_group); - } else if (server_mode == SERVER_MODE_FOREGROUND) { - become_daemon(False, no_process_group); + become_daemon(Fork, no_process_group); } #if HAVE_SETPGID @@ -987,18 +1057,15 @@ extern void build_options(BOOL screen); * If we're interactive we want to set our own process group for * signal management. */ - if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) { + if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); - } #endif if (!directory_exist(lp_lockdir(), NULL)) mkdir(lp_lockdir(), 0755); - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + if (is_daemon) pidfile_create("smbd"); - } /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ @@ -1052,10 +1119,9 @@ extern void build_options(BOOL screen); running as a daemon -- bad things will happen if smbd is launched via inetd and we fork a copy of ourselves here */ - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + + if ( is_daemon && !interactive ) start_background_queue(); - } /* Always attempt to initialize DMAPI. We will only use it later if * lp_dmapi_support is set on the share, but we need a single global @@ -1063,9 +1129,8 @@ extern void build_options(BOOL screen); */ dmapi_init_session(); - if (!open_sockets_smbd(server_mode, ports)) { + if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); - } /* * everything after this point is run after the fork() @@ -1078,8 +1143,7 @@ extern void build_options(BOOL screen); /* Possibly reload the services file. Only worth doing in * daemon mode. In inetd mode, we know we only just loaded this. */ - if (server_mode != SERVER_MODE_INETD && - server_mode != SERVER_MODE_INTERACTIVE) { + if (is_daemon) { reload_services(True); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 4daa2924a2..1c46e3776c 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -312,14 +312,7 @@ static int load_registry_service(const char *servicename) TALLOC_FREE(value); } - if (!service_ok(res)) { - /* this is actually never reached, since - * service_ok only returns False if the service - * entry does not have a service name, and we _know_ - * we do have a service name here... */ - res = -1; - } - + res = 0; error: TALLOC_FREE(key); @@ -409,6 +402,10 @@ int find_service(fstring service) if (iService < 0) { } + if (iService < 0) { + iService = load_registry_service(service); + } + /* Is it a usershare service ? */ if (iService < 0 && *lp_usershare_path()) { /* Ensure the name is canonicalized. */ @@ -444,10 +441,6 @@ int find_service(fstring service) } } - if (iService < 0) { - iService = load_registry_service(service); - } - if (iService >= 0) { if (!VALID_SNUM(iService)) { DEBUG(0,("Invalid snum %d for %s\n",iService, service)); @@ -789,6 +782,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->veto_list = NULL; conn->hide_list = NULL; conn->veto_oplock_list = NULL; + conn->aio_write_behind_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index c7cdf41fb5..8dd321fad7 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -201,12 +201,9 @@ BOOL session_claim(user_struct *vuser) sessionid.id_str, sessionid.id_num); } - TALLOC_FREE(rec); - vuser->session_keystr = talloc_strdup(vuser, keystr); if (!vuser->session_keystr) { - DEBUG(0, ("session_claim: talloc_strdup() failed for " - "session_keystr\n")); + DEBUG(0, ("session_claim: talloc_strdup() failed for session_keystr\n")); return False; } return True; diff --git a/source3/smbd/sockinit.c b/source3/smbd/sockinit.c deleted file mode 100644 index 598bbd1bda..0000000000 --- a/source3/smbd/sockinit.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) James Peach 2007 - - 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 - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "smb_launchd.h" - -extern pstring user_socket_options; - -static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) -{ - int num_interfaces = iface_count(); - char * ports; - int num_sockets = 0; - int i, s; - - /* use a reasonable default set of ports - listing on 445 and 139 */ - if (!smb_ports) { - ports = lp_smb_ports(); - if (!ports || !*ports) { - ports = smb_xstrdup(SMB_PORTS); - } else { - ports = smb_xstrdup(ports); - } - } else { - ports = smb_xstrdup(smb_ports); - } - - if (lp_interfaces() && lp_bind_interfaces_only()) { - /* We have been given an interfaces line, and been - told to only bind to those interfaces. Create a - socket per interface and bind to only these. - */ - - /* Now open a listen socket for each of the - interfaces. */ - for(i = 0; i < num_interfaces; i++) { - struct in_addr *ifip = iface_n_ip(i); - fstring tok; - const char *ptr; - - if(ifip == NULL) { - DEBUG(0,("init_sockets_smbd: interface %d has " - "NULL IP address !\n", i)); - continue; - } - - for (ptr=ports; next_token(&ptr, tok, " \t,", - sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0 || port > 0xffff) { - continue; - } - s = listenset[num_sockets] = - open_socket_in(SOCK_STREAM, - port, - 0, - ifip->s_addr, - True); - if(s == -1) - return 0; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking - * for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("listen: %s\n", - strerror(errno))); - close(s); - return 0; - } - - num_sockets++; - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: " - "Too many sockets to bind to\n")); - return 0; - } - } - } - } else { - /* Just bind to 0.0.0.0 - accept connections - from anywhere. */ - - fstring tok; - const char *ptr; - - num_interfaces = 1; - - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0 || port > 0xffff) continue; - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address()), - True); - if (s == -1) - return 0; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("init_sockets_smbd: listen: %s\n", - strerror(errno))); - close(s); - return 0; - } - - listenset[num_sockets] = s; - num_sockets++; - - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: " - "Too many sockets to bind to\n")); - return 0; - } - } - } - - SAFE_FREE(ports); - return num_sockets; -} - -static int init_sockets_launchd(const struct smb_launch_info *linfo, - const char * smb_ports, - int listenset[FD_SETSIZE]) -{ - int num_sockets; - int i; - - /* The launchd service configuration does not have to provide sockets, - * even though it's basically useless without it. - */ - if (!linfo->num_sockets) { - return init_sockets_smbd(smb_ports, listenset); - } - - /* Make sure we don't get more sockets than we can handle. */ - num_sockets = MIN(FD_SETSIZE, linfo->num_sockets); - memcpy(listenset, linfo->socket_list, num_sockets * sizeof(int)); - - /* Get the sockets ready. This could be hoisted into - * open_sockets_smbd(), but the order of socket operations might - * matter for some platforms, so this approach seems less risky. - * --jpeach - */ - for (i = 0; i < num_sockets; ++i) { - set_socket_options(listenset[i], "SO_KEEPALIVE"); - set_socket_options(listenset[i], user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(listenset[i], False); - } - - return num_sockets; -} - -/* This function is responsible for opening (or retrieving) all the sockets we - * smbd will be listening on. It should apply all the configured socket options - * and return the number of valid sockets in listenset. - */ -int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE], - struct timeval *idle) -{ - int num_sockets; - struct smb_launch_info linfo; - - ZERO_STRUCTP(idle); - - if (smb_launchd_checkin(&linfo)) { - /* We are running under launchd and launchd has - * opened some sockets for us. - */ - num_sockets = init_sockets_launchd(&linfo, - cmdline_ports, - listenset); - idle->tv_sec = linfo.idle_timeout_secs; - smb_launchd_checkout(&linfo); - } else { - num_sockets = init_sockets_smbd(cmdline_ports, - listenset); - } - - return num_sockets; -} diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c index fbcf249ffb..68e61033ae 100644 --- a/source3/smbd/srvstr.c +++ b/source3/smbd/srvstr.c @@ -79,7 +79,7 @@ ssize_t message_push_string(uint8 **outbuf, const char *str, int flags) DEBUG(0, ("srvstr_push failed\n")); return -1; } - set_message_bcc(NULL, (char *)tmp, smb_buflen(tmp) + result); + set_message_bcc((char *)tmp, smb_buflen(tmp) + result); *outbuf = tmp; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ada4868bf8..7392271b48 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2733,9 +2733,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned CIFS_UNIX_FCNTL_LOCKS_CAP| CIFS_UNIX_EXTATTR_CAP| CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP| - /* Ensure we don't do this on signed or sealed data. */ - (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP) - ))); + CIFS_UNIX_LARGE_READ_CAP))); break; case SMB_QUERY_POSIX_FS_INFO: @@ -2986,51 +2984,6 @@ cap_low = 0x%x, cap_high = 0x%x\n", } break; } - case SMB_REQUEST_TRANSPORT_ENCRYPTION: - { - NTSTATUS status; - size_t param_len = 0; - size_t data_len = total_data; - - if (!lp_unix_extensions()) { - reply_nterror( - req, NT_STATUS_INVALID_LEVEL); - return; - } - - DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n")); - - status = srv_request_encryption_setup(conn, - (unsigned char **)ppdata, - &data_len, - (unsigned char **)pparams, - ¶m_len - ); - - if (!NT_STATUS_IS_OK(status)) { - /* - * TODO: Check - * MORE_PROCESSING_REQUIRED, this used - * to have special handling here. - */ - reply_nterror(req, status); - return; - } - - send_trans2_replies(req, - *pparams, param_len, - *ppdata, data_len, - max_data_bytes); - - if (NT_STATUS_IS_OK(status)) { - /* Server-side transport encryption is now *on*. */ - status = srv_encryption_start(conn); - if (!NT_STATUS_IS_OK(status)) { - exit_server_cleanly("Failure in setting up encrypted transport"); - } - } - return; - } case SMB_FS_QUOTA_INFORMATION: { files_struct *fsp = NULL; diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 7f43740754..52174c4d83 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -220,13 +220,13 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau } /* For u-files and non-explicit w-dir, look for "utmp dir" */ - if (strlen(dirname) == 0) { + if (dirname == 0 || strlen(dirname) == 0) { pstrcpy(dirname,lp_utmpdir()); trim_char(dirname,'\0','/'); } /* If explicit directory above, use it */ - if (strlen(dirname) != 0) { + if (dirname != 0 && strlen(dirname) != 0) { pstrcpy(fname, dirname); pstrcat(fname, "/"); pstrcat(fname, uw_name); |