Windows: fs getcalleraccess
authorJeffrey Altman <jaltman@your-file-system.com>
Mon, 3 Dec 2012 18:39:18 +0000 (13:39 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Wed, 5 Dec 2012 20:14:46 +0000 (12:14 -0800)
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 <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_ioctl.h
src/WINNT/afsd/fs.c
src/WINNT/afsd/smb_iocons.h
src/WINNT/afsd/smb_ioctl.c
src/WINNT/afsd/smb_ioctl.h
src/WINNT/afsrdr/user/RDRIoctl.c
src/WINNT/afsrdr/user/RDRIoctl.h

index d760ec8..5aa05ed 100644 (file)
@@ -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;
+}
index 3ddbc1d..8227fb3 100644 (file)
@@ -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 */
index 0214976..ebe13ae 100644 (file)
@@ -932,6 +932,61 @@ ListACLCmd(struct cmd_syndesc *as, void *arock)
 }
 
 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)
 {
     afs_int32 code;
@@ -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");
 
index b8b2c3c..b5e667f 100644 (file)
@@ -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
 
index 9555070..71e5e27 100644 (file)
@@ -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;
+}
index 4ba8f4b..7e1168a 100644 (file)
@@ -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 */
index ceb81cc..ed7e43f 100644 (file)
@@ -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;
+}
index 6ff9520..d4a1605 100644 (file)
@@ -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