Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
SSPI-sample
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
Vadim Kazakov
SSPI-sample
Commits
358649bc
Commit
358649bc
authored
Dec 07, 2024
by
X1pster
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial commit
parents
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1609 additions
and
0 deletions
+1609
-0
SspiExample.h
SspiExample.h
+73
-0
sspi-client.c
sspi-client.c
+766
-0
sspi-server.c
sspi-server.c
+770
-0
No files found.
SspiExample.h
0 → 100644
View file @
358649bc
// SspiExample.h
#include <sspi.h>
#include <windows.h>
BOOL
SendMsg
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
);
BOOL
ReceiveMsg
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
,
DWORD
*
pcbRead
);
BOOL
SendBytes
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
);
BOOL
ReceiveBytes
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
,
DWORD
*
pcbRead
);
void
cleanup
();
BOOL
GenClientContext
(
BYTE
*
pIn
,
DWORD
cbIn
,
BYTE
*
pOut
,
DWORD
*
pcbOut
,
BOOL
*
pfDone
,
CHAR
*
pszTarget
,
CredHandle
*
hCred
,
struct
_SecHandle
*
hcText
);
BOOL
GenServerContext
(
BYTE
*
pIn
,
DWORD
cbIn
,
BYTE
*
pOut
,
DWORD
*
pcbOut
,
BOOL
*
pfDone
,
BOOL
fNewCredential
);
BOOL
EncryptThis
(
PBYTE
pMessage
,
ULONG
cbMessage
,
BYTE
**
ppOutput
,
LPDWORD
pcbOutput
,
ULONG
securityTrailer
);
PBYTE
DecryptThis
(
PBYTE
achData
,
LPDWORD
pcbMessage
,
struct
_SecHandle
*
hCtxt
,
ULONG
cbSecurityTrailer
);
BOOL
SignThis
(
PBYTE
pMessage
,
ULONG
cbMessage
,
BYTE
**
ppOutput
,
LPDWORD
pcbOutput
);
PBYTE
VerifyThis
(
PBYTE
pBuffer
,
LPDWORD
pcbMessage
,
struct
_SecHandle
*
hCtxt
,
ULONG
cbMaxSignature
);
void
PrintHexDump
(
DWORD
length
,
PBYTE
buffer
);
BOOL
ConnectAuthSocket
(
SOCKET
*
s
,
CredHandle
*
hCred
,
struct
_SecHandle
*
hcText
);
BOOL
CloseAuthSocket
(
SOCKET
s
);
BOOL
DoAuthentication
(
SOCKET
s
);
void
MyHandleError
(
char
*
s
);
sspi-client.c
0 → 100644
View file @
358649bc
//--------------------------------------------------------------------
// Client-side program to establish an SSPI socket connection
// with a server and exchange messages.
//--------------------------------------------------------------------
// Define macros and constants.
#define SECURITY_WIN32
#define BIG_BUFF 2048
#define SEC_SUCCESS(Status) ((Status) >= 0)
#define g_usPort 2000
#define cbMaxMessage 12000
#define MessageAttribute ISC_REQ_CONFIDENTIALITY
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
#include <schannel.h>
#include <Security.h>
#include "SspiExample.h"
CredHandle
hCred
;
struct
_SecHandle
hcText
;
// The following #define statement must be changed. ServerName must
// be defined as the name of the computer running the server sample.
// TargetName must be defined as the logon name of the user running
// the server program.
#define ServerName "Server_Computer_Name"
#define TargetName "Server_User_Logon_Name"
void
main
()
{
SOCKET
Client_Socket
;
BYTE
Data
[
BIG_BUFF
];
PCHAR
pMessage
;
WSADATA
wsaData
;
CredHandle
hCred
;
struct
_SecHandle
hCtxt
;
SECURITY_STATUS
ss
;
DWORD
cbRead
;
ULONG
cbMaxSignature
;
ULONG
cbSecurityTrailer
;
SecPkgContext_Sizes
SecPkgContextSizes
;
SecPkgContext_NegotiationInfo
SecPkgNegInfo
;
BOOL
DoAuthentication
(
SOCKET
s
);
//-------------------------------------------------------------------
// Initialize the socket and the SSP security package.
if
(
WSAStartup
(
0x0101
,
&
wsaData
))
{
MyHandleError
(
"Could not initialize winsock "
);
}
//--------------------------------------------------------------------
// Connect to a server.
if
(
!
ConnectAuthSocket
(
&
Client_Socket
,
&
hCred
,
&
hcText
))
{
MyHandleError
(
"Authenticated server connection "
);
}
//--------------------------------------------------------------------
// An authenticated session with a server has been established.
// Receive and manage a message from the server.
// First, find and display the name of the negotiated
// SSP and the size of the signature and the encryption
// trailer blocks for this SSP.
ss
=
QueryContextAttributes
(
&
hcText
,
SECPKG_ATTR_NEGOTIATION_INFO
,
&
SecPkgNegInfo
);
if
(
!
SEC_SUCCESS
(
ss
))
{
MyHandleError
(
"QueryContextAttributes failed "
);
}
else
{
printf
(
"Package Name: %s
\n
"
,
SecPkgNegInfo
.
PackageInfo
->
Name
);
}
ss
=
QueryContextAttributes
(
&
hcText
,
SECPKG_ATTR_SIZES
,
&
SecPkgContextSizes
);
if
(
!
SEC_SUCCESS
(
ss
))
{
MyHandleError
(
"Query context "
);
}
cbMaxSignature
=
SecPkgContextSizes
.
cbMaxSignature
;
cbSecurityTrailer
=
SecPkgContextSizes
.
cbSecurityTrailer
;
printf
(
"InitializeSecurityContext result = 0x%08x
\n
"
,
ss
);
//--------------------------------------------------------------------
// Decrypt and display the message from the server.
if
(
!
ReceiveBytes
(
Client_Socket
,
Data
,
BIG_BUFF
,
&
cbRead
))
{
MyHandleError
(
"No response from server "
);
}
if
(
0
==
cbRead
)
{
MyHandleError
(
"Zero bytes received "
);
}
pMessage
=
(
PCHAR
)
DecryptThis
(
Data
,
&
cbRead
,
&
hcText
,
cbSecurityTrailer
);
printf
(
"The message from the server is
\n
-> %.*s
\n
"
,
cbRead
,
pMessage
);
//--------------------------------------------------------------------
// Terminate socket and security package.
DeleteSecurityContext
(
&
hcText
);
FreeCredentialHandle
(
&
hCred
);
shutdown
(
Client_Socket
,
2
);
closesocket
(
Client_Socket
);
if
(
SOCKET_ERROR
==
WSACleanup
())
{
MyHandleError
(
"Problem with socket cleanup "
);
}
exit
(
EXIT_SUCCESS
);
}
// end main
//--------------------------------------------------------------------
// ConnectAuthSocket establishes an authenticated socket connection
// with a server and initializes needed security package resources.
BOOL
ConnectAuthSocket
(
SOCKET
*
s
,
CredHandle
*
hCred
,
struct
_SecHandle
*
hcText
)
{
unsigned
long
ulAddress
;
struct
hostent
*
pHost
;
SOCKADDR_IN
sin
;
//--------------------------------------------------------------------
// Lookup the server's address.
ulAddress
=
inet_addr
(
ServerName
);
if
(
INADDR_NONE
==
ulAddress
)
{
pHost
=
gethostbyname
(
ServerName
);
if
(
NULL
==
pHost
)
{
MyHandleError
(
"Unable to resolve host name "
);
}
memcpy
((
char
FAR
*
)
&
ulAddress
,
pHost
->
h_addr
,
pHost
->
h_length
);
}
//--------------------------------------------------------------------
// Create the socket.
*
s
=
socket
(
PF_INET
,
SOCK_STREAM
,
0
);
if
(
INVALID_SOCKET
==
*
s
)
{
MyHandleError
(
"Unable to create socket"
);
}
else
{
printf
(
"Socket created.
\n
"
);
}
sin
.
sin_family
=
AF_INET
;
sin
.
sin_addr
.
s_addr
=
ulAddress
;
sin
.
sin_port
=
htons
(
g_usPort
);
//--------------------------------------------------------------------
// Connect to the server.
if
(
connect
(
*
s
,
(
LPSOCKADDR
)
&
sin
,
sizeof
(
sin
)))
{
closesocket
(
*
s
);
MyHandleError
(
"Connect failed "
);
}
//--------------------------------------------------------------------
// Authenticate the connection.
if
(
!
DoAuthentication
(
*
s
))
{
closesocket
(
*
s
);
MyHandleError
(
"Authentication "
);
}
return
(
TRUE
);
}
// end ConnectAuthSocket
BOOL
DoAuthentication
(
SOCKET
s
)
{
BOOL
fDone
=
FALSE
;
DWORD
cbOut
=
0
;
DWORD
cbIn
=
0
;
PBYTE
pInBuf
;
PBYTE
pOutBuf
;
if
(
!
(
pInBuf
=
(
PBYTE
)
malloc
(
cbMaxMessage
)))
{
MyHandleError
(
"Memory allocation "
);
}
if
(
!
(
pOutBuf
=
(
PBYTE
)
malloc
(
cbMaxMessage
)))
{
MyHandleError
(
"Memory allocation "
);
}
cbOut
=
cbMaxMessage
;
if
(
!
GenClientContext
(
NULL
,
0
,
pOutBuf
,
&
cbOut
,
&
fDone
,
(
SEC_WCHAR
*
)
TargetName
,
&
hCred
,
&
hcText
))
{
return
(
FALSE
);
}
if
(
!
SendMsg
(
s
,
pOutBuf
,
cbOut
))
{
MyHandleError
(
"Send message failed "
);
}
while
(
!
fDone
)
{
if
(
!
ReceiveMsg
(
s
,
pInBuf
,
cbMaxMessage
,
&
cbIn
))
{
MyHandleError
(
"Receive message failed "
);
}
cbOut
=
cbMaxMessage
;
if
(
!
GenClientContext
(
pInBuf
,
cbIn
,
pOutBuf
,
&
cbOut
,
&
fDone
,
(
SEC_WCHAR
*
)
TargetName
,
&
hCred
,
&
hcText
))
{
MyHandleError
(
"GenClientContext failed"
);
}
if
(
!
SendMsg
(
s
,
pOutBuf
,
cbOut
))
{
MyHandleError
(
"Send message 2 failed "
);
}
}
free
(
pInBuf
);
free
(
pOutBuf
);
return
(
TRUE
);
}
BOOL
GenClientContext
(
BYTE
*
pIn
,
DWORD
cbIn
,
BYTE
*
pOut
,
DWORD
*
pcbOut
,
BOOL
*
pfDone
,
SEC_WCHAR
*
pszTarget
,
CredHandle
*
hCred
,
struct
_SecHandle
*
hcText
)
{
SECURITY_STATUS
ss
;
TimeStamp
Lifetime
;
SecBufferDesc
OutBuffDesc
;
SecBuffer
OutSecBuff
;
SecBufferDesc
InBuffDesc
;
SecBuffer
InSecBuff
;
ULONG
ContextAttributes
;
static
PTCHAR
lpPackageName
=
(
PTCHAR
)
NEGOSSP_NAME
;
if
(
NULL
==
pIn
)
{
ss
=
AcquireCredentialsHandle
(
NULL
,
lpPackageName
,
SECPKG_CRED_OUTBOUND
,
NULL
,
NULL
,
NULL
,
NULL
,
hCred
,
&
Lifetime
);
if
(
!
(
SEC_SUCCESS
(
ss
)))
{
MyHandleError
(
"AcquireCreds failed "
);
}
}
//--------------------------------------------------------------------
// Prepare the buffers.
OutBuffDesc
.
ulVersion
=
0
;
OutBuffDesc
.
cBuffers
=
1
;
OutBuffDesc
.
pBuffers
=
&
OutSecBuff
;
OutSecBuff
.
cbBuffer
=
*
pcbOut
;
OutSecBuff
.
BufferType
=
SECBUFFER_TOKEN
;
OutSecBuff
.
pvBuffer
=
pOut
;
//-------------------------------------------------------------------
// The input buffer is created only if a message has been received
// from the server.
if
(
pIn
)
{
InBuffDesc
.
ulVersion
=
0
;
InBuffDesc
.
cBuffers
=
1
;
InBuffDesc
.
pBuffers
=
&
InSecBuff
;
InSecBuff
.
cbBuffer
=
cbIn
;
InSecBuff
.
BufferType
=
SECBUFFER_TOKEN
;
InSecBuff
.
pvBuffer
=
pIn
;
ss
=
InitializeSecurityContext
(
hCred
,
hcText
,
(
SEC_WCHAR
*
)
pszTarget
,
MessageAttribute
,
0
,
SECURITY_NATIVE_DREP
,
&
InBuffDesc
,
0
,
hcText
,
&
OutBuffDesc
,
&
ContextAttributes
,
&
Lifetime
);
}
else
{
ss
=
InitializeSecurityContext
(
hCred
,
NULL
,
(
SEC_WCHAR
*
)
pszTarget
,
MessageAttribute
,
0
,
SECURITY_NATIVE_DREP
,
NULL
,
0
,
hcText
,
&
OutBuffDesc
,
&
ContextAttributes
,
&
Lifetime
);
}
if
(
!
SEC_SUCCESS
(
ss
))
{
MyHandleError
(
"InitializeSecurityContext failed "
);
}
//-------------------------------------------------------------------
// If necessary, complete the token.
if
((
SEC_I_COMPLETE_NEEDED
==
ss
)
||
(
SEC_I_COMPLETE_AND_CONTINUE
==
ss
))
{
ss
=
CompleteAuthToken
(
hcText
,
&
OutBuffDesc
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"complete failed: 0x%08x
\n
"
,
ss
);
return
FALSE
;
}
}
*
pcbOut
=
OutSecBuff
.
cbBuffer
;
*
pfDone
=
!
((
SEC_I_CONTINUE_NEEDED
==
ss
)
||
(
SEC_I_COMPLETE_AND_CONTINUE
==
ss
));
printf
(
"Token buffer generated (%lu bytes):
\n
"
,
OutSecBuff
.
cbBuffer
);
PrintHexDump
(
OutSecBuff
.
cbBuffer
,
(
PBYTE
)
OutSecBuff
.
pvBuffer
);
return
TRUE
;
}
PBYTE
DecryptThis
(
PBYTE
pBuffer
,
LPDWORD
pcbMessage
,
struct
_SecHandle
*
hCtxt
,
ULONG
cbSecurityTrailer
)
{
SECURITY_STATUS
ss
;
SecBufferDesc
BuffDesc
;
SecBuffer
SecBuff
[
2
];
ULONG
ulQop
=
0
;
PBYTE
pSigBuffer
;
PBYTE
pDataBuffer
;
DWORD
SigBufferSize
;
//-------------------------------------------------------------------
// By agreement, the server encrypted the message and set the size
// of the trailer block to be just what it needed. DecryptMessage
// needs the size of the trailer block.
// The size of the trailer is in the first DWORD of the
// message received.
SigBufferSize
=
*
((
DWORD
*
)
pBuffer
);
printf
(
"data before decryption including trailer (%lu bytes):
\n
"
,
*
pcbMessage
);
PrintHexDump
(
*
pcbMessage
,
(
PBYTE
)
pBuffer
);
//--------------------------------------------------------------------
// By agreement, the server placed the trailer at the beginning
// of the message that was sent immediately following the trailer
// size DWORD.
pSigBuffer
=
pBuffer
+
sizeof
(
DWORD
);
//--------------------------------------------------------------------
// The data comes after the trailer.
pDataBuffer
=
pSigBuffer
+
SigBufferSize
;
//--------------------------------------------------------------------
// *pcbMessage is reset to the size of just the encrypted bytes.
*
pcbMessage
=
*
pcbMessage
-
SigBufferSize
-
sizeof
(
DWORD
);
//--------------------------------------------------------------------
// Prepare the buffers to be passed to the DecryptMessage function.
BuffDesc
.
ulVersion
=
0
;
BuffDesc
.
cBuffers
=
2
;
BuffDesc
.
pBuffers
=
SecBuff
;
SecBuff
[
0
].
cbBuffer
=
SigBufferSize
;
SecBuff
[
0
].
BufferType
=
SECBUFFER_TOKEN
;
SecBuff
[
0
].
pvBuffer
=
pSigBuffer
;
SecBuff
[
1
].
cbBuffer
=
*
pcbMessage
;
SecBuff
[
1
].
BufferType
=
SECBUFFER_DATA
;
SecBuff
[
1
].
pvBuffer
=
pDataBuffer
;
ss
=
DecryptMessage
(
hCtxt
,
&
BuffDesc
,
0
,
&
ulQop
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"DecryptMessage failed"
);
}
//-------------------------------------------------------------------
// Return a pointer to the decrypted data. The trailer data
// is discarded.
return
pDataBuffer
;
}
PBYTE
VerifyThis
(
PBYTE
pBuffer
,
LPDWORD
pcbMessage
,
struct
_SecHandle
*
hCtxt
,
ULONG
cbMaxSignature
)
{
SECURITY_STATUS
ss
;
SecBufferDesc
BuffDesc
;
SecBuffer
SecBuff
[
2
];
ULONG
ulQop
=
0
;
PBYTE
pSigBuffer
;
PBYTE
pDataBuffer
;
//-------------------------------------------------------------------
// The global cbMaxSignature is the size of the signature
// in the message received.
printf
(
"data before verifying (including signature):
\n
"
);
PrintHexDump
(
*
pcbMessage
,
pBuffer
);
//--------------------------------------------------------------------
// By agreement with the server,
// the signature is at the beginning of the message received,
// and the data that was signed comes after the signature.
pSigBuffer
=
pBuffer
;
pDataBuffer
=
pBuffer
+
cbMaxSignature
;
//-------------------------------------------------------------------
// The size of the message is reset to the size of the data only.
*
pcbMessage
=
*
pcbMessage
-
(
cbMaxSignature
);
//--------------------------------------------------------------------
// Prepare the buffers to be passed to the signature verification
// function.
BuffDesc
.
ulVersion
=
0
;
BuffDesc
.
cBuffers
=
2
;
BuffDesc
.
pBuffers
=
SecBuff
;
SecBuff
[
0
].
cbBuffer
=
cbMaxSignature
;
SecBuff
[
0
].
BufferType
=
SECBUFFER_TOKEN
;
SecBuff
[
0
].
pvBuffer
=
pSigBuffer
;
SecBuff
[
1
].
cbBuffer
=
*
pcbMessage
;
SecBuff
[
1
].
BufferType
=
SECBUFFER_DATA
;
SecBuff
[
1
].
pvBuffer
=
pDataBuffer
;
ss
=
VerifySignature
(
hCtxt
,
&
BuffDesc
,
0
,
&
ulQop
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"VerifyMessage failed"
);
}
else
{
printf
(
"Message was properly signed.
\n
"
);
}
return
pDataBuffer
;
}
// end VerifyThis
void
PrintHexDump
(
DWORD
length
,
PBYTE
buffer
)
{
DWORD
i
,
count
,
index
;
CHAR
rgbDigits
[]
=
"0123456789abcdef"
;
CHAR
rgbLine
[
100
];
char
cbLine
;
for
(
index
=
0
;
length
;
length
-=
count
,
buffer
+=
count
,
index
+=
count
)
{
count
=
(
length
>
16
)
?
16
:
length
;
sprintf_s
(
rgbLine
,
100
,
"%4.4x "
,
index
);
cbLine
=
6
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
rgbLine
[
cbLine
++
]
=
rgbDigits
[
buffer
[
i
]
>>
4
];
rgbLine
[
cbLine
++
]
=
rgbDigits
[
buffer
[
i
]
&
0x0f
];
if
(
i
==
7
)
{
rgbLine
[
cbLine
++
]
=
':'
;
}
else
{
rgbLine
[
cbLine
++
]
=
' '
;
}
}
for
(;
i
<
16
;
i
++
)
{
rgbLine
[
cbLine
++
]
=
' '
;
rgbLine
[
cbLine
++
]
=
' '
;
rgbLine
[
cbLine
++
]
=
' '
;
}
rgbLine
[
cbLine
++
]
=
' '
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
buffer
[
i
]
<
32
||
buffer
[
i
]
>
126
)
{
rgbLine
[
cbLine
++
]
=
'.'
;
}
else
{
rgbLine
[
cbLine
++
]
=
buffer
[
i
];
}
}
rgbLine
[
cbLine
++
]
=
0
;
printf
(
"%s
\n
"
,
rgbLine
);
}
}
BOOL
SendMsg
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
)
{
if
(
0
==
cbBuf
)
return
(
TRUE
);
//----------------------------------------------------------
// Send the size of the message.
if
(
!
SendBytes
(
s
,
(
PBYTE
)
&
cbBuf
,
sizeof
(
cbBuf
)))
return
(
FALSE
);
//----------------------------------------------------------
// Send the body of the message.
if
(
!
SendBytes
(
s
,
pBuf
,
cbBuf
))
{
return
(
FALSE
);
}
return
(
TRUE
);
}
BOOL
ReceiveMsg
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
,
DWORD
*
pcbRead
)
{
DWORD
cbRead
;
DWORD
cbData
;
//----------------------------------------------------------
// Receive the number of bytes in the message.
if
(
!
ReceiveBytes
(
s
,
(
PBYTE
)
&
cbData
,
sizeof
(
cbData
),
&
cbRead
))
{
return
(
FALSE
);
}
if
(
sizeof
(
cbData
)
!=
cbRead
)
return
(
FALSE
);
//----------------------------------------------------------
// Read the full message.
if
(
!
ReceiveBytes
(
s
,
pBuf
,
cbData
,
&
cbRead
))
{
return
(
FALSE
);
}
if
(
cbRead
!=
cbData
)
return
(
FALSE
);
*
pcbRead
=
cbRead
;
return
(
TRUE
);
}
// end ReceiveMessage
BOOL
SendBytes
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
)
{
PBYTE
pTemp
=
pBuf
;
int
cbSent
;
int
cbRemaining
=
cbBuf
;
if
(
0
==
cbBuf
)
return
(
TRUE
);
while
(
cbRemaining
)
{
cbSent
=
send
(
s
,
(
const
char
*
)
pTemp
,
cbRemaining
,
0
);
if
(
SOCKET_ERROR
==
cbSent
)
{
fprintf
(
stderr
,
"send failed: %u
\n
"
,
GetLastError
());
return
FALSE
;
}
pTemp
+=
cbSent
;
cbRemaining
-=
cbSent
;
}
return
TRUE
;
}
BOOL
ReceiveBytes
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
,
DWORD
*
pcbRead
)
{
PBYTE
pTemp
=
pBuf
;
int
cbRead
,
cbRemaining
=
cbBuf
;
while
(
cbRemaining
)
{
cbRead
=
recv
(
s
,
(
char
*
)
pTemp
,
cbRemaining
,
0
);
if
(
0
==
cbRead
)
break
;
if
(
SOCKET_ERROR
==
cbRead
)
{
fprintf
(
stderr
,
"recv failed: %u
\n
"
,
GetLastError
());
return
FALSE
;
}
cbRemaining
-=
cbRead
;
pTemp
+=
cbRead
;
}
*
pcbRead
=
cbBuf
-
cbRemaining
;
return
TRUE
;
}
// end ReceiveBytes
void
MyHandleError
(
const
char
*
s
)
{
fprintf
(
stderr
,
"%s error. Exiting.
\n
"
,
s
);
exit
(
EXIT_FAILURE
);
}
sspi-server.c
0 → 100644
View file @
358649bc
//--------------------------------------------------------------------
// This is a server-side SSPI Windows Sockets program.
#define usPort 2000
#define SECURITY_WIN32
#define SEC_SUCCESS(Status) ((Status) >= 0)
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
#include "Sspiexample.h"
CredHandle
hcred
;
struct
_SecHandle
hctxt
;
static
PBYTE
g_pInBuf
=
NULL
;
static
PBYTE
g_pOutBuf
=
NULL
;
static
DWORD
g_cbMaxMessage
;
static
TCHAR
g_lpPackageName
[
1024
];
BOOL
AcceptAuthSocket
(
SOCKET
*
ServerSocket
);
void
main
()
{
CHAR
pMessage
[
200
];
DWORD
cbMessage
;
PBYTE
pDataToClient
=
NULL
;
DWORD
cbDataToClient
=
0
;
PCHAR
pUserName
=
NULL
;
DWORD
cbUserName
=
0
;
SOCKET
Server_Socket
;
WSADATA
wsaData
;
SECURITY_STATUS
ss
;
PSecPkgInfo
pkgInfo
;
SecPkgContext_Sizes
SecPkgContextSizes
;
SecPkgContext_NegotiationInfo
SecPkgNegInfo
;
ULONG
cbMaxSignature
;
ULONG
cbSecurityTrailer
;
//-----------------------------------------------------------------
// Set the default package to negotiate.
strcpy_s
(
g_lpPackageName
,
1024
*
sizeof
(
TCHAR
),
"Negotiate"
);
//-----------------------------------------------------------------
// Initialize the socket interface and the security package.
if
(
WSAStartup
(
0x0101
,
&
wsaData
))
{
fprintf
(
stderr
,
"Could not initialize winsock:
\n
"
);
cleanup
();
}
ss
=
QuerySecurityPackageInfo
(
g_lpPackageName
,
&
pkgInfo
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"Could not query package info for %s, error 0x%08x
\n
"
,
g_lpPackageName
,
ss
);
cleanup
();
}
g_cbMaxMessage
=
pkgInfo
->
cbMaxToken
;
FreeContextBuffer
(
pkgInfo
);
g_pInBuf
=
(
PBYTE
)
malloc
(
g_cbMaxMessage
);
g_pOutBuf
=
(
PBYTE
)
malloc
(
g_cbMaxMessage
);
if
(
NULL
==
g_pInBuf
||
NULL
==
g_pOutBuf
)
{
fprintf
(
stderr
,
"Memory allocation error.
\n
"
);
cleanup
();
}
//-----------------------------------------------------------------
// Start looping for clients.
while
(
TRUE
)
{
printf
(
"Waiting for client to connect...
\n
"
);
//-----------------------------------------------------------------
// Make an authenticated connection with client.
if
(
!
AcceptAuthSocket
(
&
Server_Socket
))
{
fprintf
(
stderr
,
"Could not authenticate the socket.
\n
"
);
cleanup
();
}
ss
=
QueryContextAttributes
(
&
hctxt
,
SECPKG_ATTR_SIZES
,
&
SecPkgContextSizes
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"QueryContextAttributes failed: 0x%08x
\n
"
,
ss
);
exit
(
1
);
}
//----------------------------------------------------------------
// The following values are used for encryption and signing.
cbMaxSignature
=
SecPkgContextSizes
.
cbMaxSignature
;
cbSecurityTrailer
=
SecPkgContextSizes
.
cbSecurityTrailer
;
ss
=
QueryContextAttributes
(
&
hctxt
,
SECPKG_ATTR_NEGOTIATION_INFO
,
&
SecPkgNegInfo
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"QueryContextAttributes failed: 0x%08x
\n
"
,
ss
);
exit
(
1
);
}
else
{
printf
(
"Package Name: %s
\n
"
,
SecPkgNegInfo
.
PackageInfo
->
Name
);
}
//----------------------------------------------------------------
// Free the allocated buffer.
FreeContextBuffer
(
SecPkgNegInfo
.
PackageInfo
);
//-----------------------------------------------------------------
// Impersonate the client.
ss
=
ImpersonateSecurityContext
(
&
hctxt
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"Impersonate failed: 0x%08x
\n
"
,
ss
);
cleanup
();
}
else
{
printf
(
"Impersonation worked.
\n
"
);
}
GetUserName
(
NULL
,
&
cbUserName
);
pUserName
=
(
PCHAR
)
malloc
(
cbUserName
);
if
(
!
pUserName
)
{
fprintf
(
stderr
,
"Memory allocation error.
\n
"
);
cleanup
();
}
if
(
!
GetUserName
(
pUserName
,
&
cbUserName
))
{
fprintf
(
stderr
,
"Could not get the client name.
\n
"
);
cleanup
();
}
else
{
printf
(
"Client connected as : %s
\n
"
,
pUserName
);
}
//-----------------------------------------------------------------
// Revert to self.
ss
=
RevertSecurityContext
(
&
hctxt
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"Revert failed: 0x%08x
\n
"
,
ss
);
cleanup
();
}
else
{
printf
(
"Reverted to self.
\n
"
);
}
//-----------------------------------------------------------------
// Send the client an encrypted message.
strcpy_s
(
pMessage
,
sizeof
(
pMessage
),
"This is your server speaking"
);
cbMessage
=
strlen
(
pMessage
);
EncryptThis
(
(
PBYTE
)
pMessage
,
cbMessage
,
&
pDataToClient
,
&
cbDataToClient
,
cbSecurityTrailer
);
//-----------------------------------------------------------------
// Send the encrypted data to client.
if
(
!
SendBytes
(
Server_Socket
,
pDataToClient
,
cbDataToClient
))
{
printf
(
"send message failed.
\n
"
);
cleanup
();
}
printf
(
" %d encrypted bytes sent.
\n
"
,
cbDataToClient
);
if
(
Server_Socket
)
{
DeleteSecurityContext
(
&
hctxt
);
FreeCredentialHandle
(
&
hcred
);
shutdown
(
Server_Socket
,
2
)
;
closesocket
(
Server_Socket
);
Server_Socket
=
0
;
}
if
(
pUserName
)
{
free
(
pUserName
);
pUserName
=
NULL
;
cbUserName
=
0
;
}
if
(
pDataToClient
)
{
free
(
pDataToClient
);
pDataToClient
=
NULL
;
cbDataToClient
=
0
;
}
}
// end while loop
printf
(
"Server ran to completion without error.
\n
"
);
cleanup
();
}
// end main
BOOL
AcceptAuthSocket
(
SOCKET
*
ServerSocket
)
{
SOCKET
sockListen
;
SOCKET
sockClient
;
SOCKADDR_IN
sockIn
;
//-----------------------------------------------------------------
// Create listening socket.
sockListen
=
socket
(
PF_INET
,
SOCK_STREAM
,
0
);
if
(
INVALID_SOCKET
==
sockListen
)
{
fprintf
(
stderr
,
"Failed to create socket: %u
\n
"
,
GetLastError
());
return
(
FALSE
);
}
//-----------------------------------------------------------------
// Bind to local port.
sockIn
.
sin_family
=
AF_INET
;
sockIn
.
sin_addr
.
s_addr
=
0
;
sockIn
.
sin_port
=
htons
(
usPort
);
if
(
SOCKET_ERROR
==
bind
(
sockListen
,
(
LPSOCKADDR
)
&
sockIn
,
sizeof
(
sockIn
)))
{
fprintf
(
stderr
,
"bind failed: %u
\n
"
,
GetLastError
());
return
(
FALSE
);
}
//-----------------------------------------------------------------
// Listen for client.
if
(
SOCKET_ERROR
==
listen
(
sockListen
,
1
))
{
fprintf
(
stderr
,
"Listen failed: %u
\n
"
,
GetLastError
());
return
(
FALSE
);
}
else
{
printf
(
"Listening !
\n
"
);
}
//-----------------------------------------------------------------
// Accept client.
sockClient
=
accept
(
sockListen
,
NULL
,
NULL
);
if
(
INVALID_SOCKET
==
sockClient
)
{
fprintf
(
stderr
,
"accept failed: %u
\n
"
,
GetLastError
());
return
(
FALSE
);
}
closesocket
(
sockListen
);
*
ServerSocket
=
sockClient
;
return
(
DoAuthentication
(
sockClient
));
}
// end AcceptAuthSocket
BOOL
DoAuthentication
(
SOCKET
AuthSocket
)
{
SECURITY_STATUS
ss
;
DWORD
cbIn
,
cbOut
;
BOOL
done
=
FALSE
;
TimeStamp
Lifetime
;
BOOL
fNewConversation
;
fNewConversation
=
TRUE
;
ss
=
AcquireCredentialsHandle
(
NULL
,
g_lpPackageName
,
SECPKG_CRED_INBOUND
,
NULL
,
NULL
,
NULL
,
NULL
,
&
hcred
,
&
Lifetime
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"AcquireCreds failed: 0x%08x
\n
"
,
ss
);
return
(
FALSE
);
}
while
(
!
done
)
{
if
(
!
ReceiveMsg
(
AuthSocket
,
g_pInBuf
,
g_cbMaxMessage
,
&
cbIn
))
{
return
(
FALSE
);
}
cbOut
=
g_cbMaxMessage
;
if
(
!
GenServerContext
(
g_pInBuf
,
cbIn
,
g_pOutBuf
,
&
cbOut
,
&
done
,
fNewConversation
))
{
fprintf
(
stderr
,
"GenServerContext failed.
\n
"
);
return
(
FALSE
);
}
fNewConversation
=
FALSE
;
if
(
!
SendMsg
(
AuthSocket
,
g_pOutBuf
,
cbOut
))
{
fprintf
(
stderr
,
"Sending message failed.
\n
"
);
return
(
FALSE
);
}
}
return
(
TRUE
);
}
// end DoAuthentication
BOOL
GenServerContext
(
BYTE
*
pIn
,
DWORD
cbIn
,
BYTE
*
pOut
,
DWORD
*
pcbOut
,
BOOL
*
pfDone
,
BOOL
fNewConversation
)
{
SECURITY_STATUS
ss
;
TimeStamp
Lifetime
;
SecBufferDesc
OutBuffDesc
;
SecBuffer
OutSecBuff
;
SecBufferDesc
InBuffDesc
;
SecBuffer
InSecBuff
;
ULONG
Attribs
=
0
;
//----------------------------------------------------------------
// Prepare output buffers.
OutBuffDesc
.
ulVersion
=
0
;
OutBuffDesc
.
cBuffers
=
1
;
OutBuffDesc
.
pBuffers
=
&
OutSecBuff
;
OutSecBuff
.
cbBuffer
=
*
pcbOut
;
OutSecBuff
.
BufferType
=
SECBUFFER_TOKEN
;
OutSecBuff
.
pvBuffer
=
pOut
;
//----------------------------------------------------------------
// Prepare input buffers.
InBuffDesc
.
ulVersion
=
0
;
InBuffDesc
.
cBuffers
=
1
;
InBuffDesc
.
pBuffers
=
&
InSecBuff
;
InSecBuff
.
cbBuffer
=
cbIn
;
InSecBuff
.
BufferType
=
SECBUFFER_TOKEN
;
InSecBuff
.
pvBuffer
=
pIn
;
printf
(
"Token buffer received (%lu bytes):
\n
"
,
InSecBuff
.
cbBuffer
);
PrintHexDump
(
InSecBuff
.
cbBuffer
,
(
PBYTE
)
InSecBuff
.
pvBuffer
);
ss
=
AcceptSecurityContext
(
&
hcred
,
fNewConversation
?
NULL
:
&
hctxt
,
&
InBuffDesc
,
Attribs
,
SECURITY_NATIVE_DREP
,
&
hctxt
,
&
OutBuffDesc
,
&
Attribs
,
&
Lifetime
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"AcceptSecurityContext failed: 0x%08x
\n
"
,
ss
);
return
FALSE
;
}
//----------------------------------------------------------------
// Complete token if applicable.
if
((
SEC_I_COMPLETE_NEEDED
==
ss
)
||
(
SEC_I_COMPLETE_AND_CONTINUE
==
ss
))
{
ss
=
CompleteAuthToken
(
&
hctxt
,
&
OutBuffDesc
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"complete failed: 0x%08x
\n
"
,
ss
);
return
FALSE
;
}
}
*
pcbOut
=
OutSecBuff
.
cbBuffer
;
// fNewConversation equals FALSE.
printf
(
"Token buffer generated (%lu bytes):
\n
"
,
OutSecBuff
.
cbBuffer
);
PrintHexDump
(
OutSecBuff
.
cbBuffer
,
(
PBYTE
)
OutSecBuff
.
pvBuffer
);
*
pfDone
=
!
((
SEC_I_CONTINUE_NEEDED
==
ss
)
||
(
SEC_I_COMPLETE_AND_CONTINUE
==
ss
));
printf
(
"AcceptSecurityContext result = 0x%08x
\n
"
,
ss
);
return
TRUE
;
}
// end GenServerContext
BOOL
EncryptThis
(
PBYTE
pMessage
,
ULONG
cbMessage
,
BYTE
**
ppOutput
,
ULONG
*
pcbOutput
,
ULONG
cbSecurityTrailer
)
{
SECURITY_STATUS
ss
;
SecBufferDesc
BuffDesc
;
SecBuffer
SecBuff
[
2
];
ULONG
ulQop
=
0
;
ULONG
SigBufferSize
;
//-----------------------------------------------------------------
// The size of the trailer (signature + padding) block is
// determined from the global cbSecurityTrailer.
SigBufferSize
=
cbSecurityTrailer
;
printf
(
"Data before encryption: %s
\n
"
,
pMessage
);
printf
(
"Length of data before encryption: %d
\n
"
,
cbMessage
);
//-----------------------------------------------------------------
// Allocate a buffer to hold the signature,
// encrypted data, and a DWORD
// that specifies the size of the trailer block.
*
ppOutput
=
(
PBYTE
)
malloc
(
SigBufferSize
+
cbMessage
+
sizeof
(
DWORD
));
//------------------------------------------------------------------
// Prepare buffers.
BuffDesc
.
ulVersion
=
0
;
BuffDesc
.
cBuffers
=
2
;
BuffDesc
.
pBuffers
=
SecBuff
;
SecBuff
[
0
].
cbBuffer
=
SigBufferSize
;
SecBuff
[
0
].
BufferType
=
SECBUFFER_TOKEN
;
SecBuff
[
0
].
pvBuffer
=
*
ppOutput
+
sizeof
(
DWORD
);
SecBuff
[
1
].
cbBuffer
=
cbMessage
;
SecBuff
[
1
].
BufferType
=
SECBUFFER_DATA
;
SecBuff
[
1
].
pvBuffer
=
pMessage
;
ss
=
EncryptMessage
(
&
hctxt
,
ulQop
,
&
BuffDesc
,
0
);
if
(
!
SEC_SUCCESS
(
ss
))
{
fprintf
(
stderr
,
"EncryptMessage failed: 0x%08x
\n
"
,
ss
);
return
(
FALSE
);
}
else
{
printf
(
"The message has been encrypted.
\n
"
);
}
//------------------------------------------------------------------
// Indicate the size of the buffer in the first DWORD.
*
((
DWORD
*
)
*
ppOutput
)
=
SecBuff
[
0
].
cbBuffer
;
//-----------------------------------------------------------------
// Append the encrypted data to our trailer block
// to form a single block.
// Putting trailer at the beginning of the buffer works out
// better.
memcpy
(
*
ppOutput
+
SecBuff
[
0
].
cbBuffer
+
sizeof
(
DWORD
),
pMessage
,
cbMessage
);
*
pcbOutput
=
cbMessage
+
SecBuff
[
0
].
cbBuffer
+
sizeof
(
DWORD
);
printf
(
"data after encryption including trailer (%lu bytes):
\n
"
,
*
pcbOutput
);
PrintHexDump
(
*
pcbOutput
,
*
ppOutput
);
return
TRUE
;
}
// end EncryptThis
void
PrintHexDump
(
DWORD
length
,
PBYTE
buffer
)
{
DWORD
i
,
count
,
index
;
CHAR
rgbDigits
[]
=
"0123456789abcdef"
;
CHAR
rgbLine
[
100
];
char
cbLine
;
for
(
index
=
0
;
length
;
length
-=
count
,
buffer
+=
count
,
index
+=
count
)
{
count
=
(
length
>
16
)
?
16
:
length
;
sprintf_s
(
rgbLine
,
100
,
"%4.4x "
,
index
);
cbLine
=
6
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
rgbLine
[
cbLine
++
]
=
rgbDigits
[
buffer
[
i
]
>>
4
];
rgbLine
[
cbLine
++
]
=
rgbDigits
[
buffer
[
i
]
&
0x0f
];
if
(
i
==
7
)
{
rgbLine
[
cbLine
++
]
=
':'
;
}
else
{
rgbLine
[
cbLine
++
]
=
' '
;
}
}
for
(;
i
<
16
;
i
++
)
{
rgbLine
[
cbLine
++
]
=
' '
;
rgbLine
[
cbLine
++
]
=
' '
;
rgbLine
[
cbLine
++
]
=
' '
;
}
rgbLine
[
cbLine
++
]
=
' '
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
buffer
[
i
]
<
32
||
buffer
[
i
]
>
126
)
{
rgbLine
[
cbLine
++
]
=
'.'
;
}
else
{
rgbLine
[
cbLine
++
]
=
buffer
[
i
];
}
}
rgbLine
[
cbLine
++
]
=
0
;
printf
(
"%s
\n
"
,
rgbLine
);
}
}
// end PrintHexDump
BOOL
SendMsg
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
)
{
if
(
0
==
cbBuf
)
return
(
TRUE
);
//----------------------------------------------------------------
// Send the size of the message.
if
(
!
SendBytes
(
s
,
(
PBYTE
)
&
cbBuf
,
sizeof
(
cbBuf
)))
{
return
(
FALSE
);
}
//----------------------------------------------------------------
// Send the body of the message.
if
(
!
SendBytes
(
s
,
pBuf
,
cbBuf
))
{
return
(
FALSE
);
}
return
(
TRUE
);
}
// end SendMsg
BOOL
ReceiveMsg
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
,
DWORD
*
pcbRead
)
{
DWORD
cbRead
;
DWORD
cbData
;
//-----------------------------------------------------------------
// Retrieve the number of bytes in the message.
if
(
!
ReceiveBytes
(
s
,
(
PBYTE
)
&
cbData
,
sizeof
(
cbData
),
&
cbRead
))
{
return
(
FALSE
);
}
if
(
sizeof
(
cbData
)
!=
cbRead
)
{
return
(
FALSE
);
}
//----------------------------------------------------------------
// Read the full message.
if
(
!
ReceiveBytes
(
s
,
pBuf
,
cbData
,
&
cbRead
))
{
return
(
FALSE
);
}
if
(
cbRead
!=
cbData
)
{
return
(
FALSE
);
}
*
pcbRead
=
cbRead
;
return
(
TRUE
);
}
// end ReceiveMsg
BOOL
SendBytes
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
)
{
PBYTE
pTemp
=
pBuf
;
int
cbSent
,
cbRemaining
=
cbBuf
;
if
(
0
==
cbBuf
)
{
return
(
TRUE
);
}
while
(
cbRemaining
)
{
cbSent
=
send
(
s
,
(
const
char
*
)
pTemp
,
cbRemaining
,
0
);
if
(
SOCKET_ERROR
==
cbSent
)
{
fprintf
(
stderr
,
"send failed: %u
\n
"
,
GetLastError
());
return
FALSE
;
}
pTemp
+=
cbSent
;
cbRemaining
-=
cbSent
;
}
return
TRUE
;
}
// end SendBytes
BOOL
ReceiveBytes
(
SOCKET
s
,
PBYTE
pBuf
,
DWORD
cbBuf
,
DWORD
*
pcbRead
)
{
PBYTE
pTemp
=
pBuf
;
int
cbRead
,
cbRemaining
=
cbBuf
;
while
(
cbRemaining
)
{
cbRead
=
recv
(
s
,
(
char
*
)
pTemp
,
cbRemaining
,
0
);
if
(
0
==
cbRead
)
{
break
;
}
if
(
SOCKET_ERROR
==
cbRead
)
{
fprintf
(
stderr
,
"recv failed: %u
\n
"
,
GetLastError
());
return
FALSE
;
}
cbRemaining
-=
cbRead
;
pTemp
+=
cbRead
;
}
*
pcbRead
=
cbBuf
-
cbRemaining
;
return
TRUE
;
}
// end ReceivesBytes
void
cleanup
()
{
if
(
g_pInBuf
)
free
(
g_pInBuf
);
if
(
g_pOutBuf
)
free
(
g_pOutBuf
);
WSACleanup
();
exit
(
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