Blame view

fs/cifs/cifs_spnego.c 4.71 KB
f1d662a7d   Steve French   [CIFS] Add upcall...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  /*
   *   fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS
   *
   *   Copyright (c) 2007 Red Hat, Inc.
   *   Author(s): Jeff Layton (jlayton@redhat.com)
   *
   *   This library is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU Lesser General Public License as published
   *   by the Free Software Foundation; either version 2.1 of the License, or
   *   (at your option) any later version.
   *
   *   This library is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU Lesser General Public License for more details.
   *
   *   You should have received a copy of the GNU Lesser General Public License
   *   along with this library; if not, write to the Free Software
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   */
  
  #include <linux/list.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
23
  #include <linux/slab.h>
f1d662a7d   Steve French   [CIFS] Add upcall...
24
25
26
  #include <linux/string.h>
  #include <keys/user-type.h>
  #include <linux/key-type.h>
50b64e3b7   Jeff Layton   cifs: fix IPv6 ad...
27
  #include <linux/inet.h>
f1d662a7d   Steve French   [CIFS] Add upcall...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  #include "cifsglob.h"
  #include "cifs_spnego.h"
  #include "cifs_debug.h"
  
  /* create a new cifs key */
  static int
  cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
  {
  	char *payload;
  	int ret;
  
  	ret = -ENOMEM;
  	payload = kmalloc(datalen, GFP_KERNEL);
  	if (!payload)
  		goto error;
  
  	/* attach the data */
  	memcpy(payload, data, datalen);
d9fb5c091   Jeff Layton   cifs: no need to ...
46
  	key->payload.data = payload;
f1d662a7d   Steve French   [CIFS] Add upcall...
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  	ret = 0;
  
  error:
  	return ret;
  }
  
  static void
  cifs_spnego_key_destroy(struct key *key)
  {
  	kfree(key->payload.data);
  }
  
  
  /*
   * keytype for CIFS spnego keys
   */
  struct key_type cifs_spnego_key_type = {
  	.name		= "cifs.spnego",
  	.instantiate	= cifs_spnego_key_instantiate,
  	.match		= user_match,
  	.destroy	= cifs_spnego_key_destroy,
  	.describe	= user_describe,
  };
7c9c3760b   Steve French   [CIFS] add consta...
70
71
72
73
74
75
  /* length of longest version string e.g.  strlen("ver=0xFF") */
  #define MAX_VER_STR_LEN		8
  
  /* length of longest security mechanism name, eg in future could have
   * strlen(";sec=ntlmsspi") */
  #define MAX_MECH_STR_LEN	13
7c9c3760b   Steve French   [CIFS] add consta...
76
77
78
79
80
81
82
83
  /* strlen of "host=" */
  #define HOST_KEY_LEN		5
  
  /* strlen of ";ip4=" or ";ip6=" */
  #define IP_KEY_LEN		5
  
  /* strlen of ";uid=0x" */
  #define UID_KEY_LEN		7
ba5dadbf4   Jeff Layton   cifs: account for...
84
85
  /* strlen of ";creduid=0x" */
  #define CREDUID_KEY_LEN		11
7c9c3760b   Steve French   [CIFS] add consta...
86
87
  /* strlen of ";user=" */
  #define USER_KEY_LEN		6
c4c1bff64   Jeff Layton   cifs: add pid of ...
88
89
  /* strlen of ";pid=0x" */
  #define PID_KEY_LEN		7
f1d662a7d   Steve French   [CIFS] Add upcall...
90
91
  /* get a key struct with a SPNEGO security blob, suitable for session setup */
  struct key *
96daf2b09   Steve French   [CIFS] Rename thr...
92
  cifs_get_spnego_key(struct cifs_ses *sesInfo)
