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 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/systm.h>
32 #include <sys/user.h>
33 #include <sys/vnode.h>
34 #include <sys/file.h>
35 #include <sys/dirent.h>
36 #include <sys/vfs.h>
37 #include <sys/stream.h>
38 #include <sys/strsubr.h>
39 #include <sys/debug.h>
40 #include <sys/t_lock.h>
41 #include <sys/acl.h>
42
43 #include <rpc/types.h>
44 #include <rpc/xdr.h>
45
46 #include <nfs/nfs.h>
47 #include <nfs/nfs_clnt.h>
48 #include <nfs/nfs_acl.h>
49
50 /*
51 * These are the XDR routines used to serialize and deserialize
52 * the various structures passed as parameters accross the network
53 * between ACL clients and servers.
54 */
55
56 bool_t
57 xdr_uid(XDR *xdrs, uid32_t *objp)
58 {
59 if (!xdr_u_int(xdrs, objp))
60 return (FALSE);
61 return (TRUE);
62 }
63
64 bool_t
65 xdr_o_mode(XDR *xdrs, o_mode *objp)
66 {
67
68 if (!xdr_u_short(xdrs, (ushort_t *)objp))
69 return (FALSE);
70 return (TRUE);
71 }
72
73 bool_t
74 xdr_aclent(XDR *xdrs, aclent_t *objp)
75 {
76
77 if (!xdr_int(xdrs, &objp->a_type))
78 return (FALSE);
79 if (!xdr_uid(xdrs, &objp->a_id))
80 return (FALSE);
81 if (!xdr_o_mode(xdrs, &objp->a_perm))
82 return (FALSE);
83 return (TRUE);
84 }
85
86 /*
87 * Serialize and de-serialize access control attributes
88 */
89 bool_t
90 xdr_secattr(XDR *xdrs, vsecattr_t *objp)
91 {
92 uint_t count = 0;
93 uint_t dfacount = 0;
94
95 if (!xdr_u_int(xdrs, &objp->vsa_mask)) {
96 return (FALSE);
97 }
98
99 /*
100 * Refuse request if we do not understand it completely.
101 * There should be at least one valid bit set in the mask and
102 * none of the unknown bits set.
103 */
104 if ((objp->vsa_mask &
105 (VSA_ACL | VSA_ACLCNT | VSA_DFACL | VSA_DFACLCNT)) == 0) {
106 return (FALSE);
107 }
108 if ((objp->vsa_mask &
109 ~(VSA_ACL | VSA_ACLCNT | VSA_DFACL | VSA_DFACLCNT)) != 0) {
110 return (FALSE);
111 }
112
113 if (!xdr_int(xdrs, &objp->vsa_aclcnt)) {
114 return (FALSE);
115 }
116 if (objp->vsa_aclentp != NULL) {
117 count = (uint_t)objp->vsa_aclcnt;
118 }
119
120 if (!xdr_array(xdrs, (char **)&objp->vsa_aclentp, &count,
121 NFS_ACL_MAX_ENTRIES, sizeof (aclent_t), (xdrproc_t)xdr_aclent)) {
122 return (FALSE);
123 }
124
125 if (count != 0 && count != (uint_t)objp->vsa_aclcnt) {
126 /*
127 * Assign the actual array size to vsa_aclcnt before
128 * aborting on error
129 */
130 objp->vsa_aclcnt = (int)count;
131 return (FALSE);
132 }
133
134 /*
135 * For VSA_ACL the count should be zero or there should
136 * be array attached.
137 */
138 if ((objp->vsa_mask & VSA_ACL) != 0) {
139 if ((objp->vsa_aclcnt != 0) && (objp->vsa_aclentp == NULL)) {
140 objp->vsa_aclcnt = 0;
141 return (FALSE);
142 }
143 }
144
145 if (!xdr_int(xdrs, &objp->vsa_dfaclcnt)) {
146 return (FALSE);
147 }
148 if (objp->vsa_dfaclentp != NULL) {
149 dfacount = (uint_t)objp->vsa_dfaclcnt;
150 }
151
152 if (!xdr_array(xdrs, (char **)&objp->vsa_dfaclentp, &dfacount,
153 NFS_ACL_MAX_ENTRIES, sizeof (aclent_t), (xdrproc_t)xdr_aclent)) {
154 return (FALSE);
155 }
156
157 if (dfacount != 0 && dfacount != (uint_t)objp->vsa_dfaclcnt) {
158 /*
159 * Assign the actual array size to vsa_dfaclcnt before
160 * aborting on error
161 */
162 objp->vsa_dfaclcnt = (int)dfacount;
163 return (FALSE);
164 }
165
166 /*
167 * for VSA_DFACL The count should be zero or there should
168 * be array attached
169 */
170 if ((objp->vsa_mask & VSA_DFACL) != 0) {
171 if ((objp->vsa_dfaclcnt != 0) &&
172 (objp->vsa_dfaclentp == NULL)) {
173 objp->vsa_dfaclcnt = 0;
174 return (FALSE);
175 }
176 }
177
178
179 return (TRUE);
180 }
181
182 bool_t
183 xdr_GETACL2args(XDR *xdrs, GETACL2args *objp)
184 {
185
186 if (!xdr_fhandle(xdrs, &objp->fh))
187 return (FALSE);
188 if (!xdr_u_int(xdrs, &objp->mask))
189 return (FALSE);
190 return (TRUE);
191 }
192 bool_t
193 xdr_fastGETACL2args(XDR *xdrs, GETACL2args **objpp)
194 {
195 int32_t *ptr;
196 #ifdef _LITTLE_ENDIAN
197 GETACL2args *objp;
198 #endif
199
200 if (xdrs->x_op != XDR_DECODE)
201 return (FALSE);
202
203 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (GETACL2args)));
204 if (ptr != NULL) {
205 *objpp = (GETACL2args *)ptr;
206 #ifdef _LITTLE_ENDIAN
207 objp = (GETACL2args *)ptr;
208 objp->mask = ntohl(objp->mask);
209 #endif
210 return (TRUE);
211 }
212
213 return (FALSE);
214 }
215
216 bool_t
217 xdr_GETACL2resok(XDR *xdrs, GETACL2resok *objp)
218 {
219
220 if (!xdr_fattr(xdrs, &objp->attr))
221 return (FALSE);
222 if (!xdr_secattr(xdrs, &objp->acl))
223 return (FALSE);
224 return (TRUE);
225 }
226
227 bool_t
228 xdr_GETACL2res(XDR *xdrs, GETACL2res *objp)
229 {
230
231 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
232 return (FALSE);
233 switch (objp->status) {
234 case NFS_OK:
235 if (!xdr_GETACL2resok(xdrs, &objp->resok))
236 return (FALSE);
237 break;
238 }
239 return (TRUE);
240 }
241
242 bool_t
243 xdr_SETACL2args(XDR *xdrs, SETACL2args *objp)
244 {
245
246 if (!xdr_fhandle(xdrs, &objp->fh))
247 return (FALSE);
248 if (!xdr_secattr(xdrs, &objp->acl))
249 return (FALSE);
250 return (TRUE);
251 }
252
253 bool_t
254 xdr_SETACL2resok(XDR *xdrs, SETACL2resok *objp)
255 {
256
257 if (!xdr_fattr(xdrs, &objp->attr))
258 return (FALSE);
259 return (TRUE);
260 }
261 #ifdef _LITTLE_ENDIAN
262 bool_t
263 xdr_fastSETACL2resok(XDR *xdrs, SETACL2resok *objp)
264 {
265
266 if (!xdr_fastfattr(xdrs, &objp->attr))
267 return (FALSE);
268 return (TRUE);
269 }
270 #endif
271
272 bool_t
273 xdr_SETACL2res(XDR *xdrs, SETACL2res *objp)
274 {
275
276 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
277 return (FALSE);
278 switch (objp->status) {
279 case NFS_OK:
280 if (!xdr_SETACL2resok(xdrs, &objp->resok))
281 return (FALSE);
282 break;
283 }
284 return (TRUE);
285 }
286 #ifdef _LITTLE_ENDIAN
287 bool_t
288 xdr_fastSETACL2res(XDR *xdrs, SETACL2res *objp)
289 {
290
291 if (!xdr_fastenum(xdrs, (enum_t *)&objp->status))
292 return (FALSE);
293 switch (objp->status) {
294 case NFS_OK:
295 if (!xdr_fastSETACL2resok(xdrs, &objp->resok))
296 return (FALSE);
297 break;
298 }
299 return (TRUE);
300 }
301 #endif
302
303 bool_t
304 xdr_GETATTR2args(XDR *xdrs, GETATTR2args *objp)
305 {
306
307 if (!xdr_fhandle(xdrs, &objp->fh))
308 return (FALSE);
309 return (TRUE);
310 }
311 bool_t
312 xdr_fastGETATTR2args(XDR *xdrs, GETATTR2args **objpp)
313 {
314 int32_t *ptr;
315
316 if (xdrs->x_op != XDR_DECODE)
317 return (FALSE);
318
319 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (GETATTR2args)));
320 if (ptr != NULL) {
321 *objpp = (GETATTR2args *)ptr;
322 return (TRUE);
323 }
324
325 return (FALSE);
326 }
327
328 bool_t
329 xdr_GETATTR2resok(XDR *xdrs, GETATTR2resok *objp)
330 {
331
332 if (!xdr_fattr(xdrs, &objp->attr))
333 return (FALSE);
334 return (TRUE);
335 }
336 #ifdef _LITTLE_ENDIAN
337 bool_t
338 xdr_fastGETATTR2resok(XDR *xdrs, GETATTR2resok *objp)
339 {
340
341 if (!xdr_fastfattr(xdrs, &objp->attr))
342 return (FALSE);
343 return (TRUE);
344 }
345 #endif
346
347 bool_t
348 xdr_GETATTR2res(XDR *xdrs, GETATTR2res *objp)
349 {
350
351 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
352 return (FALSE);
353 switch (objp->status) {
354 case NFS_OK:
355 if (!xdr_GETATTR2resok(xdrs, &objp->resok))
356 return (FALSE);
357 break;
358 }
359 return (TRUE);
360 }
361 #ifdef _LITTLE_ENDIAN
362 bool_t
363 xdr_fastGETATTR2res(XDR *xdrs, GETATTR2res *objp)
364 {
365
366 if (!xdr_fastenum(xdrs, (enum_t *)&objp->status))
367 return (FALSE);
368 switch (objp->status) {
369 case NFS_OK:
370 if (!xdr_fastGETATTR2resok(xdrs, &objp->resok))
371 return (FALSE);
372 break;
373 }
374 return (TRUE);
375 }
376 #endif
377
378 bool_t
379 xdr_ACCESS2args(XDR *xdrs, ACCESS2args *objp)
380 {
381
382 if (!xdr_fhandle(xdrs, &objp->fh))
383 return (FALSE);
384 if (!xdr_uint32(xdrs, &objp->access))
385 return (FALSE);
386 return (TRUE);
387 }
388 bool_t
389 xdr_fastACCESS2args(XDR *xdrs, ACCESS2args **objpp)
390 {
391 int32_t *ptr;
392 #ifdef _LITTLE_ENDIAN
393 ACCESS2args *objp;
394 #endif
395
396 if (xdrs->x_op != XDR_DECODE)
397 return (FALSE);
398
399 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (ACCESS2args)));
400 if (ptr != NULL) {
401 *objpp = (ACCESS2args *)ptr;
402 #ifdef _LITTLE_ENDIAN
403 objp = (ACCESS2args *)ptr;
404 objp->access = ntohl(objp->access);
405 #endif
406 return (TRUE);
407 }
408
409 return (FALSE);
410 }
411
412 bool_t
413 xdr_ACCESS2resok(XDR *xdrs, ACCESS2resok *objp)
414 {
415
416 if (!xdr_fattr(xdrs, &objp->attr))
417 return (FALSE);
418 if (!xdr_uint32(xdrs, &objp->access))
419 return (FALSE);
420 return (TRUE);
421 }
422 #ifdef _LITTLE_ENDIAN
423 bool_t
424 xdr_fastACCESS2resok(XDR *xdrs, ACCESS2resok *objp)
425 {
426
427 if (!xdr_fastfattr(xdrs, &objp->attr))
428 return (FALSE);
429 objp->access = ntohl(objp->access);
430 return (TRUE);
431 }
432 #endif
433
434 bool_t
435 xdr_ACCESS2res(XDR *xdrs, ACCESS2res *objp)
436 {
437
438 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
439 return (FALSE);
440 switch (objp->status) {
441 case NFS_OK:
442 if (!xdr_ACCESS2resok(xdrs, &objp->resok))
443 return (FALSE);
444 break;
445 }
446 return (TRUE);
447 }
448 #ifdef _LITTLE_ENDIAN
449 bool_t
450 xdr_fastACCESS2res(XDR *xdrs, ACCESS2res *objp)
451 {
452
453 if (!xdr_fastenum(xdrs, (enum_t *)&objp->status))
454 return (FALSE);
455 switch (objp->status) {
456 case NFS_OK:
457 if (!xdr_fastACCESS2resok(xdrs, &objp->resok))
458 return (FALSE);
459 break;
460 }
461 return (TRUE);
462 }
463 #endif
464
465 bool_t
466 xdr_GETXATTRDIR2args(XDR *xdrs, GETXATTRDIR2args *objp)
467 {
468 if (!xdr_fhandle(xdrs, &objp->fh))
469 return (FALSE);
470 if (!xdr_bool(xdrs, &objp->create))
471 return (FALSE);
472 return (TRUE);
473 }
474
475 bool_t
476 xdr_GETXATTRDIR2resok(XDR *xdrs, GETXATTRDIR2resok *objp)
477 {
478 if (!xdr_fhandle(xdrs, &objp->fh))
479 return (FALSE);
480 if (!xdr_fattr(xdrs, &objp->attr))
481 return (FALSE);
482 return (TRUE);
483 }
484
485 bool_t
486 xdr_GETXATTRDIR2res(XDR *xdrs, GETXATTRDIR2res *objp)
487 {
488 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
489 return (FALSE);
490 switch (objp->status) {
491 case NFS_OK:
492 if (!xdr_GETXATTRDIR2resok(xdrs, &objp->resok))
493 return (FALSE);
494 break;
495 }
496 return (TRUE);
497 }
498
499 bool_t
500 xdr_GETACL3args(XDR *xdrs, GETACL3args *objp)
501 {
502
503 switch (xdrs->x_op) {
504 case XDR_FREE:
505 case XDR_ENCODE:
506 if (!xdr_nfs_fh3(xdrs, &objp->fh))
507 return (FALSE);
508 break;
509 case XDR_DECODE:
510 if (!xdr_nfs_fh3_server(xdrs, &objp->fh))
511 return (FALSE);
512 break;
513 }
514 if (!xdr_u_int(xdrs, &objp->mask))
515 return (FALSE);
516 return (TRUE);
517 }
518
519 bool_t
520 xdr_GETACL3resok(XDR *xdrs, GETACL3resok *objp)
521 {
522
523 if (!xdr_post_op_attr(xdrs, &objp->attr))
524 return (FALSE);
525 if (!xdr_secattr(xdrs, &objp->acl))
526 return (FALSE);
527 return (TRUE);
528 }
529
530 bool_t
531 xdr_GETACL3resfail(XDR *xdrs, GETACL3resfail *objp)
532 {
533
534 if (!xdr_post_op_attr(xdrs, &objp->attr))
535 return (FALSE);
536 return (TRUE);
537 }
538
539 bool_t
540 xdr_GETACL3res(XDR *xdrs, GETACL3res *objp)
541 {
542
543 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
544 return (FALSE);
545 switch (objp->status) {
546 case NFS3_OK:
547 if (!xdr_GETACL3resok(xdrs, &objp->resok))
548 return (FALSE);
549 break;
550 default:
551 if (!xdr_GETACL3resfail(xdrs, &objp->resfail))
552 return (FALSE);
553 break;
554 }
555 return (TRUE);
556 }
557
558 bool_t
559 xdr_SETACL3args(XDR *xdrs, SETACL3args *objp)
560 {
561
562 switch (xdrs->x_op) {
563 case XDR_FREE:
564 case XDR_ENCODE:
565 if (!xdr_nfs_fh3(xdrs, &objp->fh))
566 return (FALSE);
567 break;
568 case XDR_DECODE:
569 if (!xdr_nfs_fh3_server(xdrs, &objp->fh))
570 return (FALSE);
571 break;
572 }
573 if (!xdr_secattr(xdrs, &objp->acl))
574 return (FALSE);
575 return (TRUE);
576 }
577
578 bool_t
579 xdr_SETACL3resok(XDR *xdrs, SETACL3resok *objp)
580 {
581
582 if (!xdr_post_op_attr(xdrs, &objp->attr))
583 return (FALSE);
584 return (TRUE);
585 }
586
587 bool_t
588 xdr_SETACL3resfail(XDR *xdrs, SETACL3resfail *objp)
589 {
590
591 if (!xdr_post_op_attr(xdrs, &objp->attr))
592 return (FALSE);
593 return (TRUE);
594 }
595
596 bool_t
597 xdr_SETACL3res(XDR *xdrs, SETACL3res *objp)
598 {
599
600 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
601 return (FALSE);
602 switch (objp->status) {
603 case NFS3_OK:
604 if (!xdr_SETACL3resok(xdrs, &objp->resok))
605 return (FALSE);
606 break;
607 default:
608 if (!xdr_SETACL3resfail(xdrs, &objp->resfail))
609 return (FALSE);
610 break;
611 }
612 return (TRUE);
613 }
614
615 bool_t
616 xdr_GETXATTRDIR3args(XDR *xdrs, GETXATTRDIR3args *objp)
617 {
618 switch (xdrs->x_op) {
619 case XDR_FREE:
620 case XDR_ENCODE:
621 if (!xdr_nfs_fh3(xdrs, &objp->fh))
622 return (FALSE);
623 break;
624 case XDR_DECODE:
625 if (!xdr_nfs_fh3_server(xdrs, &objp->fh))
626 return (FALSE);
627 break;
628 }
629 if (!xdr_bool(xdrs, &objp->create))
630 return (FALSE);
631 return (TRUE);
632 }
633
634 bool_t
635 xdr_GETXATTRDIR3resok(XDR *xdrs, GETXATTRDIR3resok *objp)
636 {
637 switch (xdrs->x_op) {
638 case XDR_ENCODE:
639 if (!xdr_nfs_fh3_server(xdrs, &objp->fh))
640 return (FALSE);
641 break;
642 case XDR_FREE:
643 case XDR_DECODE:
644 if (!xdr_nfs_fh3(xdrs, &objp->fh))
645 return (FALSE);
646 break;
647 }
648 if (!xdr_post_op_attr(xdrs, &objp->attr))
649 return (FALSE);
650 return (TRUE);
651 }
652
653 bool_t
654 xdr_GETXATTRDIR3res(XDR *xdrs, GETXATTRDIR3res *objp)
655 {
656 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
657 return (FALSE);
658 switch (objp->status) {
659 case NFS_OK:
660 if (!xdr_GETXATTRDIR3resok(xdrs, &objp->resok))
661 return (FALSE);
662 break;
663 }
664 return (TRUE);
665 }