#include #include #include "nspr.h" #include "plgetopt.h" #include "prerror.h" #include "prnetdb.h" #include "pk11func.h" #include "secitem.h" #include "ssl.h" #include "certt.h" #include "nss.h" #include "secder.h" #include "key.h" #include "sslproto.h" char nickName[] = "Server-Cert"; CERTCertificate *cert = NULL; SECKEYPrivateKey *privKey = NULL; int enableRenegotiation = 0; PRBool requireSafeRenegotiation = PR_FALSE; char * passwordArg(PK11SlotInfo *slot, PRBool retry, void *arg){ return NULL; } SECStatus readDataFromSocket(PRFileDesc *sslSocket) { int numBytes = 0; while (PR_TRUE) { char buffer[1024]; memset(buffer, 0, 1024); numBytes = PR_Read(sslSocket, buffer, 1024); if (numBytes <= 0) break; if (strstr(buffer, "end")) break; printf("Info: %d bytes read [%s]", numBytes, buffer); } printf("Info: %d bytes read returnin from readDataFromSocket()....\n", numBytes); return SECSuccess; } void printError() { printf("Error = %d", PR_GetError()); PRInt32 len = PR_GetErrorTextLength(); if (len > 0) { char arr[1024]; memset(arr,'\0',1024); PR_GetErrorText(arr); printf(" Error = %s", arr); } printf("\n"); } SECStatus authenticateSocket(PRFileDesc *sslSocket, PRBool requireCert) { SECStatus secStatus; secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_TRUE); secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, requireCert); secStatus = SSL_ReHandshake(sslSocket, PR_TRUE); if (secStatus != SECSuccess) { printf("WARNING SSL_ReHandshake"); printError(); return SECFailure; } secStatus = SSL_ForceHandshake(sslSocket); if (secStatus != SECSuccess) { printf("WARNING SSL_ForceHandshake"); printError(); return SECFailure; } return SECSuccess; } SECStatus writeDataToSocket(PRFileDesc *sslSocket) { char header[] = "

Sample SSL server



