xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_opipe.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * This module provides the interface to NDR RPC.
28  */
29 
30 #include <sys/stat.h>
31 #include <sys/door.h>
32 #include <sys/door_data.h>
33 #include <sys/uio.h>
34 #include <sys/ksynch.h>
35 #include <smbsrv/smb_kproto.h>
36 #include <smbsrv/smb_xdr.h>
37 
38 #define	SMB_OPIPE_ISOPEN(OPIPE)	\
39 	(((OPIPE)->p_hdr.dh_magic == SMB_OPIPE_HDR_MAGIC) && \
40 	((OPIPE)->p_hdr.dh_fid))
41 
42 extern volatile uint32_t smb_fids;
43 #define	SMB_UNIQ_FID()	atomic_inc_32_nv(&smb_fids)
44 
45 static int smb_opipe_do_open(smb_request_t *, smb_opipe_t *);
46 static char *smb_opipe_lookup(const char *);
47 static int smb_opipe_sethdr(smb_opipe_t *, uint32_t, uint32_t);
48 static int smb_opipe_exec(smb_opipe_t *);
49 static void smb_opipe_enter(smb_opipe_t *);
50 static void smb_opipe_exit(smb_opipe_t *);
51 
52 
53 smb_opipe_t *
54 smb_opipe_alloc(smb_server_t *sv)
55 {
56 	smb_opipe_t	*opipe;
57 
58 	opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP);
59 
60 	bzero(opipe, sizeof (smb_opipe_t));
61 	mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL);
62 	cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL);
63 	opipe->p_magic = SMB_OPIPE_MAGIC;
64 	opipe->p_server = sv;
65 
66 	smb_llist_enter(&sv->sv_opipe_list, RW_WRITER);
67 	smb_llist_insert_tail(&sv->sv_opipe_list, opipe);
68 	smb_llist_exit(&sv->sv_opipe_list);
69 
70 	return (opipe);
71 }
72 
73 void
74 smb_opipe_dealloc(smb_opipe_t *opipe)
75 {
76 	smb_server_t *sv;
77 
78 	SMB_OPIPE_VALID(opipe);
79 	sv = opipe->p_server;
80 	SMB_SERVER_VALID(sv);
81 
82 	smb_llist_enter(&sv->sv_opipe_list, RW_WRITER);
83 	smb_llist_remove(&sv->sv_opipe_list, opipe);
84 	smb_llist_exit(&sv->sv_opipe_list);
85 
86 	opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC;
87 	smb_event_destroy(opipe->p_event);
88 	cv_destroy(&opipe->p_cv);
89 	mutex_destroy(&opipe->p_mutex);
90 
91 	kmem_cache_free(smb_cache_opipe, opipe);
92 }
93 
94 /*
95  * smb_opipe_open
96  *
97  * Open a well-known RPC named pipe. This routine should be called if
98  * a file open is requested on a share of type STYPE_IPC.
99  * If we recognize the pipe, we setup a new ofile.
100  *
101  * Returns 0 on success, Otherwise an NT status is returned to indicate
102  * an error.
103  */
104 int
105 smb_opipe_open(smb_request_t *sr)
106 {
107 	smb_arg_open_t	*op = &sr->sr_open;
108 	smb_ofile_t *of;
109 	smb_opipe_t *opipe;
110 	smb_doorhdr_t hdr;
111 	smb_error_t err;
112 	char *pipe_name;
113 
114 	if ((pipe_name = smb_opipe_lookup(op->fqi.fq_path.pn_path)) == NULL)
115 		return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
116 
117 	/*
118 	 * If printing is disabled, pretend spoolss does not exist.
119 	 */
120 	if (sr->sr_server->sv_cfg.skc_print_enable == 0 &&
121 	    strcmp(pipe_name, "SPOOLSS") == 0)
122 		return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
123 
124 	op->create_options = 0;
125 
126 	of = smb_ofile_open(sr, NULL, sr->smb_pid, op, SMB_FTYPE_MESG_PIPE,
127 	    SMB_UNIQ_FID(), &err);
128 
129 	if (of == NULL)
130 		return (err.status);
131 
132 	if (!smb_tree_is_connected(sr->tid_tree)) {
133 		smb_ofile_close(of, 0);
134 		smb_ofile_release(of);
135 		return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
136 	}
137 
138 	op->dsize = 0x01000;
139 	op->dattr = FILE_ATTRIBUTE_NORMAL;
140 	op->ftype = SMB_FTYPE_MESG_PIPE;
141 	op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */
142 	op->devstate = SMB_PIPE_READMODE_MESSAGE
143 	    | SMB_PIPE_TYPE_MESSAGE
144 	    | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
145 	op->fileid = of->f_fid;
146 
147 	sr->smb_fid = of->f_fid;
148 	sr->fid_ofile = of;
149 
150 	opipe = of->f_pipe;
151 	smb_opipe_enter(opipe);
152 
153 	opipe->p_server = of->f_server;
154 	opipe->p_name = pipe_name;
155 	opipe->p_doorbuf = kmem_zalloc(SMB_OPIPE_DOOR_BUFSIZE, KM_SLEEP);
156 
157 	/*
158 	 * p_data points to the offset within p_doorbuf at which
159 	 * data will be written or read.
160 	 */
161 	opipe->p_data = opipe->p_doorbuf + xdr_sizeof(smb_doorhdr_xdr, &hdr);
162 
163 	if (smb_opipe_do_open(sr, opipe) != 0) {
164 		/*
165 		 * On error, reset the header to clear the fid,
166 		 * which avoids confusion when smb_opipe_close() is
167 		 * called by smb_ofile_close().
168 		 */
169 		bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t));
170 		kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE);
171 		smb_opipe_exit(opipe);
172 		smb_ofile_close(of, 0);
173 		return (NT_STATUS_NO_MEMORY);
174 	}
175 	smb_opipe_exit(opipe);
176 	return (NT_STATUS_SUCCESS);
177 }
178 
179 /*
180  * smb_opipe_lookup
181  *
182  * Lookup a path to see if it's a well-known RPC named pipe that we support.
183  * The full pipe path will be in the form \\PIPE\\SERVICE.  The first part
184  * can be assumed, so all we need here are the service names.
185  *
186  * Returns a pointer to the pipe name (without any leading \'s) on success.
187  * Otherwise returns a null pointer.
188  */
189 static char *
190 smb_opipe_lookup(const char *path)
191 {
192 	static char *named_pipes[] = {
193 		"lsass",
194 		"LSARPC",
195 		"NETLOGON",
196 		"SAMR",
197 		"SPOOLSS",
198 		"SRVSVC",
199 		"SVCCTL",
200 		"WINREG",
201 		"WKSSVC",
202 		"EVENTLOG",
203 		"NETDFS"
204 	};
205 
206 	const char *name;
207 	int i;
208 
209 	if (path == NULL)
210 		return (NULL);
211 
212 	name = path;
213 	name += strspn(name, "\\");
214 	if (smb_strcasecmp(name, "PIPE", 4) == 0) {
215 		path += 4;
216 		name += strspn(name, "\\");
217 	}
218 
219 	for (i = 0; i < sizeof (named_pipes) / sizeof (named_pipes[0]); ++i) {
220 		if (smb_strcasecmp(name, named_pipes[i], 0) == 0)
221 			return (named_pipes[i]);
222 	}
223 
224 	return (NULL);
225 }
226 
227 /*
228  * Initialize the opipe header and context, and make the door call.
229  */
230 static int
231 smb_opipe_do_open(smb_request_t *sr, smb_opipe_t *opipe)
232 {
233 	smb_netuserinfo_t *userinfo = &opipe->p_user;
234 	smb_user_t *user = sr->uid_user;
235 	smb_server_t *sv = sr->sr_server;
236 	uint8_t *buf = opipe->p_doorbuf;
237 	uint32_t buflen = SMB_OPIPE_DOOR_BUFSIZE;
238 	uint32_t len;
239 
240 	if ((opipe->p_event = smb_event_create(sv, SMB_EVENT_TIMEOUT)) == NULL)
241 		return (-1);
242 
243 	smb_user_netinfo_init(user, userinfo);
244 	len = xdr_sizeof(smb_netuserinfo_xdr, userinfo);
245 
246 	bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t));
247 	opipe->p_hdr.dh_magic = SMB_OPIPE_HDR_MAGIC;
248 	opipe->p_hdr.dh_flags = SMB_DF_SYSSPACE;
249 	opipe->p_hdr.dh_fid = smb_event_txid(opipe->p_event);
250 
251 	if (smb_opipe_sethdr(opipe, SMB_OPIPE_OPEN, len) == -1)
252 		return (-1);
253 
254 	len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr);
255 	buf += len;
256 	buflen -= len;
257 
258 	if (smb_netuserinfo_encode(userinfo, buf, buflen, NULL) == -1)
259 		return (-1);
260 
261 	return (smb_opipe_door_call(opipe));
262 }
263 
264 /*
265  * smb_opipe_close
266  *
267  * Called whenever an IPC file/pipe is closed.
268  */
269 void
270 smb_opipe_close(smb_ofile_t *of)
271 {
272 	smb_opipe_t *opipe;
273 
274 	ASSERT(of);
275 	ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
276 
277 	opipe = of->f_pipe;
278 	SMB_OPIPE_VALID(opipe);
279 
280 	(void) smb_server_cancel_event(of->f_server, opipe->p_hdr.dh_fid);
281 	smb_opipe_enter(opipe);
282 
283 	if (SMB_OPIPE_ISOPEN(opipe)) {
284 		(void) smb_opipe_sethdr(opipe, SMB_OPIPE_CLOSE, 0);
285 		(void) smb_opipe_door_call(opipe);
286 		bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t));
287 		kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE);
288 	}
289 
290 	smb_user_netinfo_fini(&opipe->p_user);
291 	smb_opipe_exit(opipe);
292 }
293 
294 static int
295 smb_opipe_sethdr(smb_opipe_t *opipe, uint32_t cmd, uint32_t datalen)
296 {
297 	opipe->p_hdr.dh_op = cmd;
298 	opipe->p_hdr.dh_txid = opipe->p_hdr.dh_fid;
299 	opipe->p_hdr.dh_datalen = datalen;
300 	opipe->p_hdr.dh_resid = 0;
301 	opipe->p_hdr.dh_door_rc = EINVAL;
302 
303 	return (smb_doorhdr_encode(&opipe->p_hdr, opipe->p_doorbuf,
304 	    SMB_OPIPE_DOOR_BUFSIZE));
305 }
306 
307 /*
308  * smb_opipe_transact
309  *
310  * This is the entry point for RPC bind and request transactions.
311  * The fid is an arbitrary id used to associate RPC requests with a
312  * particular binding handle.
313  *
314  * If the data to be returned is larger than the client expects, we
315  * return as much as the client can handle and report a buffer overflow
316  * warning, which informs the client that we have more data to return.
317  * The residual data remains in the pipe until the client claims it or
318  * closes the pipe.
319  */
320 smb_sdrc_t
321 smb_opipe_transact(smb_request_t *sr, struct uio *uio)
322 {
323 	smb_xa_t *xa;
324 	smb_opipe_t *opipe;
325 	struct mbuf *mhead;
326 	int mdrcnt;
327 	int nbytes;
328 	int rc;
329 
330 	if ((rc = smb_opipe_write(sr, uio)) != 0) {
331 		if (rc == EBADF)
332 			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
333 			    ERRDOS, ERROR_INVALID_HANDLE);
334 		else
335 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
336 			    ERRDOS, ERROR_INTERNAL_ERROR);
337 		return (SDRC_ERROR);
338 	}
339 
340 	opipe = sr->fid_ofile->f_pipe;
341 
342 	if ((rc = smb_opipe_exec(opipe)) != 0) {
343 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
344 		    ERRDOS, ERROR_INTERNAL_ERROR);
345 		return (SDRC_ERROR);
346 	}
347 
348 	xa = sr->r_xa;
349 	mdrcnt = xa->smb_mdrcnt;
350 	smb_opipe_enter(opipe);
351 
352 	if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, mdrcnt) == -1) {
353 		smb_opipe_exit(opipe);
354 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
355 		    ERRDOS, ERROR_INTERNAL_ERROR);
356 		return (SDRC_ERROR);
357 	}
358 
359 	rc = smb_opipe_door_call(opipe);
360 	nbytes = opipe->p_hdr.dh_datalen;
361 
362 	if (rc != 0) {
363 		smb_opipe_exit(opipe);
364 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
365 		    ERRDOS, ERROR_INTERNAL_ERROR);
366 		return (SDRC_ERROR);
367 	}
368 
369 	if (nbytes) {
370 		mhead = smb_mbuf_get(opipe->p_data, nbytes);
371 		xa->rep_data_mb.max_bytes = nbytes;
372 		MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead);
373 	}
374 
375 	if (opipe->p_hdr.dh_resid) {
376 		/*
377 		 * The pipe contains more data than mdrcnt, warn the
378 		 * client that there is more data in the pipe.
379 		 * Typically, the client will call SmbReadX, which
380 		 * will call smb_opipe_read, to get the data.
381 		 */
382 		smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW,
383 		    ERRDOS, ERROR_MORE_DATA);
384 	}
385 
386 	smb_opipe_exit(opipe);
387 	return (SDRC_SUCCESS);
388 }
389 
390 /*
391  * smb_opipe_write
392  *
393  * Write RPC request data to the pipe.  The client should call smb_opipe_read
394  * to complete the exchange and obtain the RPC response.
395  *
396  * Returns 0 on success or an errno on failure.
397  */
398 int
399 smb_opipe_write(smb_request_t *sr, struct uio *uio)
400 {
401 	smb_opipe_t *opipe;
402 	uint32_t buflen;
403 	uint32_t len;
404 	int rc;
405 
406 	ASSERT(sr->fid_ofile);
407 	ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
408 
409 	opipe = sr->fid_ofile->f_pipe;
410 	SMB_OPIPE_VALID(opipe);
411 	smb_opipe_enter(opipe);
412 
413 	if (!SMB_OPIPE_ISOPEN(opipe)) {
414 		smb_opipe_exit(opipe);
415 		return (EBADF);
416 	}
417 
418 	rc = smb_opipe_sethdr(opipe, SMB_OPIPE_WRITE, uio->uio_resid);
419 	len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr);
420 	if (rc == -1 || len == 0) {
421 		smb_opipe_exit(opipe);
422 		return (ENOMEM);
423 	}
424 
425 	buflen = SMB_OPIPE_DOOR_BUFSIZE - len;
426 	(void) uiomove((caddr_t)opipe->p_data, buflen, UIO_WRITE, uio);
427 
428 	rc = smb_opipe_door_call(opipe);
429 
430 	smb_opipe_exit(opipe);
431 	return ((rc == 0) ? 0 : EIO);
432 }
433 
434 /*
435  * smb_opipe_read
436  *
437  * This interface may be called because smb_opipe_transact could not return
438  * all of the data in the original transaction or to form the second half
439  * of a transaction set up using smb_opipe_write.  Either way, we just need
440  * to read data from the pipe and return it.
441  *
442  * The response data is encoded into raw_data as required by the smb_read
443  * functions.  The uio_resid value indicates the number of bytes read.
444  */
445 int
446 smb_opipe_read(smb_request_t *sr, struct uio *uio)
447 {
448 	smb_opipe_t *opipe;
449 	struct mbuf *mhead;
450 	uint32_t nbytes;
451 	int rc;
452 
453 	ASSERT(sr->fid_ofile);
454 	ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
455 
456 	opipe = sr->fid_ofile->f_pipe;
457 	SMB_OPIPE_VALID(opipe);
458 
459 	if ((rc = smb_opipe_exec(opipe)) != 0)
460 		return (EIO);
461 
462 	smb_opipe_enter(opipe);
463 
464 	if (!SMB_OPIPE_ISOPEN(opipe)) {
465 		smb_opipe_exit(opipe);
466 		return (EBADF);
467 	}
468 
469 	if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, uio->uio_resid) == -1) {
470 		smb_opipe_exit(opipe);
471 		return (ENOMEM);
472 	}
473 
474 	rc = smb_opipe_door_call(opipe);
475 	nbytes = opipe->p_hdr.dh_datalen;
476 
477 	if (rc != 0 || nbytes > uio->uio_resid) {
478 		smb_opipe_exit(opipe);
479 		return (EIO);
480 	}
481 
482 	if (nbytes) {
483 		mhead = smb_mbuf_get(opipe->p_data, nbytes);
484 		MBC_SETUP(&sr->raw_data, nbytes);
485 		MBC_ATTACH_MBUF(&sr->raw_data, mhead);
486 		uio->uio_resid -= nbytes;
487 	}
488 
489 	smb_opipe_exit(opipe);
490 	return (rc);
491 }
492 
493 static int
494 smb_opipe_exec(smb_opipe_t *opipe)
495 {
496 	uint32_t	len;
497 	int		rc;
498 
499 	smb_opipe_enter(opipe);
500 
501 	rc = smb_opipe_sethdr(opipe, SMB_OPIPE_EXEC, 0);
502 	len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr);
503 	if (rc == -1 || len == 0) {
504 		smb_opipe_exit(opipe);
505 		return (ENOMEM);
506 	}
507 
508 	if ((rc = smb_opipe_door_call(opipe)) == 0)
509 		rc = smb_event_wait(opipe->p_event);
510 
511 	smb_opipe_exit(opipe);
512 	return (rc);
513 }
514 
515 /*
516  * Named pipe I/O is serialized per fid to ensure that each request
517  * has exclusive opipe access for the duration of the request.
518  */
519 static void
520 smb_opipe_enter(smb_opipe_t *opipe)
521 {
522 	mutex_enter(&opipe->p_mutex);
523 
524 	while (opipe->p_busy)
525 		cv_wait(&opipe->p_cv, &opipe->p_mutex);
526 
527 	opipe->p_busy = 1;
528 	mutex_exit(&opipe->p_mutex);
529 }
530 
531 /*
532  * Exit busy state.  If we have exec'd an RPC, we may have
533  * to wait for notification that processing has completed.
534  */
535 static void
536 smb_opipe_exit(smb_opipe_t *opipe)
537 {
538 	mutex_enter(&opipe->p_mutex);
539 	opipe->p_busy = 0;
540 	cv_signal(&opipe->p_cv);
541 	mutex_exit(&opipe->p_mutex);
542 }
543