source: trunk/server/source4/smbd/service_named_pipe.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 6.9 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 helper functions for NAMED PIPE servers
5
6 Copyright (C) Stefan (metze) Metzmacher 2008
7
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.
12
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.
17
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/>.
20*/
21
22#include "includes.h"
23#include <tevent.h>
24#include "smbd/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"
39
40struct named_pipe_socket {
41 const char *pipe_name;
42 const char *pipe_path;
43 const struct stream_server_ops *ops;
44 void *private_data;
45};
46
47static void named_pipe_accept_done(struct tevent_req *subreq);
48
49static void named_pipe_accept(struct stream_connection *conn)
50{
51 struct tstream_context *plain_tstream;
52 int fd;
53 struct tevent_req *subreq;
54 int ret;
55
56 /* Let tstream take over fd operations */
57
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);
62
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;
68 }
69
70 subreq = tstream_npa_accept_existing_send(conn, conn->event.ctx,
71 plain_tstream,
72 FILE_TYPE_MESSAGE_MODE_PIPE,
73 0xff | 0x0400 | 0x0100,
74 4096);
75 if (subreq == NULL) {
76 stream_terminate_connection(conn,
77 "named_pipe_accept: "
78 "no memory for tstream_npa_accept_existing_send");
79 return;
80 }
81 tevent_req_set_callback(subreq, named_pipe_accept_done, conn);
82}
83
84static void named_pipe_accept_done(struct tevent_req *subreq)
85{
86 struct stream_connection *conn = tevent_req_callback_data(subreq,
87 struct stream_connection);
88 struct named_pipe_socket *pipe_sock =
89 talloc_get_type(conn->private_data,
90 struct named_pipe_socket);
91 struct tsocket_address *client;
92 char *client_name;
93 struct tsocket_address *server;
94 char *server_name;
95 struct auth_session_info_transport *session_info_transport;
96 const char *reason = NULL;
97 TALLOC_CTX *tmp_ctx;
98 int error;
99 int ret;
100
101 tmp_ctx = talloc_new(conn);
102 if (!tmp_ctx) {
103 reason = "Out of memory!\n";
104 goto out;
105 }
106
107 ret = tstream_npa_accept_existing_recv(subreq, &error, tmp_ctx,
108 &conn->tstream,
109 &client,
110 &client_name,
111 &server,
112 &server_name,
113 &session_info_transport);
114 TALLOC_FREE(subreq);
115 if (ret != 0) {
116 reason = talloc_asprintf(conn,
117 "tstream_npa_accept_existing_recv()"
118 " failed: %s", strerror(error));
119 goto out;
120 }
121
122 DEBUG(10, ("Accepted npa connection from %s. "
123 "Client: %s (%s). Server: %s (%s)\n",
124 tsocket_address_string(conn->remote_address, tmp_ctx),
125 client_name, tsocket_address_string(client, tmp_ctx),
126 server_name, tsocket_address_string(server, tmp_ctx)));
127
128 conn->session_info = auth_session_info_from_transport(conn, session_info_transport,
129 conn->lp_ctx,
130 &reason);
131 if (!conn->session_info) {
132 goto out;
133 }
134
135 /*
136 * hand over to the real pipe implementation,
137 * now that we have setup the transport session_info
138 */
139 conn->ops = pipe_sock->ops;
140 conn->private_data = pipe_sock->private_data;
141 conn->ops->accept_connection(conn);
142
143 DEBUG(10, ("named pipe connection [%s] established\n",
144 conn->ops->name));
145
146 talloc_free(tmp_ctx);
147 return;
148
149out:
150 talloc_free(tmp_ctx);
151 if (!reason) {
152 reason = "Internal error";
153 }
154 stream_terminate_connection(conn, reason);
155}
156
157/*
158 called when a pipe socket becomes readable
159*/
160static void named_pipe_recv(struct stream_connection *conn, uint16_t flags)
161{
162 stream_terminate_connection(conn, "named_pipe_recv: called");
163}
164
165/*
166 called when a pipe socket becomes writable
167*/
168static void named_pipe_send(struct stream_connection *conn, uint16_t flags)
169{
170 stream_terminate_connection(conn, "named_pipe_send: called");
171}
172
173static const struct stream_server_ops named_pipe_stream_ops = {
174 .name = "named_pipe",
175 .accept_connection = named_pipe_accept,
176 .recv_handler = named_pipe_recv,
177 .send_handler = named_pipe_send,
178};
179
180NTSTATUS tstream_setup_named_pipe(TALLOC_CTX *mem_ctx,
181 struct tevent_context *event_context,
182 struct loadparm_context *lp_ctx,
183 const struct model_ops *model_ops,
184 const struct stream_server_ops *stream_ops,
185 const char *pipe_name,
186 void *private_data)
187{
188 char *dirname;
189 struct named_pipe_socket *pipe_sock;
190 NTSTATUS status = NT_STATUS_NO_MEMORY;;
191
192 pipe_sock = talloc(mem_ctx, struct named_pipe_socket);
193 if (pipe_sock == NULL) {
194 goto fail;
195 }
196
197 /* remember the details about the pipe */
198 pipe_sock->pipe_name = talloc_strdup(pipe_sock, pipe_name);
199 if (pipe_sock->pipe_name == NULL) {
200 goto fail;
201 }
202
203 if (!directory_create_or_exist(lpcfg_ncalrpc_dir(lp_ctx), geteuid(), 0755)) {
204 status = map_nt_error_from_unix(errno);
205 DEBUG(0,(__location__ ": Failed to create ncalrpc pipe directory '%s' - %s\n",
206 lpcfg_ncalrpc_dir(lp_ctx), nt_errstr(status)));
207 goto fail;
208 }
209
210 dirname = talloc_asprintf(pipe_sock, "%s/np", lpcfg_ncalrpc_dir(lp_ctx));
211 if (dirname == NULL) {
212 goto fail;
213 }
214
215 if (!directory_create_or_exist(dirname, geteuid(), 0700)) {
216 status = map_nt_error_from_unix(errno);
217 DEBUG(0,(__location__ ": Failed to create stream pipe directory %s - %s\n",
218 dirname, nt_errstr(status)));
219 goto fail;
220 }
221
222 if (strncmp(pipe_name, "\\pipe\\", 6) == 0) {
223 pipe_name += 6;
224 }
225
226 pipe_sock->pipe_path = talloc_asprintf(pipe_sock, "%s/%s", dirname,
227 pipe_name);
228 if (pipe_sock->pipe_path == NULL) {
229 goto fail;
230 }
231
232 talloc_free(dirname);
233
234 pipe_sock->ops = stream_ops;
235 pipe_sock->private_data = private_data;
236
237 status = stream_setup_socket(pipe_sock,
238 event_context,
239 lp_ctx,
240 model_ops,
241 &named_pipe_stream_ops,
242 "unix",
243 pipe_sock->pipe_path,
244 NULL,
245 NULL,
246 pipe_sock);
247 if (!NT_STATUS_IS_OK(status)) {
248 goto fail;
249 }
250 return NT_STATUS_OK;
251
252 fail:
253 talloc_free(pipe_sock);
254 return status;
255}
Note: See TracBrowser for help on using the repository browser.