Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
34f598ca
Commit
34f598ca
authored
Jan 18, 2012
by
Steve French
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git+ssh://git.samba.org/data/git/sfrench/cifs-2.6
parents
dcd169b7
789b4588
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
312 additions
and
63 deletions
+312
-63
fs/cifs/cifs_debug.c
fs/cifs/cifs_debug.c
+10
-1
fs/cifs/cifs_spnego.c
fs/cifs/cifs_spnego.c
+7
-3
fs/cifs/cifsencrypt.c
fs/cifs/cifsencrypt.c
+8
-3
fs/cifs/connect.c
fs/cifs/connect.c
+246
-55
include/keys/user-type.h
include/keys/user-type.h
+2
-1
security/keys/internal.h
security/keys/internal.h
+1
-0
security/keys/key.c
security/keys/key.c
+1
-0
security/keys/user_defined.c
security/keys/user_defined.c
+37
-0
No files found.
fs/cifs/cifs_debug.c
View file @
34f598ca
...
...
@@ -676,14 +676,23 @@ static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
{
char
c
;
int
rc
;
static
bool
warned
;
rc
=
get_user
(
c
,
buffer
);
if
(
rc
)
return
rc
;
if
(
c
==
'0'
||
c
==
'n'
||
c
==
'N'
)
multiuser_mount
=
0
;
else
if
(
c
==
'1'
||
c
==
'y'
||
c
==
'Y'
)
else
if
(
c
==
'1'
||
c
==
'y'
||
c
==
'Y'
)
{
multiuser_mount
=
1
;
if
(
!
warned
)
{
warned
=
true
;
printk
(
KERN_WARNING
"CIFS VFS: The legacy multiuser "
"mount code is scheduled to be deprecated in "
"3.5. Please switch to using the multiuser "
"mount option."
);
}
}
return
count
;
}
...
...
fs/cifs/cifs_spnego.c
View file @
34f598ca
...
...
@@ -113,9 +113,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
MAX_MECH_STR_LEN
+
UID_KEY_LEN
+
(
sizeof
(
uid_t
)
*
2
)
+
CREDUID_KEY_LEN
+
(
sizeof
(
uid_t
)
*
2
)
+
USER_KEY_LEN
+
strlen
(
sesInfo
->
user_name
)
+
PID_KEY_LEN
+
(
sizeof
(
pid_t
)
*
2
)
+
1
;
if
(
sesInfo
->
user_name
)
desc_len
+=
USER_KEY_LEN
+
strlen
(
sesInfo
->
user_name
);
spnego_key
=
ERR_PTR
(
-
ENOMEM
);
description
=
kzalloc
(
desc_len
,
GFP_KERNEL
);
if
(
description
==
NULL
)
...
...
@@ -152,8 +154,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
dp
=
description
+
strlen
(
description
);
sprintf
(
dp
,
";creduid=0x%x"
,
sesInfo
->
cred_uid
);
dp
=
description
+
strlen
(
description
);
sprintf
(
dp
,
";user=%s"
,
sesInfo
->
user_name
);
if
(
sesInfo
->
user_name
)
{
dp
=
description
+
strlen
(
description
);
sprintf
(
dp
,
";user=%s"
,
sesInfo
->
user_name
);
}
dp
=
description
+
strlen
(
description
);
sprintf
(
dp
,
";pid=0x%x"
,
current
->
pid
);
...
...
fs/cifs/cifsencrypt.c
View file @
34f598ca
...
...
@@ -420,15 +420,20 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
}
/* convert ses->user_name to unicode and uppercase */
len
=
s
trlen
(
ses
->
user_name
)
;
len
=
s
es
->
user_name
?
strlen
(
ses
->
user_name
)
:
0
;
user
=
kmalloc
(
2
+
(
len
*
2
),
GFP_KERNEL
);
if
(
user
==
NULL
)
{
cERROR
(
1
,
"calc_ntlmv2_hash: user mem alloc failure
\n
"
);
rc
=
-
ENOMEM
;
return
rc
;
}
len
=
cifs_strtoUCS
((
__le16
*
)
user
,
ses
->
user_name
,
len
,
nls_cp
);
UniStrupr
(
user
);
if
(
len
)
{
len
=
cifs_strtoUCS
((
__le16
*
)
user
,
ses
->
user_name
,
len
,
nls_cp
);
UniStrupr
(
user
);
}
else
{
memset
(
user
,
'\0'
,
2
);
}
rc
=
crypto_shash_update
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
(
char
*
)
user
,
2
*
len
);
...
...
fs/cifs/connect.c
View file @
34f598ca
...
...
@@ -38,6 +38,7 @@
#include <asm/processor.h>
#include <linux/inet.h>
#include <linux/module.h>
#include <keys/user-type.h>
#include <net/ipv6.h>
#include "cifspdu.h"
#include "cifsglob.h"
...
...
@@ -225,74 +226,90 @@ static int check2ndT2(struct smb_hdr *pSMB)
static
int
coalesce_t2
(
struct
smb_hdr
*
psecond
,
struct
smb_hdr
*
pTargetSMB
)
{
struct
smb_t2_rsp
*
pSMB
2
=
(
struct
smb_t2_rsp
*
)
psecond
;
struct
smb_t2_rsp
*
pSMB
s
=
(
struct
smb_t2_rsp
*
)
psecond
;
struct
smb_t2_rsp
*
pSMBt
=
(
struct
smb_t2_rsp
*
)
pTargetSMB
;
char
*
data_area_of_t
arge
t
;
char
*
data_area_of_
buf2
;
char
*
data_area_of_t
g
t
;
char
*
data_area_of_
src
;
int
remaining
;
unsigned
int
byte_count
,
total_in_
buf
;
__u16
t
otal_data_size
,
total_in_buf2
;
unsigned
int
byte_count
,
total_in_
tgt
;
__u16
t
gt_total_cnt
,
src_total_cnt
,
total_in_src
;
total_data_size
=
get_unaligned_le16
(
&
pSMBt
->
t2_rsp
.
TotalDataCount
);
src_total_cnt
=
get_unaligned_le16
(
&
pSMBs
->
t2_rsp
.
TotalDataCount
);
tgt_total_cnt
=
get_unaligned_le16
(
&
pSMBt
->
t2_rsp
.
TotalDataCount
);
if
(
t
otal_data_size
!=
get_unaligned_le16
(
&
pSMB2
->
t2_rsp
.
TotalDataCount
))
cFYI
(
1
,
"total data size of primary and secondary t2 differ"
);
if
(
t
gt_total_cnt
!=
src_total_cnt
)
cFYI
(
1
,
"total data count of primary and secondary t2 differ "
"source=%hu target=%hu"
,
src_total_cnt
,
tgt_total_cnt
);
total_in_
buf
=
get_unaligned_le16
(
&
pSMBt
->
t2_rsp
.
DataCount
);
total_in_
tgt
=
get_unaligned_le16
(
&
pSMBt
->
t2_rsp
.
DataCount
);
remaining
=
t
otal_data_size
-
total_in_buf
;
remaining
=
t
gt_total_cnt
-
total_in_tgt
;
if
(
remaining
<
0
)
if
(
remaining
<
0
)
{
cFYI
(
1
,
"Server sent too much data. tgt_total_cnt=%hu "
"total_in_tgt=%hu"
,
tgt_total_cnt
,
total_in_tgt
);
return
-
EPROTO
;
}
if
(
remaining
==
0
)
/* nothing to do, ignore */
if
(
remaining
==
0
)
{
/* nothing to do, ignore */
cFYI
(
1
,
"no more data remains"
);
return
0
;
}
total_in_
buf2
=
get_unaligned_le16
(
&
pSMB2
->
t2_rsp
.
DataCount
);
if
(
remaining
<
total_in_
buf2
)
{
total_in_
src
=
get_unaligned_le16
(
&
pSMBs
->
t2_rsp
.
DataCount
);
if
(
remaining
<
total_in_
src
)
cFYI
(
1
,
"transact2 2nd response contains too much data"
);
}
/* find end of first SMB data area */
data_area_of_t
arge
t
=
(
char
*
)
&
pSMBt
->
hdr
.
Protocol
+
data_area_of_t
g
t
=
(
char
*
)
&
pSMBt
->
hdr
.
Protocol
+
get_unaligned_le16
(
&
pSMBt
->
t2_rsp
.
DataOffset
);
/* validate target area */
data_area_of_buf2
=
(
char
*
)
&
pSMB2
->
hdr
.
Protocol
+
get_unaligned_le16
(
&
pSMB2
->
t2_rsp
.
DataOffset
);
/* validate target area */
data_area_of_src
=
(
char
*
)
&
pSMBs
->
hdr
.
Protocol
+
get_unaligned_le16
(
&
pSMBs
->
t2_rsp
.
DataOffset
);
data_area_of_t
arget
+=
total_in_buf
;
data_area_of_t
gt
+=
total_in_tgt
;
/* copy second buffer into end of first buffer */
total_in_buf
+=
total_in_buf2
;
total_in_tgt
+=
total_in_src
;
/* is the result too big for the field? */
if
(
total_in_buf
>
USHRT_MAX
)
if
(
total_in_tgt
>
USHRT_MAX
)
{
cFYI
(
1
,
"coalesced DataCount too large (%u)"
,
total_in_tgt
);
return
-
EPROTO
;
put_unaligned_le16
(
total_in_buf
,
&
pSMBt
->
t2_rsp
.
DataCount
);
}
put_unaligned_le16
(
total_in_tgt
,
&
pSMBt
->
t2_rsp
.
DataCount
);
/* fix up the BCC */
byte_count
=
get_bcc
(
pTargetSMB
);
byte_count
+=
total_in_
buf2
;
byte_count
+=
total_in_
src
;
/* is the result too big for the field? */
if
(
byte_count
>
USHRT_MAX
)
if
(
byte_count
>
USHRT_MAX
)
{
cFYI
(
1
,
"coalesced BCC too large (%u)"
,
byte_count
);
return
-
EPROTO
;
}
put_bcc
(
byte_count
,
pTargetSMB
);
byte_count
=
be32_to_cpu
(
pTargetSMB
->
smb_buf_length
);
byte_count
+=
total_in_
buf2
;
byte_count
+=
total_in_
src
;
/* don't allow buffer to overflow */
if
(
byte_count
>
CIFSMaxBufSize
+
MAX_CIFS_HDR_SIZE
-
4
)
if
(
byte_count
>
CIFSMaxBufSize
+
MAX_CIFS_HDR_SIZE
-
4
)
{
cFYI
(
1
,
"coalesced BCC exceeds buffer size (%u)"
,
byte_count
);
return
-
ENOBUFS
;
}
pTargetSMB
->
smb_buf_length
=
cpu_to_be32
(
byte_count
);
memcpy
(
data_area_of_target
,
data_area_of_buf2
,
total_in_buf2
);
/* copy second buffer into end of first buffer */
memcpy
(
data_area_of_tgt
,
data_area_of_src
,
total_in_src
);
if
(
remaining
==
total_in_buf2
)
{
cFYI
(
1
,
"found the last secondary response"
);
return
0
;
/* we are done */
}
else
/* more responses to go */
if
(
remaining
!=
total_in_src
)
{
/* more responses to go */
cFYI
(
1
,
"waiting for more secondary responses"
);
return
1
;
}
/* we are done */
cFYI
(
1
,
"found the last secondary response"
);
return
0
;
}
static
void
...
...
@@ -1578,11 +1595,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
}
}
if
(
vol
->
multiuser
&&
!
(
vol
->
secFlg
&
CIFSSEC_MAY_KRB5
))
{
cERROR
(
1
,
"Multiuser mounts currently require krb5 "
"authentication!"
);
#ifndef CONFIG_KEYS
/* Muliuser mounts require CONFIG_KEYS support */
if
(
vol
->
multiuser
)
{
cERROR
(
1
,
"Multiuser mounts require kernels with "
"CONFIG_KEYS enabled."
);
goto
cifs_parse_mount_err
;
}
#endif
if
(
vol
->
UNCip
==
NULL
)
vol
->
UNCip
=
&
vol
->
UNC
[
2
];
...
...
@@ -1981,10 +2001,16 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
return
0
;
break
;
default:
/* NULL username means anonymous session */
if
(
ses
->
user_name
==
NULL
)
{
if
(
!
vol
->
nullauth
)
return
0
;
break
;
}
/* anything else takes username/password */
if
(
ses
->
user_name
==
NULL
)
return
0
;
if
(
strncmp
(
ses
->
user_name
,
vol
->
username
,
if
(
strncmp
(
ses
->
user_name
,
vol
->
username
?
vol
->
username
:
""
,
MAX_USERNAME_SIZE
))
return
0
;
if
(
strlen
(
vol
->
username
)
!=
0
&&
...
...
@@ -2039,6 +2065,132 @@ cifs_put_smb_ses(struct cifs_ses *ses)
cifs_put_tcp_session
(
server
);
}
#ifdef CONFIG_KEYS
/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
/* Populate username and pw fields from keyring if possible */
static
int
cifs_set_cifscreds
(
struct
smb_vol
*
vol
,
struct
cifs_ses
*
ses
)
{
int
rc
=
0
;
char
*
desc
,
*
delim
,
*
payload
;
ssize_t
len
;
struct
key
*
key
;
struct
TCP_Server_Info
*
server
=
ses
->
server
;
struct
sockaddr_in
*
sa
;
struct
sockaddr_in6
*
sa6
;
struct
user_key_payload
*
upayload
;
desc
=
kmalloc
(
CIFSCREDS_DESC_SIZE
,
GFP_KERNEL
);
if
(
!
desc
)
return
-
ENOMEM
;
/* try to find an address key first */
switch
(
server
->
dstaddr
.
ss_family
)
{
case
AF_INET
:
sa
=
(
struct
sockaddr_in
*
)
&
server
->
dstaddr
;
sprintf
(
desc
,
"cifs:a:%pI4"
,
&
sa
->
sin_addr
.
s_addr
);
break
;
case
AF_INET6
:
sa6
=
(
struct
sockaddr_in6
*
)
&
server
->
dstaddr
;
sprintf
(
desc
,
"cifs:a:%pI6c"
,
&
sa6
->
sin6_addr
.
s6_addr
);
break
;
default:
cFYI
(
1
,
"Bad ss_family (%hu)"
,
server
->
dstaddr
.
ss_family
);
rc
=
-
EINVAL
;
goto
out_err
;
}
cFYI
(
1
,
"%s: desc=%s"
,
__func__
,
desc
);
key
=
request_key
(
&
key_type_logon
,
desc
,
""
);
if
(
IS_ERR
(
key
))
{
if
(
!
ses
->
domainName
)
{
cFYI
(
1
,
"domainName is NULL"
);
rc
=
PTR_ERR
(
key
);
goto
out_err
;
}
/* didn't work, try to find a domain key */
sprintf
(
desc
,
"cifs:d:%s"
,
ses
->
domainName
);
cFYI
(
1
,
"%s: desc=%s"
,
__func__
,
desc
);
key
=
request_key
(
&
key_type_logon
,
desc
,
""
);
if
(
IS_ERR
(
key
))
{
rc
=
PTR_ERR
(
key
);
goto
out_err
;
}
}
down_read
(
&
key
->
sem
);
upayload
=
key
->
payload
.
data
;
if
(
IS_ERR_OR_NULL
(
upayload
))
{
rc
=
PTR_ERR
(
key
);
goto
out_key_put
;
}
/* find first : in payload */
payload
=
(
char
*
)
upayload
->
data
;
delim
=
strnchr
(
payload
,
upayload
->
datalen
,
':'
);
cFYI
(
1
,
"payload=%s"
,
payload
);
if
(
!
delim
)
{
cFYI
(
1
,
"Unable to find ':' in payload (datalen=%d)"
,
upayload
->
datalen
);
rc
=
-
EINVAL
;
goto
out_key_put
;
}
len
=
delim
-
payload
;
if
(
len
>
MAX_USERNAME_SIZE
||
len
<=
0
)
{
cFYI
(
1
,
"Bad value from username search (len=%ld)"
,
len
);
rc
=
-
EINVAL
;
goto
out_key_put
;
}
vol
->
username
=
kstrndup
(
payload
,
len
,
GFP_KERNEL
);
if
(
!
vol
->
username
)
{
cFYI
(
1
,
"Unable to allocate %ld bytes for username"
,
len
);
rc
=
-
ENOMEM
;
goto
out_key_put
;
}
cFYI
(
1
,
"%s: username=%s"
,
__func__
,
vol
->
username
);
len
=
key
->
datalen
-
(
len
+
1
);
if
(
len
>
MAX_PASSWORD_SIZE
||
len
<=
0
)
{
cFYI
(
1
,
"Bad len for password search (len=%ld)"
,
len
);
rc
=
-
EINVAL
;
kfree
(
vol
->
username
);
vol
->
username
=
NULL
;
goto
out_key_put
;
}
++
delim
;
vol
->
password
=
kstrndup
(
delim
,
len
,
GFP_KERNEL
);
if
(
!
vol
->
password
)
{
cFYI
(
1
,
"Unable to allocate %ld bytes for password"
,
len
);
rc
=
-
ENOMEM
;
kfree
(
vol
->
username
);
vol
->
username
=
NULL
;
goto
out_key_put
;
}
out_key_put:
up_read
(
&
key
->
sem
);
key_put
(
key
);
out_err:
kfree
(
desc
);
cFYI
(
1
,
"%s: returning %d"
,
__func__
,
rc
);
return
rc
;
}
#else
/* ! CONFIG_KEYS */
static
inline
int
cifs_set_cifscreds
(
struct
smb_vol
*
vol
__attribute__
((
unused
)),
struct
cifs_ses
*
ses
__attribute__
((
unused
)))
{
return
-
ENOSYS
;
}
#endif
/* CONFIG_KEYS */
static
bool
warned_on_ntlm
;
/* globals init to false automatically */
static
struct
cifs_ses
*
...
...
@@ -2914,18 +3066,33 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
/*
* Windows only supports a max of 60k reads. Default to that when posix
* extensions aren't in force.
* Windows only supports a max of 60kb reads and 65535 byte writes. Default to
* those values when posix extensions aren't in force. In actuality here, we
* use 65536 to allow for a write that is a multiple of 4k. Most servers seem
* to be ok with the extra byte even though Windows doesn't send writes that
* are that large.
*
* Citation:
*
* http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
*/
#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
static
unsigned
int
cifs_negotiate_wsize
(
struct
cifs_tcon
*
tcon
,
struct
smb_vol
*
pvolume_info
)
{
__u64
unix_cap
=
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
);
struct
TCP_Server_Info
*
server
=
tcon
->
ses
->
server
;
unsigned
int
wsize
=
pvolume_info
->
wsize
?
pvolume_info
->
wsize
:
CIFS_DEFAULT_IOSIZE
;
unsigned
int
wsize
;
/* start with specified wsize, or default */
if
(
pvolume_info
->
wsize
)
wsize
=
pvolume_info
->
wsize
;
else
if
(
tcon
->
unix_ext
&&
(
unix_cap
&
CIFS_UNIX_LARGE_WRITE_CAP
))
wsize
=
CIFS_DEFAULT_IOSIZE
;
else
wsize
=
CIFS_DEFAULT_NON_POSIX_WSIZE
;
/* can server support 24-bit write sizes? (via UNIX extensions) */
if
(
!
tcon
->
unix_ext
||
!
(
unix_cap
&
CIFS_UNIX_LARGE_WRITE_CAP
))
...
...
@@ -3136,10 +3303,9 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
return
-
EINVAL
;
if
(
volume_info
->
nullauth
)
{
cFYI
(
1
,
"null user"
);
volume_info
->
username
=
kzalloc
(
1
,
GFP_KERNEL
);
if
(
volume_info
->
username
==
NULL
)
return
-
ENOMEM
;
cFYI
(
1
,
"Anonymous login"
);
kfree
(
volume_info
->
username
);
volume_info
->
username
=
NULL
;
}
else
if
(
volume_info
->
username
)
{
/* BB fixme parse for domain name here */
cFYI
(
1
,
"Username: %s"
,
volume_info
->
username
);
...
...
@@ -3657,16 +3823,38 @@ int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
return
rc
;
}
static
int
cifs_set_vol_auth
(
struct
smb_vol
*
vol
,
struct
cifs_ses
*
ses
)
{
switch
(
ses
->
server
->
secType
)
{
case
Kerberos
:
vol
->
secFlg
=
CIFSSEC_MUST_KRB5
;
return
0
;
case
NTLMv2
:
vol
->
secFlg
=
CIFSSEC_MUST_NTLMV2
;
break
;
case
NTLM
:
vol
->
secFlg
=
CIFSSEC_MUST_NTLM
;
break
;
case
RawNTLMSSP
:
vol
->
secFlg
=
CIFSSEC_MUST_NTLMSSP
;
break
;
case
LANMAN
:
vol
->
secFlg
=
CIFSSEC_MUST_LANMAN
;
break
;
}
return
cifs_set_cifscreds
(
vol
,
ses
);
}
static
struct
cifs_tcon
*
cifs_construct_tcon
(
struct
cifs_sb_info
*
cifs_sb
,
uid_t
fsuid
)
{
int
rc
;
struct
cifs_tcon
*
master_tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
struct
cifs_ses
*
ses
;
struct
cifs_tcon
*
tcon
=
NULL
;
struct
smb_vol
*
vol_info
;
char
username
[
28
];
/* big enough for "krb50x" + hex of ULONG_MAX 6+16 */
/* We used to have this as MAX_USERNAME which is */
/* way too big now (256 instead of 32) */
vol_info
=
kzalloc
(
sizeof
(
*
vol_info
),
GFP_KERNEL
);
if
(
vol_info
==
NULL
)
{
...
...
@@ -3674,8 +3862,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
goto
out
;
}
snprintf
(
username
,
sizeof
(
username
),
"krb50x%x"
,
fsuid
);
vol_info
->
username
=
username
;
vol_info
->
local_nls
=
cifs_sb
->
local_nls
;
vol_info
->
linux_uid
=
fsuid
;
vol_info
->
cred_uid
=
fsuid
;
...
...
@@ -3685,8 +3871,11 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
vol_info
->
local_lease
=
master_tcon
->
local_lease
;
vol_info
->
no_linux_ext
=
!
master_tcon
->
unix_ext
;
/* FIXME: allow for other secFlg settings */
vol_info
->
secFlg
=
CIFSSEC_MUST_KRB5
;
rc
=
cifs_set_vol_auth
(
vol_info
,
master_tcon
->
ses
);
if
(
rc
)
{
tcon
=
ERR_PTR
(
rc
);
goto
out
;
}
/* get a reference for the same TCP session */
spin_lock
(
&
cifs_tcp_ses_lock
);
...
...
@@ -3709,6 +3898,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
if
(
ses
->
capabilities
&
CAP_UNIX
)
reset_cifs_unix_caps
(
0
,
tcon
,
NULL
,
vol_info
);
out:
kfree
(
vol_info
->
username
);
kfree
(
vol_info
->
password
);
kfree
(
vol_info
);
return
tcon
;
...
...
include/keys/user-type.h
View file @
34f598ca
...
...
@@ -17,7 +17,7 @@
/*****************************************************************************/
/*
* the payload for a key of type "user"
* the payload for a key of type "user"
or "logon"
* - once filled in and attached to a key:
* - the payload struct is invariant may not be changed, only replaced
* - the payload must be read with RCU procedures or with the key semaphore
...
...
@@ -33,6 +33,7 @@ struct user_key_payload {
};
extern
struct
key_type
key_type_user
;
extern
struct
key_type
key_type_logon
;
extern
int
user_instantiate
(
struct
key
*
key
,
const
void
*
data
,
size_t
datalen
);
extern
int
user_update
(
struct
key
*
key
,
const
void
*
data
,
size_t
datalen
);
...
...
security/keys/internal.h
View file @
34f598ca
...
...
@@ -33,6 +33,7 @@
extern
struct
key_type
key_type_dead
;
extern
struct
key_type
key_type_user
;
extern
struct
key_type
key_type_logon
;
/*****************************************************************************/
/*
...
...
security/keys/key.c
View file @
34f598ca
...
...
@@ -999,6 +999,7 @@ void __init key_init(void)
list_add_tail
(
&
key_type_keyring
.
link
,
&
key_types_list
);
list_add_tail
(
&
key_type_dead
.
link
,
&
key_types_list
);
list_add_tail
(
&
key_type_user
.
link
,
&
key_types_list
);
list_add_tail
(
&
key_type_logon
.
link
,
&
key_types_list
);
/* record the root user tracking */
rb_link_node
(
&
root_key_user
.
node
,
...
...
security/keys/user_defined.c
View file @
34f598ca
...
...
@@ -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
*/
...
...
@@ -189,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
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment