ctdb-common: Map ENOENT for a missing event script to ENOEXEC
[samba4-gss.git] / source4 / samba / service_named_pipe.c
blobbf2350c1a60f00b11d91e7f23a82ff9b282c801f
1 /*
2 Unix SMB/CIFS implementation.
4 helper functions for NAMED PIPE servers
6 Copyright (C) Stefan (metze) Metzmacher 2008
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include <tevent.h>
24 #include "samba/service.h"
25 #include "param/param.h"
26 #include "auth/auth.h"
27 #include "auth/session.h"
28 #include "auth/auth_sam_reply.h"
29 #include "lib/socket/socket.h"
30 #include "lib/tsocket/tsocket.h"
31 #include "libcli/util/tstream.h"
32 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
33 #include "system/passwd.h"
34 #include "system/network.h"
35 #include "libcli/raw/smb.h"
36 #include "auth/session.h"
37 #include "libcli/security/security.h"
38 #include "libcli/named_pipe_auth/npa_tstream.h"
40 struct named_pipe_socket {
41 const char *pipe_name;
42 const char *pipe_path;
43 const struct stream_server_ops *ops;
44 void *private_data;
47 static void named_pipe_accept_done(struct tevent_req *subreq);
49 static void named_pipe_accept(struct stream_connection *conn)
51 struct tstream_context *plain_tstream;
52 int fd;
53 struct tevent_req *subreq;
54 int ret;
56 /* Let tstream take over fd operations */
58 fd = socket_get_fd(conn->socket);
59 socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE);
60 TALLOC_FREE(conn->event.fde);
61 TALLOC_FREE(conn->socket);
63 ret = tstream_bsd_existing_socket(conn, fd, &plain_tstream);
64 if (ret != 0) {
65 stream_terminate_connection(conn,
66 "named_pipe_accept: out of memory");
67 return;
69 /* as server we want to fail early */
70 tstream_bsd_fail_readv_first_error(plain_tstream, true);
72 subreq = tstream_npa_accept_existing_send(conn, conn->event.ctx,
73 plain_tstream,
74 FILE_TYPE_MESSAGE_MODE_PIPE,
75 0xff | 0x0400 | 0x0100,
76 4096);
77 if (subreq == NULL) {
78 stream_terminate_connection(conn,
79 "named_pipe_accept: "
80 "no memory for tstream_npa_accept_existing_send");
81 return;
83 tevent_req_set_callback(subreq, named_pipe_accept_done, conn);
86 static void named_pipe_accept_done(struct tevent_req *subreq)
88 struct stream_connection *conn = tevent_req_callback_data(subreq,
89 struct stream_connection);
90 struct named_pipe_socket *pipe_sock =
91 talloc_get_type(conn->private_data,
92 struct named_pipe_socket);
93 enum dcerpc_transport_t transport;
94 struct tsocket_address *remote_client_addr;
95 char *remote_client_name;
96 struct tsocket_address *local_server_addr;
97 char *local_server_name;
98 struct auth_session_info_transport *session_info_transport;
99 const char *reason = NULL;
100 TALLOC_CTX *tmp_ctx;
101 int error;
102 int ret;
104 tmp_ctx = talloc_new(conn);
105 if (!tmp_ctx) {
106 reason = "Out of memory!\n";
107 goto out;
110 ret = tstream_npa_accept_existing_recv(subreq, &error, tmp_ctx,
111 &conn->tstream,
112 NULL,
113 &transport,
114 &remote_client_addr,
115 &remote_client_name,
116 &local_server_addr,
117 &local_server_name,
118 &session_info_transport);
119 TALLOC_FREE(subreq);
120 if (ret != 0) {
121 reason = talloc_asprintf(conn,
122 "tstream_npa_accept_existing_recv()"
123 " failed: %s", strerror(error));
124 goto out;
127 conn->local_address = talloc_move(conn, &local_server_addr);
128 conn->remote_address = talloc_move(conn, &remote_client_addr);
130 DBG_DEBUG("Accepted npa connection from %s. "
131 "Client: %s (%s). Server: %s (%s)\n",
132 tsocket_address_string(conn->remote_address, tmp_ctx),
133 local_server_name,
134 tsocket_address_string(local_server_addr, tmp_ctx),
135 remote_client_name,
136 tsocket_address_string(remote_client_addr, tmp_ctx));
138 conn->session_info = auth_session_info_from_transport(conn, session_info_transport,
139 conn->lp_ctx,
140 &reason);
141 if (!conn->session_info) {
142 goto out;
145 if (transport == NCACN_NP) {
146 if (security_token_is_system(conn->session_info->security_token)) {
147 reason = talloc_asprintf(
148 conn,
149 "System token not allowed on transport %d\n",
150 transport);
151 goto out;
153 } else if (transport == NCALRPC) {
155 * TODO:
156 * we should somehow remember the given transport on
157 * the connection, but that's a task for another day
158 * as it's not trivial to do...
160 } else {
161 reason = talloc_asprintf(
162 conn,
163 "Only allow NCACN_NP or NCALRPC transport on named pipes, "
164 "got %d\n",
165 (int)transport);
166 goto out;
170 * hand over to the real pipe implementation,
171 * now that we have setup the transport session_info
173 conn->ops = pipe_sock->ops;
174 conn->private_data = pipe_sock->private_data;
175 conn->ops->accept_connection(conn);
177 DBG_DEBUG("named pipe connection [%s] established\n", conn->ops->name);
179 talloc_free(tmp_ctx);
180 return;
182 out:
183 talloc_free(tmp_ctx);
184 if (!reason) {
185 reason = "Internal error";
187 stream_terminate_connection(conn, reason);
191 called when a pipe socket becomes readable
193 static void named_pipe_recv(struct stream_connection *conn, uint16_t flags)
195 stream_terminate_connection(conn, "named_pipe_recv: called");
199 called when a pipe socket becomes writable
201 static void named_pipe_send(struct stream_connection *conn, uint16_t flags)
203 stream_terminate_connection(conn, "named_pipe_send: called");
206 static const struct stream_server_ops named_pipe_stream_ops = {
207 .name = "named_pipe",
208 .accept_connection = named_pipe_accept,
209 .recv_handler = named_pipe_recv,
210 .send_handler = named_pipe_send,
213 NTSTATUS tstream_setup_named_pipe(TALLOC_CTX *mem_ctx,
214 struct tevent_context *event_context,
215 struct loadparm_context *lp_ctx,
216 const struct model_ops *model_ops,
217 const struct stream_server_ops *stream_ops,
218 const char *pipe_name,
219 void *private_data,
220 void *process_context)
222 char *dirname;
223 struct named_pipe_socket *pipe_sock;
224 NTSTATUS status = NT_STATUS_NO_MEMORY;;
226 pipe_sock = talloc(mem_ctx, struct named_pipe_socket);
227 if (pipe_sock == NULL) {
228 goto fail;
231 /* remember the details about the pipe */
232 pipe_sock->pipe_name = strlower_talloc(pipe_sock, pipe_name);
233 if (pipe_sock->pipe_name == NULL) {
234 goto fail;
237 if (!directory_create_or_exist(lpcfg_ncalrpc_dir(lp_ctx), 0755)) {
238 status = map_nt_error_from_unix_common(errno);
239 DBG_ERR("Failed to create ncalrpc pipe directory '%s' - %s\n",
240 lpcfg_ncalrpc_dir(lp_ctx), nt_errstr(status));
241 goto fail;
244 dirname = talloc_asprintf(pipe_sock, "%s/np", lpcfg_ncalrpc_dir(lp_ctx));
245 if (dirname == NULL) {
246 goto fail;
249 if (!directory_create_or_exist_strict(dirname, geteuid(), 0700)) {
250 status = map_nt_error_from_unix_common(errno);
251 DBG_ERR("Failed to create stream pipe directory '%s' - %s\n",
252 dirname, nt_errstr(status));
253 goto fail;
256 if (strncmp(pipe_name, "\\pipe\\", 6) == 0) {
257 pipe_name += 6;
260 pipe_sock->pipe_path = talloc_asprintf(pipe_sock, "%s/%s", dirname,
261 pipe_name);
262 if (pipe_sock->pipe_path == NULL) {
263 goto fail;
266 talloc_free(dirname);
268 pipe_sock->ops = stream_ops;
269 pipe_sock->private_data = private_data;
271 status = stream_setup_socket(pipe_sock,
272 event_context,
273 lp_ctx,
274 model_ops,
275 &named_pipe_stream_ops,
276 "unix",
277 pipe_sock->pipe_path,
278 NULL,
279 NULL,
280 pipe_sock,
281 process_context);
282 if (!NT_STATUS_IS_OK(status)) {
283 goto fail;
285 return NT_STATUS_OK;
287 fail:
288 talloc_free(pipe_sock);
289 return status;