~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to fs/cifs/cifs_spnego.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS
 
3
 *
 
4
 *   Copyright (c) 2007 Red Hat, Inc.
 
5
 *   Author(s): Jeff Layton (jlayton@redhat.com)
 
6
 *
 
7
 *   This library is free software; you can redistribute it and/or modify
 
8
 *   it under the terms of the GNU Lesser General Public License as published
 
9
 *   by the Free Software Foundation; either version 2.1 of the License, or
 
10
 *   (at your option) any later version.
 
11
 *
 
12
 *   This library is distributed in the hope that it will be useful,
 
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 
15
 *   the GNU Lesser General Public License for more details.
 
16
 *
 
17
 *   You should have received a copy of the GNU Lesser General Public License
 
18
 *   along with this library; if not, write to the Free Software
 
19
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
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/inet.h>
 
28
#include "cifsglob.h"
 
29
#include "cifs_spnego.h"
 
30
#include "cifs_debug.h"
 
31
 
 
32
/* create a new cifs key */
 
33
static int
 
34
cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
 
35
{
 
36
        char *payload;
 
37
        int ret;
 
38
 
 
39
        ret = -ENOMEM;
 
40
        payload = kmalloc(datalen, GFP_KERNEL);
 
41
        if (!payload)
 
42
                goto error;
 
43
 
 
44
        /* attach the data */
 
45
        memcpy(payload, data, datalen);
 
46
        key->payload.data = payload;
 
47
        ret = 0;
 
48
 
 
49
error:
 
50
        return ret;
 
51
}
 
52
 
 
53
static void
 
54
cifs_spnego_key_destroy(struct key *key)
 
55
{
 
56
        kfree(key->payload.data);
 
57
}
 
58
 
 
59
 
 
60
/*
 
61
 * keytype for CIFS spnego keys
 
62
 */
 
63
struct key_type cifs_spnego_key_type = {
 
64
        .name           = "cifs.spnego",
 
65
        .instantiate    = cifs_spnego_key_instantiate,
 
66
        .match          = user_match,
 
67
        .destroy        = cifs_spnego_key_destroy,
 
68
        .describe       = user_describe,
 
69
};
 
70
 
 
71
/* length of longest version string e.g.  strlen("ver=0xFF") */
 
72
#define MAX_VER_STR_LEN         8
 
73
 
 
74
/* length of longest security mechanism name, eg in future could have
 
75
 * strlen(";sec=ntlmsspi") */
 
76
#define MAX_MECH_STR_LEN        13
 
77
 
 
78
/* strlen of "host=" */
 
79
#define HOST_KEY_LEN            5
 
80
 
 
81
/* strlen of ";ip4=" or ";ip6=" */
 
82
#define IP_KEY_LEN              5
 
83
 
 
84
/* strlen of ";uid=0x" */
 
85
#define UID_KEY_LEN             7
 
86
 
 
87
/* strlen of ";creduid=0x" */
 
88
#define CREDUID_KEY_LEN         11
 
89
 
 
90
/* strlen of ";user=" */
 
91
#define USER_KEY_LEN            6
 
92
 
 
93
/* strlen of ";pid=0x" */
 
94
#define PID_KEY_LEN             7
 
95
 
 
96
/* get a key struct with a SPNEGO security blob, suitable for session setup */
 
97
struct key *
 
98
cifs_get_spnego_key(struct cifs_ses *sesInfo)
 
99
{
 
100
        struct TCP_Server_Info *server = sesInfo->server;
 
101
        struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
 
102
        struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
 
103
        char *description, *dp;
 
104
        size_t desc_len;
 
105
        struct key *spnego_key;
 
106
        const char *hostname = server->hostname;
 
107
 
 
108
        /* length of fields (with semicolons): ver=0xyz ip4=ipaddress
 
109
           host=hostname sec=mechanism uid=0xFF user=username */
 
110
        desc_len = MAX_VER_STR_LEN +
 
111
                   HOST_KEY_LEN + strlen(hostname) +
 
112
                   IP_KEY_LEN + INET6_ADDRSTRLEN +
 
113
                   MAX_MECH_STR_LEN +
 
114
                   UID_KEY_LEN + (sizeof(uid_t) * 2) +
 
115
                   CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
 
116
                   USER_KEY_LEN + strlen(sesInfo->user_name) +
 
117
                   PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
 
118
 
 
119
        spnego_key = ERR_PTR(-ENOMEM);
 
120
        description = kzalloc(desc_len, GFP_KERNEL);
 
121
        if (description == NULL)
 
122
                goto out;
 
123
 
 
124
        dp = description;
 
125
        /* start with version and hostname portion of UNC string */
 
126
        spnego_key = ERR_PTR(-EINVAL);
 
127
        sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
 
128
                hostname);
 
129
        dp = description + strlen(description);
 
130
 
 
131
        /* add the server address */
 
132
        if (server->dstaddr.ss_family == AF_INET)
 
133
                sprintf(dp, "ip4=%pI4", &sa->sin_addr);
 
134
        else if (server->dstaddr.ss_family == AF_INET6)
 
135
                sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
 
136
        else
 
137
                goto out;
 
138
 
 
139
        dp = description + strlen(description);
 
140
 
 
141
        /* for now, only sec=krb5 and sec=mskrb5 are valid */
 
142
        if (server->sec_kerberos)
 
143
                sprintf(dp, ";sec=krb5");
 
144
        else if (server->sec_mskerberos)
 
145
                sprintf(dp, ";sec=mskrb5");
 
146
        else
 
147
                goto out;
 
148
 
 
149
        dp = description + strlen(description);
 
150
        sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
 
151
 
 
152
        dp = description + strlen(description);
 
153
        sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
 
154
 
 
155
        dp = description + strlen(description);
 
156
        sprintf(dp, ";user=%s", sesInfo->user_name);
 
157
 
 
158
        dp = description + strlen(description);
 
159
        sprintf(dp, ";pid=0x%x", current->pid);
 
160
 
 
161
        cFYI(1, "key description = %s", description);
 
162
        spnego_key = request_key(&cifs_spnego_key_type, description, "");
 
163
 
 
164
#ifdef CONFIG_CIFS_DEBUG2
 
165
        if (cifsFYI && !IS_ERR(spnego_key)) {
 
166
                struct cifs_spnego_msg *msg = spnego_key->payload.data;
 
167
                cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U,
 
168
                                msg->secblob_len + msg->sesskey_len));
 
169
        }
 
170
#endif /* CONFIG_CIFS_DEBUG2 */
 
171
 
 
172
out:
 
173
        kfree(description);
 
174
        return spnego_key;
 
175
}