Add rxgk support to userok
[openafs.git] / src / auth / userok.c
index 2a258df..52afca3 100644 (file)
@@ -20,6 +20,9 @@
 #include <rx/xdr.h>
 #include <rx/rx.h>
 #include <rx/rx_identity.h>
+#ifdef AFS_RXGK_ENV
+# include <rx/rxgk.h>
+#endif
 #include <afs/afsutil.h>
 #include <afs/fileutil.h>
 
@@ -46,7 +49,6 @@ UserListFileName(struct afsconf_dir *adir,
     strcompose(buffer, len, adir->name, "/", AFSDIR_ULIST_FILE, (char *)NULL);
 }
 
-#if !defined(UKERNEL)
 int
 afsconf_CheckAuth(void *arock, struct rx_call *acall)
 {
@@ -57,7 +59,6 @@ afsconf_CheckAuth(void *arock, struct rx_call *acall)
     UNLOCK_GLOBAL_MUTEX;
     return rc;
 }
-#endif /* !defined(UKERNEL) */
 
 static int
 GetNoAuthFlag(struct afsconf_dir *adir)
@@ -294,6 +295,7 @@ afsconf_DeleteUser(struct afsconf_dir *adir, char *name)
  * GetNthIdentity or GetNthUser. The parameter 'id' indicates
  * whether we are counting all identities (if true), or just
  * ones which can be represented by the old-style interfaces
+ * We return -1 for EOF, 0 for success, and >0 for all errors.
  */
 static int
 GetNthIdentityOrUser(struct afsconf_dir *dir, int count,
@@ -314,12 +316,14 @@ GetNthIdentityOrUser(struct afsconf_dir *dir, int count,
     if (!bp) {
        UNLOCK_GLOBAL_MUTEX;
        free(tbuffer);
-       return EIO;
+       return -1;
     }
     while (1) {
        code = BufioGets(bp, tbuffer, AFSDIR_PATH_MAX);
-       if (code < 0)
+       if (code < 0) {
+           code = -1;
            break;
+       }
 
        code = ParseLine(tbuffer, &fileUser);
        if (code != 0)
@@ -356,7 +360,10 @@ GetNthIdentityOrUser(struct afsconf_dir *dir, int count,
  * @param[out] identity
  *     A pointer to the Nth identity
  * @returns
- *     0 on success, non-zero on failure
+ *      status code
+ * @retval 0 Success
+ * @retval -1 We have searched beyond the end of the list.
+ * @retval >0 Error
  */
 
 int
@@ -384,11 +391,17 @@ afsconf_GetNthIdentity(struct afsconf_dir *dir, int count,
  * @param abufferLen
  *     The length of the buffer passed in abuffer
  * @returns
- *     0 on success, non-zero on failure
+ *      status code
+ * @retval 0 Success
+ * @retval 1 Either an EPERM error, or we have searched beyond the end of the
+ *           list.
+ * @retval >1 All other errors.
  *
  * This function is deprecated, all new callers should use
  * GetNthIdentity instead. This function is particularly dangerous
- * as it will hide any new-style identities from callers.
+ * as it will hide any new-style identities from callers. It is also
+ * impossible to distinguish an EPERM error from a normal end-of-file
+ * condition with this function.
  */
 
 int
@@ -403,6 +416,11 @@ afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer,
        strlcpy(abuffer, identity->displayName, abufferLen);
        rx_identity_free(&identity);
     }
+    if (code == -1) {
+       /* The new functions use -1 to indicate EOF, but the old interface
+        * uses 1 to indicate EOF. */
+       code = 1;
+    }
     return code;
 }
 
@@ -498,6 +516,9 @@ afsconf_IsSuperIdentity(struct afsconf_dir *adir,
     int match;
     afs_int32 code;
 
+    if (user->kind == RX_ID_SUPERUSER)
+       return 1;
+
     tbuffer = malloc(AFSDIR_PATH_MAX);
     if (tbuffer == NULL)
        return 0;
@@ -705,6 +726,32 @@ rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall,
     return kerberosSuperUser(adir, tname, tinst, tcell, identity);
 }
 
+#ifdef AFS_RXGK_ENV
+static int
+rxgkSuperUser(struct afsconf_dir *adir, struct rx_call *acall,
+             struct rx_identity **identity_out)
+{
+    struct rx_identity *identity = NULL;
+    int is_super = 0;
+
+    if (rxgk_GetServerInfo(rx_ConnectionOf(acall), NULL /*level*/, NULL /*expiry*/,
+                           &identity) != 0)
+        return 0;
+
+    if (afsconf_IsSuperIdentity(adir, identity)) {
+        is_super = 1;
+        if (identity_out != NULL) {
+            *identity_out = identity;
+            identity = NULL;
+        }
+    }
+    if (identity != NULL) {
+        rx_identity_free(&identity);
+    }
+    return is_super;
+}
+#endif /* AFS_RXGK_ENV */
+
 /*!
  * Check whether the user authenticated on a given RX call is a super
  * user or not. If they are, return a pointer to the identity of that
@@ -755,6 +802,12 @@ afsconf_SuperIdentity(struct afsconf_dir *adir, struct rx_call *acall,
        flag = rxkadSuperUser(adir, acall, identity);
        UNLOCK_GLOBAL_MUTEX;
        return flag;
+#ifdef AFS_RXGK_ENV
+    } else if (code == RX_SECIDX_GK) {
+       flag = rxgkSuperUser(adir, acall, identity);
+       UNLOCK_GLOBAL_MUTEX;
+       return flag;
+#endif
     } else {                   /* some other auth type */
        UNLOCK_GLOBAL_MUTEX;
        return 0;               /* mysterious, just say no */