Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
5015f388
Commit
5015f388
authored
Mar 13, 2011
by
Ken Thomases
Committed by
Alexandre Julliard
Mar 14, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
secur32: Add alternative schannel implementation for Mac OS X.
It uses the native Secure Transport API rather than GnuTLS.
parent
25ed687f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
798 additions
and
5 deletions
+798
-5
Makefile.in
dlls/secur32/Makefile.in
+2
-0
schannel.c
dlls/secur32/schannel.c
+3
-3
schannel_gnutls.c
dlls/secur32/schannel_gnutls.c
+2
-2
schannel_macosx.c
dlls/secur32/schannel_macosx.c
+791
-0
No files found.
dlls/secur32/Makefile.in
View file @
5015f388
...
...
@@ -3,6 +3,7 @@ IMPORTLIB = secur32
IMPORTS
=
netapi32 advapi32
DELAYIMPORTS
=
crypt32
EXTRAINCL
=
@GNUTLSINCL@
EXTRALIBS
=
@SECURITYLIB@
C_SRCS
=
\
base64_codec.c
\
...
...
@@ -13,6 +14,7 @@ C_SRCS = \
ntlm.c
\
schannel.c
\
schannel_gnutls.c
\
schannel_macosx.c
\
secur32.c
\
thunks.c
\
util.c
\
...
...
dlls/secur32/schannel.c
View file @
5015f388
...
...
@@ -33,7 +33,7 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
secur32
);
#if
def SONAME_LIBGNUTLS
#if
defined(SONAME_LIBGNUTLS) || defined (HAVE_SECURITY_SECURITY_H)
#define SCHAN_INVALID_HANDLE ~0UL
...
...
@@ -1316,7 +1316,7 @@ void SECUR32_deinitSchannelSP(void)
schan_imp_deinit
();
}
#else
/* SONAME_LIBGNUTLS */
#else
/* SONAME_LIBGNUTLS
|| HAVE_SECURITY_SECURITY_H
*/
void
SECUR32_initSchannelSP
(
void
)
{
...
...
@@ -1325,4 +1325,4 @@ void SECUR32_initSchannelSP(void)
void
SECUR32_deinitSchannelSP
(
void
)
{}
#endif
/* SONAME_LIBGNUTLS */
#endif
/* SONAME_LIBGNUTLS
|| HAVE_SECURITY_SECURITY_H
*/
dlls/secur32/schannel_gnutls.c
View file @
5015f388
...
...
@@ -37,7 +37,7 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
secur32
);
#if
def SONAME_LIBGNUTLS
#if
defined(SONAME_LIBGNUTLS) && !defined(HAVE_SECURITY_SECURITY_H)
static
void
*
libgnutls_handle
;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
...
...
@@ -459,4 +459,4 @@ void schan_imp_deinit(void)
libgnutls_handle
=
NULL
;
}
#endif
/* SONAME_LIBGNUTLS */
#endif
/* SONAME_LIBGNUTLS
&& !HAVE_SECURITY_SECURITY_H
*/
dlls/secur32/schannel_macosx.c
0 → 100644
View file @
5015f388
/*
* Mac OS X Secure Transport implementation of the schannel (SSL/TLS) provider.
*
* Copyright 2005 Juan Lang
* Copyright 2008 Henri Verbeet
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#ifdef HAVE_SECURITY_SECURITY_H
#include <Security/Security.h>
#define GetCurrentThread GetCurrentThread_Mac
#define LoadResource LoadResource_Mac
#include <CoreServices/CoreServices.h>
#undef GetCurrentThread
#undef LoadResource
#undef DPRINTF
#endif
#include "windef.h"
#include "winbase.h"
#include "sspi.h"
#include "schannel.h"
#include "secur32_priv.h"
#include "wine/debug.h"
#include "wine/library.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
secur32
);
#ifdef HAVE_SECURITY_SECURITY_H
struct
mac_session
{
SSLContextRef
context
;
struct
schan_transport
*
transport
;
};
enum
{
schan_proto_SSL
,
schan_proto_TLS
,
};
enum
{
schan_kx_DH_anon_EXPORT
,
schan_kx_DH_anon
,
schan_kx_DH_DSS_EXPORT
,
schan_kx_DH_DSS
,
schan_kx_DH_RSA_EXPORT
,
schan_kx_DH_RSA
,
schan_kx_DHE_DSS_EXPORT
,
schan_kx_DHE_DSS
,
schan_kx_DHE_RSA_EXPORT
,
schan_kx_DHE_RSA
,
schan_kx_ECDH_anon
,
schan_kx_ECDH_ECDSA
,
schan_kx_ECDH_RSA
,
schan_kx_ECDHE_ECDSA
,
schan_kx_ECDHE_RSA
,
schan_kx_FORTEZZA_DMS
,
schan_kx_NULL
,
schan_kx_RSA_EXPORT
,
schan_kx_RSA
,
};
enum
{
schan_enc_3DES_EDE_CBC
,
schan_enc_AES_128_CBC
,
schan_enc_AES_256_CBC
,
schan_enc_DES_CBC
,
schan_enc_DES40_CBC
,
schan_enc_FORTEZZA_CBC
,
schan_enc_IDEA_CBC
,
schan_enc_NULL
,
schan_enc_RC2_CBC
,
schan_enc_RC2_CBC_40
,
schan_enc_RC4_128
,
schan_enc_RC4_40
,
};
enum
{
schan_mac_MD5
,
schan_mac_NULL
,
schan_mac_SHA
,
};
struct
cipher_suite
{
SSLCipherSuite
suite
;
int
protocol
;
int
kx_alg
;
int
enc_alg
;
int
mac_alg
;
};
/* This table corresponds to the enum in <Security/CipherSuite.h>. */
static
const
struct
cipher_suite
cipher_suites
[]
=
{
#define CIPHER_SUITE(p, kx, enc, mac) { p##_##kx##_WITH_##enc##_##mac, schan_proto_##p, \
schan_kx_##kx, schan_enc_##enc, schan_mac_##mac }
CIPHER_SUITE
(
SSL
,
RSA
,
NULL
,
MD5
),
CIPHER_SUITE
(
SSL
,
RSA
,
NULL
,
MD5
),
CIPHER_SUITE
(
SSL
,
RSA
,
NULL
,
SHA
),
CIPHER_SUITE
(
SSL
,
RSA_EXPORT
,
RC4_40
,
MD5
),
CIPHER_SUITE
(
SSL
,
RSA
,
RC4_128
,
MD5
),
CIPHER_SUITE
(
SSL
,
RSA
,
RC4_128
,
SHA
),
CIPHER_SUITE
(
SSL
,
RSA_EXPORT
,
RC2_CBC_40
,
MD5
),
CIPHER_SUITE
(
SSL
,
RSA
,
IDEA_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
RSA_EXPORT
,
DES40_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
RSA
,
DES_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
RSA
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_DSS_EXPORT
,
DES40_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_DSS
,
DES_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_DSS
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_RSA_EXPORT
,
DES40_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_RSA
,
DES_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_RSA
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DHE_DSS_EXPORT
,
DES40_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DHE_DSS
,
DES_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DHE_DSS
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DHE_RSA_EXPORT
,
DES40_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DHE_RSA
,
DES_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DHE_RSA
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_anon_EXPORT
,
RC4_40
,
MD5
),
CIPHER_SUITE
(
SSL
,
DH_anon
,
RC4_128
,
MD5
),
CIPHER_SUITE
(
SSL
,
DH_anon_EXPORT
,
DES40_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_anon
,
DES_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
DH_anon
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
SSL
,
FORTEZZA_DMS
,
NULL
,
SHA
),
CIPHER_SUITE
(
SSL
,
FORTEZZA_DMS
,
FORTEZZA_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
RSA
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DH_DSS
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DH_RSA
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DHE_DSS
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DHE_RSA
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DH_anon
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
RSA
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DH_DSS
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DH_RSA
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DHE_DSS
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DHE_RSA
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
DH_anon
,
AES_256_CBC
,
SHA
),
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
CIPHER_SUITE
(
TLS
,
ECDH_ECDSA
,
NULL
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_ECDSA
,
RC4_128
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_ECDSA
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_ECDSA
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_ECDSA
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_ECDSA
,
NULL
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_ECDSA
,
RC4_128
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_ECDSA
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_ECDSA
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_ECDSA
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_RSA
,
NULL
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_RSA
,
RC4_128
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_RSA
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_RSA
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_RSA
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_RSA
,
NULL
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_RSA
,
RC4_128
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_RSA
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_RSA
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDHE_RSA
,
AES_256_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_anon
,
NULL
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_anon
,
RC4_128
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_anon
,
3
DES_EDE_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_anon
,
AES_128_CBC
,
SHA
),
CIPHER_SUITE
(
TLS
,
ECDH_anon
,
AES_256_CBC
,
SHA
),
#endif
CIPHER_SUITE
(
SSL
,
RSA
,
RC2_CBC
,
MD5
),
CIPHER_SUITE
(
SSL
,
RSA
,
IDEA_CBC
,
MD5
),
CIPHER_SUITE
(
SSL
,
RSA
,
DES_CBC
,
MD5
),
CIPHER_SUITE
(
SSL
,
RSA
,
3
DES_EDE_CBC
,
MD5
),
#undef CIPHER_SUITE
};
static
const
struct
cipher_suite
*
get_cipher_suite
(
SSLCipherSuite
cipher_suite
)
{
int
i
;
for
(
i
=
0
;
i
<
sizeof
(
cipher_suites
)
/
sizeof
(
cipher_suites
[
0
]);
i
++
)
{
if
(
cipher_suites
[
i
].
suite
==
cipher_suite
)
return
&
cipher_suites
[
i
];
}
return
NULL
;
}
static
DWORD
schan_get_session_protocol
(
struct
mac_session
*
s
)
{
SSLProtocol
protocol
;
OSStatus
status
;
TRACE
(
"(%p/%p)
\n
"
,
s
,
s
->
context
);
status
=
SSLGetNegotiatedProtocolVersion
(
s
->
context
,
&
protocol
);
if
(
status
!=
noErr
)
{
ERR
(
"Failed to get session protocol: %ld
\n
"
,
status
);
return
0
;
}
TRACE
(
"protocol %d
\n
"
,
protocol
);
switch
(
protocol
)
{
case
kSSLProtocol2
:
return
SP_PROT_SSL2_CLIENT
;
case
kSSLProtocol3
:
return
SP_PROT_SSL3_CLIENT
;
case
kTLSProtocol1
:
return
SP_PROT_TLS1_CLIENT
;
default:
FIXME
(
"unknown protocol %d
\n
"
,
protocol
);
return
0
;
}
}
static
ALG_ID
schan_get_cipher_algid
(
const
struct
cipher_suite
*
c
)
{
TRACE
(
"(%#x)
\n
"
,
(
unsigned
int
)
c
->
suite
);
switch
(
c
->
enc_alg
)
{
case
schan_enc_3DES_EDE_CBC
:
return
CALG_3DES
;
case
schan_enc_AES_128_CBC
:
return
CALG_AES_128
;
case
schan_enc_AES_256_CBC
:
return
CALG_AES_256
;
case
schan_enc_DES_CBC
:
return
CALG_DES
;
case
schan_enc_DES40_CBC
:
return
CALG_DES
;
case
schan_enc_NULL
:
return
0
;
case
schan_enc_RC2_CBC_40
:
return
CALG_RC2
;
case
schan_enc_RC2_CBC
:
return
CALG_RC2
;
case
schan_enc_RC4_128
:
return
CALG_RC4
;
case
schan_enc_RC4_40
:
return
CALG_RC4
;
case
schan_enc_FORTEZZA_CBC
:
case
schan_enc_IDEA_CBC
:
FIXME
(
"Don't know CALG for encryption algorithm %d, returning 0
\n
"
,
c
->
enc_alg
);
return
0
;
default:
FIXME
(
"Unknown encryption algorithm %d for cipher suite %#x, returning 0
\n
"
,
c
->
enc_alg
,
(
unsigned
int
)
c
->
suite
);
return
0
;
}
}
static
unsigned
int
schan_get_cipher_key_size
(
const
struct
cipher_suite
*
c
)
{
TRACE
(
"(%#x)
\n
"
,
(
unsigned
int
)
c
->
suite
);
switch
(
c
->
enc_alg
)
{
case
schan_enc_3DES_EDE_CBC
:
return
168
;
case
schan_enc_AES_128_CBC
:
return
128
;
case
schan_enc_AES_256_CBC
:
return
256
;
case
schan_enc_DES_CBC
:
return
56
;
case
schan_enc_DES40_CBC
:
return
40
;
case
schan_enc_NULL
:
return
0
;
case
schan_enc_RC2_CBC_40
:
return
40
;
case
schan_enc_RC2_CBC
:
return
128
;
case
schan_enc_RC4_128
:
return
128
;
case
schan_enc_RC4_40
:
return
40
;
case
schan_enc_FORTEZZA_CBC
:
case
schan_enc_IDEA_CBC
:
FIXME
(
"Don't know key size for encryption algorithm %d, returning 0
\n
"
,
c
->
enc_alg
);
return
0
;
default:
FIXME
(
"Unknown encryption algorithm %d for cipher suite %#x, returning 0
\n
"
,
c
->
enc_alg
,
(
unsigned
int
)
c
->
suite
);
return
0
;
}
}
static
ALG_ID
schan_get_mac_algid
(
const
struct
cipher_suite
*
c
)
{
TRACE
(
"(%#x)
\n
"
,
(
unsigned
int
)
c
->
suite
);
switch
(
c
->
mac_alg
)
{
case
schan_mac_MD5
:
return
CALG_MD5
;
case
schan_mac_NULL
:
return
0
;
case
schan_mac_SHA
:
return
CALG_SHA
;
default:
FIXME
(
"Unknown hashing algorithm %d for cipher suite %#x, returning 0
\n
"
,
c
->
mac_alg
,
(
unsigned
)
c
->
suite
);
return
0
;
}
}
static
unsigned
int
schan_get_mac_key_size
(
const
struct
cipher_suite
*
c
)
{
TRACE
(
"(%#x)
\n
"
,
(
unsigned
int
)
c
->
suite
);
switch
(
c
->
mac_alg
)
{
case
schan_mac_MD5
:
return
128
;
case
schan_mac_NULL
:
return
0
;
case
schan_mac_SHA
:
return
160
;
default:
FIXME
(
"Unknown hashing algorithm %d for cipher suite %#x, returning 0
\n
"
,
c
->
mac_alg
,
(
unsigned
)
c
->
suite
);
return
0
;
}
}
static
ALG_ID
schan_get_kx_algid
(
const
struct
cipher_suite
*
c
)
{
TRACE
(
"(%#x)
\n
"
,
(
unsigned
int
)
c
->
suite
);
switch
(
c
->
kx_alg
)
{
case
schan_kx_DHE_DSS_EXPORT
:
case
schan_kx_DHE_DSS
:
case
schan_kx_DHE_RSA_EXPORT
:
case
schan_kx_DHE_RSA
:
return
CALG_DH_EPHEM
;
case
schan_kx_NULL
:
return
0
;
case
schan_kx_RSA
:
return
CALG_RSA_KEYX
;
case
schan_kx_DH_anon_EXPORT
:
case
schan_kx_DH_anon
:
case
schan_kx_DH_DSS_EXPORT
:
case
schan_kx_DH_DSS
:
case
schan_kx_DH_RSA_EXPORT
:
case
schan_kx_DH_RSA
:
case
schan_kx_ECDH_anon
:
case
schan_kx_ECDH_ECDSA
:
case
schan_kx_ECDH_RSA
:
case
schan_kx_ECDHE_ECDSA
:
case
schan_kx_ECDHE_RSA
:
case
schan_kx_FORTEZZA_DMS
:
case
schan_kx_RSA_EXPORT
:
FIXME
(
"Don't know CALG for key exchange algorithm %d for cipher suite %#x, returning 0
\n
"
,
c
->
kx_alg
,
(
unsigned
)
c
->
suite
);
return
0
;
default:
FIXME
(
"Unknown key exchange algorithm %d for cipher suite %#x, returning 0
\n
"
,
c
->
kx_alg
,
(
unsigned
)
c
->
suite
);
return
0
;
}
}
/* schan_pull_adapter
* Callback registered with SSLSetIOFuncs as the read function for a
* session. Reads data from the session connection. Conforms to the
* SSLReadFunc type.
*
* transport - The session connection
* buff - The buffer into which to store the read data. Must be at least
* *buff_len bytes in length.
* *buff_len - On input, the desired length to read. On successful return,
* the number of bytes actually read.
*
* Returns:
* noErr on complete success meaning the requested length was successfully
* read.
* errSSLWouldBlock when the requested length could not be read without
* blocking. *buff_len indicates how much was actually read. The
* caller should try again if/when they want to read more.
* errSSLClosedGraceful when the connection has closed and there's no
* more data to be read.
* other error code for failure.
*/
static
OSStatus
schan_pull_adapter
(
SSLConnectionRef
transport
,
void
*
buff
,
size_t
*
buff_len
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
transport
;
size_t
requested
=
*
buff_len
;
int
status
;
OSStatus
ret
;
TRACE
(
"(%p/%p, %p, %p/%lu)
\n
"
,
s
,
s
->
transport
,
buff
,
buff_len
,
(
unsigned
long
)
*
buff_len
);
status
=
schan_pull
(
s
->
transport
,
buff
,
buff_len
);
if
(
status
==
0
)
{
if
(
*
buff_len
==
0
)
{
TRACE
(
"Connection closed
\n
"
);
ret
=
errSSLClosedGraceful
;
}
else
if
(
*
buff_len
<
requested
)
{
TRACE
(
"Pulled %lu bytes before would block
\n
"
,
(
unsigned
long
)
*
buff_len
);
ret
=
errSSLWouldBlock
;
}
else
{
TRACE
(
"Pulled %lu bytes
\n
"
,
(
unsigned
long
)
*
buff_len
);
ret
=
noErr
;
}
}
else
if
(
status
==
EAGAIN
)
{
TRACE
(
"Would block before being able to pull anything
\n
"
);
ret
=
errSSLWouldBlock
;
}
else
{
FIXME
(
"Unknown status code from schan_pull: %d
\n
"
,
status
);
ret
=
ioErr
;
}
return
ret
;
}
/* schan_push_adapter
* Callback registered with SSLSetIOFuncs as the write function for a
* session. Writes data to the session connection. Conforms to the
* SSLWriteFunc type.
*
* transport - The session connection
* buff - The buffer of data to write. Must be at least *buff_len bytes in length.
* *buff_len - On input, the desired length to write. On successful return,
* the number of bytes actually written.
*
* Returns:
* noErr on complete or partial success; *buff_len indicates how much data
* was actually written, which may be less than requrested.
* errSSLWouldBlock when no data could be written without blocking. The
* caller should try again.
* other error code for failure.
*/
static
OSStatus
schan_push_adapter
(
SSLConnectionRef
transport
,
const
void
*
buff
,
size_t
*
buff_len
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
transport
;
int
status
;
OSStatus
ret
;
TRACE
(
"(%p/%p, %p, %p/%lu)
\n
"
,
s
,
s
->
transport
,
buff
,
buff_len
,
(
unsigned
long
)
*
buff_len
);
status
=
schan_push
(
s
->
transport
,
buff
,
buff_len
);
if
(
status
==
0
)
{
TRACE
(
"Pushed %lu bytes
\n
"
,
(
unsigned
long
)
*
buff_len
);
ret
=
noErr
;
}
else
if
(
status
==
EAGAIN
)
{
TRACE
(
"Would block before being able to push anything
\n
"
);
ret
=
errSSLWouldBlock
;
}
else
{
FIXME
(
"Unknown status code from schan_push: %d
\n
"
,
status
);
ret
=
ioErr
;
}
return
ret
;
}
BOOL
schan_imp_create_session
(
schan_imp_session
*
session
,
BOOL
is_server
,
schan_imp_certificate_credentials
cred
)
{
struct
mac_session
*
s
;
OSStatus
status
;
TRACE
(
"(%p, %d)
\n
"
,
session
,
is_server
);
s
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
s
));
if
(
!
s
)
return
FALSE
;
status
=
SSLNewContext
(
is_server
,
&
s
->
context
);
if
(
status
!=
noErr
)
{
ERR
(
"Failed to create session context: %ld
\n
"
,
(
long
)
status
);
goto
fail
;
}
status
=
SSLSetConnection
(
s
->
context
,
s
);
if
(
status
!=
noErr
)
{
ERR
(
"Failed to set session connection: %ld
\n
"
,
(
long
)
status
);
goto
fail
;
}
status
=
SSLSetEnableCertVerify
(
s
->
context
,
FALSE
);
if
(
status
!=
noErr
)
{
ERR
(
"Failed to disable certificate verification: %ld
\n
"
,
(
long
)
status
);
goto
fail
;
}
status
=
SSLSetProtocolVersionEnabled
(
s
->
context
,
kSSLProtocol2
,
FALSE
);
if
(
status
!=
noErr
)
{
ERR
(
"Failed to disable SSL version 2: %ld
\n
"
,
(
long
)
status
);
goto
fail
;
}
status
=
SSLSetIOFuncs
(
s
->
context
,
schan_pull_adapter
,
schan_push_adapter
);
if
(
status
!=
noErr
)
{
ERR
(
"Failed to set session I/O funcs: %ld
\n
"
,
(
long
)
status
);
goto
fail
;
}
TRACE
(
" -> %p/%p
\n
"
,
s
,
s
->
context
);
*
session
=
(
schan_imp_session
)
s
;
return
TRUE
;
fail:
HeapFree
(
GetProcessHeap
(),
0
,
s
);
return
FALSE
;
}
void
schan_imp_dispose_session
(
schan_imp_session
session
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
session
;
OSStatus
status
;
TRACE
(
"(%p/%p)
\n
"
,
s
,
s
->
context
);
status
=
SSLDisposeContext
(
s
->
context
);
if
(
status
!=
noErr
)
ERR
(
"Failed to dispose of session context: %ld
\n
"
,
status
);
HeapFree
(
GetProcessHeap
(),
0
,
s
);
}
void
schan_imp_set_session_transport
(
schan_imp_session
session
,
struct
schan_transport
*
t
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
session
;
TRACE
(
"(%p/%p, %p)
\n
"
,
s
,
s
->
context
,
t
);
s
->
transport
=
t
;
}
SECURITY_STATUS
schan_imp_handshake
(
schan_imp_session
session
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
session
;
OSStatus
status
;
TRACE
(
"(%p/%p)
\n
"
,
s
,
s
->
context
);
status
=
SSLHandshake
(
s
->
context
);
if
(
status
==
noErr
)
{
TRACE
(
"Handshake completed
\n
"
);
return
SEC_E_OK
;
}
else
if
(
status
==
errSSLWouldBlock
)
{
TRACE
(
"Continue...
\n
"
);
return
SEC_I_CONTINUE_NEEDED
;
}
else
if
(
errSecErrnoBase
<=
status
&&
status
<=
errSecErrnoLimit
)
{
ERR
(
"Handshake failed: %s
\n
"
,
strerror
(
status
));
return
SEC_E_INTERNAL_ERROR
;
}
else
{
ERR
(
"Handshake failed: %ld
\n
"
,
(
long
)
status
);
cssmPerror
(
"SSLHandshake"
,
status
);
return
SEC_E_INTERNAL_ERROR
;
}
/* Never reached */
return
SEC_E_OK
;
}
unsigned
int
schan_imp_get_session_cipher_block_size
(
schan_imp_session
session
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
session
;
SSLCipherSuite
cipherSuite
;
const
struct
cipher_suite
*
c
;
OSStatus
status
;
TRACE
(
"(%p/%p)
\n
"
,
s
,
s
->
context
);
status
=
SSLGetNegotiatedCipher
(
s
->
context
,
&
cipherSuite
);
if
(
status
!=
noErr
)
{
ERR
(
"Failed to get session cipher suite: %ld
\n
"
,
status
);
return
0
;
}
c
=
get_cipher_suite
(
cipherSuite
);
if
(
!
c
)
{
ERR
(
"Unknown session cipher suite: %#x
\n
"
,
(
unsigned
int
)
cipherSuite
);
return
0
;
}
switch
(
c
->
enc_alg
)
{
case
schan_enc_3DES_EDE_CBC
:
return
64
;
case
schan_enc_AES_128_CBC
:
return
128
;
case
schan_enc_AES_256_CBC
:
return
128
;
case
schan_enc_DES_CBC
:
return
64
;
case
schan_enc_DES40_CBC
:
return
64
;
case
schan_enc_NULL
:
return
0
;
case
schan_enc_RC2_CBC_40
:
return
64
;
case
schan_enc_RC2_CBC
:
return
64
;
case
schan_enc_RC4_128
:
return
0
;
case
schan_enc_RC4_40
:
return
0
;
case
schan_enc_FORTEZZA_CBC
:
case
schan_enc_IDEA_CBC
:
FIXME
(
"Don't know block size for encryption algorithm %d, returning 0
\n
"
,
c
->
enc_alg
);
return
0
;
default:
FIXME
(
"Unknown encryption algorithm %d for cipher suite %#x, returning 0
\n
"
,
c
->
enc_alg
,
(
unsigned
int
)
c
->
suite
);
return
0
;
}
}
SECURITY_STATUS
schan_imp_get_connection_info
(
schan_imp_session
session
,
SecPkgContext_ConnectionInfo
*
info
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
session
;
SSLCipherSuite
cipherSuite
;
const
struct
cipher_suite
*
c
;
OSStatus
status
;
TRACE
(
"(%p/%p, %p)
\n
"
,
s
,
s
->
context
,
info
);
status
=
SSLGetNegotiatedCipher
(
s
->
context
,
&
cipherSuite
);
if
(
status
!=
noErr
)
{
ERR
(
"Failed to get session cipher suite: %ld
\n
"
,
status
);
return
SEC_E_INTERNAL_ERROR
;
}
c
=
get_cipher_suite
(
cipherSuite
);
if
(
!
c
)
{
ERR
(
"Unknown session cipher suite: %#x
\n
"
,
(
unsigned
int
)
cipherSuite
);
return
SEC_E_INTERNAL_ERROR
;
}
info
->
dwProtocol
=
schan_get_session_protocol
(
s
);
info
->
aiCipher
=
schan_get_cipher_algid
(
c
);
info
->
dwCipherStrength
=
schan_get_cipher_key_size
(
c
);
info
->
aiHash
=
schan_get_mac_algid
(
c
);
info
->
dwHashStrength
=
schan_get_mac_key_size
(
c
);
info
->
aiExch
=
schan_get_kx_algid
(
c
);
/* FIXME: info->dwExchStrength? */
info
->
dwExchStrength
=
0
;
return
SEC_E_OK
;
}
SECURITY_STATUS
schan_imp_get_session_peer_certificate
(
schan_imp_session
session
,
PCCERT_CONTEXT
*
cert
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
session
;
SECURITY_STATUS
ret
=
SEC_E_INTERNAL_ERROR
;
CFArrayRef
certs
;
OSStatus
status
;
TRACE
(
"(%p/%p, %p)
\n
"
,
s
,
s
->
context
,
cert
);
status
=
SSLCopyPeerCertificates
(
s
->
context
,
&
certs
);
if
(
status
==
noErr
&&
certs
)
{
SecCertificateRef
mac_cert
;
CFDataRef
data
;
if
(
CFArrayGetCount
(
certs
)
&&
(
mac_cert
=
(
SecCertificateRef
)
CFArrayGetValueAtIndex
(
certs
,
0
))
&&
(
SecKeychainItemExport
(
mac_cert
,
kSecFormatX509Cert
,
0
,
NULL
,
&
data
)
==
noErr
))
{
*
cert
=
CertCreateCertificateContext
(
X509_ASN_ENCODING
,
CFDataGetBytePtr
(
data
),
CFDataGetLength
(
data
));
if
(
*
cert
)
ret
=
SEC_E_OK
;
else
{
ret
=
GetLastError
();
WARN
(
"CertCreateCertificateContext failed: %x
\n
"
,
ret
);
}
CFRelease
(
data
);
}
else
WARN
(
"Couldn't extract certificate data
\n
"
);
CFRelease
(
certs
);
}
else
WARN
(
"SSLCopyPeerCertificates failed: %ld
\n
"
,
(
long
)
status
);
return
ret
;
}
SECURITY_STATUS
schan_imp_send
(
schan_imp_session
session
,
const
void
*
buffer
,
size_t
*
length
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
session
;
OSStatus
status
;
TRACE
(
"(%p/%p, %p, %p/%lu)
\n
"
,
s
,
s
->
context
,
buffer
,
length
,
(
unsigned
long
)
*
length
);
status
=
SSLWrite
(
s
->
context
,
buffer
,
*
length
,
length
);
if
(
status
==
noErr
)
TRACE
(
"Wrote %lu bytes
\n
"
,
(
unsigned
long
)
*
length
);
else
if
(
status
==
errSSLWouldBlock
)
{
if
(
!*
length
)
{
TRACE
(
"Would block before being able to write anything
\n
"
);
return
SEC_I_CONTINUE_NEEDED
;
}
else
TRACE
(
"Wrote %lu bytes before would block
\n
"
,
(
unsigned
long
)
*
length
);
}
else
{
WARN
(
"SSLWrite failed: %ld
\n
"
,
(
long
)
status
);
return
SEC_E_INTERNAL_ERROR
;
}
return
SEC_E_OK
;
}
SECURITY_STATUS
schan_imp_recv
(
schan_imp_session
session
,
void
*
buffer
,
size_t
*
length
)
{
struct
mac_session
*
s
=
(
struct
mac_session
*
)
session
;
OSStatus
status
;
TRACE
(
"(%p/%p, %p, %p/%lu)
\n
"
,
s
,
s
->
context
,
buffer
,
length
,
(
unsigned
long
)
*
length
);
status
=
SSLRead
(
s
->
context
,
buffer
,
*
length
,
length
);
if
(
status
==
noErr
)
TRACE
(
"Read %lu bytes
\n
"
,
(
unsigned
long
)
*
length
);
else
if
(
status
==
errSSLWouldBlock
)
{
if
(
!*
length
)
{
TRACE
(
"Would block before being able to read anything
\n
"
);
return
SEC_I_CONTINUE_NEEDED
;
}
else
TRACE
(
"Read %lu bytes before would block
\n
"
,
(
unsigned
long
)
*
length
);
}
else
{
WARN
(
"SSLRead failed: %ld
\n
"
,
(
long
)
status
);
return
SEC_E_INTERNAL_ERROR
;
}
return
SEC_E_OK
;
}
BOOL
schan_imp_allocate_certificate_credentials
(
schan_imp_certificate_credentials
*
c
)
{
/* The certificate is never really used for anything. */
*
c
=
NULL
;
return
TRUE
;
}
void
schan_imp_free_certificate_credentials
(
schan_imp_certificate_credentials
c
)
{
}
BOOL
schan_imp_init
(
void
)
{
TRACE
(
"()
\n
"
);
return
TRUE
;
}
void
schan_imp_deinit
(
void
)
{
TRACE
(
"()
\n
"
);
}
#endif
/* HAVE_SECURITY_SECURITY_H */
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