sslstrength.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:17k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #ifdef SSLTELNET
  34. #include <termios.h>
  35. #endif
  36. /* Portable layer header files */
  37. #include "prinit.h"
  38. #include "prprf.h"
  39. #include "prsystem.h"
  40. #include "prmem.h"
  41. #include "plstr.h"
  42. #include "prnetdb.h"
  43. #include "prinrval.h"
  44. #include "secutil.h"
  45. /* Security library files */
  46. #include "cert.h"
  47. #include "cdbhdl.h"
  48. #include "ssl.h"
  49. #include "sslproto.h"
  50. /* define this if you want telnet capability! */
  51. /* #define SSLTELNET 1 */
  52. PRInt32 debug;
  53. #ifdef DEBUG_stevep
  54. #define dbmsg(x) if (verbose) PR_fprintf(PR_STDOUT,x);
  55. #else
  56. #define dbmsg(x) ;
  57. #endif
  58. /* Set SSL Policy to Domestic (strong=1) or Export (strong=0) */
  59. #define ALLOW(x) SSL_SetPolicy(x,SSL_ALLOWED); SSL_EnableCipher(x,1);
  60. #define DISALLOW(x) SSL_SetPolicy(x,SSL_NOT_ALLOWED); SSL_EnableCipher(x,0);
  61. #define MAYBEALLOW(x) SSL_SetPolicy(x,SSL_RESTRICTED); SSL_EnableCipher(x,1);
  62. struct CipherPolicy {
  63.   char number;
  64.   long id;
  65.   char *name;
  66.   PRInt32 pref;
  67.   PRInt32 domestic;
  68.   PRInt32 export;
  69. };
  70. struct CipherPolicy ciphers[] = {
  71.   { 'a',SSL_EN_RC4_128_WITH_MD5,              "SSL_EN_RC4_128_WITH_MD5              (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
  72.   { 'b',SSL_EN_RC2_128_CBC_WITH_MD5,          "SSL_EN_RC2_128_CBC_WITH_MD5          (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },  
  73.   { 'c',SSL_EN_DES_192_EDE3_CBC_WITH_MD5,     "SSL_EN_DES_192_EDE3_CBC_WITH_MD5     (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
  74.   { 'd',SSL_EN_DES_64_CBC_WITH_MD5,           "SSL_EN_DES_64_CBC_WITH_MD5           (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
  75.   { 'e',SSL_EN_RC4_128_EXPORT40_WITH_MD5,     "SSL_EN_RC4_128_EXPORT40_WITH_MD5     (ssl2)",1, SSL_ALLOWED,SSL_ALLOWED },
  76.   { 'f',SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_ALLOWED },
  77. #ifdef FORTEZZA
  78.   { 'g',SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",1,SSL_ALLOWED,SSL_NOT_ALLOWED },
  79.   { 'h',SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, "SSL_FORTEZZA_DMS_WITH_RC4_128_SHA",1,          SSL_ALLOWED,SSL_NOT_ALLOWED },
  80. #endif
  81.   { 'i',SSL_RSA_WITH_RC4_128_MD5,             "SSL_RSA_WITH_RC4_128_MD5             (ssl3)",1, SSL_ALLOWED,SSL_RESTRICTED },
  82.   { 'j',SSL_RSA_WITH_3DES_EDE_CBC_SHA,        "SSL_RSA_WITH_3DES_EDE_CBC_SHA        (ssl3)",1, SSL_ALLOWED,SSL_RESTRICTED },
  83.   { 'k',SSL_RSA_WITH_DES_CBC_SHA,             "SSL_RSA_WITH_DES_CBC_SHA             (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
  84.   { 'l',SSL_RSA_EXPORT_WITH_RC4_40_MD5,       "SSL_RSA_EXPORT_WITH_RC4_40_MD5       (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
  85.   { 'm',SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,   "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5   (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
  86. #ifdef FORTEZZA
  87.   { 'n',SSL_FORTEZZA_DMS_WITH_NULL_SHA, "SSL_FORTEZZA_DMS_WITH_NULL_SHA",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
  88. #endif
  89.   { 'o',SSL_RSA_WITH_NULL_MD5,                "SSL_RSA_WITH_NULL_MD5                (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
  90.   { 'p',SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,   "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA   (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
  91.   { 'q',SSL_RSA_FIPS_WITH_DES_CBC_SHA,        "SSL_RSA_FIPS_WITH_DES_CBC_SHA        (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED }
  92. };
  93. void PrintErrString(char *progName,char *msg) {
  94.   
  95.   PRErrorCode e = PORT_GetError();
  96.   char *s=NULL;
  97.   if ((e >= PR_NSPR_ERROR_BASE) && (e < PR_MAX_ERROR)) {
  98.     
  99.     if (e == PR_DIRECTORY_LOOKUP_ERROR) 
  100.       s = PL_strdup("Hostname Lookup Failed");
  101.     else if (e == PR_NETWORK_UNREACHABLE_ERROR)
  102.       s = PL_strdup("Network Unreachable");
  103.     else if (e == PR_CONNECT_TIMEOUT_ERROR)
  104.       s = PL_strdup("Connection Timed Out");
  105.     else s = PR_smprintf("%d",e);
  106.     if (!s) return;
  107.   }
  108.   else {
  109.     s = PL_strdup(SECU_ErrorString(e));
  110.   }
  111.     
  112.   PR_fprintf(PR_STDOUT,"%s: ",progName);
  113.   if (s) {
  114.     if (strlen(s) > 0) 
  115.       PR_fprintf(PR_STDOUT, "%sn", s);
  116.     else
  117.       PR_fprintf(PR_STDOUT, "n");
  118.     
  119.     PR_Free(s);
  120.   }
  121.   
  122. }
  123. void PrintCiphers(int onlyenabled) {
  124.   int ciphercount,i;
  125.   
  126.   if (onlyenabled) {
  127.     PR_fprintf(PR_STDOUT,"Your Cipher preference:n");
  128.   }
  129.   ciphercount = sizeof(ciphers)/sizeof(struct CipherPolicy);
  130.     PR_fprintf(PR_STDOUT,
  131.        " %s    %-45s  %-12s %-12sn","id","CipherName","Domestic","Export");
  132.   for (i=0;i<ciphercount;i++) {
  133.     if ( (onlyenabled ==0) || ((onlyenabled==1)&&(ciphers[i].pref))) {
  134.       PR_fprintf(PR_STDOUT,
  135.  " %c     %-45s  %-12s %-12sn",ciphers[i].number,ciphers[i].name,
  136.  (ciphers[i].domestic==SSL_ALLOWED)?"Yes":
  137.  ( (ciphers[i].domestic==SSL_NOT_ALLOWED)?"No":"Step-up only"),
  138.  (ciphers[i].export==SSL_ALLOWED)?"Yes":
  139.  ( (ciphers[i].export==SSL_NOT_ALLOWED)?"No":"Step-up only"));
  140. }
  141.   }
  142. }
  143. void SetPolicy(char *c,int policy) {  /* policy==1 : domestic,   policy==0, export */
  144.   int i,j,cpolicy;
  145.   /* first, enable all relevant ciphers according to policy */
  146.   for (j=0;j<(sizeof(ciphers)/sizeof(struct CipherPolicy));j++) {
  147.     SSL_SetPolicy(ciphers[j].id,policy?ciphers[j].domestic:ciphers[j].export);
  148.     SSL_EnableCipher(ciphers[j].id,0);
  149.     ciphers[j].pref =0;
  150.   }
  151.   
  152.   for (i=0;i<PL_strlen(c);i++) {
  153.     for (j=0;j<(sizeof(ciphers)/sizeof(struct CipherPolicy));j++) {
  154.       if (ciphers[j].number == c[i]) {
  155. cpolicy = policy?ciphers[j].domestic:ciphers[j].export;
  156. if (cpolicy == SSL_NOT_ALLOWED) {
  157.   PR_fprintf(PR_STDOUT, "You're trying to enable a cipher (%c:%s) outside of your policy. ignoredn",
  158.      c[i],ciphers[j].name);
  159. }
  160. else {
  161.   ciphers[j].pref=1;
  162.   SSL_EnableCipher(ciphers[j].id,1);
  163. }
  164.       }
  165.     }
  166.   }
  167. }
  168. int MyAuthCertificateHook(void *arg, PRFileDesc *fd, PRBool checksig, PRBool isserver) {
  169.   return SECSuccess;
  170. }
  171. void Usage() {
  172. #ifdef SSLTELNET
  173.     PR_fprintf(PR_STDOUT,"SSLTelnet ");
  174. #else
  175.     PR_fprintf(PR_STDOUT,"SSLStrength (No telnet functionality) ");
  176. #endif
  177.     PR_fprintf(PR_STDOUT,"Version 1.5n");
  178.  
  179.     PR_fprintf(PR_STDOUT,"Usage:n   sslstrength hostname[:port] [ciphers=xyz] [certdir=x] [debug] [verbose] "
  180. #ifdef SSLTELNET
  181. "[telnet]|[servertype]|[querystring=<string>] "
  182. #endif
  183. "[policy=export|domestic]n   sslstrength ciphersn");
  184. }
  185. PRInt32 debug = 0;
  186. PRInt32 verbose = 0;
  187. PRInt32 main(PRInt32 argc,char **argv, char **envp)
  188. {
  189.   
  190.   /* defaults for command line arguments */
  191.   char *hostnamearg=NULL;
  192.   char *portnumarg=NULL;
  193.   char *sslversionarg=NULL;
  194.   char *keylenarg=NULL;
  195.   char *certdir=NULL;
  196.   char *hostname;
  197.   char *nickname=NULL;
  198.   char *progname=NULL;
  199.   /*  struct sockaddr_in addr; */
  200.   PRNetAddr addr;
  201.   int ss_on;
  202.   char *ss_cipher;
  203.   int ss_keysize;
  204.   int ss_secretsize;
  205.   char *ss_issuer;
  206.   char *ss_subject;
  207.   int policy=1;
  208.   char *set_ssl_policy=NULL;
  209.   int print_ciphers=0;
  210.   
  211.   char buf[10];
  212.   char netdbbuf[PR_NETDB_BUF_SIZE];
  213.   PRHostEnt hp;
  214.   PRStatus r;
  215.   PRNetAddr na;
  216.   SECStatus rv;
  217.   int portnum=443;   /* default https: port */
  218.   PRFileDesc *s,*fd;
  219.   
  220.   CERTCertDBHandle *handle;
  221.   CERTCertificate *c;
  222.   PRInt32 i;
  223. #ifdef SSLTELNET
  224.   struct termios tmp_tc;
  225.   char cb;
  226.   int prev_lflag,prev_oflag,prev_iflag;
  227.   int t_fin,t_fout;
  228.   int servertype=0, telnet=0;
  229.   char *querystring=NULL;
  230. #endif
  231.   debug = 0;
  232.   progname = (char *)PL_strrchr(argv[0], '/');
  233.   progname = progname ? progname+1 : argv[0];
  234.   /* Read in command line args */
  235.   if (argc == 1) {
  236.     Usage();
  237.     return(0);
  238.   }
  239.   
  240.   if (! PL_strcmp("ciphers",argv[1])) {
  241.     PrintCiphers(0);
  242.     exit(0);
  243.   }
  244.   hostname = argv[1];
  245.   if (!PL_strcmp(hostname , "usage") || !PL_strcmp(hostname, "-help") ) {
  246.     Usage();
  247.     exit(0);
  248.     }
  249.   if ((portnumarg = PL_strchr(hostname,':'))) {
  250.     *portnumarg = 0;
  251.     portnumarg = &portnumarg[1];
  252.   }
  253.   
  254.   if (portnumarg) {
  255.     if (PL_strlen(portnumarg) == 0) {
  256.       PR_fprintf(PR_STDOUT,"malformed port number suppliedn");
  257.       return(1);
  258.     }
  259.     portnum = atoi(portnumarg);
  260.   }
  261.   
  262.   for (i = 2  ; i < argc; i++)
  263.     {
  264.       if (!PL_strncmp(argv[i] , "sslversion=",11) )
  265. sslversionarg=&(argv[i][11]);
  266.       else if (!PL_strncmp(argv[i], "certdir=",8) )
  267. certdir = &(argv[i][8]);
  268.       else if (!PL_strncmp(argv[i], "ciphers=",8) )
  269. {
  270.   set_ssl_policy=&(argv[i][8]);
  271. }
  272.       else if (!PL_strncmp(argv[i], "policy=",7) ) {
  273. if (!PL_strcmp(&(argv[i][7]),"domestic")) policy=1;
  274. else if (!PL_strcmp(&(argv[i][7]),"export")) policy=0;
  275. else {
  276.   PR_fprintf(PR_STDOUT,"sslstrength: invalid argument. policy must be one of (domestic,export)n");
  277. }
  278.       }
  279.       else if (!PL_strcmp(argv[i] , "debug") )
  280. debug = 1;
  281. #ifdef SSLTELNET
  282.       else if (!PL_strcmp(argv[i] , "telnet") )
  283. telnet = 1;
  284.       else if (!PL_strcmp(argv[i] , "servertype") )
  285. servertype = 1;
  286.       else if (!PL_strncmp(argv[i] , "querystring=",11) )
  287. querystring = &argv[i][12];
  288. #endif
  289.       else if (!PL_strcmp(argv[i] , "verbose") )
  290. verbose = 1;
  291.     }
  292.   
  293. #ifdef SSLTELNET
  294.   if (telnet && (servertype || querystring)) {
  295.     PR_fprintf(PR_STDOUT,"You can't use telnet and (server or querystring) options at the same timen");
  296.     exit(1);
  297.   }
  298. #endif
  299.   PR_fprintf(PR_STDOUT,"Using %s policyn",policy?"domestic":"export");
  300.   
  301.   /* use current directory for certificate database if not set */
  302.   
  303.   if (! certdir) {   
  304.     certdir = PR_smprintf(".");
  305.   }
  306.   
  307.   SECU_ConfigDirectory(certdir);
  308.   
  309.   
  310.   /* allow you to set env var SSLDIR to set the cert directory */
  311.   if (! certdir) certdir = SECU_DefaultSSLDir();  
  312.   if (certdir) SECU_ConfigDirectory(certdir);
  313.   
  314.   /* PR_Init(progname, 1, 1, 0); */
  315.   SECU_PKCS11Init(PR_FALSE /*readOnly==PR_FALSE*/);
  316.   
  317.   /* Lookup host */
  318.   r = PR_GetHostByName(hostname,netdbbuf,PR_NETDB_BUF_SIZE,&hp);
  319.   
  320.   if (r) {
  321.     PrintErrString(progname,"Host Name lookup failed");
  322.     return(1);
  323.   }
  324.   
  325.   /* should the third field really be 0? */
  326.   PR_EnumerateHostEnt(0,&hp,0,&na);
  327.   PR_InitializeNetAddr(PR_IpAddrNull,portnum,&na);
  328.   PR_fprintf(PR_STDOUT,"Connecting to %s:%dn",hostname, portnum);
  329.   
  330.   /* Create socket */
  331.   fd = PR_NewTCPSocket();
  332.   if (fd == NULL) {
  333.     PrintErrString(progname, "error creating socket");
  334.     return -1;
  335.   }
  336.   s = SSL_ImportFD(NULL,fd);
  337.   if (s == NULL) {
  338.     PrintErrString(progname, "error creating socket");
  339.     return -1;
  340.   }
  341.   
  342.   /* Initialize all the libsec goodies */
  343.   SEC_Init();
  344.   
  345.   dbmsg("10: About to enable securityn");
  346.   
  347.   rv = SSL_Enable(s, SSL_SECURITY, 1);
  348.   if (rv < 0) {
  349.     PrintErrString(progname, "error enabling socket");
  350.     return -1;
  351.   }
  352.   
  353.   if (set_ssl_policy) {
  354.     SetPolicy(set_ssl_policy,policy);
  355.   }
  356.   else {
  357.     PR_fprintf(PR_STDOUT,"Using all ciphersuites usually found in clientn");
  358.     if (policy) {
  359.       SetPolicy("abcdefghijklmnopqrst",policy);
  360.     }
  361.     else {
  362.       SetPolicy("efghijlmo",policy);
  363.     }
  364.   }
  365.   PrintCiphers(1);
  366.   rv = SSL_Enable(s, SSL_HANDSHAKE_AS_CLIENT, 1);
  367.   if (rv < 0) {
  368.     PrintErrString(progname, "error enabling client handshake");
  369.     return -1;
  370.   }
  371.   
  372.   handle = (CERTCertDBHandle *)PORT_ZAlloc(sizeof(CERTCertDBHandle));
  373.   if (!handle) {
  374.     PrintErrString(progname, "could not allocate database handle");
  375.     return -1;
  376.   }
  377.   
  378.   dbmsg("20: About to open certificate databasen");
  379.   
  380.   
  381.   /* Open up the certificate database */
  382.   rv = CERT_OpenCertDBFilename(handle, "cert7.db", PR_TRUE);
  383.   if ( rv ) {
  384.     PrintErrString(progname, "unable to open cert database");
  385.     rv = CERT_OpenVolatileCertDB(handle);
  386.   }
  387.   
  388.      CERT_SetDefaultCertDB(handle);
  389.   
  390.   dbmsg("30: About to set AuthCertificateHookn");
  391.   
  392.   
  393.   SSL_AuthCertificateHook(s, MyAuthCertificateHook, (void *)handle);
  394.   /* SSL_AuthCertificateHook(s, SSL_AuthCertificate, (void *)handle); */
  395.   /* SSL_GetClientAuthDataHook(s, GetClientAuthDataHook, (void *)nickname);*/
  396.   
  397.   
  398.   dbmsg("40: About to SSLConnectn");
  399.   
  400.   /* Try to connect to the server */
  401.   /* now SSL_Connect takes new arguments. */
  402.   
  403.   
  404.   r = PR_Connect(s, &na, PR_TicksPerSecond()*5);
  405.   if (r < 0) {
  406.     PrintErrString(progname, "unable to connect");
  407.     return -1;
  408.   }
  409.   
  410.   rv = SSL_ForceHandshake(s);
  411.   
  412.   if (rv) {
  413.     PrintErrString(progname,"SSL Handshake failed. ");
  414.     exit(1);
  415.   }
  416.   rv = SSL_SecurityStatus(s, &ss_on, &ss_cipher,
  417.   &ss_keysize, &ss_secretsize,
  418.   &ss_issuer, &ss_subject);
  419.   
  420.   dbmsg("60:  done with security status, about to printn");
  421.   
  422.   c = SSL_PeerCertificate(s);
  423.   if (!c) PR_fprintf(PR_STDOUT,"Couldn't retrieve peers Certificaten");
  424.   PR_fprintf(PR_STDOUT,"SSL Connection Statusn",rv);
  425.   
  426.   PR_fprintf(PR_STDOUT,"   Cipher:          %sn",ss_cipher);
  427.   PR_fprintf(PR_STDOUT,"   Key Size:        %dn",ss_keysize);
  428.   PR_fprintf(PR_STDOUT,"   Secret Key Size: %dn",ss_secretsize);
  429.   PR_fprintf(PR_STDOUT,"   Issuer:          %sn",ss_issuer);
  430.   PR_fprintf(PR_STDOUT,"   Subject:         %sn",ss_subject);
  431.   PR_fprintf(PR_STDOUT,"   Valid:           from %s to %sn",
  432.      c==NULL?"???":DER_UTCDayToAscii(&c->validity.notBefore),
  433.      c==NULL?"???":DER_UTCDayToAscii(&c->validity.notAfter));
  434. #ifdef SSLTELNET
  435.  
  436.   if (servertype || querystring) {
  437.     char buffer[1024];
  438.     char ch;
  439.     char qs[] = "HEAD / HTTP/1.0";
  440.     if (!querystring) querystring = qs;
  441.     PR_fprintf(PR_STDOUT,"nServer query moden>>Sending:n%sn",querystring);
  442.     PR_fprintf(PR_STDOUT,"n*** Server said:n");
  443.     ch = querystring[PL_strlen(querystring)-1];
  444.     if (ch == '"' || ch == ''') {
  445.       PR_fprintf(PR_STDOUT,"Warning: I'm not smart enough to cope with quotes mid-string like thatn");
  446.     }
  447.     
  448.     rv = PR_Write(s,querystring,PL_strlen(querystring));
  449.     if ((rv < 1) ) {
  450.       PR_fprintf(PR_STDOUT,"Oh dear - couldn't send servertype queryn");
  451.       goto closedown;
  452.     }
  453.     rv = PR_Write(s,"rnrn",4);
  454.     rv = PR_Read(s,buffer,1024);
  455.     if ((rv < 1) ) {
  456.       PR_fprintf(PR_STDOUT,"Oh dear - couldn't read server repsonsen");
  457.       goto closedown;
  458.     }
  459.       PR_Write(PR_STDOUT,buffer,rv);
  460.   }
  461.     
  462.   if (telnet) {
  463.     PR_fprintf(PR_STDOUT,"---------------------------n"
  464.        "telnet mode. CTRL-C to exitn"
  465.        "---------------------------n");
  466.     
  467.     /* fudge terminal attributes */
  468.     t_fin = PR_FileDesc2NativeHandle(PR_STDIN);
  469.     t_fout = PR_FileDesc2NativeHandle(PR_STDOUT);
  470.     
  471.     tcgetattr(t_fin,&tmp_tc);
  472.     prev_lflag = tmp_tc.c_lflag;
  473.     prev_oflag = tmp_tc.c_oflag;
  474.     prev_iflag = tmp_tc.c_iflag;
  475.     tmp_tc.c_lflag &= ~ECHO;
  476.     /*    tmp_tc.c_oflag &= ~ONLCR; */
  477.     tmp_tc.c_lflag &= ~ICANON;
  478.     tmp_tc.c_iflag &= ~ICRNL;
  479.     tmp_tc.c_cflag |= CS8;
  480.     tmp_tc.c_cc[VMIN] = 1;
  481.     tmp_tc.c_cc[VTIME] = 0;
  482.     
  483.     tcsetattr(t_fin, TCSANOW, &tmp_tc);
  484.     /*   ioctl(tin, FIONBIO, (char *)&onoff); 
  485.  ioctl(tout, FIONBIO, (char *)&onoff);*/
  486.     
  487.     
  488.     {
  489.       PRPollDesc pds[2];
  490.       char buffer[1024];
  491.       int amt,amtwritten;
  492.       char *x;
  493.       
  494.       /* STDIN */
  495.       pds[0].fd = PR_STDIN;
  496.       pds[0].in_flags = PR_POLL_READ;
  497.       pds[1].fd = s;
  498.       pds[1].in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
  499.       
  500.       while (1) {
  501. int nfds;
  502. nfds = PR_Poll(pds,2,PR_SecondsToInterval(2));
  503. if (nfds == 0) continue;
  504. /** read input from keyboard*/
  505. /*  note: this is very inefficient if reading from a file */
  506. if (pds[0].out_flags & PR_POLL_READ) {
  507.   amt = PR_Read(PR_STDIN,&buffer,1);
  508.   /* PR_fprintf(PR_STDOUT,"fd[0]:%d=%drn",amt,buffer[0]); */
  509.   if (amt == 0) {
  510.     PR_fprintf(PR_STDOUT,"n");
  511.     goto loser;
  512.   }
  513.   
  514.   if (buffer[0] == 'r') {
  515.     buffer[0] = 'r';
  516.     buffer[1] = 'n';
  517.     amt = 2;
  518.   }
  519.   rv = PR_Write(PR_STDOUT,buffer,amt);
  520.   
  521.   
  522.   rv = PR_Write(s,buffer,amt);
  523.   if (rv == -1) {
  524.     PR_fprintf(PR_STDOUT,"Error writing to socket: %dn",PR_GetError());
  525.   }
  526. }
  527. /***/
  528. /***/
  529. if (pds[1].out_flags & PR_POLL_EXCEPT) {
  530.   PR_fprintf(PR_STDOUT,"rnServer closed connectionrn");
  531.   goto loser;
  532. }
  533. if (pds[1].out_flags & PR_POLL_READ) {
  534.   amt = PR_Read(s,&buffer,1024);
  535.   
  536.   if (amt == 0) {
  537.     PR_fprintf(PR_STDOUT,"rnServer closed connectionrn");
  538.     goto loser;
  539.   }
  540.   rv = PR_Write(PR_STDOUT,buffer,amt);
  541. }
  542. /***/
  543.       }
  544.     }
  545.   loser:
  546.     
  547.     /* set terminal back to normal */
  548.     tcgetattr(t_fin,&tmp_tc);
  549.     
  550.     tmp_tc.c_lflag = prev_lflag;
  551.     tmp_tc.c_oflag = prev_oflag;
  552.     tmp_tc.c_iflag = prev_iflag;
  553.     tcsetattr(t_fin, TCSANOW, &tmp_tc);
  554.     
  555.     /*   ioctl(tin, FIONBIO, (char *)&onoff);
  556.  ioctl(tout, FIONBIO, (char *)&onoff); */
  557.   }
  558. #endif
  559.   /* SSLTELNET */
  560.  closedown:
  561.   PR_Close(s);
  562.   return(0);
  563. } /* main */
  564. /*EOF*/