This source file includes following definitions.
- cifs_spnego_key_instantiate
- cifs_spnego_key_destroy
- cifs_get_spnego_key
- init_cifs_spnego
- exit_cifs_spnego
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 #include <linux/list.h>
  23 #include <linux/slab.h>
  24 #include <linux/string.h>
  25 #include <keys/user-type.h>
  26 #include <linux/key-type.h>
  27 #include <linux/keyctl.h>
  28 #include <linux/inet.h>
  29 #include "cifsglob.h"
  30 #include "cifs_spnego.h"
  31 #include "cifs_debug.h"
  32 #include "cifsproto.h"
  33 static const struct cred *spnego_cred;
  34 
  35 
  36 static int
  37 cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
  38 {
  39         char *payload;
  40         int ret;
  41 
  42         ret = -ENOMEM;
  43         payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
  44         if (!payload)
  45                 goto error;
  46 
  47         
  48         key->payload.data[0] = payload;
  49         ret = 0;
  50 
  51 error:
  52         return ret;
  53 }
  54 
  55 static void
  56 cifs_spnego_key_destroy(struct key *key)
  57 {
  58         kfree(key->payload.data[0]);
  59 }
  60 
  61 
  62 
  63 
  64 
  65 struct key_type cifs_spnego_key_type = {
  66         .name           = "cifs.spnego",
  67         .instantiate    = cifs_spnego_key_instantiate,
  68         .destroy        = cifs_spnego_key_destroy,
  69         .describe       = user_describe,
  70 };
  71 
  72 
  73 #define MAX_VER_STR_LEN         8
  74 
  75 
  76 
  77 #define MAX_MECH_STR_LEN        13
  78 
  79 
  80 #define HOST_KEY_LEN            5
  81 
  82 
  83 #define IP_KEY_LEN              5
  84 
  85 
  86 #define UID_KEY_LEN             7
  87 
  88 
  89 #define CREDUID_KEY_LEN         11
  90 
  91 
  92 #define USER_KEY_LEN            6
  93 
  94 
  95 #define PID_KEY_LEN             7
  96 
  97 
  98 struct key *
  99 cifs_get_spnego_key(struct cifs_ses *sesInfo)
 100 {
 101         struct TCP_Server_Info *server = sesInfo->server;
 102         struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
 103         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
 104         char *description, *dp;
 105         size_t desc_len;
 106         struct key *spnego_key;
 107         const char *hostname = server->hostname;
 108         const struct cred *saved_cred;
 109 
 110         
 111 
 112         desc_len = MAX_VER_STR_LEN +
 113                    HOST_KEY_LEN + strlen(hostname) +
 114                    IP_KEY_LEN + INET6_ADDRSTRLEN +
 115                    MAX_MECH_STR_LEN +
 116                    UID_KEY_LEN + (sizeof(uid_t) * 2) +
 117                    CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
 118                    PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
 119 
 120         if (sesInfo->user_name)
 121                 desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
 122 
 123         spnego_key = ERR_PTR(-ENOMEM);
 124         description = kzalloc(desc_len, GFP_KERNEL);
 125         if (description == NULL)
 126                 goto out;
 127 
 128         dp = description;
 129         
 130         spnego_key = ERR_PTR(-EINVAL);
 131         sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
 132                 hostname);
 133         dp = description + strlen(description);
 134 
 135         
 136         if (server->dstaddr.ss_family == AF_INET)
 137                 sprintf(dp, "ip4=%pI4", &sa->sin_addr);
 138         else if (server->dstaddr.ss_family == AF_INET6)
 139                 sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
 140         else
 141                 goto out;
 142 
 143         dp = description + strlen(description);
 144 
 145         
 146         if (server->sec_kerberos)
 147                 sprintf(dp, ";sec=krb5");
 148         else if (server->sec_mskerberos)
 149                 sprintf(dp, ";sec=mskrb5");
 150         else {
 151                 cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n");
 152                 sprintf(dp, ";sec=krb5");
 153         }
 154 
 155         dp = description + strlen(description);
 156         sprintf(dp, ";uid=0x%x",
 157                 from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
 158 
 159         dp = description + strlen(description);
 160         sprintf(dp, ";creduid=0x%x",
 161                 from_kuid_munged(&init_user_ns, sesInfo->cred_uid));
 162 
 163         if (sesInfo->user_name) {
 164                 dp = description + strlen(description);
 165                 sprintf(dp, ";user=%s", sesInfo->user_name);
 166         }
 167 
 168         dp = description + strlen(description);
 169         sprintf(dp, ";pid=0x%x", current->pid);
 170 
 171         cifs_dbg(FYI, "key description = %s\n", description);
 172         saved_cred = override_creds(spnego_cred);
 173         spnego_key = request_key(&cifs_spnego_key_type, description, "");
 174         revert_creds(saved_cred);
 175 
 176 #ifdef CONFIG_CIFS_DEBUG2
 177         if (cifsFYI && !IS_ERR(spnego_key)) {
 178                 struct cifs_spnego_msg *msg = spnego_key->payload.data[0];
 179                 cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U,
 180                                 msg->secblob_len + msg->sesskey_len));
 181         }
 182 #endif 
 183 
 184 out:
 185         kfree(description);
 186         return spnego_key;
 187 }
 188 
 189 int
 190 init_cifs_spnego(void)
 191 {
 192         struct cred *cred;
 193         struct key *keyring;
 194         int ret;
 195 
 196         cifs_dbg(FYI, "Registering the %s key type\n",
 197                  cifs_spnego_key_type.name);
 198 
 199         
 200 
 201 
 202 
 203 
 204         cred = prepare_kernel_cred(NULL);
 205         if (!cred)
 206                 return -ENOMEM;
 207 
 208         keyring = keyring_alloc(".cifs_spnego",
 209                                 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
 210                                 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
 211                                 KEY_USR_VIEW | KEY_USR_READ,
 212                                 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
 213         if (IS_ERR(keyring)) {
 214                 ret = PTR_ERR(keyring);
 215                 goto failed_put_cred;
 216         }
 217 
 218         ret = register_key_type(&cifs_spnego_key_type);
 219         if (ret < 0)
 220                 goto failed_put_key;
 221 
 222         
 223 
 224 
 225 
 226         set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
 227         cred->thread_keyring = keyring;
 228         cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
 229         spnego_cred = cred;
 230 
 231         cifs_dbg(FYI, "cifs spnego keyring: %d\n", key_serial(keyring));
 232         return 0;
 233 
 234 failed_put_key:
 235         key_put(keyring);
 236 failed_put_cred:
 237         put_cred(cred);
 238         return ret;
 239 }
 240 
 241 void
 242 exit_cifs_spnego(void)
 243 {
 244         key_revoke(spnego_cred->thread_keyring);
 245         unregister_key_type(&cifs_spnego_key_type);
 246         put_cred(spnego_cred);
 247         cifs_dbg(FYI, "Unregistered %s key type\n", cifs_spnego_key_type.name);
 248 }