2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
17 * This is the named pipe service for smbd.
20 #include <sys/types.h>
34 #include <smbsrv/libsmb.h>
35 #include <smbsrv/libmlsvc.h>
36 #include <smbsrv/smb_xdr.h>
39 struct pipe_listener
{
47 static void *pipesvc_listener(void *);
48 static void *pipesvc_worker(void *);
49 static int pipe_send(ndr_pipe_t
*, void *, size_t);
50 static int pipe_recv(ndr_pipe_t
*, void *, size_t);
52 mutex_t pipesvc_mutex
= DEFAULTMUTEX
;
53 int pipesvc_workers_max
= 500;
54 int pipesvc_workers_cur
= 0;
56 uint16_t pipe_max_msgsize
= SMB_PIPE_MAX_MSGSIZE
;
59 * Allow more opens on SRVSVC because that's used by many clients
60 * to get the share list, etc.
62 #define SRVSVC_MAX_OPENS 200
63 #define DEF_MAX_OPENS 50
66 static struct pipe_listener
67 pipe_listeners
[NLISTENERS
] = {
68 { "eventlog", DEF_MAX_OPENS
, 0, 0 },
69 { "lsarpc", DEF_MAX_OPENS
, 0, 0 },
70 { "lsass", DEF_MAX_OPENS
, 0, 0 },
71 { "netdfs", DEF_MAX_OPENS
, 0, 0 },
72 { "netlogon", DEF_MAX_OPENS
, 0, 0 },
73 { "samr", DEF_MAX_OPENS
, 0, 0 },
74 { "spoolss", DEF_MAX_OPENS
, 0, 0 },
75 { "srvsvc", SRVSVC_MAX_OPENS
, 0, 0 },
76 { "svcctl", DEF_MAX_OPENS
, 0, 0 },
77 { "winreg", DEF_MAX_OPENS
, 0, 0 },
78 { "wkssvc", DEF_MAX_OPENS
, 0, 0 },
82 np_new(struct pipe_listener
*pl
, int fid
)
88 * Allocating ndr_pipe_t + smb_netuserinfo_t as one.
89 * We could just make that part of ndr_pipe_t, but
90 * that struct is opaque to libmlrpc.
92 len
= sizeof (*np
) + sizeof (smb_netuserinfo_t
);
99 np
->np_endpoint
= pl
->name
;
100 np
->np_user
= (void*)(np
+ 1);
101 np
->np_send
= pipe_send
;
102 np
->np_recv
= pipe_recv
;
104 np
->np_max_xmit_frag
= pipe_max_msgsize
;
105 np
->np_max_recv_frag
= pipe_max_msgsize
;
111 np_free(ndr_pipe_t
*np
)
113 (void) close(np
->np_fid
);
118 * Create the smbd opipe door service.
119 * Returns the door descriptor on success. Otherwise returns -1.
122 smbd_pipesvc_start(void)
125 pthread_attr_t tattr
;
126 struct pipe_listener
*pl
;
129 if (mlsvc_init() != 0) {
130 smbd_report("msrpc initialization failed");
134 (void) pthread_attr_init(&tattr
);
135 (void) pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
137 for (i
= 0; i
< NLISTENERS
; i
++) {
138 pl
= &pipe_listeners
[i
];
141 if (strcasecmp(pl
->name
, "spoolss") == 0 &&
142 smb_config_getbool(SMB_CI_PRINT_ENABLE
) == B_FALSE
)
145 rc
= pthread_create(&tid
, &tattr
, pipesvc_listener
, pl
);
148 pipe_listeners
[i
].tid
= tid
;
152 smbd_report("pipesvc pthread_create, %d", rc
);
155 (void) pthread_attr_destroy(&tattr
);
161 smbd_pipesvc_stop(void)
165 (void) mutex_lock(&pipesvc_mutex
);
166 for (i
= 0; i
< NLISTENERS
; i
++) {
167 if (pipe_listeners
[i
].tid
== 0)
169 (void) pthread_kill(pipe_listeners
[i
].tid
, SIGTERM
);
170 pipe_listeners
[i
].tid
= 0;
172 (void) mutex_unlock(&pipesvc_mutex
);
176 pipesvc_listener(void *varg
)
178 struct sockaddr_un sa
;
179 int err
, listen_fd
, newfd
;
181 struct pipe_listener
*pl
= varg
;
186 listen_fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
188 smbd_report("pipesvc_listener, so_create: %d", errno
);
192 bzero(&sa
, sizeof (sa
));
193 sa
.sun_family
= AF_UNIX
;
194 (void) snprintf(sa
.sun_path
, sizeof (sa
.sun_path
),
195 "%s/%s", SMB_PIPE_DIR
, pl
->name
);
197 /* Bind it to a listening name. */
198 (void) unlink(sa
.sun_path
);
199 if (bind(listen_fd
, (struct sockaddr
*)&sa
, sizeof (sa
)) < 0) {
200 smbd_report("pipesvc_listener, so_bind: %d", errno
);
201 (void) close(listen_fd
);
205 if (listen(listen_fd
, SOMAXCONN
) < 0) {
206 smbd_report("pipesvc_listener, listen: %d", errno
);
207 (void) close(listen_fd
);
214 newfd
= accept(listen_fd
, (struct sockaddr
*)&sa
, &snlen
);
221 /* normal termination */
224 smbd_report("pipesvc_listener, "
225 "accept failed: %d", errno
);
227 smbd_report("pipesvc_listener, accept: %d", err
);
231 np
= np_new(pl
, newfd
);
233 smbd_report("pipesvc_listener, alloc1 failed");
238 rc
= pthread_create(&tid
, NULL
, pipesvc_worker
, np
);
240 smbd_report("pipesvc_listener, pthread_create: %d",
245 (void) pthread_detach(tid
);
247 /* Note: np_free in pipesvc_worker */
252 (void) close(listen_fd
);
258 pipesvc_worker(void *varg
)
262 ndr_pipe_t
*np
= varg
;
263 struct pipe_listener
*pl
= np
->np_listener
;
268 (void) mutex_lock(&pipesvc_mutex
);
269 if (pipesvc_workers_cur
>= pipesvc_workers_max
||
270 pl
->current
>= pl
->max_allowed
) {
271 (void) mutex_unlock(&pipesvc_mutex
);
272 status
= NT_STATUS_PIPE_NOT_AVAILABLE
;
273 (void) send(np
->np_fid
, &status
, sizeof (status
), 0);
276 pipesvc_workers_cur
++;
278 if (pl
->max_seen
< pl
->current
)
279 pl
->max_seen
= pl
->current
;
280 (void) mutex_unlock(&pipesvc_mutex
);
283 * The smbsrv kmod sends us one initial message containing an
284 * XDR encoded smb_netuserinfo_t that we read and decode here,
285 * all unbeknownst to libmlrpc.
287 * Might be nice to enhance getpeerucred() so it can give us
288 * all the info smb_netuserinfo_t carries, and then use that,
289 * which would allow using a more generic RPC service.
291 rc
= pipe_recv(np
, &phdr
, sizeof (phdr
));
293 smbd_report("pipesvc_worker, recv1: %d", rc
);
296 if (phdr
.ph_magic
!= SMB_PIPE_HDR_MAGIC
||
297 phdr
.ph_uilen
> 8192) {
298 smbd_report("pipesvc_worker, bad hdr");
301 buf
= malloc(phdr
.ph_uilen
);
303 smbd_report("pipesvc_worker, alloc1 failed");
306 rc
= pipe_recv(np
, buf
, phdr
.ph_uilen
);
308 smbd_report("pipesvc_worker, recv2: %d", rc
);
312 xdrmem_create(&xdrs
, buf
, phdr
.ph_uilen
, XDR_DECODE
);
313 if (!smb_netuserinfo_xdr(&xdrs
, np
->np_user
)) {
314 smbd_report("pipesvc_worker, bad uinfo");
319 * Later, could disallow opens of some pipes by
320 * anonymous users, etc. For now, reply "OK".
323 rc
= pipe_send(np
, &status
, sizeof (status
));
325 smbd_report("pipesvc_worker, send1: %d", rc
);
330 * Run the RPC service loop worker, which
331 * returns when it sees the pipe close.
335 xdrs
.x_op
= XDR_FREE
;
336 (void) smb_netuserinfo_xdr(&xdrs
, np
->np_user
);
343 (void) mutex_lock(&pipesvc_mutex
);
344 pipesvc_workers_cur
--;
346 (void) mutex_unlock(&pipesvc_mutex
);
349 /* Cleanup what came in by varg. */
350 (void) shutdown(np
->np_fid
, SHUT_RDWR
);
356 * These are the transport get/put callback functions provided
357 * via the ndr_pipe_t object to the libmlrpc`ndr_pipe_worker.
358 * These are called only with known PDU sizes and should
359 * loop as needed to transfer the entire message.
362 pipe_recv(ndr_pipe_t
*np
, void *buf
, size_t len
)
367 x
= recv(np
->np_fid
, buf
, len
, 0);
372 buf
= (char *)buf
+ x
;
380 pipe_send(ndr_pipe_t
*np
, void *buf
, size_t len
)
385 x
= send(np
->np_fid
, buf
, len
, 0);
390 buf
= (char *)buf
+ x
;