"; /* Write a header to the socket. */ int numBytes = PR_Write(sslSocket, header, strlen(header)); if (numBytes < 0) { printf("WARNING PR_Write"); printError(); return SECFailure; } /* Complete the HTTP transaction. */ numBytes = PR_Write(sslSocket, "EOF\r\n\r\n\r\n", 9); if (numBytes < 0) { printf("WARNING PR_Write"); printError(); return SECFailure; } return SECSuccess; } SECStatus handle_connection(void *tcp_sock) { PRSocketOptionData socketOption; socketOption.option = PR_SockOpt_Nonblocking; socketOption.value.non_blocking = PR_FALSE; PR_SetSocketOption(tcp_sock, &socketOption); PRFileDesc *sslSocket = SSL_ImportFD(NULL, tcp_sock); if (!sslSocket) { printf("WARNING SSL_ImportFD"); printError(); return SECFailure; } SECStatus secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE); secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_SERVER, PR_TRUE); secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_TRUE); secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, PR_FALSE); secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeRenegotiation); printf("Info: setting SSL_REQUIRE_SAFE_NEGOTIATION %d rv=%d\n", requireSafeRenegotiation, secStatus); secStatus = SSL_OptionSet(sslSocket, SSL_ENABLE_RENEGOTIATION, enableRenegotiation); printf("Info: setting SSL_ENABLE_RENEGOTIATION %d rv=%d\n", enableRenegotiation, secStatus); secStatus = SSL_SetPKCS11PinArg(sslSocket, passwordArg); if (secStatus != SECSuccess) { printf("WARNING SSL_HandshakeCallback"); printError(); return SECFailure; } SSLKEAType certKEA = NSS_FindCertKEAType(cert); secStatus = SSL_ConfigSecureServer(sslSocket, cert, privKey, certKEA); if (secStatus != SECSuccess) { printf("WARNING SSL_ConfigSecureServer"); printError(); return SECFailure; } if (sslSocket == NULL) { printf("WARNING Unable to SSL_ConfigSecureServer"); printError(); goto cleanup; } secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_TRUE); if (secStatus != SECSuccess) { printf("WARNING SSL_ResetHandshake"); printError(); goto cleanup; } printf( "\nInfo: Reading data from socket...\n\n"); secStatus = readDataFromSocket(sslSocket); printf( "\nInfo: Reading data from socket succeeded...\n\n"); if (secStatus != SECSuccess) { printError(); goto cleanup; } printf( "\nInfo: authenticateSocket() being called.\n\n"); secStatus = authenticateSocket(sslSocket, PR_TRUE); if (secStatus != SECSuccess) { printf( "\nWARNING: authenticateSocket failed.\n\n"); printError(); goto cleanup; } printf( "\nInfo: Writing data to socket...\n\n"); secStatus = writeDataToSocket(sslSocket); printf( "\nInfo: Writing data to socket returned %d...\n\n", secStatus); cleanup: /* Close down the socket. */ PRStatus prStatus = PR_Close(tcp_sock); if (prStatus != PR_SUCCESS) { printf("WARNING PR_Close"); printError(); } return secStatus; } int main(int argc, char **argv) { if (argc < 4) { printf("Usage ./server port 0/1(1=>requireSafeNegotiation) [0=>SSL_RENEGOTIATE_NEVER 1=>SSL_RENEGOTIATE_UNRESTRICTED 2=>SSL_RENEGOTIATE_REQUIRES_XTN 3=>SSL_RENEGOTIATE_TRANSITIONAL]\n"); exit(-1); } unsigned short port = atoi(argv[1]); requireSafeRenegotiation = (atoi(argv[2])==1)?PR_TRUE:PR_FALSE; /* 0=SSL_RENEGOTIATE_NEVER 1=SSL_RENEGOTIATE_UNRESTRICTED 2=SSL_RENEGOTIATE_REQUIRES_XTN 3=SSL_RENEGOTIATE_TRANSITIONAL */ enableRenegotiation= atoi(argv[3]); PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); SECStatus secStatus = NSS_Init("."); if (secStatus != SECSuccess) { printf("ERROR NSS_Init"); printError(); exit(-1); } secStatus = NSS_SetDomesticPolicy(); PK11_SetPasswordFunc(passwordArg); cert = PK11_FindCertFromNickname(nickName, passwordArg); if (cert == NULL) { printf("ERROR PK11_FindCertFromNickname returned NULL cert"); printError(); exit(-1);} privKey = PK11_FindKeyByAnyCert(cert, passwordArg); if (privKey == NULL) { printf("ERROR PK11_FindKeyByAnyCert has no priv key"); printError(); exit(-1);} SSL_ConfigMPServerSIDCache(256, 0, 0, NULL); PRFileDesc *listenSocket = PR_NewTCPSocket(); if (listenSocket == NULL) { printf("ERROR PR_NewTCPSocket"); printError(); exit(-1); } PRSocketOptionData socketOption; socketOption.option = PR_SockOpt_Nonblocking; socketOption.value.non_blocking = PR_FALSE; PRStatus prStatus = PR_SetSocketOption(listenSocket, &socketOption); if (prStatus != PR_SUCCESS) { printf("ERROR PR_SetSocketOption"); printError();} secStatus = SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_SHA, PR_TRUE); if (secStatus != SECSuccess) { printf("ERROR SSL_CipherPrefSetDefault:SSL_RSA_WITH_NULL_SHA"); exit(-1); } PRNetAddr addr; addr.inet.family = PR_AF_INET; addr.inet.ip = PR_INADDR_ANY; addr.inet.port = PR_htons(port); prStatus = PR_Bind(listenSocket, &addr); if (prStatus != PR_SUCCESS) { printf("ERROR PR_Bind"); printError(); exit(-1); } prStatus = PR_Listen(listenSocket, 5); if (prStatus != PR_SUCCESS) { printf("ERROR PR_Listen"); printError(); exit(-1); } PRNetAddr addr1; while (1) { fprintf(stderr, "\n\n\nAbout to call accept.\n"); PRFileDesc * tcpSocket = PR_Accept(listenSocket, &addr1, PR_INTERVAL_NO_TIMEOUT); fprintf(stderr, "\n\n\naccept succeeded.\n"); if (tcpSocket == NULL) { printf("WARNING PR_Accept"); printError(); break; } SECStatus result = handle_connection(tcpSocket); if (result != SECSuccess) break; } fprintf(stderr, "Info: Closing listen socket.\n"); prStatus = PR_Close(listenSocket); if (prStatus != PR_SUCCESS) { printf("ERROR PR_Close"); exit(-1); } if (NSS_Shutdown() != SECSuccess) { exit(-1); } PR_Cleanup(); return 0; }