From 5616b7e2f91c9cdac1f026b852b8db923de11a10 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 3 Dec 2012 13:39:18 -0500 Subject: [PATCH] Windows: fs getcalleraccess Implement VIOC_GETCALLERACCESS and associated 'fs getcalleraccess' for Windows. Varies from the Unix implementation in the following ways: * getcalleraccess supports the -literal switch to permit querying rights of symlinks and mount points * multiple files can be provided on a single command line The VIOC_GETCALLERACCESS pioctl returns the user access rights and the anyuser access rights. Change-Id: I75f636956bbafcc91144b44bd2d7729b8643605c Reviewed-on: http://gerrit.openafs.org/8598 Tested-by: BuildBot Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsd/cm_ioctl.c | 38 ++++++++++++++++++++ src/WINNT/afsd/cm_ioctl.h | 2 ++ src/WINNT/afsd/fs.c | 61 ++++++++++++++++++++++++++++++++ src/WINNT/afsd/smb_iocons.h | 1 + src/WINNT/afsd/smb_ioctl.c | 34 ++++++++++++++++++ src/WINNT/afsd/smb_ioctl.h | 2 ++ src/WINNT/afsrdr/user/RDRIoctl.c | 32 +++++++++++++++++ src/WINNT/afsrdr/user/RDRIoctl.h | 2 ++ 8 files changed, 172 insertions(+) diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index d760ec8b0..5aa05ed97 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -3629,3 +3629,41 @@ cm_IoctlSetVerifyData(cm_ioctl_t *ioctlp) return 0; } +/* + * VIOC_GETCALLERACCESS internals. + * + * Assumes that pioctl path has been parsed or skipped. + */ + +afs_int32 +cm_IoctlGetCallerAccess(cm_ioctl_t *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp) +{ + afs_int32 code; + afs_uint32 rights = 0; + int haveRights = 0; + char *cp; + + lock_ObtainWrite(&scp->rw); + code = cm_SyncOp(scp, NULL, userp, reqp, 0, + CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + if (code == 0) { + haveRights = cm_HaveAccessRights(scp, userp, reqp, 0xFF0000FF, &rights); + cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + } + lock_ReleaseWrite(&scp->rw); + + cp = ioctlp->outDatap; + /* Copy all this junk into msg->im_data, keeping track of the lengths. */ + if (haveRights) + memcpy(cp, (char *)&rights, sizeof(afs_uint32)); + else + memcpy(cp, (char *)&scp->anyAccess, sizeof(afs_uint32)); + cp += sizeof(afs_uint32); + memcpy(cp, (char *)&scp->anyAccess, sizeof(afs_uint32)); + cp += sizeof(afs_uint32); + + /* return new size */ + ioctlp->outDatap = cp; + + return code; +} diff --git a/src/WINNT/afsd/cm_ioctl.h b/src/WINNT/afsd/cm_ioctl.h index 3ddbc1d28..8227fb3d4 100644 --- a/src/WINNT/afsd/cm_ioctl.h +++ b/src/WINNT/afsd/cm_ioctl.h @@ -290,6 +290,8 @@ extern afs_int32 cm_IoctlGetVerifyData(cm_ioctl_t *ioctlp); extern afs_int32 cm_IoctlSetVerifyData(cm_ioctl_t *ioctlp); +extern afs_int32 cm_IoctlGetCallerAccess(cm_ioctl_t *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp); + #endif /* __CM_IOCTL_INTERFACES_ONLY__ */ #endif /* OPENAFS_WINNT_AFSD_CM_IOCTL_H */ diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index 021497688..ebe13ae52 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -931,6 +931,61 @@ ListACLCmd(struct cmd_syndesc *as, void *arock) return error; } +static int +GetCallerAccess(struct cmd_syndesc *as, void *arock) +{ + afs_int32 code; + struct ViceIoctl blob; + struct cmd_item *ti; + int error = 0; + int literal = 0; + cm_ioctlQueryOptions_t options; + + if (as->parms[1].items) + literal = 1; + + SetDotDefault(&as->parms[0].items); + for(ti=as->parms[0].items; ti; ti=ti->next) { + cm_fid_t fid; + afs_uint32 rights[2]; + + /* once per file */ + memset(&fid, 0, sizeof(fid)); + memset(&options, 0, sizeof(options)); + options.size = sizeof(options); + options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL; + options.literal = literal; + blob.in_size = options.size; /* no variable length data */ + blob.in = &options; + + blob.out_size = sizeof(cm_fid_t); + blob.out = (char *) &fid; + if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1) && + blob.out_size == sizeof(cm_fid_t)) { + options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID; + options.fid = fid; + } else { + fs_Die(errno, ti->data); + error = 1; + continue; + } + + blob.out_size = sizeof(rights); + blob.out = rights; + code = pioctl_utf8(ti->data, VIOC_GETCALLERACCESS, &blob, 1); + if (code || blob.out_size != sizeof(rights)) { + fs_Die(errno, ti->data); + error = 1; + continue; + } + + printf("Callers access to '%s' is ", ti->data); + PRights(rights[0], 0); + printf("\n"); + } + return error; +} + static int FlushAllCmd(struct cmd_syndesc *as, void *arock) { @@ -5164,6 +5219,12 @@ int wmain(int argc, wchar_t **wargv) cmd_AddParm(ts, "-cmd", CMD_FLAG, CMD_OPTIONAL, "output as 'fs setacl' command"); cmd_CreateAlias(ts, "la"); + ts = cmd_CreateSyntax("getcalleraccess", GetCallerAccess, NULL, + "list callers access"); + cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path"); + cmd_AddParm(ts, "-literal", CMD_FLAG, CMD_OPTIONAL, "literal evaluation of mountpoints and symlinks"); + cmd_CreateAlias(ts, "gca"); + ts = cmd_CreateSyntax("cleanacl", CleanACLCmd, NULL, "clean up access control list"); cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path"); diff --git a/src/WINNT/afsd/smb_iocons.h b/src/WINNT/afsd/smb_iocons.h index b8b2c3c7f..b5e667fc5 100644 --- a/src/WINNT/afsd/smb_iocons.h +++ b/src/WINNT/afsd/smb_iocons.h @@ -103,6 +103,7 @@ struct sbstruct { #define VIOC_SETUNIXMODE 0x39 #define VIOC_GETVERIFYDATA 0x3A #define VIOC_SETVERIFYDATA 0x3B +#define VIOC_GETCALLERACCESS 0x3C #define VIOC_VOLSTAT_TEST 0x3F diff --git a/src/WINNT/afsd/smb_ioctl.c b/src/WINNT/afsd/smb_ioctl.c index 955507054..71e5e279b 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -98,6 +98,7 @@ smb_InitIoctl(void) smb_ioctlProcsp[VIOC_GETUNIXMODE] = smb_IoctlGetUnixMode; smb_ioctlProcsp[VIOC_SETVERIFYDATA] = smb_IoctlSetVerifyData; smb_ioctlProcsp[VIOC_GETVERIFYDATA] = smb_IoctlGetVerifyData; + smb_ioctlProcsp[VIOC_GETCALLERACCESS] = smb_IoctlGetCallerAccess; } /* called to make a fid structure into an IOCTL fid structure */ @@ -2197,3 +2198,36 @@ smb_IoctlSetVerifyData(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint return cm_IoctlSetVerifyData(&ioctlp->ioctl); } +afs_int32 +smb_IoctlGetCallerAccess(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags) +{ + afs_int32 code; + cm_scache_t *scp; + cm_req_t req; + cm_ioctlQueryOptions_t * optionsp; + afs_uint32 flags = 0; + + smb_InitReq(&req); + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, NULL, &scp, userp, &req); + } else { + code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlGetCallerAccess(&ioctlp->ioctl, userp, scp, &req); + + cm_ReleaseSCache(scp); + + return code; +} diff --git a/src/WINNT/afsd/smb_ioctl.h b/src/WINNT/afsd/smb_ioctl.h index 4ba8f4b3d..7e1168aff 100644 --- a/src/WINNT/afsd/smb_ioctl.h +++ b/src/WINNT/afsd/smb_ioctl.h @@ -215,4 +215,6 @@ extern afs_int32 smb_IoctlGetVerifyData(struct smb_ioctl *ioctlp, struct cm_user extern afs_int32 smb_IoctlSetVerifyData(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 flags); +extern afs_int32 smb_IoctlGetCallerAccess(struct smb_ioctl_t *ioctlp, struct cm_user *userp, afs_uint32 flags); + #endif /* OPENAFS_WINNT_AFSD_SMB_IOCTL_H */ diff --git a/src/WINNT/afsrdr/user/RDRIoctl.c b/src/WINNT/afsrdr/user/RDRIoctl.c index ceb81ccd0..ed7e43fe8 100644 --- a/src/WINNT/afsrdr/user/RDRIoctl.c +++ b/src/WINNT/afsrdr/user/RDRIoctl.c @@ -149,6 +149,7 @@ RDR_InitIoctl(void) RDR_ioctlProcsp[VIOC_SETUNIXMODE] = RDR_IoctlSetUnixMode; RDR_ioctlProcsp[VIOC_GETVERIFYDATA] = RDR_IoctlGetVerifyData; RDR_ioctlProcsp[VIOC_SETVERIFYDATA] = RDR_IoctlSetVerifyData; + RDR_ioctlProcsp[VIOC_GETCALLERACCESS] = RDR_IoctlGetCallerAccess; } void @@ -1961,3 +1962,34 @@ RDR_IoctlSetVerifyData(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint return cm_IoctlSetVerifyData(&ioctlp->ioctl); } + +afs_int32 +RDR_IoctlGetCallerAccess(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags) +{ + afs_int32 code; + cm_scache_t *scp; + cm_ioctlQueryOptions_t * optionsp; + afs_uint32 flags = 0; + + optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp); + if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp)) + flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0); + + if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) { + cm_fid_t fid; + cm_SkipIoctlPath(&ioctlp->ioctl); + cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume, + optionsp->fid.vnode, optionsp->fid.unique); + code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req); + } else { + code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags); + } + if (code) + return code; + + code = cm_IoctlGetCallerAccess(&ioctlp->ioctl, userp, scp, &ioctlp->req); + + cm_ReleaseSCache(scp); + + return code; +} diff --git a/src/WINNT/afsrdr/user/RDRIoctl.h b/src/WINNT/afsrdr/user/RDRIoctl.h index 6ff952060..d4a1605c6 100644 --- a/src/WINNT/afsrdr/user/RDRIoctl.h +++ b/src/WINNT/afsrdr/user/RDRIoctl.h @@ -195,5 +195,7 @@ extern afs_int32 RDR_IoctlGetVerifyData(RDR_ioctl_t *ioctlp, cm_user_t *userp, a extern afs_int32 RDR_IoctlSetVerifyData(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags); +extern afs_int32 RDR_IoctlGetCallerAccess(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags); + #endif -- 2.39.5