diff options
-rw-r--r-- | source3/Makefile.in | 35 | ||||
-rw-r--r-- | source3/include/fake_file.h | 3 | ||||
-rw-r--r-- | source3/include/proto.h | 4 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe_hnd.c | 184 | ||||
-rw-r--r-- | source3/smbd/files.c | 5 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 15 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 16 |
7 files changed, 194 insertions, 68 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 01ea90ab9e..ac9770dae7 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -2723,7 +2723,40 @@ proto:: etags:: etags `find $(srcdir) -name "*.[ch]"` etags --append `find $(srcdir)/../lib -name "*.[ch]"` - etags --append `find $(srcdir)/../source4 -name "*.[ch]"` + etags --append `find $(srcdir)/../librpc -name "*.[ch]"` + etags --append `find $(srcdir)/../libcli -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/client -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/auth -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/rpc_server -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/kdc -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/winbind -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/scripting -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/heimdal_build -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/libcli -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/ntp_signd -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/ldap_server -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/smb_server -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/include -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/nsswitch -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/cldap_server -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/utils -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/librpc -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/libnet -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/web_server -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/heimdal -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/wrepl_server -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/dynconfig -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/param -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/lib -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/nbt_server -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/build -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/ntvfs -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/torture -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/cluster -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/ntptr -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/smbd -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/script -name "*.[ch]"` + etags --append `find $(srcdir)/../source4/dsdb -name "*.[ch]"` ctags:: ctags `find $(srcdir)/.. -name "*.[ch]"` diff --git a/source3/include/fake_file.h b/source3/include/fake_file.h index c4b271f85d..6b34005625 100644 --- a/source3/include/fake_file.h +++ b/source3/include/fake_file.h @@ -23,7 +23,8 @@ enum FAKE_FILE_TYPE { FAKE_FILE_TYPE_NONE = 0, FAKE_FILE_TYPE_QUOTA, - FAKE_FILE_TYPE_NAMED_PIPE + FAKE_FILE_TYPE_NAMED_PIPE, + FAKE_FILE_TYPE_NAMED_PIPE_PROXY }; /* diff --git a/source3/include/proto.h b/source3/include/proto.h index 83cd740a78..e4a445bcd0 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1663,6 +1663,9 @@ size_t str_list_length( const char * const*list ); bool str_list_sub_basic( char **list, const char *smb_name, const char *domain_name ); bool str_list_substitute(char **list, const char *pattern, const char *insert); +bool str_list_check(const char **list, const char *s); +bool str_list_check_ci(const char **list, const char *s); + char *ipstr_list_make(char **ipstr_list, const struct ip_service *ip_list, int ip_count); @@ -7110,7 +7113,6 @@ bool api_pipe_request(pipes_struct *p); pipes_struct *get_first_internal_pipe(void); pipes_struct *get_next_internal_pipe(pipes_struct *p); -void set_pipe_handle_offset(int max_open_files); void init_rpc_pipe_hnd(void); bool fsp_is_np(struct files_struct *fsp); diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index c8037e6e43..b892755396 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -55,22 +55,6 @@ pipes_struct *get_next_internal_pipe(pipes_struct *p) return p->next; } -/* this must be larger than the sum of the open files and directories */ -static int pipe_handle_offset; - -/**************************************************************************** - Set the pipe_handle_offset. Called from smbd/files.c -****************************************************************************/ - -void set_pipe_handle_offset(int max_open_files) -{ - if(max_open_files < 0x7000) { - pipe_handle_offset = 0x7000; - } else { - pipe_handle_offset = max_open_files + 10; /* For safety. :-) */ - } -} - /**************************************************************************** Initialise pipe handle states. ****************************************************************************/ @@ -929,9 +913,74 @@ static int close_internal_rpc_pipe_hnd(struct pipes_struct *p) bool fsp_is_np(struct files_struct *fsp) { - return ((fsp != NULL) - && (fsp->fake_file_handle != NULL) - && (fsp->fake_file_handle->type == FAKE_FILE_TYPE_NAMED_PIPE)); + enum FAKE_FILE_TYPE type; + + if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) { + return false; + } + + type = fsp->fake_file_handle->type; + + return ((type == FAKE_FILE_TYPE_NAMED_PIPE) + || (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY)); +} + +struct np_proxy_state { + int fd; +}; + +static int np_proxy_state_destructor(struct np_proxy_state *state) +{ + if (state->fd != -1) { + close(state->fd); + } + return 0; +} + +static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx, + const char *pipe_name, + struct auth_serversupplied_info *server_info) +{ + struct np_proxy_state *result; + struct sockaddr_un addr; + char *socket_path; + + result = talloc(mem_ctx, struct np_proxy_state); + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + result->fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (result->fd == -1) { + DEBUG(10, ("socket(2) failed: %s\n", strerror(errno))); + goto fail; + } + talloc_set_destructor(result, np_proxy_state_destructor); + + ZERO_STRUCT(addr); + addr.sun_family = AF_UNIX; + + socket_path = talloc_asprintf(talloc_tos(), "%s/%s", + get_dyn_NCALRPCDIR(), "DEFAULT"); + if (socket_path == NULL) { + DEBUG(0, ("talloc_asprintf failed\n")); + goto fail; + } + strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)); + TALLOC_FREE(socket_path); + + if (sys_connect(result->fd, (struct sockaddr *)&addr) == -1) { + DEBUG(0, ("connect(%s) failed: %s\n", addr.sun_path, + strerror(errno))); + goto fail; + } + + return result; + + fail: + TALLOC_FREE(result); + return NULL; } NTSTATUS np_open(struct smb_request *smb_req, struct connection_struct *conn, @@ -939,7 +988,9 @@ NTSTATUS np_open(struct smb_request *smb_req, struct connection_struct *conn, { NTSTATUS status; struct files_struct *fsp; - struct pipes_struct *p; + const char **proxy_list; + + proxy_list = lp_parm_string_list(SNUM(conn), "np", "proxy", NULL); status = file_new(smb_req, conn, &fsp); if (!NT_STATUS_IS_OK(status)) { @@ -959,16 +1010,36 @@ NTSTATUS np_open(struct smb_request *smb_req, struct connection_struct *conn, file_free(smb_req, fsp); return NT_STATUS_NO_MEMORY; } - fsp->fake_file_handle->type = FAKE_FILE_TYPE_NAMED_PIPE; - p = make_internal_rpc_pipe_p(fsp->fake_file_handle, name, - conn->client_address, conn->server_info, - smb_req->vuid); - if (p == NULL) { + if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) { + struct np_proxy_state *p; + + p = make_external_rpc_pipe_p(fsp->fake_file_handle, name, + conn->server_info); + + fsp->fake_file_handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY; + fsp->fake_file_handle->private_data = p; + } else { + struct pipes_struct *p; + + if (!is_known_pipename(name)) { + file_free(smb_req, fsp); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + p = make_internal_rpc_pipe_p(fsp->fake_file_handle, name, + conn->client_address, + conn->server_info, + smb_req->vuid); + + fsp->fake_file_handle->type = FAKE_FILE_TYPE_NAMED_PIPE; + fsp->fake_file_handle->private_data = p; + } + + if (fsp->fake_file_handle->private_data == NULL) { file_free(smb_req, fsp); return NT_STATUS_PIPE_NOT_AVAILABLE; } - fsp->fake_file_handle->private_data = p; *pfsp = fsp; @@ -978,20 +1049,33 @@ NTSTATUS np_open(struct smb_request *smb_req, struct connection_struct *conn, NTSTATUS np_write(struct files_struct *fsp, uint8_t *data, size_t len, ssize_t *nwritten) { - struct pipes_struct *p; - if (!fsp_is_np(fsp)) { return NT_STATUS_INVALID_HANDLE; } - p = talloc_get_type_abort( - fsp->fake_file_handle->private_data, struct pipes_struct); - DEBUG(6, ("np_write: %x name: %s len: %d\n", (int)fsp->fnum, fsp->fsp_name, (int)len)); dump_data(50, data, len); - *nwritten = write_to_internal_pipe(p, (char *)data, len); + switch (fsp->fake_file_handle->type) { + case FAKE_FILE_TYPE_NAMED_PIPE: { + struct pipes_struct *p = talloc_get_type_abort( + fsp->fake_file_handle->private_data, + struct pipes_struct); + *nwritten = write_to_internal_pipe(p, (char *)data, len); + break; + } + case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: { + struct np_proxy_state *p = talloc_get_type_abort( + fsp->fake_file_handle->private_data, + struct np_proxy_state); + *nwritten = write_data(p->fd, (char *)data, len); + break; + } + default: + return NT_STATUS_INVALID_HANDLE; + break; + } return ((*nwritten) >= 0) ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; @@ -1000,19 +1084,41 @@ NTSTATUS np_write(struct files_struct *fsp, uint8_t *data, size_t len, NTSTATUS np_read(struct files_struct *fsp, uint8_t *data, size_t len, ssize_t *nread, bool *is_data_outstanding) { - struct pipes_struct *p; - if (!fsp_is_np(fsp)) { return NT_STATUS_INVALID_HANDLE; } - p = talloc_get_type_abort( - fsp->fake_file_handle->private_data, struct pipes_struct); + switch (fsp->fake_file_handle->type) { + case FAKE_FILE_TYPE_NAMED_PIPE: { + struct pipes_struct *p = talloc_get_type_abort( + fsp->fake_file_handle->private_data, + struct pipes_struct); + *nread = read_from_internal_pipe(p, (char *)data, len, + is_data_outstanding); + break; + } + case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: { + struct np_proxy_state *p = talloc_get_type_abort( + fsp->fake_file_handle->private_data, + struct np_proxy_state); + int available = 0; + + *nread = sys_read(p->fd, (char *)data, len); - *nread = read_from_internal_pipe(p, (char *)data, len, - is_data_outstanding); + /* + * We don't look at the ioctl result. We don't really care + * if there is data available, because this is racy anyway. + */ + ioctl(p->fd, FIONREAD, &available); + *is_data_outstanding = (available > 0); + + break; + } + default: + return NT_STATUS_INVALID_HANDLE; + break; + } return ((*nread) >= 0) ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR; - } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 4a27d02cfe..d3bfce7499 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -200,11 +200,6 @@ open files, %d are available.\n", request_max_open_files, real_max_open_files)); if (!file_bmap) { exit_server("out of memory in file_init"); } - - /* - * Ensure that pipe_handle_oppset is set correctly. - */ - set_pipe_handle_offset(real_max_open_files); } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b78c946388..30841686fb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -276,21 +276,16 @@ static void nt_open_pipe(char *fname, connection_struct *conn, DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); - /* See if it is one we want to handle. */ - - if (!is_known_pipename(fname)) { - reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, - ERRDOS, ERRbadpipe); - return; - } - /* Strip \\ off the name. */ fname++; - DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname)); - status = np_open(req, conn, fname, &fsp); if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, + ERRDOS, ERRbadpipe); + return; + } reply_nterror(req, status); return; } diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 25a1fe2e63..d971e9dc62 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -66,13 +66,6 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) DEBUG(4,("Opening pipe %s.\n", pipe_name)); - /* See if it is one we want to handle. */ - if (!is_known_pipename(pipe_name)) { - reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, - ERRDOS, ERRbadpipe); - return; - } - /* Strip \PIPE\ off the name. */ fname = pipe_name + PIPELEN; @@ -86,12 +79,13 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) } #endif - /* Known pipes arrive with DIR attribs. Remove it so a regular file */ - /* can be opened and add it in after the open. */ - DEBUG(3,("Known pipe %s opening.\n",fname)); - status = np_open(req, conn, fname, &fsp); if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, + ERRDOS, ERRbadpipe); + return; + } reply_nterror(req, status); return; } |