Finish removal of iconv_convenience in public API's.
[amitay/samba.git] / source4 / smbd / service_named_pipe.c
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/credentials/credentials.h"
37 #include "auth/credentials/credentials_krb5.h"
38
39 struct named_pipe_socket {
40         const char *pipe_name;
41         const char *pipe_path;
42         const struct stream_server_ops *ops;
43         void *private_data;
44 };
45
46 struct named_pipe_connection {
47         struct stream_connection *connection;
48         const struct named_pipe_socket *pipe_sock;
49         struct tstream_context *tstream;
50 };
51
52 static void named_pipe_terminate_connection(struct named_pipe_connection *pipe_conn, const char *reason)
53 {
54         stream_terminate_connection(pipe_conn->connection, reason);
55 }
56
57 static NTSTATUS named_pipe_full_request(void *private_data, DATA_BLOB blob, size_t *size)
58 {
59         if (blob.length < 8) {
60                 return STATUS_MORE_ENTRIES;
61         }
62
63         if (memcmp(NAMED_PIPE_AUTH_MAGIC, &blob.data[4], 4) != 0) {
64                 DEBUG(0,("named_pipe_full_request: wrong protocol\n"));
65                 *size = blob.length;
66                 /* the error will be handled in named_pipe_recv_auth_request */
67                 return NT_STATUS_OK;
68         }
69
70         *size = 4 + RIVAL(blob.data, 0);
71         if (*size > blob.length) {
72                 return STATUS_MORE_ENTRIES;
73         }
74
75         return NT_STATUS_OK;
76 }
77
78 static void named_pipe_auth_request(struct tevent_req *subreq);
79
80 static void named_pipe_accept(struct stream_connection *conn)
81 {
82         struct named_pipe_socket *pipe_sock = talloc_get_type(conn->private_data,
83                                                 struct named_pipe_socket);
84         struct named_pipe_connection *pipe_conn;
85         struct tevent_req *subreq;
86         int rc, fd;
87
88         pipe_conn = talloc_zero(conn, struct named_pipe_connection);
89         if (pipe_conn == NULL) {
90                 stream_terminate_connection(conn,
91                                 "named_pipe_accept: out of memory");
92                 return;
93         }
94
95         TALLOC_FREE(conn->event.fde);
96
97         /*
98          * We have to duplicate the fd, cause it gets closed when the tstream
99          * is freed and you shouldn't work a fd the tstream is based on.
100          */
101         fd = dup(socket_get_fd(conn->socket));
102         if (fd == -1) {
103                 char *reason;
104
105                 reason = talloc_asprintf(conn,
106                                          "named_pipe_accept: failed to duplicate the file descriptor - %s",
107                                          strerror(errno));
108                 if (reason == NULL) {
109                         reason = strerror(errno);
110                 }
111                 stream_terminate_connection(conn, reason);
112         }
113         rc = tstream_bsd_existing_socket(pipe_conn,
114                                          fd,
115                                          &pipe_conn->tstream);
116         if (rc < 0) {
117                 stream_terminate_connection(conn,
118                                 "named_pipe_accept: out of memory");
119                 return;
120         }
121
122         pipe_conn->connection = conn;
123         pipe_conn->pipe_sock = pipe_sock;
124         conn->private_data = pipe_conn;
125
126         /*
127          * The named pipe pdu's have the length as 8 byte (initial_read_size),
128          * named_pipe_full_request provides the pdu length then.
129          */
130         subreq = tstream_read_pdu_blob_send(pipe_conn,
131                                             pipe_conn->connection->event.ctx,
132                                             pipe_conn->tstream,
133                                             8, /* initial_read_size */
134                                             named_pipe_full_request,
135                                             pipe_conn);
136         if (subreq == NULL) {
137                 named_pipe_terminate_connection(pipe_conn,
138                                 "named_pipe_accept: "
139                                 "no memory for tstream_read_pdu_blob_send");
140                 return;
141         }
142         tevent_req_set_callback(subreq, named_pipe_auth_request, pipe_conn);
143 }
144
145 struct named_pipe_call {
146         struct named_pipe_connection *pipe_conn;
147         DATA_BLOB in;
148         DATA_BLOB out;
149         struct iovec out_iov[1];
150         NTSTATUS status;
151 };
152
153 static void named_pipe_handover_connection(struct tevent_req *subreq);
154
155 static void named_pipe_auth_request(struct tevent_req *subreq)
156 {
157         struct named_pipe_connection *pipe_conn = tevent_req_callback_data(subreq,
158                                       struct named_pipe_connection);
159         struct stream_connection *conn = pipe_conn->connection;
160         struct named_pipe_call *call;
161         enum ndr_err_code ndr_err;
162         union netr_Validation val;
163         struct auth_serversupplied_info *server_info;
164         struct named_pipe_auth_req pipe_request;
165         struct named_pipe_auth_rep pipe_reply;
166         struct auth_context *auth_context;
167         NTSTATUS status;
168         int ret;
169
170         call = talloc(pipe_conn, struct named_pipe_call);
171         if (call == NULL) {
172                 named_pipe_terminate_connection(pipe_conn,
173                                 "named_pipe_auth_request: "
174                                 "no memory for named_pipe_call");
175                 return;
176         }
177         call->pipe_conn = pipe_conn;
178
179         status = tstream_read_pdu_blob_recv(subreq,
180                                             call,
181                                             &call->in);
182         TALLOC_FREE(subreq);
183         if (!NT_STATUS_IS_OK(status)) {
184                 const char *reason;
185
186                 reason = talloc_asprintf(call, "named_pipe_call_loop: "
187                                          "tstream_read_pdu_blob_recv() - %s",
188                                          nt_errstr(status));
189                 if (reason == NULL) {
190                         reason = nt_errstr(status);
191                 }
192
193                 named_pipe_terminate_connection(pipe_conn, reason);
194                 return;
195         }
196
197         DEBUG(10,("Received named_pipe packet of length %lu from %s\n",
198                  (long) call->in.length,
199                  tsocket_address_string(pipe_conn->connection->remote_address, call)));
200         dump_data(11, call->in.data, call->in.length);
201
202         /*
203          * TODO: check it's a root (uid == 0) pipe
204          */
205
206         ZERO_STRUCT(pipe_reply);
207         pipe_reply.level = 0;
208         pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
209
210         /* parse the passed credentials */
211         ndr_err = ndr_pull_struct_blob_all(
212                         &call->in,
213                         pipe_conn,
214                         &pipe_request,
215                         (ndr_pull_flags_fn_t) ndr_pull_named_pipe_auth_req);
216         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
217                 pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
218                 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
219                           nt_errstr(pipe_reply.status)));
220                 goto reply;
221         }
222
223         if (DEBUGLVL(10)) {
224                 NDR_PRINT_DEBUG(named_pipe_auth_req, &pipe_request);
225         }
226
227         if (strcmp(NAMED_PIPE_AUTH_MAGIC, pipe_request.magic) != 0) {
228                 DEBUG(2, ("named_pipe_auth_req: invalid magic '%s' != %s\n",
229                           pipe_request.magic, NAMED_PIPE_AUTH_MAGIC));
230                 pipe_reply.status = NT_STATUS_INVALID_PARAMETER;
231                 goto reply;
232         }
233
234         switch (pipe_request.level) {
235         case 0:
236                 /*
237                  * anon connection, we don't create a session info
238                  * and leave it NULL
239                  */
240                 pipe_reply.level = 0;
241                 pipe_reply.status = NT_STATUS_OK;
242                 break;
243         case 1:
244                 val.sam3 = &pipe_request.info.info1;
245
246                 pipe_reply.level = 1;
247                 pipe_reply.status = make_server_info_netlogon_validation(pipe_conn,
248                                                                          "TODO",
249                                                                          3, &val,
250                                                                          &server_info);
251                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
252                         DEBUG(2, ("make_server_info_netlogon_validation returned "
253                                   "%s\n", nt_errstr(pipe_reply.status)));
254                         goto reply;
255                 }
256
257                 pipe_reply.status = auth_context_create(conn,
258                                                         conn->event.ctx, conn->msg_ctx,
259                                                         conn->lp_ctx,
260                                                         &auth_context);
261                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
262                         DEBUG(2, ("auth_context_create returned "
263                                   "%s\n", nt_errstr(pipe_reply.status)));
264                         goto reply;
265                 }
266
267
268                 /* setup the session_info on the connection */
269                 pipe_reply.status = auth_context->generate_session_info(conn,
270                                                                         auth_context,
271                                                                         server_info,
272                                                                         &conn->session_info);
273                 talloc_free(auth_context);
274                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
275                         DEBUG(2, ("auth_generate_session_info failed: %s\n",
276                                   nt_errstr(pipe_reply.status)));
277                         goto reply;
278                 }
279
280                 break;
281         case 2:
282                 pipe_reply.level = 2;
283                 pipe_reply.info.info2.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
284                 pipe_reply.info.info2.device_state = 0xff | 0x0400 | 0x0100;
285                 pipe_reply.info.info2.allocation_size = 4096;
286
287                 if (pipe_request.info.info2.sam_info3 == NULL) {
288                         /*
289                          * anon connection, we don't create a session info
290                          * and leave it NULL
291                          */
292                         pipe_reply.status = NT_STATUS_OK;
293                         break;
294                 }
295
296                 val.sam3 = pipe_request.info.info2.sam_info3;
297
298                 pipe_reply.status = make_server_info_netlogon_validation(pipe_conn,
299                                                 val.sam3->base.account_name.string,
300                                                 3, &val, &server_info);
301                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
302                         DEBUG(2, ("make_server_info_netlogon_validation returned "
303                                   "%s\n", nt_errstr(pipe_reply.status)));
304                         goto reply;
305                 }
306
307                 /* setup the session_info on the connection */
308                 pipe_reply.status = auth_context_create(conn,
309                                                         conn->event.ctx, conn->msg_ctx,
310                                                         conn->lp_ctx,
311                                                         &auth_context);
312                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
313                         DEBUG(2, ("auth_context_create returned "
314                                   "%s\n", nt_errstr(pipe_reply.status)));
315                         goto reply;
316                 }
317
318                 pipe_reply.status = auth_context->generate_session_info(conn,
319                                                                         auth_context,
320                                                                         server_info,
321                                                                         &conn->session_info);
322                 talloc_free(auth_context);
323                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
324                         DEBUG(2, ("auth_generate_session_info failed: %s\n",
325                                   nt_errstr(pipe_reply.status)));
326                         goto reply;
327                 }
328
329                 conn->session_info->session_key = data_blob_const(pipe_request.info.info2.session_key,
330                                                         pipe_request.info.info2.session_key_length);
331                 talloc_steal(conn->session_info, pipe_request.info.info2.session_key);
332
333                 break;
334         case 3:
335                 pipe_reply.level = 3;
336                 pipe_reply.info.info3.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
337                 pipe_reply.info.info3.device_state = 0xff | 0x0400 | 0x0100;
338                 pipe_reply.info.info3.allocation_size = 4096;
339
340                 if (pipe_request.info.info3.server_addr == NULL) {
341                         pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
342                         DEBUG(2, ("Missing server address\n"));
343                         goto reply;
344                 }
345                 if (pipe_request.info.info3.client_addr == NULL) {
346                         pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
347                         DEBUG(2, ("Missing client address\n"));
348                         goto reply;
349                 }
350
351                 ret = tsocket_address_inet_from_strings(conn, "ip",
352                                                         pipe_request.info.info3.server_addr,
353                                                         pipe_request.info.info3.server_port,
354                                                         &conn->local_address);
355                 if (ret != 0) {
356                         DEBUG(2, ("Invalid server address[%s] port[%u] - %s\n",
357                                 pipe_request.info.info3.server_addr,
358                                 pipe_request.info.info3.server_port,
359                                 strerror(errno)));
360                         pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
361                         goto reply;
362                 }
363
364                 ret = tsocket_address_inet_from_strings(conn, "ip",
365                                                         pipe_request.info.info3.client_addr,
366                                                         pipe_request.info.info3.client_port,
367                                                         &conn->remote_address);
368                 if (ret != 0) {
369                         DEBUG(2, ("Invalid client address[%s] port[%u] - %s\n",
370                                 pipe_request.info.info3.client_addr,
371                                 pipe_request.info.info3.client_port,
372                                 strerror(errno)));
373                         pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
374                         goto reply;
375                 }
376
377                 if (pipe_request.info.info3.sam_info3 == NULL) {
378                         /*
379                          * anon connection, we don't create a session info
380                          * and leave it NULL
381                          */
382                         pipe_reply.status = NT_STATUS_OK;
383                         break;
384                 }
385
386                 val.sam3 = pipe_request.info.info3.sam_info3;
387
388                 pipe_reply.status = make_server_info_netlogon_validation(pipe_conn,
389                                                 val.sam3->base.account_name.string,
390                                                 3, &val, &server_info);
391                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
392                         DEBUG(2, ("make_server_info_netlogon_validation returned "
393                                   "%s\n", nt_errstr(pipe_reply.status)));
394                         goto reply;
395                 }
396
397                 /* setup the session_info on the connection */
398                 pipe_reply.status = auth_context_create(conn,
399                                                         conn->event.ctx, conn->msg_ctx,
400                                                         conn->lp_ctx,
401                                                         &auth_context);
402                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
403                         DEBUG(2, ("auth_context_create returned "
404                                   "%s\n", nt_errstr(pipe_reply.status)));
405                         goto reply;
406                 }
407
408                 /* setup the session_info on the connection */
409                 pipe_reply.status = auth_context->generate_session_info(conn,
410                                                                         auth_context,
411                                                                         server_info,
412                                                                         &conn->session_info);
413                 talloc_free(auth_context);
414                 if (!NT_STATUS_IS_OK(pipe_reply.status)) {
415                         DEBUG(2, ("auth_generate_session_info failed: %s\n",
416                                   nt_errstr(pipe_reply.status)));
417                         goto reply;
418                 }
419
420                 if (pipe_request.info.info3.gssapi_delegated_creds_length) {
421                         OM_uint32 minor_status;
422                         gss_buffer_desc cred_token;
423                         gss_cred_id_t cred_handle;
424                         const char *error_string;
425
426                         DEBUG(10, ("named_pipe_auth: delegated credentials supplied by client\n"));
427
428                         cred_token.value = pipe_request.info.info3.gssapi_delegated_creds;
429                         cred_token.length = pipe_request.info.info3.gssapi_delegated_creds_length;
430
431                         ret = gss_import_cred(&minor_status,
432                                                &cred_token,
433                                                &cred_handle);
434                         if (ret != GSS_S_COMPLETE) {
435                                 pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
436                                 goto reply;
437                         }
438
439                         conn->session_info->credentials = cli_credentials_init(conn->session_info);
440                         if (conn->session_info->credentials == NULL) {
441                                 pipe_reply.status = NT_STATUS_NO_MEMORY;
442                                 goto reply;
443                         }
444
445                         cli_credentials_set_conf(conn->session_info->credentials,
446                                                  conn->lp_ctx);
447                         /* Just so we don't segfault trying to get at a username */
448                         cli_credentials_set_anonymous(conn->session_info->credentials);
449
450                         ret = cli_credentials_set_client_gss_creds(conn->session_info->credentials,
451                                                                    conn->event.ctx,
452                                                                    conn->lp_ctx,
453                                                                    cred_handle,
454                                                                    CRED_SPECIFIED, &error_string);
455                         if (ret) {
456                                 pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
457                                 DEBUG(2, ("Failed to set pipe forwarded creds: %s\n", error_string));
458                                 goto reply;
459                         }
460
461                         /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
462                         cli_credentials_set_kerberos_state(conn->session_info->credentials,
463                                                            CRED_MUST_USE_KERBEROS);
464                 }
465
466                 conn->session_info->session_key = data_blob_const(pipe_request.info.info3.session_key,
467                                                         pipe_request.info.info3.session_key_length);
468                 talloc_steal(conn->session_info, pipe_request.info.info3.session_key);
469
470                 break;
471         default:
472                 DEBUG(0, ("named_pipe_auth_req: unknown level %u\n",
473                           pipe_request.level));
474                 pipe_reply.level = 0;
475                 pipe_reply.status = NT_STATUS_INVALID_LEVEL;
476                 goto reply;
477         }
478
479 reply:
480         /* create the output */
481         ndr_err = ndr_push_struct_blob(&call->out, pipe_conn,
482                         &pipe_reply,
483                         (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_rep);
484         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
485                 const char *reason;
486                 status = ndr_map_error2ntstatus(ndr_err);
487
488                 reason = talloc_asprintf(pipe_conn, "named_pipe_auth_request: could not marshall named_pipe_auth_rep: %s\n",
489                                          nt_errstr(status));
490                 if (reason == NULL) {
491                         reason = "named_pipe_auth_request: could not marshall named_pipe_auth_rep";
492                 }
493                 named_pipe_terminate_connection(pipe_conn, reason);
494                 return;
495         }
496
497         DEBUG(10,("named_pipe_auth_request: named_pipe_auth reply[%u]\n",
498                   (unsigned) call->out.length));
499         dump_data(11, call->out.data, call->out.length);
500         if (DEBUGLVL(10)) {
501                 NDR_PRINT_DEBUG(named_pipe_auth_rep, &pipe_reply);
502         }
503
504         call->status = pipe_reply.status;
505
506         call->out_iov[0].iov_base = call->out.data;
507         call->out_iov[0].iov_len = call->out.length;
508
509         subreq = tstream_writev_send(call,
510                                      pipe_conn->connection->event.ctx,
511                                      pipe_conn->tstream,
512                                      call->out_iov, 1);
513         if (subreq == NULL) {
514                 named_pipe_terminate_connection(pipe_conn, "named_pipe_auth_request: "
515                                 "no memory for tstream_writev_send");
516                 return;
517         }
518
519         tevent_req_set_callback(subreq, named_pipe_handover_connection, call);
520 }
521
522 static void named_pipe_handover_connection(struct tevent_req *subreq)
523 {
524         struct named_pipe_call *call = tevent_req_callback_data(subreq,
525                         struct named_pipe_call);
526         struct named_pipe_connection *pipe_conn = call->pipe_conn;
527         struct stream_connection *conn = pipe_conn->connection;
528         int sys_errno;
529         int rc;
530
531         rc = tstream_writev_recv(subreq, &sys_errno);
532         TALLOC_FREE(subreq);
533         if (rc == -1) {
534                 const char *reason;
535
536                 reason = talloc_asprintf(call, "named_pipe_handover_connection: "
537                                          "tstream_writev_recv() - %d:%s",
538                                          sys_errno, strerror(sys_errno));
539                 if (reason == NULL) {
540                         reason = "named_pipe_handover_connection: "
541                                  "tstream_writev_recv() failed";
542                 }
543
544                 named_pipe_terminate_connection(pipe_conn, reason);
545                 return;
546         }
547
548         if (!NT_STATUS_IS_OK(call->status)) {
549                 const char *reason;
550
551                 reason = talloc_asprintf(call, "named_pipe_handover_connection: "
552                                         "reply status - %s", nt_errstr(call->status));
553                 if (reason == NULL) {
554                         reason = nt_errstr(call->status);
555                 }
556
557                 named_pipe_terminate_connection(pipe_conn, reason);
558                 return;
559         }
560
561         /*
562          * remove the named_pipe layer together with its packet layer
563          */
564         conn->ops               = pipe_conn->pipe_sock->ops;
565         conn->private_data      = pipe_conn->pipe_sock->private_data;
566         talloc_unlink(conn, pipe_conn);
567
568         conn->event.fde = tevent_add_fd(conn->event.ctx,
569                                         conn,
570                                         socket_get_fd(conn->socket),
571                                         TEVENT_FD_READ,
572                                         stream_io_handler_fde,
573                                         conn);
574         if (conn->event.fde == NULL) {
575                 named_pipe_terminate_connection(pipe_conn, "named_pipe_handover_connection: "
576                                 "setting up the stream_io_handler_fde failed");
577                 return;
578         }
579
580         /*
581          * hand over to the real pipe implementation,
582          * now that we have setup the transport session_info
583          */
584         conn->ops->accept_connection(conn);
585
586         DEBUG(10,("named_pipe_handover_connection[%s]: succeeded\n",
587               conn->ops->name));
588
589         /* we don't have to free call here as the connection got closed */
590 }
591
592 /*
593   called when a pipe socket becomes readable
594 */
595 static void named_pipe_recv(struct stream_connection *conn, uint16_t flags)
596 {
597         struct named_pipe_connection *pipe_conn = talloc_get_type(
598                 conn->private_data, struct named_pipe_connection);
599
600         named_pipe_terminate_connection(pipe_conn,
601                                         "named_pipe_recv: called");
602 }
603
604 /*
605   called when a pipe socket becomes writable
606 */
607 static void named_pipe_send(struct stream_connection *conn, uint16_t flags)
608 {
609         struct named_pipe_connection *pipe_conn = talloc_get_type(
610                 conn->private_data, struct named_pipe_connection);
611
612         named_pipe_terminate_connection(pipe_conn,
613                                         "named_pipe_send: called");
614 }
615
616 static const struct stream_server_ops named_pipe_stream_ops = {
617         .name                   = "named_pipe",
618         .accept_connection      = named_pipe_accept,
619         .recv_handler           = named_pipe_recv,
620         .send_handler           = named_pipe_send,
621 };
622
623 NTSTATUS stream_setup_named_pipe(struct tevent_context *event_context,
624                                  struct loadparm_context *lp_ctx,
625                                  const struct model_ops *model_ops,
626                                  const struct stream_server_ops *stream_ops,
627                                  const char *pipe_name,
628                                  void *private_data)
629 {
630         char *dirname;
631         struct named_pipe_socket *pipe_sock;
632         NTSTATUS status = NT_STATUS_NO_MEMORY;;
633
634         pipe_sock = talloc(event_context, struct named_pipe_socket);
635         if (pipe_sock == NULL) {
636                 goto fail;
637         }
638
639         /* remember the details about the pipe */
640         pipe_sock->pipe_name    = talloc_strdup(pipe_sock, pipe_name);
641         if (pipe_sock->pipe_name == NULL) {
642                 goto fail;
643         }
644
645         dirname = talloc_asprintf(pipe_sock, "%s/np", lp_ncalrpc_dir(lp_ctx));
646         if (dirname == NULL) {
647                 goto fail;
648         }
649
650         if (!directory_create_or_exist(dirname, geteuid(), 0700)) {
651                 status = map_nt_error_from_unix(errno);
652                 DEBUG(0,(__location__ ": Failed to create stream pipe directory %s - %s\n",
653                          dirname, nt_errstr(status)));
654                 goto fail;
655         }
656
657         if (strncmp(pipe_name, "\\pipe\\", 6) == 0) {
658                 pipe_name += 6;
659         }
660
661         pipe_sock->pipe_path = talloc_asprintf(pipe_sock, "%s/%s", dirname,
662                                                pipe_name);
663         if (pipe_sock->pipe_path == NULL) {
664                 goto fail;
665         }
666
667         talloc_free(dirname);
668
669         pipe_sock->ops          = stream_ops;
670         pipe_sock->private_data = talloc_reference(pipe_sock, private_data);
671
672         status = stream_setup_socket(event_context,
673                                      lp_ctx,
674                                      model_ops,
675                                      &named_pipe_stream_ops,
676                                      "unix",
677                                      pipe_sock->pipe_path,
678                                      NULL,
679                                      NULL,
680                                      pipe_sock);
681         if (!NT_STATUS_IS_OK(status)) {
682                 goto fail;
683         }
684         return NT_STATUS_OK;
685
686  fail:
687         talloc_free(pipe_sock);
688         return status;
689 }