2025-04-27 07:49:33 -04:00

625 lines
13 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <buffer.hxx>
#include "..\..\tigris.hxx"
extern "C" {
#define SECURITY_WIN32
#include <rpc.h>
#include <sspi.h>
#include <sslsp.h>
#include <spseal.h>
#include <issperr.h>
}
#include "..\..\security.h"
#include "..\inc\sec.h"
#define IO_BUFFER_SIZE 4096
WSADATA WsaData;
CHAR ourArticle[1024];
CSecurityCtx *NntpServer = NULL;
VOID
NNTPProcess(
SOCKET s,
BOOL isSSL
);
DWORD
WINAPI
DoSSLServer(
PVOID Context
);
DWORD
WINAPI
SSPIServer(
PVOID Context
);
BOOL
DoNtLm(
SOCKET s,
BOOL IsSSL
);
BOOL fNtlm = FALSE;
BOOL
ReadOurArticle(
)
{
HANDLE hFile;
DWORD nbytes;
hFile = CreateFile(
"c:\\nntproot\\junk",
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
if ( hFile == INVALID_HANDLE_VALUE ) {
goto error;
}
if (!ReadFile(
hFile,
ourArticle,
1024,
&nbytes,
NULL
) ) {
goto error;
}
CloseHandle(hFile);
ourArticle[nbytes] = '\0';
return(TRUE);
error:
return(FALSE);
}
void
_CRTAPI1
main( int argc, char * argv[] )
{
INT err;
err = WSAStartup( 0x0101, &WsaData );
if ( err == SOCKET_ERROR ) {
return;
}
InitAsyncTrace( );
NntpInitializeSecurity( );
if ( argc > 1 ) {
printf("enable ntlm\n");
fNtlm = TRUE;
}
//
// read out article
//
if (!ReadOurArticle( ))
return;
{
HANDLE hThread;
DWORD threadId;
hThread = CreateThread(
NULL, // attributes
0, // stack size
DoSSLServer, // thread start
(PVOID)0, // param
0, // creation params
&threadId
);
if ( hThread != NULL ) {
CloseHandle(hThread);
}
}
SSPIServer( NULL );
NntpTerminateSecurity( );
TermAsyncTrace( );
WSACleanup( );
} // main()
VOID
NntpReply(
SOCKET s,
PCHAR Reply,
BOOL isSSL
)
{
INT err;
BUFFER out;
DWORD nbytes;
//
// reseal it and give it back
//
if ( isSSL ) {
err = strlen(Reply);
if (!NntpServer->SealMessage(
(LPBYTE)Reply,
err,
&out,
&nbytes
)) {
return;
}
} else {
nbytes = strlen(Reply);
}
err = send(s,(PCHAR)out.QueryPtr(),nbytes,0);
if ( err == SOCKET_ERROR ) {
printf("hello send failed\n");
return;
}
}
DWORD
WINAPI
DoSSLServer(
PVOID Context
)
{
SOCKET listenSocket;
SOCKET acceptSocket;
SOCKADDR_IN address;
INT err;
SOCKADDR_IN remoteAddress;
INT remoteSockaddrLength;
BOOL authInProgress;
BOOL authFailed;
CHAR IoBuffer[IO_BUFFER_SIZE];
BUFFER out;
NEG_BLOCK neg;
PCHAR msg;
DWORD nbytes;
//
// Set up a socket listening on the SSL port 563
//
listenSocket = socket( AF_INET, SOCK_STREAM, 0 );
if ( listenSocket == INVALID_SOCKET ) {
printf( "socket() failed for listenSocket: %ld\n", GetLastError( ) );
return 1;
}
RtlZeroMemory( &address, sizeof(address) );
address.sin_family = AF_INET;
address.sin_port = htons( NNTP_SSL_PORT );
err = bind( listenSocket, (PSOCKADDR)&address, sizeof(address) );
if ( err == SOCKET_ERROR ) {
printf( "bind failed: %ld\n", GetLastError( ) );
return 1;
}
err = listen( listenSocket, 5 );
if ( err == SOCKET_ERROR ) {
printf( "listen failed: %ld\n", GetLastError( ) );
return 1;
}
//
// Loop processing connections.
//
while (TRUE ) {
//
// First accept an incoming connection.
//
remoteSockaddrLength = sizeof(remoteAddress);
printf("Waiting for SSL connection\n");
acceptSocket = accept( listenSocket, (LPSOCKADDR)&remoteAddress,
&remoteSockaddrLength );
if ( acceptSocket == INVALID_SOCKET ) {
printf( "accept() failed: %ld\n", GetLastError( ) );
return 1;
}
authInProgress = TRUE;
authFailed = FALSE;
NntpServer = new CSecurityCtx;
if ( (NntpServer == NULL) ||
!NntpServer->Initialize( FALSE )) {
printf("cannot initialize sec ctx\n");
closesocket(acceptSocket);
delete NntpServer;
continue;
}
do {
BOOL moredata;
err = recv( acceptSocket, IoBuffer, IO_BUFFER_SIZE, 0 );
if ( err == SOCKET_ERROR ) {
printf(" recv failed: %d\n", GetLastError() );
closesocket( acceptSocket );
break;
} else {
printf("recv auth data, %d bytes\n", err );
}
if ( !NntpServer->Converse(
IoBuffer,
err,
&out,
&nbytes,
&moredata,
AuthProtocolSSL30
) ) {
printf("converse failed %x\n",GetLastError());
authFailed = TRUE;
break;
}
printf("Sending %d bytes auth data\n",nbytes);
if ( nbytes > 0 ) {
err = send(
acceptSocket,
(PCHAR)out.QueryPtr( ),
nbytes,
0
);
if ( err == SOCKET_ERROR ) {
printf("send failed\n");
authFailed = TRUE;
break;
} else if ( !moredata ) {
//
// We completed the auth exchanges!
//
authInProgress = FALSE ;
}
} else {
break;
}
} while ( authInProgress );
if ( authFailed ) {
printf("auth failed\n");
} else {
printf("successful!\n");
}
if ( fNtlm) {
DoNtLm( acceptSocket, TRUE );
}
NNTPProcess( acceptSocket, TRUE );
closesocket( acceptSocket );
delete NntpServer;
NntpServer = NULL;
} // while
closesocket(listenSocket);
return 1;
} // SSLServer
DWORD
WINAPI
SSPIServer(
PVOID Context
)
{
SOCKET listenSocket;
SOCKET acceptSocket;
SOCKADDR_IN address;
SOCKADDR_IN remoteAddress;
INT remoteSockaddrLength;
INT err;
//
// Set up a socket listening on the SSL port 563
//
listenSocket = socket( AF_INET, SOCK_STREAM, 0 );
if ( listenSocket == INVALID_SOCKET ) {
printf( "socket() failed for listenSocket: %ld\n", GetLastError( ) );
return 1;
}
RtlZeroMemory( &address, sizeof(address) );
address.sin_family = AF_INET;
address.sin_port = htons( NNTP_PORT );
err = bind( listenSocket, (PSOCKADDR)&address, sizeof(address) );
if ( err == SOCKET_ERROR ) {
printf( "bind failed: %ld\n", GetLastError( ) );
return 1;
}
err = listen( listenSocket, 5 );
if ( err == SOCKET_ERROR ) {
printf( "listen failed: %ld\n", GetLastError( ) );
return 1;
}
while (TRUE ) {
//
// First accept an incoming connection.
//
remoteSockaddrLength = sizeof(remoteAddress);
printf("Waiting for SSPI connection\n");
acceptSocket = accept( listenSocket, (LPSOCKADDR)&remoteAddress,
&remoteSockaddrLength );
if ( acceptSocket == INVALID_SOCKET ) {
printf( "accept() failed: %ld\n", GetLastError( ) );
return 1;
}
if ( fNtlm) {
DoNtLm( acceptSocket, FALSE );
}
NNTPProcess( acceptSocket, FALSE );
closesocket(acceptSocket);
}
closesocket(listenSocket);
return 1;
} // SSPIServer
BOOL
DoNtLm(
SOCKET s,
BOOL IsSSL
)
{
BOOL authFailed;
BOOL authInProgress;
CHAR IoBuffer[IO_BUFFER_SIZE];
INT err;
BUFFER out;
printf("Doing NTLM\n");
printf("Allocating a new ctx\n");
if ( NntpServer == NULL ) {
NntpServer = new CSecurityCtx;
if ( (NntpServer == NULL) ||
(!NntpServer->Initialize(FALSE)) ) {
delete NntpServer;
NntpServer = NULL;
printf("Cannot initialize ntlm\n");
return(FALSE);
}
}
authFailed = FALSE;
authInProgress = TRUE;
do {
BOOL moredata;
DWORD nbytes;
err = recv( s, IoBuffer, IO_BUFFER_SIZE, 0 );
if ( err == SOCKET_ERROR ) {
printf(" recv failed: %d\n", GetLastError() );
closesocket( s );
break;
} else {
printf("NTLM:recv %d bytes\n", err );
}
if ( IsSSL ) {
// unseal
}
if ( !NntpServer->Converse(
IoBuffer,
err,
&out,
&nbytes,
&moredata,
AuthProtocolNtLm
) ) {
printf("converse failed %x\n",GetLastError());
authFailed = TRUE;
break;
}
printf("NTLM: Sending %d bytes\n",nbytes);
if ( nbytes > 0 ) {
#if 0
if ( isSSL ) {
SSLCtx->SealMessage(
}
#endif
err = send(
s,
(PCHAR)out.QueryPtr( ),
nbytes,
0
);
if ( err == SOCKET_ERROR ) {
printf("send failed\n");
authFailed = TRUE;
break;
} else if ( !moredata ) {
//
// We completed the auth exchanges!
//
authInProgress = FALSE ;
}
} else {
break;
}
} while ( authInProgress );
if ( authFailed ) {
printf("auth failed\n");
return(FALSE);
} else {
printf("successful!\n");
return(TRUE);
}
} // DoNtLm
VOID
NNTPProcess(
SOCKET s,
BOOL isSSL
)
{
CHAR buffer[4096];
PCHAR start;
DWORD nbytes;
INT err;
PCHAR msg;
BUFFER out;
INT i;
PCHAR p;
//
// Send Hello
//
msg = "200 Johnson's cool SNEWS server Ready\r\n";
//
// reseal it and give it back
//
NntpReply(s,msg,isSSL);
printf("processing command\n");
for (; ; ) {
err = recv(s,buffer,4096,0);
if ( err == SOCKET_ERROR ) {
printf(" recv failed: %d\n", GetLastError() );
break;
} else {
printf("PROCESS:recv %d bytes\n", err );
}
buffer[err] = '\0';
if ( isSSL ) {
if (!NntpServer->UnsealMessage(
(LPBYTE)buffer,
err,
(LPBYTE*)&start,
&nbytes
)) {
printf("unseal failed\n");
}
} else {
start = buffer;
}
printf("Command %s\n", start);
//
// try to get the first token
//
if ( (p = strtok(start," \r\t\n")) == NULL) {
NntpReply(s,"501 eeee",isSSL);
continue;
}
if(!_stricmp(p,"MODE")) {
NntpReply(s,"201 Hello, you can't post\r\n",isSSL);
} else if(!_stricmp(p,"LIST")) {
NntpReply(s,
"215 Newsgroups are\r\ncomp.tigris 1 1 n\r\n.\r\n",
isSSL
);
} else if(!_stricmp(p,"NEWGROUPS")) {
NntpReply(s,
"231 Newsgroups are\r\n.\r\n",
isSSL
);
} else if(!_stricmp(p,"GROUP")) {
NntpReply(s,
"211 1 1 1 comp.tigris\r\n",
isSSL
);
} else if(!_stricmp(p,"XOVER")) {
NntpReply(s,
"224 Info follows\r\n1\ttest1\tmole@msn.com\t8 Nov 95\t123123@jasdk\t3818923\t437\t34\r\n.\r\n",
isSSL
);
} else if(!_stricmp(p,"ARTICLE")) {
NntpReply(s,
ourArticle,
isSSL
);
}
}
} // NNTPProcess