server.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 823 行 · 第 1/2 页

C
823
字号
		                           PR_TRANSMITFILE_KEEP_OPEN,		                           PR_INTERVAL_NO_TIMEOUT);		/* Error in transmission. */		if (numBytes < 0) {			errWarn("PR_TransmitFile");			/*			i = PORT_Strlen(errString);			PORT_Memcpy(buf, errString, i);			*/		/* Transmitted bytes successfully. */		} else {			numBytes -= headerLength;			fprintf(stderr, "PR_TransmitFile wrote %d bytes from %s\n",			        numBytes, fileName);		}		PORT_Free(fileName);		PR_Close(local_file_fd);	}writerequest:	/* Write a header to the socket. */	numBytes = PR_Write(sslSocket, reqhd, PORT_Strlen(reqhd));	if (numBytes < 0) {		errWarn("PR_Write");		goto loser;	}	/* Write the buffer data to the socket. */	if (buffer->index <= 0) {		/* Reached the EOF.  Report incomplete transaction to socket. */		PORT_Sprintf(messageBuffer,		             "GET or POST incomplete after %d bytes.\r\n",		             buffer->dataEnd);		numBytes = PR_Write(sslSocket, messageBuffer, 		                    PORT_Strlen(messageBuffer));		if (numBytes < 0) {			errWarn("PR_Write");			goto loser;		}	} else {		/* Display the buffer data. */		fwrite(buffer->data, 1, buffer->index, stdout);		/* Write the buffer data to the socket. */		numBytes = PR_Write(sslSocket, buffer->data, buffer->index);		if (numBytes < 0) {			errWarn("PR_Write");			goto loser;		}		/* Display security information for the socket. */		printSecurityInfo(sslSocket);		/* Write any discarded data out to the socket. */		if (buffer->index < buffer->dataEnd) {			PORT_Sprintf(buffer->data, "Discarded %d characters.\r\n", 			             buffer->dataEnd - buffer->index);			numBytes = PR_Write(sslSocket, buffer->data, 			                    PORT_Strlen(buffer->data));			if (numBytes < 0) {				errWarn("PR_Write");				goto loser;			}		}	}	/* Write a footer to the socket. */	numBytes = PR_Write(sslSocket, footer, PORT_Strlen(footer));	if (numBytes < 0) {		errWarn("PR_Write");		goto loser;	}	/* Write a link to the socket. */	numBytes = PR_Write(sslSocket, link, PORT_Strlen(link));	if (numBytes < 0) {		errWarn("PR_Write");		goto loser;	}	/* Complete the HTTP transaction. */	numBytes = PR_Write(sslSocket, "EOF\r\n\r\n\r\n", 9);	if (numBytes < 0) {		errWarn("PR_Write");		goto loser;	}	/* Do a nice shutdown if asked. */	if (!strncmp(buffer->data, stopCmd, strlen(stopCmd))) {		stopping = 1;	}	return SECSuccess;loser:	/* Do a nice shutdown if asked. */	if (!strncmp(buffer->data, stopCmd, strlen(stopCmd))) {		stopping = 1;	}	return SECFailure;}/* Function:  int handle_connection() * * Purpose:  Thread to handle a connection to a socket. * */SECStatushandle_connection(void *tcp_sock, int requestCert){	PRFileDesc *       tcpSocket = (PRFileDesc *)tcp_sock;	PRFileDesc *       sslSocket = NULL;	SECStatus          secStatus = SECFailure;	PRStatus           prStatus;	PRSocketOptionData socketOption;	DataBuffer         buffer;	char *             fileName = NULL;	/* Initialize the data buffer. */	memset(buffer.data, 0, BUFFER_SIZE);	buffer.remaining = BUFFER_SIZE;	buffer.index = 0;	buffer.dataStart = 0;	buffer.dataEnd = 0;	/* Make sure the socket is blocking. */	socketOption.option             = PR_SockOpt_Nonblocking;	socketOption.value.non_blocking = PR_FALSE;	PR_SetSocketOption(tcpSocket, &socketOption);	sslSocket = setupSSLSocket(tcpSocket, requestCert);	if (sslSocket == NULL) {		errWarn("setupSSLSocket");		goto cleanup;	}	secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_TRUE);	if (secStatus != SECSuccess) {		errWarn("SSL_ResetHandshake");		goto cleanup;	}	/* Read data from the socket, parse it for HTTP content.	 * If the user is requesting/requiring authentication, authenticate	 * the socket.  Then write the result back to the socket.  */	fprintf(stdout, "\nReading data from socket...\n\n");	secStatus = readDataFromSocket(sslSocket, &buffer, &fileName);	if (secStatus != SECSuccess) {		goto cleanup;	}	if (requestCert >= REQUEST_CERT_ALL) {		fprintf(stdout, "\nAuthentication requested.\n\n");		secStatus = authenticateSocket(sslSocket, 		                               (requestCert == REQUIRE_CERT_ALL));		if (secStatus != SECSuccess) {			goto cleanup;		}	}	fprintf(stdout, "\nWriting data to socket...\n\n");	secStatus = writeDataToSocket(sslSocket, &buffer, fileName);cleanup:	/* Close down the socket. */	prStatus = PR_Close(tcpSocket);	if (prStatus != PR_SUCCESS) {		errWarn("PR_Close");	}	return secStatus;}/* Function:  int accept_connection() * * Purpose:  Thread to accept a connection to the socket. * */SECStatusaccept_connection(void *listener, int requestCert){	PRFileDesc *listenSocket = (PRFileDesc*)listener;	PRNetAddr   addr;	PRStatus    prStatus;	/* XXX need an SSL socket here? */	while (!stopping) {		PRFileDesc *tcpSocket;		SECStatus	result;		fprintf(stderr, "\n\n\nAbout to call accept.\n");		/* Accept a connection to the socket. */		tcpSocket = PR_Accept(listenSocket, &addr, PR_INTERVAL_NO_TIMEOUT);		if (tcpSocket == NULL) {			errWarn("PR_Accept");			break;		}		/* Accepted the connection, now handle it. */		result = launch_thread(&threadMGR, handle_connection, 		                       tcpSocket, requestCert);		if (result != SECSuccess) {			prStatus = PR_Close(tcpSocket);			if (prStatus != PR_SUCCESS) {				exitErr("PR_Close");			}			break;		}	}	fprintf(stderr, "Closing listen socket.\n");	prStatus = PR_Close(listenSocket);	if (prStatus != PR_SUCCESS) {		exitErr("PR_Close");	}	return SECSuccess;}/* Function:  void server_main() * * Purpose:  This is the server's main function.  It configures a socket *			 and listens to it. * */voidserver_main(	unsigned short      port, 	int                 requestCert, 	SECKEYPrivateKey *  privKey,	CERTCertificate *   cert, 	PRBool              disableSSL3){	SECStatus           secStatus;	PRStatus            prStatus;	PRFileDesc *        listenSocket;	PRNetAddr           addr;	PRSocketOptionData  socketOption;	/* Create a new socket. */	listenSocket = PR_NewTCPSocket();	if (listenSocket == NULL) {		exitErr("PR_NewTCPSocket");	}	/* Set socket to be blocking -	 * on some platforms the default is nonblocking.	 */	socketOption.option = PR_SockOpt_Nonblocking;	socketOption.value.non_blocking = PR_FALSE;	prStatus = PR_SetSocketOption(listenSocket, &socketOption);	if (prStatus != PR_SUCCESS) {		exitErr("PR_SetSocketOption");	}	/* This cipher is not on by default. The Acceptance test	 * would like it to be. Turn this cipher on.	 */	secStatus = SSL_EnableCipher(SSL_RSA_WITH_NULL_MD5, PR_TRUE);	if (secStatus != SECSuccess) {		exitErr("SSL_EnableCipher:SSL_RSA_WITH_NULL_MD5");	}	/* Configure the network connection. */	addr.inet.family = PR_AF_INET;	addr.inet.ip	 = PR_INADDR_ANY;	addr.inet.port	 = PR_htons(port);	/* Bind the address to the listener socket. */	prStatus = PR_Bind(listenSocket, &addr);	if (prStatus != PR_SUCCESS) {		exitErr("PR_Bind");	}	/* Listen for connection on the socket.  The second argument is	 * the maximum size of the queue for pending connections.	 */	prStatus = PR_Listen(listenSocket, 5);	if (prStatus != PR_SUCCESS) {		exitErr("PR_Listen");	}	/* Launch thread to handle connections to the socket. */	secStatus = launch_thread(&threadMGR, accept_connection,                               listenSocket, requestCert);	if (secStatus != SECSuccess) {		PR_Close(listenSocket);	} else {		reap_threads(&threadMGR);		destroy_thread_data(&threadMGR);	}}/* Function: int main() * * Purpose:  Parses command arguments and configures SSL server. * */intmain(int argc, char **argv){	char *              progName      = NULL;	char *              nickName      = NULL;	char *              cipherString  = NULL;	char *              dir           = ".";	int                 requestCert   = 0;	unsigned short      port          = 0;	SECStatus           secStatus;	PRBool              disableSSL3   = PR_FALSE;	PLOptState *        optstate;	PLOptStatus         status;	/* Zero out the thread manager. */	PORT_Memset(&threadMGR, 0, sizeof(threadMGR));	progName = PL_strdup(argv[0]);	optstate = PL_CreateOptState(argc, argv, "3FRc:d:fp:n:rw:");	while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {		switch(optstate->option) {		case '3': disableSSL3 = PR_TRUE;                      break;		case 'F': requestCert = REQUIRE_CERT_ALL;             break;		case 'R': requestCert = REQUEST_CERT_ALL;             break;		case 'c': cipherString = PL_strdup(optstate->value);  break;		case 'd': dir = PL_strdup(optstate->value);           break;		case 'f': requestCert = REQUIRE_CERT_ONCE;            break;		case 'n': nickName = PL_strdup(optstate->value);      break;		case 'p': port = PORT_Atoi(optstate->value);          break;		case 'r': requestCert = REQUEST_CERT_ONCE;            break;		case 'w': password = PL_strdup(optstate->value);      break;		default:		case '?': Usage(progName);		}	}	if (nickName == NULL || port == 0)		Usage(progName);	/* Call the NSPR initialization routines. */	PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);	/* Set the cert database password callback. */	PK11_SetPasswordFunc(myPasswd);	/* Initialize NSS. */	secStatus = NSS_Init(dir);	if (secStatus != SECSuccess) {		exitErr("NSS_Init");	}	/* Set the policy for this server (REQUIRED - no default). */	secStatus = NSS_SetDomesticPolicy();	if (secStatus != SECSuccess) {		exitErr("NSS_SetDomesticPolicy");	}	/* XXX keep this? */	/* all the SSL2 and SSL3 cipher suites are enabled by default. */	if (cipherString) {		int ndx;		/* disable all the ciphers, then enable the ones we want. */		disableSSL2Ciphers();		disableSSL3Ciphers();		while (0 != (ndx = *cipherString++)) {			int *cptr;			int  cipher;			if (! isalpha(ndx))				Usage(progName);			cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;			for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; ) 				/* do nothing */;				if (cipher) {					SECStatus status;					status = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED);				if (status != SECSuccess) 					errWarn("SSL_CipherPrefSetDefault()");			}		}	}	/* Get own certificate and private key. */	cert = PK11_FindCertFromNickname(nickName, password);	if (cert == NULL) {		exitErr("PK11_FindCertFromNickname");	}	privKey = PK11_FindKeyByAnyCert(cert, password);	if (privKey == NULL) {		exitErr("PK11_FindKeyByAnyCert");	}	/* Configure the server's cache for a multi-process application	 * using default timeout values (24 hrs) and directory location (/tmp). 	 */	SSL_ConfigMPServerSIDCache(256, 0, 0, NULL);	/* Launch server. */	server_main(port, requestCert, privKey, cert, disableSSL3);	/* Shutdown NSS and exit NSPR gracefully. */	NSS_Shutdown();	PR_Cleanup();	return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?