f1d662a7d   Steve French   [CIFS] Add upcall...
93
94
  {
  	struct TCP_Server_Info *server = sesInfo->server;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
95
96
  	struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
  	struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
f1d662a7d   Steve French   [CIFS] Add upcall...
97
98
99
  	char *description, *dp;
  	size_t desc_len;
  	struct key *spnego_key;
d6c2e4d02   Jeff Layton   [CIFS] have cifs_...
100
  	const char *hostname = server->hostname;
f1d662a7d   Steve French   [CIFS] Add upcall...
101

66b8bd3c4   Jeff Layton   [CIFS] properly a...
102
103
104
  	/* length of fields (with semicolons): ver=0xyz ip4=ipaddress
  	   host=hostname sec=mechanism uid=0xFF user=username */
  	desc_len = MAX_VER_STR_LEN +
7c9c3760b   Steve French   [CIFS] add consta...
105
  		   HOST_KEY_LEN + strlen(hostname) +
50b64e3b7   Jeff Layton   cifs: fix IPv6 ad...
106
  		   IP_KEY_LEN + INET6_ADDRSTRLEN +
66b8bd3c4   Jeff Layton   [CIFS] properly a...
107
  		   MAX_MECH_STR_LEN +
7c9c3760b   Steve French   [CIFS] add consta...
108
  		   UID_KEY_LEN + (sizeof(uid_t) * 2) +
ba5dadbf4   Jeff Layton   cifs: account for...
109
  		   CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
8727c8a85   Steve French   Allow user names ...
110
  		   USER_KEY_LEN + strlen(sesInfo->user_name) +
c4c1bff64   Jeff Layton   cifs: add pid of ...
111
  		   PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
66b8bd3c4   Jeff Layton   [CIFS] properly a...
112

f1d662a7d   Steve French   [CIFS] Add upcall...
113
114
115
116
117
118
119
120
  	spnego_key = ERR_PTR(-ENOMEM);
  	description = kzalloc(desc_len, GFP_KERNEL);
  	if (description == NULL)
  		goto out;
  
  	dp = description;
  	/* start with version and hostname portion of UNC string */
  	spnego_key = ERR_PTR(-EINVAL);
68bf728a2   Steve French   [CIFS] add ver= p...
121
  	sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
f1d662a7d   Steve French   [CIFS] Add upcall...
122
123
124
125
  		hostname);
  	dp = description + strlen(description);
  
  	/* add the server address */
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
126
127
128
129
  	if (server->dstaddr.ss_family == AF_INET)
  		sprintf(dp, "ip4=%pI4", &sa->sin_addr);
  	else if (server->dstaddr.ss_family == AF_INET6)
  		sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
f1d662a7d   Steve French   [CIFS] Add upcall...
130
131
132
133
  	else
  		goto out;
  
  	dp = description + strlen(description);
c16fefa56   Steve French   [CIFS] distinguis...
134
  	/* for now, only sec=krb5 and sec=mskrb5 are valid */
26efa0bac   Jeff Layton   cifs: have decode...
135
  	if (server->sec_kerberos)
f1d662a7d   Steve French   [CIFS] Add upcall...
136
  		sprintf(dp, ";sec=krb5");
26efa0bac   Jeff Layton   cifs: have decode...
137
  	else if (server->sec_mskerberos)
c16fefa56   Steve French   [CIFS] distinguis...
138
  		sprintf(dp, ";sec=mskrb5");
f1d662a7d   Steve French   [CIFS] Add upcall...
139
140
  	else
  		goto out;
9eae8a890   Igor Mammedov   [CIFS] Add uid to...
141
142
  	dp = description + strlen(description);
  	sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
e4058245a   Igor Mammedov   Adds username in ...
143
  	dp = description + strlen(description);
3e4b3e1f6   Jeff Layton   cifs: add separat...
144
145
146
  	sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
  
  	dp = description + strlen(description);
8727c8a85   Steve French   Allow user names ...
147
  	sprintf(dp, ";user=%s", sesInfo->user_name);
e4058245a   Igor Mammedov   Adds username in ...
148

c4c1bff64   Jeff Layton   cifs: add pid of ...
149
150
  	dp = description + strlen(description);
  	sprintf(dp, ";pid=0x%x", current->pid);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
151
  	cFYI(1, "key description = %s", description);
f1d662a7d   Steve French   [CIFS] Add upcall...
152
  	spnego_key = request_key(&cifs_spnego_key_type, description, "");
05b3de63d   Jeff Layton   [CIFS] Only dump ...
153
  #ifdef CONFIG_CIFS_DEBUG2
f1d662a7d   Steve French   [CIFS] Add upcall...
154
155
  	if (cifsFYI && !IS_ERR(spnego_key)) {
  		struct cifs_spnego_msg *msg = spnego_key->payload.data;
ead03e30b   Andrew Morton   [CIFS] fix warnin...
156
  		cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U,
05b3de63d   Jeff Layton   [CIFS] Only dump ...
157
  				msg->secblob_len + msg->sesskey_len));
f1d662a7d   Steve French   [CIFS] Add upcall...
158
  	}
05b3de63d   Jeff Layton   [CIFS] Only dump ...
159
  #endif /* CONFIG_CIFS_DEBUG2 */
f1d662a7d   Steve French   [CIFS] Add upcall...
160
161
162
163
164
  
  out:
  	kfree(description);
  	return spnego_key;
  }