keys: add a "logon" key type
[linux-2.6.git] / security / keys / user_defined.c
index 63bb1aaffc0a056d316d5631b14dc761467c7534..6e1a6276649fdbd12289221decdd6ce83d11fb1f 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/uaccess.h>
 #include "internal.h"
 
+static int logon_vet_description(const char *desc);
+
 /*
  * user defined keys take an arbitrary string as the description and an
  * arbitrary blob of data as the payload
@@ -35,6 +37,24 @@ struct key_type key_type_user = {
 
 EXPORT_SYMBOL_GPL(key_type_user);
 
+/*
+ * This key type is essentially the same as key_type_user, but it does
+ * not define a .read op. This is suitable for storing username and
+ * password pairs in the keyring that you do not want to be readable
+ * from userspace.
+ */
+struct key_type key_type_logon = {
+       .name                   = "logon",
+       .instantiate            = user_instantiate,
+       .update                 = user_update,
+       .match                  = user_match,
+       .revoke                 = user_revoke,
+       .destroy                = user_destroy,
+       .describe               = user_describe,
+       .vet_description        = logon_vet_description,
+};
+EXPORT_SYMBOL_GPL(key_type_logon);
+
 /*
  * instantiate a user defined key
  */
@@ -68,18 +88,6 @@ error:
 
 EXPORT_SYMBOL_GPL(user_instantiate);
 
-/*
- * dispose of the old data from an updated user defined key
- */
-static void user_update_rcu_disposal(struct rcu_head *rcu)
-{
-       struct user_key_payload *upayload;
-
-       upayload = container_of(rcu, struct user_key_payload, rcu);
-
-       kfree(upayload);
-}
-
 /*
  * update a user defined key
  * - the key's semaphore is write-locked
@@ -114,7 +122,8 @@ int user_update(struct key *key, const void *data, size_t datalen)
                key->expiry = 0;
        }
 
-       call_rcu(&zap->rcu, user_update_rcu_disposal);
+       if (zap)
+               kfree_rcu(zap, rcu);
 
 error:
        return ret;
@@ -145,7 +154,7 @@ void user_revoke(struct key *key)
 
        if (upayload) {
                rcu_assign_pointer(key->payload.data, NULL);
-               call_rcu(&upayload->rcu, user_update_rcu_disposal);
+               kfree_rcu(upayload, rcu);
        }
 }
 
@@ -200,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
 }
 
 EXPORT_SYMBOL_GPL(user_read);
+
+/* Vet the description for a "logon" key */
+static int logon_vet_description(const char *desc)
+{
+       char *p;
+
+       /* require a "qualified" description string */
+       p = strchr(desc, ':');
+       if (!p)
+               return -EINVAL;
+
+       /* also reject description with ':' as first char */
+       if (p == desc)
+               return -EINVAL;
+
+       return 0;
+}