168b2bbf2SGordon Ross /*
268b2bbf2SGordon Ross * This file and its contents are supplied under the terms of the
368b2bbf2SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
468b2bbf2SGordon Ross * You may only use this file in accordance with the terms of version
568b2bbf2SGordon Ross * 1.0 of the CDDL.
668b2bbf2SGordon Ross *
768b2bbf2SGordon Ross * A full copy of the text of the CDDL should have accompanied this
868b2bbf2SGordon Ross * source. A copy of the CDDL is also available via the Internet at
968b2bbf2SGordon Ross * http://www.illumos.org/license/CDDL.
1068b2bbf2SGordon Ross */
1168b2bbf2SGordon Ross
1268b2bbf2SGordon Ross /*
1368b2bbf2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
14*5d8538b6SGordon Ross * Copyright 2022-2023 RackTop Systems, Inc.
1568b2bbf2SGordon Ross */
1668b2bbf2SGordon Ross
1768b2bbf2SGordon Ross /*
1868b2bbf2SGordon Ross * This is the named pipe service for smbd.
1968b2bbf2SGordon Ross */
2068b2bbf2SGordon Ross
2168b2bbf2SGordon Ross #include <sys/types.h>
2268b2bbf2SGordon Ross #include <sys/stat.h>
2368b2bbf2SGordon Ross
2468b2bbf2SGordon Ross #include <stdio.h>
2568b2bbf2SGordon Ross #include <strings.h>
2668b2bbf2SGordon Ross #include <stdlib.h>
2768b2bbf2SGordon Ross #include <synch.h>
2868b2bbf2SGordon Ross #include <unistd.h>
2968b2bbf2SGordon Ross #include <fcntl.h>
3068b2bbf2SGordon Ross #include <door.h>
3168b2bbf2SGordon Ross #include <errno.h>
3268b2bbf2SGordon Ross #include <pthread.h>
3368b2bbf2SGordon Ross #include <signal.h>
34b6b7639aSGordon Ross #include <ucred.h>
35b6b7639aSGordon Ross #include <priv.h>
3668b2bbf2SGordon Ross
3768b2bbf2SGordon Ross #include <smbsrv/libsmb.h>
3868b2bbf2SGordon Ross #include <smbsrv/libmlsvc.h>
3968b2bbf2SGordon Ross #include <smbsrv/smb_xdr.h>
4068b2bbf2SGordon Ross #include "smbd.h"
4168b2bbf2SGordon Ross
4268b2bbf2SGordon Ross struct pipe_listener {
4368b2bbf2SGordon Ross const char *name;
4468b2bbf2SGordon Ross int max_allowed;
4568b2bbf2SGordon Ross int max_seen;
4668b2bbf2SGordon Ross int current;
4768b2bbf2SGordon Ross pthread_t tid;
4868b2bbf2SGordon Ross };
4968b2bbf2SGordon Ross
5068b2bbf2SGordon Ross static void *pipesvc_listener(void *);
5168b2bbf2SGordon Ross static void *pipesvc_worker(void *);
5268b2bbf2SGordon Ross static int pipe_send(ndr_pipe_t *, void *, size_t);
5368b2bbf2SGordon Ross static int pipe_recv(ndr_pipe_t *, void *, size_t);
5468b2bbf2SGordon Ross
5568b2bbf2SGordon Ross mutex_t pipesvc_mutex = DEFAULTMUTEX;
5668b2bbf2SGordon Ross int pipesvc_workers_max = 500;
5768b2bbf2SGordon Ross int pipesvc_workers_cur = 0;
5868b2bbf2SGordon Ross
5968b2bbf2SGordon Ross uint16_t pipe_max_msgsize = SMB_PIPE_MAX_MSGSIZE;
6068b2bbf2SGordon Ross
6168b2bbf2SGordon Ross /*
6268b2bbf2SGordon Ross * Allow more opens on SRVSVC because that's used by many clients
6368b2bbf2SGordon Ross * to get the share list, etc.
6468b2bbf2SGordon Ross */
6568b2bbf2SGordon Ross #define SRVSVC_MAX_OPENS 200
6668b2bbf2SGordon Ross #define DEF_MAX_OPENS 50
6768b2bbf2SGordon Ross
6868b2bbf2SGordon Ross #define NLISTENERS 11
6968b2bbf2SGordon Ross static struct pipe_listener
7068b2bbf2SGordon Ross pipe_listeners[NLISTENERS] = {
7168b2bbf2SGordon Ross { "eventlog", DEF_MAX_OPENS, 0, 0 },
7268b2bbf2SGordon Ross { "lsarpc", DEF_MAX_OPENS, 0, 0 },
7368b2bbf2SGordon Ross { "lsass", DEF_MAX_OPENS, 0, 0 },
7468b2bbf2SGordon Ross { "netdfs", DEF_MAX_OPENS, 0, 0 },
7568b2bbf2SGordon Ross { "netlogon", DEF_MAX_OPENS, 0, 0 },
7668b2bbf2SGordon Ross { "samr", DEF_MAX_OPENS, 0, 0 },
7768b2bbf2SGordon Ross { "spoolss", DEF_MAX_OPENS, 0, 0 },
7868b2bbf2SGordon Ross { "srvsvc", SRVSVC_MAX_OPENS, 0, 0 },
7968b2bbf2SGordon Ross { "svcctl", DEF_MAX_OPENS, 0, 0 },
8068b2bbf2SGordon Ross { "winreg", DEF_MAX_OPENS, 0, 0 },
8168b2bbf2SGordon Ross { "wkssvc", DEF_MAX_OPENS, 0, 0 },
8268b2bbf2SGordon Ross };
8368b2bbf2SGordon Ross
8468b2bbf2SGordon Ross static ndr_pipe_t *
np_new(struct pipe_listener * pl,int fid)8568b2bbf2SGordon Ross np_new(struct pipe_listener *pl, int fid)
8668b2bbf2SGordon Ross {
8768b2bbf2SGordon Ross ndr_pipe_t *np;
8868b2bbf2SGordon Ross size_t len;
8968b2bbf2SGordon Ross
9068b2bbf2SGordon Ross /*
9168b2bbf2SGordon Ross * Allocating ndr_pipe_t + smb_netuserinfo_t as one.
9268b2bbf2SGordon Ross * We could just make that part of ndr_pipe_t, but
9368b2bbf2SGordon Ross * that struct is opaque to libmlrpc.
9468b2bbf2SGordon Ross */
9568b2bbf2SGordon Ross len = sizeof (*np) + sizeof (smb_netuserinfo_t);
9668b2bbf2SGordon Ross np = malloc(len);
9768b2bbf2SGordon Ross if (np == NULL)
9868b2bbf2SGordon Ross return (NULL);
9968b2bbf2SGordon Ross
10068b2bbf2SGordon Ross bzero(np, len);
10168b2bbf2SGordon Ross np->np_listener = pl;
10268b2bbf2SGordon Ross np->np_endpoint = pl->name;
10368b2bbf2SGordon Ross np->np_user = (void*)(np + 1);
10468b2bbf2SGordon Ross np->np_send = pipe_send;
10568b2bbf2SGordon Ross np->np_recv = pipe_recv;
10668b2bbf2SGordon Ross np->np_fid = fid;
10768b2bbf2SGordon Ross np->np_max_xmit_frag = pipe_max_msgsize;
10868b2bbf2SGordon Ross np->np_max_recv_frag = pipe_max_msgsize;
10968b2bbf2SGordon Ross
11068b2bbf2SGordon Ross return (np);
11168b2bbf2SGordon Ross }
11268b2bbf2SGordon Ross
11368b2bbf2SGordon Ross static void
np_free(ndr_pipe_t * np)11468b2bbf2SGordon Ross np_free(ndr_pipe_t *np)
11568b2bbf2SGordon Ross {
11668b2bbf2SGordon Ross (void) close(np->np_fid);
11768b2bbf2SGordon Ross free(np);
11868b2bbf2SGordon Ross }
11968b2bbf2SGordon Ross
12068b2bbf2SGordon Ross /*
12168b2bbf2SGordon Ross * Create the smbd opipe door service.
12268b2bbf2SGordon Ross * Returns the door descriptor on success. Otherwise returns -1.
12368b2bbf2SGordon Ross */
12468b2bbf2SGordon Ross int
smbd_pipesvc_start(void)12568b2bbf2SGordon Ross smbd_pipesvc_start(void)
12668b2bbf2SGordon Ross {
12768b2bbf2SGordon Ross pthread_t tid;
12868b2bbf2SGordon Ross pthread_attr_t tattr;
12968b2bbf2SGordon Ross struct pipe_listener *pl;
13068b2bbf2SGordon Ross int i, rc;
13168b2bbf2SGordon Ross
13268b2bbf2SGordon Ross if (mlsvc_init() != 0) {
13368b2bbf2SGordon Ross smbd_report("msrpc initialization failed");
13468b2bbf2SGordon Ross return (-1);
13568b2bbf2SGordon Ross }
13668b2bbf2SGordon Ross
13768b2bbf2SGordon Ross (void) pthread_attr_init(&tattr);
13868b2bbf2SGordon Ross (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
13968b2bbf2SGordon Ross
14068b2bbf2SGordon Ross for (i = 0; i < NLISTENERS; i++) {
14168b2bbf2SGordon Ross pl = &pipe_listeners[i];
14268b2bbf2SGordon Ross pl->max_seen = 0;
14368b2bbf2SGordon Ross
14468b2bbf2SGordon Ross if (strcasecmp(pl->name, "spoolss") == 0 &&
14568b2bbf2SGordon Ross smb_config_getbool(SMB_CI_PRINT_ENABLE) == B_FALSE)
14668b2bbf2SGordon Ross continue;
14768b2bbf2SGordon Ross
14868b2bbf2SGordon Ross rc = pthread_create(&tid, &tattr, pipesvc_listener, pl);
14968b2bbf2SGordon Ross if (rc != 0)
15068b2bbf2SGordon Ross break;
15168b2bbf2SGordon Ross pipe_listeners[i].tid = tid;
15268b2bbf2SGordon Ross }
15368b2bbf2SGordon Ross
15468b2bbf2SGordon Ross if (rc != 0) {
15568b2bbf2SGordon Ross smbd_report("pipesvc pthread_create, %d", rc);
15668b2bbf2SGordon Ross }
15768b2bbf2SGordon Ross
15868b2bbf2SGordon Ross (void) pthread_attr_destroy(&tattr);
15968b2bbf2SGordon Ross
16068b2bbf2SGordon Ross return (rc);
16168b2bbf2SGordon Ross }
16268b2bbf2SGordon Ross
16368b2bbf2SGordon Ross void
smbd_pipesvc_stop(void)16468b2bbf2SGordon Ross smbd_pipesvc_stop(void)
16568b2bbf2SGordon Ross {
16668b2bbf2SGordon Ross int i;
16768b2bbf2SGordon Ross
16868b2bbf2SGordon Ross (void) mutex_lock(&pipesvc_mutex);
16968b2bbf2SGordon Ross for (i = 0; i < NLISTENERS; i++) {
17068b2bbf2SGordon Ross if (pipe_listeners[i].tid == 0)
17168b2bbf2SGordon Ross continue;
17268b2bbf2SGordon Ross (void) pthread_kill(pipe_listeners[i].tid, SIGTERM);
17368b2bbf2SGordon Ross pipe_listeners[i].tid = 0;
17468b2bbf2SGordon Ross }
17568b2bbf2SGordon Ross (void) mutex_unlock(&pipesvc_mutex);
17668b2bbf2SGordon Ross }
17768b2bbf2SGordon Ross
17868b2bbf2SGordon Ross static void *
pipesvc_listener(void * varg)17968b2bbf2SGordon Ross pipesvc_listener(void *varg)
18068b2bbf2SGordon Ross {
18168b2bbf2SGordon Ross struct sockaddr_un sa;
18268b2bbf2SGordon Ross int err, listen_fd, newfd, snlen;
18368b2bbf2SGordon Ross struct pipe_listener *pl = varg;
18468b2bbf2SGordon Ross ndr_pipe_t *np;
18568b2bbf2SGordon Ross pthread_t tid;
18668b2bbf2SGordon Ross int rc;
18768b2bbf2SGordon Ross
18868b2bbf2SGordon Ross listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
18968b2bbf2SGordon Ross if (listen_fd < 0) {
19068b2bbf2SGordon Ross smbd_report("pipesvc_listener, so_create: %d", errno);
19168b2bbf2SGordon Ross return (NULL);
19268b2bbf2SGordon Ross }
19368b2bbf2SGordon Ross
19468b2bbf2SGordon Ross bzero(&sa, sizeof (sa));
19568b2bbf2SGordon Ross sa.sun_family = AF_UNIX;
19668b2bbf2SGordon Ross (void) snprintf(sa.sun_path, sizeof (sa.sun_path),
19768b2bbf2SGordon Ross "%s/%s", SMB_PIPE_DIR, pl->name);
19868b2bbf2SGordon Ross
19968b2bbf2SGordon Ross /* Bind it to a listening name. */
20068b2bbf2SGordon Ross (void) unlink(sa.sun_path);
20168b2bbf2SGordon Ross if (bind(listen_fd, (struct sockaddr *)&sa, sizeof (sa)) < 0) {
20268b2bbf2SGordon Ross smbd_report("pipesvc_listener, so_bind: %d", errno);
20368b2bbf2SGordon Ross (void) close(listen_fd);
20468b2bbf2SGordon Ross return (NULL);
20568b2bbf2SGordon Ross }
20668b2bbf2SGordon Ross
20768b2bbf2SGordon Ross if (listen(listen_fd, SOMAXCONN) < 0) {
20868b2bbf2SGordon Ross smbd_report("pipesvc_listener, listen: %d", errno);
20968b2bbf2SGordon Ross (void) close(listen_fd);
21068b2bbf2SGordon Ross return (NULL);
21168b2bbf2SGordon Ross }
21268b2bbf2SGordon Ross
21368b2bbf2SGordon Ross for (;;) {
21468b2bbf2SGordon Ross
21568b2bbf2SGordon Ross snlen = sizeof (sa);
21668b2bbf2SGordon Ross newfd = accept(listen_fd, (struct sockaddr *)&sa, &snlen);
21768b2bbf2SGordon Ross if (newfd < 0) {
21868b2bbf2SGordon Ross err = errno;
21968b2bbf2SGordon Ross switch (err) {
22068b2bbf2SGordon Ross case ECONNABORTED:
22168b2bbf2SGordon Ross continue;
22268b2bbf2SGordon Ross case EINTR:
22368b2bbf2SGordon Ross /* normal termination */
22468b2bbf2SGordon Ross goto out;
22568b2bbf2SGordon Ross default:
22668b2bbf2SGordon Ross smbd_report("pipesvc_listener, "
22768b2bbf2SGordon Ross "accept failed: %d", errno);
22868b2bbf2SGordon Ross }
22968b2bbf2SGordon Ross smbd_report("pipesvc_listener, accept: %d", err);
23068b2bbf2SGordon Ross break;
23168b2bbf2SGordon Ross }
23268b2bbf2SGordon Ross
23368b2bbf2SGordon Ross np = np_new(pl, newfd);
23468b2bbf2SGordon Ross if (np == NULL) {
23568b2bbf2SGordon Ross smbd_report("pipesvc_listener, alloc1 failed");
23668b2bbf2SGordon Ross (void) close(newfd);
2376926de2eSGordon Ross smbd_nomem();
23868b2bbf2SGordon Ross }
23968b2bbf2SGordon Ross
24068b2bbf2SGordon Ross rc = pthread_create(&tid, NULL, pipesvc_worker, np);
24168b2bbf2SGordon Ross if (rc != 0) {
24268b2bbf2SGordon Ross smbd_report("pipesvc_listener, pthread_create: %d",
24368b2bbf2SGordon Ross errno);
24468b2bbf2SGordon Ross np_free(np);
2456926de2eSGordon Ross smbd_nomem();
24668b2bbf2SGordon Ross }
24768b2bbf2SGordon Ross (void) pthread_detach(tid);
24868b2bbf2SGordon Ross
24968b2bbf2SGordon Ross /* Note: np_free in pipesvc_worker */
25068b2bbf2SGordon Ross np = NULL;
25168b2bbf2SGordon Ross }
25268b2bbf2SGordon Ross
25368b2bbf2SGordon Ross out:
25468b2bbf2SGordon Ross (void) close(listen_fd);
25568b2bbf2SGordon Ross pl->tid = 0;
25668b2bbf2SGordon Ross return (NULL);
25768b2bbf2SGordon Ross }
25868b2bbf2SGordon Ross
259b6b7639aSGordon Ross #ifndef FKSMBD
260*5d8538b6SGordon Ross /*
261*5d8538b6SGordon Ross * Decide whether we should trust the (in-band) user information
262*5d8538b6SGordon Ross * that the client sends us over the named pipe. The (in-kernel)
263*5d8538b6SGordon Ross * SMB service calls this with the credential of the logged-on
264*5d8538b6SGordon Ross * SMB user. The privileges are normally:
265*5d8538b6SGordon Ross * effective: basic,file_dac_search
266*5d8538b6SGordon Ross * inheritable: basic
267*5d8538b6SGordon Ross * permitted: basic,file_dac_search,sys_smb
268*5d8538b6SGordon Ross * limit: all
269*5d8538b6SGordon Ross * This tests the permitted set for the presence of PRIV_SYS_SMB,
270*5d8538b6SGordon Ross * which should only be granted to the SMB server.
271*5d8538b6SGordon Ross */
272b6b7639aSGordon Ross static boolean_t
pipe_has_priv(ndr_pipe_t * np)273b6b7639aSGordon Ross pipe_has_priv(ndr_pipe_t *np)
274b6b7639aSGordon Ross {
275b6b7639aSGordon Ross ucred_t *uc = NULL;
276b6b7639aSGordon Ross const priv_set_t *ps = NULL;
277b6b7639aSGordon Ross boolean_t ret = B_FALSE;
278b6b7639aSGordon Ross pid_t clpid;
279b6b7639aSGordon Ross
280b6b7639aSGordon Ross if (getpeerucred(np->np_fid, &uc) != 0) {
281b6b7639aSGordon Ross smbd_report("pipesvc: getpeerucred err %d", errno);
282b6b7639aSGordon Ross return (B_FALSE);
283b6b7639aSGordon Ross }
284b6b7639aSGordon Ross clpid = ucred_getpid(uc);
285*5d8538b6SGordon Ross ps = ucred_getprivset(uc, PRIV_PERMITTED);
286b6b7639aSGordon Ross if (ps == NULL) {
287b6b7639aSGordon Ross smbd_report("pipesvc: ucred_getprivset failed");
288b6b7639aSGordon Ross goto out;
289b6b7639aSGordon Ross }
290b6b7639aSGordon Ross
291b6b7639aSGordon Ross /*
292*5d8538b6SGordon Ross * Require sys_smb priv.
293b6b7639aSGordon Ross */
294b6b7639aSGordon Ross if (priv_ismember(ps, PRIV_SYS_SMB)) {
295b6b7639aSGordon Ross ret = B_TRUE;
296b6b7639aSGordon Ross goto out;
297b6b7639aSGordon Ross }
298b6b7639aSGordon Ross
299b6b7639aSGordon Ross if (smbd.s_debug) {
300b6b7639aSGordon Ross smbd_report("pipesvc: non-privileged client "
301b6b7639aSGordon Ross "PID = %d UID = %d",
302b6b7639aSGordon Ross (int)clpid, ucred_getruid(uc));
303b6b7639aSGordon Ross }
304b6b7639aSGordon Ross
305b6b7639aSGordon Ross out:
306b6b7639aSGordon Ross /* ps is free'd with the ucred */
307b6b7639aSGordon Ross if (uc != NULL)
308b6b7639aSGordon Ross ucred_free(uc);
309b6b7639aSGordon Ross
310b6b7639aSGordon Ross return (ret);
311b6b7639aSGordon Ross }
312b6b7639aSGordon Ross #endif
313b6b7639aSGordon Ross
31468b2bbf2SGordon Ross static void *
pipesvc_worker(void * varg)31568b2bbf2SGordon Ross pipesvc_worker(void *varg)
31668b2bbf2SGordon Ross {
31768b2bbf2SGordon Ross XDR xdrs;
31868b2bbf2SGordon Ross smb_pipehdr_t phdr;
31968b2bbf2SGordon Ross ndr_pipe_t *np = varg;
32068b2bbf2SGordon Ross struct pipe_listener *pl = np->np_listener;
32168b2bbf2SGordon Ross void *buf = NULL;
32268b2bbf2SGordon Ross uint32_t status;
32368b2bbf2SGordon Ross ssize_t rc;
32468b2bbf2SGordon Ross
32568b2bbf2SGordon Ross (void) mutex_lock(&pipesvc_mutex);
32668b2bbf2SGordon Ross if (pipesvc_workers_cur >= pipesvc_workers_max ||
32768b2bbf2SGordon Ross pl->current >= pl->max_allowed) {
32868b2bbf2SGordon Ross (void) mutex_unlock(&pipesvc_mutex);
32968b2bbf2SGordon Ross status = NT_STATUS_PIPE_NOT_AVAILABLE;
33068b2bbf2SGordon Ross (void) send(np->np_fid, &status, sizeof (status), 0);
33168b2bbf2SGordon Ross goto out_free_np;
33268b2bbf2SGordon Ross }
33368b2bbf2SGordon Ross pipesvc_workers_cur++;
33468b2bbf2SGordon Ross pl->current++;
33568b2bbf2SGordon Ross if (pl->max_seen < pl->current)
33668b2bbf2SGordon Ross pl->max_seen = pl->current;
33768b2bbf2SGordon Ross (void) mutex_unlock(&pipesvc_mutex);
33868b2bbf2SGordon Ross
33968b2bbf2SGordon Ross /*
34068b2bbf2SGordon Ross * The smbsrv kmod sends us one initial message containing an
34168b2bbf2SGordon Ross * XDR encoded smb_netuserinfo_t that we read and decode here,
34268b2bbf2SGordon Ross * all unbeknownst to libmlrpc.
34368b2bbf2SGordon Ross *
34468b2bbf2SGordon Ross * Might be nice to enhance getpeerucred() so it can give us
34568b2bbf2SGordon Ross * all the info smb_netuserinfo_t carries, and then use that,
34668b2bbf2SGordon Ross * which would allow using a more generic RPC service.
34768b2bbf2SGordon Ross */
34868b2bbf2SGordon Ross rc = pipe_recv(np, &phdr, sizeof (phdr));
34968b2bbf2SGordon Ross if (rc != 0) {
35068b2bbf2SGordon Ross smbd_report("pipesvc_worker, recv1: %d", rc);
35168b2bbf2SGordon Ross goto out_decr;
35268b2bbf2SGordon Ross }
35368b2bbf2SGordon Ross if (phdr.ph_magic != SMB_PIPE_HDR_MAGIC ||
35468b2bbf2SGordon Ross phdr.ph_uilen > 8192) {
35568b2bbf2SGordon Ross smbd_report("pipesvc_worker, bad hdr");
35668b2bbf2SGordon Ross goto out_decr;
35768b2bbf2SGordon Ross }
35868b2bbf2SGordon Ross buf = malloc(phdr.ph_uilen);
35968b2bbf2SGordon Ross if (buf == NULL) {
36068b2bbf2SGordon Ross smbd_report("pipesvc_worker, alloc1 failed");
36168b2bbf2SGordon Ross goto out_decr;
36268b2bbf2SGordon Ross }
36368b2bbf2SGordon Ross rc = pipe_recv(np, buf, phdr.ph_uilen);
36468b2bbf2SGordon Ross if (rc != 0) {
36568b2bbf2SGordon Ross smbd_report("pipesvc_worker, recv2: %d", rc);
36668b2bbf2SGordon Ross goto out_decr;
36768b2bbf2SGordon Ross }
36868b2bbf2SGordon Ross
36968b2bbf2SGordon Ross xdrmem_create(&xdrs, buf, phdr.ph_uilen, XDR_DECODE);
37068b2bbf2SGordon Ross if (!smb_netuserinfo_xdr(&xdrs, np->np_user)) {
37168b2bbf2SGordon Ross smbd_report("pipesvc_worker, bad uinfo");
37268b2bbf2SGordon Ross goto out_free_buf;
37368b2bbf2SGordon Ross }
37468b2bbf2SGordon Ross
375b6b7639aSGordon Ross /*
376b6b7639aSGordon Ross * Don't trust the netuserinfo unless the client side
377b6b7639aSGordon Ross * has the necessary privileges
378b6b7639aSGordon Ross */
379b6b7639aSGordon Ross #ifndef FKSMBD
380b6b7639aSGordon Ross if (!pipe_has_priv(np)) {
381b6b7639aSGordon Ross np->np_user->ui_flags = SMB_ATF_ANON;
382b6b7639aSGordon Ross }
383b6b7639aSGordon Ross #endif
384b6b7639aSGordon Ross
38568b2bbf2SGordon Ross /*
38668b2bbf2SGordon Ross * Later, could disallow opens of some pipes by
38768b2bbf2SGordon Ross * anonymous users, etc. For now, reply "OK".
38868b2bbf2SGordon Ross */
38968b2bbf2SGordon Ross status = 0;
39068b2bbf2SGordon Ross rc = pipe_send(np, &status, sizeof (status));
39168b2bbf2SGordon Ross if (rc != 0) {
39268b2bbf2SGordon Ross smbd_report("pipesvc_worker, send1: %d", rc);
39368b2bbf2SGordon Ross goto out_free_buf;
39468b2bbf2SGordon Ross }
39568b2bbf2SGordon Ross
39668b2bbf2SGordon Ross /*
39768b2bbf2SGordon Ross * Run the RPC service loop worker, which
39868b2bbf2SGordon Ross * returns when it sees the pipe close.
39968b2bbf2SGordon Ross */
40068b2bbf2SGordon Ross ndr_pipe_worker(np);
40168b2bbf2SGordon Ross
40268b2bbf2SGordon Ross xdrs.x_op = XDR_FREE;
40368b2bbf2SGordon Ross (void) smb_netuserinfo_xdr(&xdrs, np->np_user);
40468b2bbf2SGordon Ross
40568b2bbf2SGordon Ross out_free_buf:
40668b2bbf2SGordon Ross free(buf);
40768b2bbf2SGordon Ross xdr_destroy(&xdrs);
40868b2bbf2SGordon Ross
40968b2bbf2SGordon Ross out_decr:
41068b2bbf2SGordon Ross (void) mutex_lock(&pipesvc_mutex);
41168b2bbf2SGordon Ross pipesvc_workers_cur--;
41268b2bbf2SGordon Ross pl->current--;
41368b2bbf2SGordon Ross (void) mutex_unlock(&pipesvc_mutex);
41468b2bbf2SGordon Ross
41568b2bbf2SGordon Ross out_free_np:
41668b2bbf2SGordon Ross /* Cleanup what came in by varg. */
41768b2bbf2SGordon Ross (void) shutdown(np->np_fid, SHUT_RDWR);
41868b2bbf2SGordon Ross np_free(np);
41968b2bbf2SGordon Ross return (NULL);
42068b2bbf2SGordon Ross }
42168b2bbf2SGordon Ross
42268b2bbf2SGordon Ross /*
42368b2bbf2SGordon Ross * These are the transport get/put callback functions provided
42468b2bbf2SGordon Ross * via the ndr_pipe_t object to the libmlrpc`ndr_pipe_worker.
42568b2bbf2SGordon Ross * These are called only with known PDU sizes and should
42668b2bbf2SGordon Ross * loop as needed to transfer the entire message.
42768b2bbf2SGordon Ross */
42868b2bbf2SGordon Ross static int
pipe_recv(ndr_pipe_t * np,void * buf,size_t len)42968b2bbf2SGordon Ross pipe_recv(ndr_pipe_t *np, void *buf, size_t len)
43068b2bbf2SGordon Ross {
43168b2bbf2SGordon Ross int x;
43268b2bbf2SGordon Ross
43368b2bbf2SGordon Ross while (len > 0) {
43468b2bbf2SGordon Ross x = recv(np->np_fid, buf, len, 0);
43568b2bbf2SGordon Ross if (x < 0)
43668b2bbf2SGordon Ross return (errno);
43768b2bbf2SGordon Ross if (x == 0)
43868b2bbf2SGordon Ross return (EIO);
43968b2bbf2SGordon Ross buf = (char *)buf + x;
44068b2bbf2SGordon Ross len -= x;
44168b2bbf2SGordon Ross }
44268b2bbf2SGordon Ross
44368b2bbf2SGordon Ross return (0);
44468b2bbf2SGordon Ross }
44568b2bbf2SGordon Ross
44668b2bbf2SGordon Ross static int
pipe_send(ndr_pipe_t * np,void * buf,size_t len)44768b2bbf2SGordon Ross pipe_send(ndr_pipe_t *np, void *buf, size_t len)
44868b2bbf2SGordon Ross {
44968b2bbf2SGordon Ross int x;
45068b2bbf2SGordon Ross
45168b2bbf2SGordon Ross while (len > 0) {
45268b2bbf2SGordon Ross x = send(np->np_fid, buf, len, 0);
45368b2bbf2SGordon Ross if (x < 0)
45468b2bbf2SGordon Ross return (errno);
45568b2bbf2SGordon Ross if (x == 0)
45668b2bbf2SGordon Ross return (EIO);
45768b2bbf2SGordon Ross buf = (char *)buf + x;
45868b2bbf2SGordon Ross len -= x;
45968b2bbf2SGordon Ross }
46068b2bbf2SGordon Ross
46168b2bbf2SGordon Ross return (0);
46268b2bbf2SGordon Ross }
463