1162 kmem_free(resok_val, count * sizeof (secinfo4)); |
1171 kmem_free(resok_val, count * sizeof (secinfo4)); |
1163 resp->SECINFO4resok_len = 0; |
1172 resp->SECINFO4resok_len = 0; |
1164 resp->SECINFO4resok_val = NULL; |
1173 resp->SECINFO4resok_val = NULL; |
1165 } |
1174 } |
1166 |
1175 |
|
1176 /* |
|
1177 * do label check on client label and server's file lable. |
|
1178 */ |
|
1179 static boolean_t |
|
1180 do_rfs4_label_check(bslabel_t *clabel, vnode_t *vp, int flag) |
|
1181 { |
|
1182 bslabel_t *slabel; |
|
1183 ts_label_t *tslabel; |
|
1184 boolean_t result; |
|
1185 |
|
1186 if ((tslabel = nfs4_getflabel(vp)) == NULL) { |
|
1187 return (B_FALSE); |
|
1188 } |
|
1189 slabel = label2bslabel(tslabel); |
|
1190 DTRACE_PROBE4(tx__rfs4__log__info__labelcheck, char *, |
|
1191 "comparing server's file label(1) with client label(2) (vp(3))", |
|
1192 bslabel_t *, slabel, bslabel_t *, clabel, vnode_t *, vp); |
|
1193 |
|
1194 if (flag == EQUALITY_CHECK) |
|
1195 result = blequal(clabel, slabel); |
|
1196 else |
|
1197 result = bldominates(clabel, slabel); |
|
1198 label_rele(tslabel); |
|
1199 return (result); |
|
1200 } |
|
1201 |
1167 /* ARGSUSED */ |
1202 /* ARGSUSED */ |
1168 static void |
1203 static void |
1169 rfs4_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, |
1204 rfs4_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, |
1170 struct compound_state *cs) |
1205 struct compound_state *cs) |
1171 { |
1206 { |
1215 error = VOP_GETATTR(vp, &va, 0, cr); |
1253 error = VOP_GETATTR(vp, &va, 0, cr); |
1216 if (error) { |
1254 if (error) { |
1217 *cs->statusp = resp->status = puterrno4(error); |
1255 *cs->statusp = resp->status = puterrno4(error); |
1218 return; |
1256 return; |
1219 } |
1257 } |
1220 |
|
1221 resp->access = 0; |
1258 resp->access = 0; |
1222 resp->supported = 0; |
1259 resp->supported = 0; |
1223 |
1260 |
|
1261 if (is_system_labeled()) { |
|
1262 ASSERT(req->rq_label != NULL); |
|
1263 clabel = req->rq_label; |
|
1264 DTRACE_PROBE2(tx__rfs4__log__info__opaccess__clabel, char *, |
|
1265 "got client label from request(1)", |
|
1266 struct svc_req *, req); |
|
1267 if (!blequal(&l_admin_low->tsl_label, clabel)) { |
|
1268 if ((tslabel = nfs4_getflabel(vp)) == NULL) { |
|
1269 *cs->statusp = resp->status = puterrno4(EACCES); |
|
1270 return; |
|
1271 } |
|
1272 slabel = label2bslabel(tslabel); |
|
1273 DTRACE_PROBE3(tx__rfs4__log__info__opaccess__slabel, |
|
1274 char *, "got server label(1) for vp(2)", |
|
1275 bslabel_t *, slabel, vnode_t *, vp); |
|
1276 |
|
1277 admin_low_client = B_FALSE; |
|
1278 } else |
|
1279 admin_low_client = B_TRUE; |
|
1280 } |
|
1281 |
1224 if (args->access & ACCESS4_READ) { |
1282 if (args->access & ACCESS4_READ) { |
1225 error = VOP_ACCESS(vp, VREAD, 0, cr); |
1283 error = VOP_ACCESS(vp, VREAD, 0, cr); |
1226 if (!error && !MANDLOCK(vp, va.va_mode)) |
1284 if (!error && !MANDLOCK(vp, va.va_mode) && |
|
1285 (!is_system_labeled() || admin_low_client || |
|
1286 bldominates(clabel, slabel))) |
1227 resp->access |= ACCESS4_READ; |
1287 resp->access |= ACCESS4_READ; |
1228 resp->supported |= ACCESS4_READ; |
1288 resp->supported |= ACCESS4_READ; |
1229 } |
1289 } |
1230 if ((args->access & ACCESS4_LOOKUP) && vp->v_type == VDIR) { |
1290 if ((args->access & ACCESS4_LOOKUP) && vp->v_type == VDIR) { |
1231 error = VOP_ACCESS(vp, VEXEC, 0, cr); |
1291 error = VOP_ACCESS(vp, VEXEC, 0, cr); |
1232 if (!error) |
1292 if (!error && (!is_system_labeled() || admin_low_client || |
|
1293 bldominates(clabel, slabel))) |
1233 resp->access |= ACCESS4_LOOKUP; |
1294 resp->access |= ACCESS4_LOOKUP; |
1234 resp->supported |= ACCESS4_LOOKUP; |
1295 resp->supported |= ACCESS4_LOOKUP; |
1235 } |
1296 } |
1236 if (checkwriteperm && |
1297 if (checkwriteperm && |
1237 (args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND))) { |
1298 (args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND))) { |
1238 error = VOP_ACCESS(vp, VWRITE, 0, cr); |
1299 error = VOP_ACCESS(vp, VWRITE, 0, cr); |
1239 if (!error && !MANDLOCK(vp, va.va_mode)) |
1300 if (!error && !MANDLOCK(vp, va.va_mode) && |
|
1301 (!is_system_labeled() || admin_low_client || |
|
1302 blequal(clabel, slabel))) |
1240 resp->access |= |
1303 resp->access |= |
1241 (args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND)); |
1304 (args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND)); |
1242 resp->supported |= (ACCESS4_MODIFY|ACCESS4_EXTEND); |
1305 resp->supported |= (ACCESS4_MODIFY|ACCESS4_EXTEND); |
1243 } |
1306 } |
1244 |
1307 |
1245 if (checkwriteperm && |
1308 if (checkwriteperm && |
1246 (args->access & ACCESS4_DELETE) && vp->v_type == VDIR) { |
1309 (args->access & ACCESS4_DELETE) && vp->v_type == VDIR) { |
1247 error = VOP_ACCESS(vp, VWRITE, 0, cr); |
1310 error = VOP_ACCESS(vp, VWRITE, 0, cr); |
1248 if (!error) |
1311 if (!error && (!is_system_labeled() || admin_low_client || |
|
1312 blequal(clabel, slabel))) |
1249 resp->access |= ACCESS4_DELETE; |
1313 resp->access |= ACCESS4_DELETE; |
1250 resp->supported |= ACCESS4_DELETE; |
1314 resp->supported |= ACCESS4_DELETE; |
1251 } |
1315 } |
1252 if (args->access & ACCESS4_EXECUTE && vp->v_type != VDIR) { |
1316 if (args->access & ACCESS4_EXECUTE && vp->v_type != VDIR) { |
1253 error = VOP_ACCESS(vp, VEXEC, 0, cr); |
1317 error = VOP_ACCESS(vp, VEXEC, 0, cr); |
1254 if (!error && !MANDLOCK(vp, va.va_mode)) |
1318 if (!error && !MANDLOCK(vp, va.va_mode) && |
|
1319 (!is_system_labeled() || admin_low_client || |
|
1320 bldominates(clabel, slabel))) |
1255 resp->access |= ACCESS4_EXECUTE; |
1321 resp->access |= ACCESS4_EXECUTE; |
1256 resp->supported |= ACCESS4_EXECUTE; |
1322 resp->supported |= ACCESS4_EXECUTE; |
1257 } |
1323 } |
|
1324 |
|
1325 if (is_system_labeled() && !admin_low_client) |
|
1326 label_rele(tslabel); |
1258 |
1327 |
1259 *cs->statusp = resp->status = NFS4_OK; |
1328 *cs->statusp = resp->status = NFS4_OK; |
1260 } |
1329 } |
1261 |
1330 |
1262 /* ARGSUSED */ |
1331 /* ARGSUSED */ |
2539 cs->vp = oldvp; |
2608 cs->vp = oldvp; |
2540 return (stat); |
2609 return (stat); |
2541 } |
2610 } |
2542 } |
2611 } |
2543 |
2612 |
|
2613 /* |
|
2614 * After various NFS checks, do a label check on the path |
|
2615 * component. The label on this path should either be the |
|
2616 * global zone's label or a zone's label. We are only |
|
2617 * interested in the zone's label because exported files |
|
2618 * in global zone is accessible (though read-only) to |
|
2619 * clients. The exportability/visibility check is already |
|
2620 * done before reaching this code. |
|
2621 */ |
|
2622 if (is_system_labeled()) { |
|
2623 bslabel_t *clabel; |
|
2624 |
|
2625 ASSERT(req->rq_label != NULL); |
|
2626 clabel = req->rq_label; |
|
2627 DTRACE_PROBE2(tx__rfs4__log__info__oplookup__clabel, char *, |
|
2628 "got client label from request(1)", struct svc_req *, req); |
|
2629 |
|
2630 if (!blequal(&l_admin_low->tsl_label, clabel)) { |
|
2631 if (!do_rfs4_label_check(clabel, vp, DOMINANCE_CHECK)) { |
|
2632 error = EACCES; |
|
2633 goto err_out; |
|
2634 } |
|
2635 } else { |
|
2636 /* |
|
2637 * We grant access to admin_low label clients |
|
2638 * only if the client is trusted, i.e. also |
|
2639 * running Solaris Trusted Extension. |
|
2640 */ |
|
2641 struct sockaddr *ca; |
|
2642 int addr_type; |
|
2643 void *ipaddr; |
|
2644 tsol_tpc_t *tp; |
|
2645 |
|
2646 ca = (struct sockaddr *)svc_getrpccaller( |
|
2647 req->rq_xprt)->buf; |
|
2648 if (ca->sa_family == AF_INET) { |
|
2649 addr_type = IPV4_VERSION; |
|
2650 ipaddr = &((struct sockaddr_in *)ca)->sin_addr; |
|
2651 } else if (ca->sa_family == AF_INET6) { |
|
2652 addr_type = IPV6_VERSION; |
|
2653 ipaddr = &((struct sockaddr_in6 *) |
|
2654 ca)->sin6_addr; |
|
2655 } |
|
2656 tp = find_tpc(ipaddr, addr_type, B_FALSE); |
|
2657 if (tp == NULL || tp->tpc_tp.tp_doi != |
|
2658 l_admin_low->tsl_doi || tp->tpc_tp.host_type != |
|
2659 SUN_CIPSO) { |
|
2660 error = EACCES; |
|
2661 goto err_out; |
|
2662 } |
|
2663 } |
|
2664 } |
|
2665 |
2544 error = makefh4(&cs->fh, vp, cs->exi); |
2666 error = makefh4(&cs->fh, vp, cs->exi); |
2545 |
2667 |
|
2668 err_out: |
2546 if (error) { |
2669 if (error) { |
2547 if (is_newvp) { |
2670 if (is_newvp) { |
2548 VN_RELE(cs->vp); |
2671 VN_RELE(cs->vp); |
2549 cs->vp = oldvp; |
2672 cs->vp = oldvp; |
2550 } else |
2673 } else |
3896 if (rdonly4(cs->exi, cs->vp, req)) { |
4044 if (rdonly4(cs->exi, cs->vp, req)) { |
3897 *cs->statusp = resp->status = NFS4ERR_ROFS; |
4045 *cs->statusp = resp->status = NFS4ERR_ROFS; |
3898 kmem_free(onm, olen); |
4046 kmem_free(onm, olen); |
3899 kmem_free(nnm, nlen); |
4047 kmem_free(nnm, nlen); |
3900 return; |
4048 return; |
|
4049 } |
|
4050 |
|
4051 /* check label of the target dir */ |
|
4052 if (is_system_labeled()) { |
|
4053 ASSERT(req->rq_label != NULL); |
|
4054 clabel = req->rq_label; |
|
4055 DTRACE_PROBE2(tx__rfs4__log__info__oprename__clabel, char *, |
|
4056 "got client label from request(1)", |
|
4057 struct svc_req *, req); |
|
4058 if (!blequal(&l_admin_low->tsl_label, clabel)) { |
|
4059 if (!do_rfs4_label_check(clabel, ndvp, |
|
4060 EQUALITY_CHECK)) { |
|
4061 *cs->statusp = resp->status = NFS4ERR_ACCESS; |
|
4062 return; |
|
4063 } |
|
4064 } |
3901 } |
4065 } |
3902 |
4066 |
3903 /* |
4067 /* |
3904 * Is the source a file and have a delegation? |
4068 * Is the source a file and have a delegation? |
3905 * We don't need to acquire va_seq before these lookups, if |
4069 * We don't need to acquire va_seq before these lookups, if |
4730 resp->attrsset = 0; |
4895 resp->attrsset = 0; |
4731 |
4896 |
4732 if (rdonly4(cs->exi, cs->vp, req)) { |
4897 if (rdonly4(cs->exi, cs->vp, req)) { |
4733 *cs->statusp = resp->status = NFS4ERR_ROFS; |
4898 *cs->statusp = resp->status = NFS4ERR_ROFS; |
4734 return; |
4899 return; |
|
4900 } |
|
4901 |
|
4902 /* check label before setting attributes */ |
|
4903 if (is_system_labeled()) { |
|
4904 ASSERT(req->rq_label != NULL); |
|
4905 clabel = req->rq_label; |
|
4906 DTRACE_PROBE2(tx__rfs4__log__info__opsetattr__clabel, char *, |
|
4907 "got client label from request(1)", |
|
4908 struct svc_req *, req); |
|
4909 if (!blequal(&l_admin_low->tsl_label, clabel)) { |
|
4910 if (!do_rfs4_label_check(clabel, cs->vp, |
|
4911 EQUALITY_CHECK)) { |
|
4912 *cs->statusp = resp->status = NFS4ERR_ACCESS; |
|
4913 return; |
|
4914 } |
|
4915 } |
4735 } |
4916 } |
4736 |
4917 |
4737 *cs->statusp = resp->status = |
4918 *cs->statusp = resp->status = |
4738 do_rfs4_op_setattr(&resp->attrsset, &args->obj_attributes, cs, |
4919 do_rfs4_op_setattr(&resp->attrsset, &args->obj_attributes, cs, |
4739 &args->stateid); |
4920 &args->stateid); |
5575 len_t reqsize; |
5764 len_t reqsize; |
5576 int error; |
5765 int error; |
5577 bool_t trunc; |
5766 bool_t trunc; |
5578 caller_context_t ct; |
5767 caller_context_t ct; |
5579 component4 *component; |
5768 component4 *component; |
|
5769 bslabel_t *clabel; |
5580 |
5770 |
5581 sarg.sbp = &sb; |
5771 sarg.sbp = &sb; |
5582 |
5772 |
5583 dvp = cs->vp; |
5773 dvp = cs->vp; |
5584 |
5774 |
5585 /* Check if the file system is read only */ |
5775 /* Check if the file system is read only */ |
5586 if (rdonly4(cs->exi, dvp, req)) |
5776 if (rdonly4(cs->exi, dvp, req)) |
5587 return (NFS4ERR_ROFS); |
5777 return (NFS4ERR_ROFS); |
|
5778 |
|
5779 /* check the label of including directory */ |
|
5780 if (is_system_labeled()) { |
|
5781 ASSERT(req->rq_label != NULL); |
|
5782 clabel = req->rq_label; |
|
5783 DTRACE_PROBE2(tx__rfs4__log__info__opremove__clabel, char *, |
|
5784 "got client label from request(1)", |
|
5785 struct svc_req *, req); |
|
5786 if (!blequal(&l_admin_low->tsl_label, clabel)) { |
|
5787 if (!do_rfs4_label_check(clabel, dvp, EQUALITY_CHECK)) { |
|
5788 return (NFS4ERR_ACCESS); |
|
5789 } |
|
5790 } |
|
5791 } |
5588 |
5792 |
5589 /* |
5793 /* |
5590 * Get the last component of path name in nm. cs will reference |
5794 * Get the last component of path name in nm. cs will reference |
5591 * the including directory on success. |
5795 * the including directory on success. |
5592 */ |
5796 */ |