sslstrength.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:17k
- /*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
- #ifdef SSLTELNET
- #include <termios.h>
- #endif
- /* Portable layer header files */
- #include "prinit.h"
- #include "prprf.h"
- #include "prsystem.h"
- #include "prmem.h"
- #include "plstr.h"
- #include "prnetdb.h"
- #include "prinrval.h"
- #include "secutil.h"
- /* Security library files */
- #include "cert.h"
- #include "cdbhdl.h"
- #include "ssl.h"
- #include "sslproto.h"
- /* define this if you want telnet capability! */
- /* #define SSLTELNET 1 */
- PRInt32 debug;
- #ifdef DEBUG_stevep
- #define dbmsg(x) if (verbose) PR_fprintf(PR_STDOUT,x);
- #else
- #define dbmsg(x) ;
- #endif
- /* Set SSL Policy to Domestic (strong=1) or Export (strong=0) */
- #define ALLOW(x) SSL_SetPolicy(x,SSL_ALLOWED); SSL_EnableCipher(x,1);
- #define DISALLOW(x) SSL_SetPolicy(x,SSL_NOT_ALLOWED); SSL_EnableCipher(x,0);
- #define MAYBEALLOW(x) SSL_SetPolicy(x,SSL_RESTRICTED); SSL_EnableCipher(x,1);
- struct CipherPolicy {
- char number;
- long id;
- char *name;
- PRInt32 pref;
- PRInt32 domestic;
- PRInt32 export;
- };
- struct CipherPolicy ciphers[] = {
- { 'a',SSL_EN_RC4_128_WITH_MD5, "SSL_EN_RC4_128_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
- { 'b',SSL_EN_RC2_128_CBC_WITH_MD5, "SSL_EN_RC2_128_CBC_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
- { 'c',SSL_EN_DES_192_EDE3_CBC_WITH_MD5, "SSL_EN_DES_192_EDE3_CBC_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
- { 'd',SSL_EN_DES_64_CBC_WITH_MD5, "SSL_EN_DES_64_CBC_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
- { 'e',SSL_EN_RC4_128_EXPORT40_WITH_MD5, "SSL_EN_RC4_128_EXPORT40_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_ALLOWED },
- { 'f',SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_ALLOWED },
- #ifdef FORTEZZA
- { 'g',SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",1,SSL_ALLOWED,SSL_NOT_ALLOWED },
- { 'h',SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, "SSL_FORTEZZA_DMS_WITH_RC4_128_SHA",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
- #endif
- { 'i',SSL_RSA_WITH_RC4_128_MD5, "SSL_RSA_WITH_RC4_128_MD5 (ssl3)",1, SSL_ALLOWED,SSL_RESTRICTED },
- { 'j',SSL_RSA_WITH_3DES_EDE_CBC_SHA, "SSL_RSA_WITH_3DES_EDE_CBC_SHA (ssl3)",1, SSL_ALLOWED,SSL_RESTRICTED },
- { 'k',SSL_RSA_WITH_DES_CBC_SHA, "SSL_RSA_WITH_DES_CBC_SHA (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
- { 'l',SSL_RSA_EXPORT_WITH_RC4_40_MD5, "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
- { 'm',SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
- #ifdef FORTEZZA
- { 'n',SSL_FORTEZZA_DMS_WITH_NULL_SHA, "SSL_FORTEZZA_DMS_WITH_NULL_SHA",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
- #endif
- { 'o',SSL_RSA_WITH_NULL_MD5, "SSL_RSA_WITH_NULL_MD5 (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
- { 'p',SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
- { 'q',SSL_RSA_FIPS_WITH_DES_CBC_SHA, "SSL_RSA_FIPS_WITH_DES_CBC_SHA (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED }
- };
- void PrintErrString(char *progName,char *msg) {
-
- PRErrorCode e = PORT_GetError();
- char *s=NULL;
- if ((e >= PR_NSPR_ERROR_BASE) && (e < PR_MAX_ERROR)) {
-
- if (e == PR_DIRECTORY_LOOKUP_ERROR)
- s = PL_strdup("Hostname Lookup Failed");
- else if (e == PR_NETWORK_UNREACHABLE_ERROR)
- s = PL_strdup("Network Unreachable");
- else if (e == PR_CONNECT_TIMEOUT_ERROR)
- s = PL_strdup("Connection Timed Out");
- else s = PR_smprintf("%d",e);
- if (!s) return;
- }
- else {
- s = PL_strdup(SECU_ErrorString(e));
- }
-
- PR_fprintf(PR_STDOUT,"%s: ",progName);
- if (s) {
- if (strlen(s) > 0)
- PR_fprintf(PR_STDOUT, "%sn", s);
- else
- PR_fprintf(PR_STDOUT, "n");
-
- PR_Free(s);
- }
-
- }
- void PrintCiphers(int onlyenabled) {
- int ciphercount,i;
-
- if (onlyenabled) {
- PR_fprintf(PR_STDOUT,"Your Cipher preference:n");
- }
- ciphercount = sizeof(ciphers)/sizeof(struct CipherPolicy);
- PR_fprintf(PR_STDOUT,
- " %s %-45s %-12s %-12sn","id","CipherName","Domestic","Export");
- for (i=0;i<ciphercount;i++) {
- if ( (onlyenabled ==0) || ((onlyenabled==1)&&(ciphers[i].pref))) {
- PR_fprintf(PR_STDOUT,
- " %c %-45s %-12s %-12sn",ciphers[i].number,ciphers[i].name,
- (ciphers[i].domestic==SSL_ALLOWED)?"Yes":
- ( (ciphers[i].domestic==SSL_NOT_ALLOWED)?"No":"Step-up only"),
- (ciphers[i].export==SSL_ALLOWED)?"Yes":
- ( (ciphers[i].export==SSL_NOT_ALLOWED)?"No":"Step-up only"));
- }
- }
- }
- void SetPolicy(char *c,int policy) { /* policy==1 : domestic, policy==0, export */
- int i,j,cpolicy;
- /* first, enable all relevant ciphers according to policy */
- for (j=0;j<(sizeof(ciphers)/sizeof(struct CipherPolicy));j++) {
- SSL_SetPolicy(ciphers[j].id,policy?ciphers[j].domestic:ciphers[j].export);
- SSL_EnableCipher(ciphers[j].id,0);
- ciphers[j].pref =0;
- }
-
- for (i=0;i<PL_strlen(c);i++) {
- for (j=0;j<(sizeof(ciphers)/sizeof(struct CipherPolicy));j++) {
- if (ciphers[j].number == c[i]) {
- cpolicy = policy?ciphers[j].domestic:ciphers[j].export;
- if (cpolicy == SSL_NOT_ALLOWED) {
- PR_fprintf(PR_STDOUT, "You're trying to enable a cipher (%c:%s) outside of your policy. ignoredn",
- c[i],ciphers[j].name);
- }
- else {
- ciphers[j].pref=1;
- SSL_EnableCipher(ciphers[j].id,1);
- }
- }
- }
- }
- }
- int MyAuthCertificateHook(void *arg, PRFileDesc *fd, PRBool checksig, PRBool isserver) {
- return SECSuccess;
- }
- void Usage() {
- #ifdef SSLTELNET
- PR_fprintf(PR_STDOUT,"SSLTelnet ");
- #else
- PR_fprintf(PR_STDOUT,"SSLStrength (No telnet functionality) ");
- #endif
- PR_fprintf(PR_STDOUT,"Version 1.5n");
-
- PR_fprintf(PR_STDOUT,"Usage:n sslstrength hostname[:port] [ciphers=xyz] [certdir=x] [debug] [verbose] "
- #ifdef SSLTELNET
- "[telnet]|[servertype]|[querystring=<string>] "
- #endif
- "[policy=export|domestic]n sslstrength ciphersn");
- }
- PRInt32 debug = 0;
- PRInt32 verbose = 0;
- PRInt32 main(PRInt32 argc,char **argv, char **envp)
- {
-
- /* defaults for command line arguments */
- char *hostnamearg=NULL;
- char *portnumarg=NULL;
- char *sslversionarg=NULL;
- char *keylenarg=NULL;
- char *certdir=NULL;
- char *hostname;
- char *nickname=NULL;
- char *progname=NULL;
- /* struct sockaddr_in addr; */
- PRNetAddr addr;
- int ss_on;
- char *ss_cipher;
- int ss_keysize;
- int ss_secretsize;
- char *ss_issuer;
- char *ss_subject;
- int policy=1;
- char *set_ssl_policy=NULL;
- int print_ciphers=0;
-
- char buf[10];
- char netdbbuf[PR_NETDB_BUF_SIZE];
- PRHostEnt hp;
- PRStatus r;
- PRNetAddr na;
- SECStatus rv;
- int portnum=443; /* default https: port */
- PRFileDesc *s,*fd;
-
- CERTCertDBHandle *handle;
- CERTCertificate *c;
- PRInt32 i;
- #ifdef SSLTELNET
- struct termios tmp_tc;
- char cb;
- int prev_lflag,prev_oflag,prev_iflag;
- int t_fin,t_fout;
- int servertype=0, telnet=0;
- char *querystring=NULL;
- #endif
- debug = 0;
- progname = (char *)PL_strrchr(argv[0], '/');
- progname = progname ? progname+1 : argv[0];
- /* Read in command line args */
- if (argc == 1) {
- Usage();
- return(0);
- }
-
- if (! PL_strcmp("ciphers",argv[1])) {
- PrintCiphers(0);
- exit(0);
- }
- hostname = argv[1];
- if (!PL_strcmp(hostname , "usage") || !PL_strcmp(hostname, "-help") ) {
- Usage();
- exit(0);
- }
- if ((portnumarg = PL_strchr(hostname,':'))) {
- *portnumarg = 0;
- portnumarg = &portnumarg[1];
- }
-
- if (portnumarg) {
- if (PL_strlen(portnumarg) == 0) {
- PR_fprintf(PR_STDOUT,"malformed port number suppliedn");
- return(1);
- }
- portnum = atoi(portnumarg);
- }
-
- for (i = 2 ; i < argc; i++)
- {
- if (!PL_strncmp(argv[i] , "sslversion=",11) )
- sslversionarg=&(argv[i][11]);
- else if (!PL_strncmp(argv[i], "certdir=",8) )
- certdir = &(argv[i][8]);
- else if (!PL_strncmp(argv[i], "ciphers=",8) )
- {
- set_ssl_policy=&(argv[i][8]);
- }
- else if (!PL_strncmp(argv[i], "policy=",7) ) {
- if (!PL_strcmp(&(argv[i][7]),"domestic")) policy=1;
- else if (!PL_strcmp(&(argv[i][7]),"export")) policy=0;
- else {
- PR_fprintf(PR_STDOUT,"sslstrength: invalid argument. policy must be one of (domestic,export)n");
- }
- }
- else if (!PL_strcmp(argv[i] , "debug") )
- debug = 1;
- #ifdef SSLTELNET
- else if (!PL_strcmp(argv[i] , "telnet") )
- telnet = 1;
- else if (!PL_strcmp(argv[i] , "servertype") )
- servertype = 1;
- else if (!PL_strncmp(argv[i] , "querystring=",11) )
- querystring = &argv[i][12];
- #endif
- else if (!PL_strcmp(argv[i] , "verbose") )
- verbose = 1;
- }
-
- #ifdef SSLTELNET
- if (telnet && (servertype || querystring)) {
- PR_fprintf(PR_STDOUT,"You can't use telnet and (server or querystring) options at the same timen");
- exit(1);
- }
- #endif
- PR_fprintf(PR_STDOUT,"Using %s policyn",policy?"domestic":"export");
-
- /* use current directory for certificate database if not set */
-
- if (! certdir) {
- certdir = PR_smprintf(".");
- }
-
- SECU_ConfigDirectory(certdir);
-
-
- /* allow you to set env var SSLDIR to set the cert directory */
- if (! certdir) certdir = SECU_DefaultSSLDir();
- if (certdir) SECU_ConfigDirectory(certdir);
-
- /* PR_Init(progname, 1, 1, 0); */
- SECU_PKCS11Init(PR_FALSE /*readOnly==PR_FALSE*/);
-
- /* Lookup host */
- r = PR_GetHostByName(hostname,netdbbuf,PR_NETDB_BUF_SIZE,&hp);
-
- if (r) {
- PrintErrString(progname,"Host Name lookup failed");
- return(1);
- }
-
- /* should the third field really be 0? */
- PR_EnumerateHostEnt(0,&hp,0,&na);
- PR_InitializeNetAddr(PR_IpAddrNull,portnum,&na);
- PR_fprintf(PR_STDOUT,"Connecting to %s:%dn",hostname, portnum);
-
- /* Create socket */
- fd = PR_NewTCPSocket();
- if (fd == NULL) {
- PrintErrString(progname, "error creating socket");
- return -1;
- }
- s = SSL_ImportFD(NULL,fd);
- if (s == NULL) {
- PrintErrString(progname, "error creating socket");
- return -1;
- }
-
- /* Initialize all the libsec goodies */
- SEC_Init();
-
- dbmsg("10: About to enable securityn");
-
- rv = SSL_Enable(s, SSL_SECURITY, 1);
- if (rv < 0) {
- PrintErrString(progname, "error enabling socket");
- return -1;
- }
-
- if (set_ssl_policy) {
- SetPolicy(set_ssl_policy,policy);
- }
- else {
- PR_fprintf(PR_STDOUT,"Using all ciphersuites usually found in clientn");
- if (policy) {
- SetPolicy("abcdefghijklmnopqrst",policy);
- }
- else {
- SetPolicy("efghijlmo",policy);
- }
- }
- PrintCiphers(1);
- rv = SSL_Enable(s, SSL_HANDSHAKE_AS_CLIENT, 1);
- if (rv < 0) {
- PrintErrString(progname, "error enabling client handshake");
- return -1;
- }
-
- handle = (CERTCertDBHandle *)PORT_ZAlloc(sizeof(CERTCertDBHandle));
- if (!handle) {
- PrintErrString(progname, "could not allocate database handle");
- return -1;
- }
-
- dbmsg("20: About to open certificate databasen");
-
-
- /* Open up the certificate database */
- rv = CERT_OpenCertDBFilename(handle, "cert7.db", PR_TRUE);
- if ( rv ) {
- PrintErrString(progname, "unable to open cert database");
- rv = CERT_OpenVolatileCertDB(handle);
- }
-
- CERT_SetDefaultCertDB(handle);
-
- dbmsg("30: About to set AuthCertificateHookn");
-
-
- SSL_AuthCertificateHook(s, MyAuthCertificateHook, (void *)handle);
- /* SSL_AuthCertificateHook(s, SSL_AuthCertificate, (void *)handle); */
- /* SSL_GetClientAuthDataHook(s, GetClientAuthDataHook, (void *)nickname);*/
-
-
- dbmsg("40: About to SSLConnectn");
-
- /* Try to connect to the server */
- /* now SSL_Connect takes new arguments. */
-
-
- r = PR_Connect(s, &na, PR_TicksPerSecond()*5);
- if (r < 0) {
- PrintErrString(progname, "unable to connect");
- return -1;
- }
-
- rv = SSL_ForceHandshake(s);
-
- if (rv) {
- PrintErrString(progname,"SSL Handshake failed. ");
- exit(1);
- }
- rv = SSL_SecurityStatus(s, &ss_on, &ss_cipher,
- &ss_keysize, &ss_secretsize,
- &ss_issuer, &ss_subject);
-
- dbmsg("60: done with security status, about to printn");
-
- c = SSL_PeerCertificate(s);
- if (!c) PR_fprintf(PR_STDOUT,"Couldn't retrieve peers Certificaten");
- PR_fprintf(PR_STDOUT,"SSL Connection Statusn",rv);
-
- PR_fprintf(PR_STDOUT," Cipher: %sn",ss_cipher);
- PR_fprintf(PR_STDOUT," Key Size: %dn",ss_keysize);
- PR_fprintf(PR_STDOUT," Secret Key Size: %dn",ss_secretsize);
- PR_fprintf(PR_STDOUT," Issuer: %sn",ss_issuer);
- PR_fprintf(PR_STDOUT," Subject: %sn",ss_subject);
- PR_fprintf(PR_STDOUT," Valid: from %s to %sn",
- c==NULL?"???":DER_UTCDayToAscii(&c->validity.notBefore),
- c==NULL?"???":DER_UTCDayToAscii(&c->validity.notAfter));
- #ifdef SSLTELNET
-
- if (servertype || querystring) {
- char buffer[1024];
- char ch;
- char qs[] = "HEAD / HTTP/1.0";
- if (!querystring) querystring = qs;
- PR_fprintf(PR_STDOUT,"nServer query moden>>Sending:n%sn",querystring);
- PR_fprintf(PR_STDOUT,"n*** Server said:n");
- ch = querystring[PL_strlen(querystring)-1];
- if (ch == '"' || ch == ''') {
- PR_fprintf(PR_STDOUT,"Warning: I'm not smart enough to cope with quotes mid-string like thatn");
- }
-
- rv = PR_Write(s,querystring,PL_strlen(querystring));
- if ((rv < 1) ) {
- PR_fprintf(PR_STDOUT,"Oh dear - couldn't send servertype queryn");
- goto closedown;
- }
- rv = PR_Write(s,"rnrn",4);
- rv = PR_Read(s,buffer,1024);
- if ((rv < 1) ) {
- PR_fprintf(PR_STDOUT,"Oh dear - couldn't read server repsonsen");
- goto closedown;
- }
- PR_Write(PR_STDOUT,buffer,rv);
- }
-
- if (telnet) {
- PR_fprintf(PR_STDOUT,"---------------------------n"
- "telnet mode. CTRL-C to exitn"
- "---------------------------n");
-
- /* fudge terminal attributes */
- t_fin = PR_FileDesc2NativeHandle(PR_STDIN);
- t_fout = PR_FileDesc2NativeHandle(PR_STDOUT);
-
- tcgetattr(t_fin,&tmp_tc);
- prev_lflag = tmp_tc.c_lflag;
- prev_oflag = tmp_tc.c_oflag;
- prev_iflag = tmp_tc.c_iflag;
- tmp_tc.c_lflag &= ~ECHO;
- /* tmp_tc.c_oflag &= ~ONLCR; */
- tmp_tc.c_lflag &= ~ICANON;
- tmp_tc.c_iflag &= ~ICRNL;
- tmp_tc.c_cflag |= CS8;
- tmp_tc.c_cc[VMIN] = 1;
- tmp_tc.c_cc[VTIME] = 0;
-
- tcsetattr(t_fin, TCSANOW, &tmp_tc);
- /* ioctl(tin, FIONBIO, (char *)&onoff);
- ioctl(tout, FIONBIO, (char *)&onoff);*/
-
-
- {
- PRPollDesc pds[2];
- char buffer[1024];
- int amt,amtwritten;
- char *x;
-
- /* STDIN */
- pds[0].fd = PR_STDIN;
- pds[0].in_flags = PR_POLL_READ;
- pds[1].fd = s;
- pds[1].in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
-
- while (1) {
- int nfds;
- nfds = PR_Poll(pds,2,PR_SecondsToInterval(2));
- if (nfds == 0) continue;
- /** read input from keyboard*/
- /* note: this is very inefficient if reading from a file */
-
- if (pds[0].out_flags & PR_POLL_READ) {
- amt = PR_Read(PR_STDIN,&buffer,1);
- /* PR_fprintf(PR_STDOUT,"fd[0]:%d=%drn",amt,buffer[0]); */
- if (amt == 0) {
- PR_fprintf(PR_STDOUT,"n");
- goto loser;
- }
-
- if (buffer[0] == 'r') {
- buffer[0] = 'r';
- buffer[1] = 'n';
- amt = 2;
- }
- rv = PR_Write(PR_STDOUT,buffer,amt);
-
-
- rv = PR_Write(s,buffer,amt);
- if (rv == -1) {
- PR_fprintf(PR_STDOUT,"Error writing to socket: %dn",PR_GetError());
- }
- }
-
- /***/
-
-
- /***/
- if (pds[1].out_flags & PR_POLL_EXCEPT) {
- PR_fprintf(PR_STDOUT,"rnServer closed connectionrn");
- goto loser;
- }
- if (pds[1].out_flags & PR_POLL_READ) {
- amt = PR_Read(s,&buffer,1024);
-
- if (amt == 0) {
- PR_fprintf(PR_STDOUT,"rnServer closed connectionrn");
- goto loser;
- }
- rv = PR_Write(PR_STDOUT,buffer,amt);
- }
- /***/
-
- }
- }
- loser:
-
- /* set terminal back to normal */
- tcgetattr(t_fin,&tmp_tc);
-
- tmp_tc.c_lflag = prev_lflag;
- tmp_tc.c_oflag = prev_oflag;
- tmp_tc.c_iflag = prev_iflag;
- tcsetattr(t_fin, TCSANOW, &tmp_tc);
-
- /* ioctl(tin, FIONBIO, (char *)&onoff);
- ioctl(tout, FIONBIO, (char *)&onoff); */
- }
- #endif
- /* SSLTELNET */
- closedown:
- PR_Close(s);
- return(0);
- } /* main */
- /*EOF*/