import java.awt.*; import java.applet.*; import java.io.*; import java.lang.*; import java.net.*; import java.util.Date; // ---------------------------------------------------------------------------- // File: Flash.java // Date: March 28, 1996 // Purpose: // This file contains the public class Flash and its supporting classes // (TopPiece and BitString). This code implements the client side of a // client/server application. It handles all user interface resposibilities, // including: // - receiving and displaying the challenge from the server (both in the // form of a bar code and textual (numeric) representation // - accepting the users input as to their userid and the response generate // by the Access Key II, and passing that information onto the server // for validation. // - indicating the acceptance or denial of the entered information, if // accepted the user is sent on to the next Web page. // // // Authors: // Brian Odeen - Vasco Data Security // Roger Chen - TriNet Services, Inc. // Fred Burke - TriNet Services, Inc. // // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Class: Flash // Purpose: // // ---------------------------------------------------------------------------- public class Flash extends java.applet.Applet implements Runnable { // The following string is the only piece of code that needs to be altered // in this file. Set its value to be the portion of the URL path up to but // not including the directory 'flash'. Note that the trailing '/' will be // appened below where needed. String validationURL = "http://vdsi.trinet.com:80/flash/servauth.cgi"; String successURL = "http://vdsi.trinet.com:80/flash/start.html"; String title; String message; Font titleFont; Font msgfont; FontMetrics titleFontMetrics; int titleHeight = 15; // ChallengePanel cpnl; TopPiece tpx; Image picture; Thread kicker = null; BitString the_flash; int loopslot = 0; boolean threadSuspended = false; boolean restart = false; int period = 10; int operiod = 10; boolean do_i_paint = true; boolean entryallowed = false; boolean first = true; TextField user, rc; int columns = 4; int values[]; Object colors[]; Color bg_col; int size = 4; int scale = 6; int maxLabelWidth = 0; int max = 0; Image speed; Image wide; Image logo; Image triLogo; Image submit, reset; int cycle = 75; public synchronized void init() { String new_url; do_i_paint = true; bg_col = new Color(85, 85, 85); setLayout(new BorderLayout()); setBackground(bg_col); resize(440, 360); titleFont = new java.awt.Font("Courier", Font.BOLD, 12); titleFontMetrics = getFontMetrics(titleFont); title = "Access Key II Demo"; msgfont = new Font("TimesRoman",Font.BOLD,36); // Attempt to read the applet URL params from the web page new_url = this.getParameter("successURL"); if(new_url != null) successURL = new_url; new_url = this.getParameter("validationURL"); if(new_url != null) validationURL = new_url; picture = getImage(getCodeBase(), "images/authkey.gif"); speed = getImage(getCodeBase(), "images/rate.gif"); wide = getImage(getCodeBase(), "images/wide.gif"); triLogo = getImage(getCodeBase(), "images/trinet.gif"); logo = getImage(getCodeBase(), "images/VSDIrev.gif"); submit = getImage(getCodeBase(), "images/submit.gif"); reset = getImage(getCodeBase(), "images/reset.gif"); message = "Ready"; values = new int[columns]; colors = new Color[columns]; tpx = new TopPiece(); add("North", tpx); } public void start() { if (kicker == null) { kicker = new Thread(this); kicker.start(); } } public void stop() { kicker = null; } public void run() { int newdata; int dataside = 0; int state[] = new int[2]; int nextbit = 0; while (kicker != null) { dataside = 0; nextbit = 0; state[0] = 0; state[1] = 0; restart = false; Thread.currentThread().setPriority(Thread.MAX_PRIORITY); the_flash = new BitString(); //bpx.setChallengeText(the_flash.kpstring); //bpx.setChallengeText(Integer.toString(the_flash.GetRandnum())); while (restart == false && kicker != null) { newdata = the_flash.flashbits[nextbit]; if (newdata == state[dataside]) { dataside = 1 - dataside; nextbit++; if (nextbit >= the_flash.length) nextbit = 0; } state[dataside] = 1 - state[dataside]; loopslot = (state[0] * 2) + state[1]; if (do_i_paint == true) repaint(); if (entryallowed && !do_i_paint) { repaint(); try Thread.sleep(2000); catch (InterruptedException e){} newURL(successURL); // Now reset everything so that when we use the back // buttonto get to the challenge/response page it does // not immediately send you on again. do_i_paint = true; entryallowed = false; tpx.response.setText(""); } try { Thread.sleep(10 + period); } catch (InterruptedException e){} } } } public synchronized void update(Graphics g) { int center_x = 220; int org_x = 50, org_y = 80; int x1 = 0, x2 = 7, x3 = 10, x4 = 13; int w1 = 7, w2 = 3, w3 = 3, w4 = 7; int height = 70; char kpstmp[]; org_x = center_x - 10 * scale; x1 = scale * x1; x2 = scale * x2; x3 = scale * x3; x4 = scale * x4; w1 = scale * w1; w2 = scale * w2; w3 = scale * w3; w4 = scale * w4; //height = scale * height; if (do_i_paint == true) { switch (loopslot) { case 0: // present off/on/on/off g.setColor(Color.black); g.fillRect(org_x + x1, org_y, w1, height); g.fillRect(org_x + x4, org_y, w4, height); g.setColor(Color.white); g.fillRect(org_x + x2, org_y, w2, height); g.fillRect(org_x + x3, org_y, w3, height); break; case 1: // present off/on/off/on g.setColor(Color.black); g.fillRect(org_x + x1, org_y, w1, height); g.fillRect(org_x + x3, org_y, w3, height); g.setColor(Color.white); g.fillRect(org_x + x2, org_y, w2, height); g.fillRect(org_x + x4, org_y, w4, height); break; case 2: // present on/off/on/off g.setColor(Color.black); g.fillRect(org_x + x2, org_y, w2, height); g.fillRect(org_x + x4, org_y, w4, height); g.setColor(Color.white); g.fillRect(org_x + x1, org_y, w1, height); g.fillRect(org_x + x3, org_y, w3, height); break; case 3: // present on/off/off/on g.setColor(Color.black); g.fillRect(org_x + x2, org_y, w2, height); g.fillRect(org_x + x3, org_y, w3, height); g.setColor(Color.white); g.fillRect(org_x + x1, org_y, w1, height); g.fillRect(org_x + x4, org_y, w4, height); break; } } else { g.setColor(bg_col); g.fillRect(org_x,org_y,(w1+w2+w3+w4),height); g.setFont(msgfont); if (entryallowed == true) { //System.out.println("allowed"); g.setColor(Color.green); g.fillRect(org_x,org_y,(w1+w2+w3+w4),height); g.setColor(Color.black); g.drawString("Access",org_x+10,org_y+30); g.drawString("Allowed",org_x+10,org_y+60); } else { //System.out.println("denied"); g.setColor(Color.red); g.fillRect(org_x,org_y,(w1+w2+w3+w4),height); g.setColor(Color.black); g.drawString("Access",org_x+10,org_y+30); g.drawString("Denied",org_x+10,org_y+60); } //kicker.stop(); //kicker = null; } // // Draw challenge code on screen // g.setColor(new Color(0, 85, 85)); // g.fillRect(100, 55, 100, 15); g.setFont(titleFont); g.setColor(Color.white); g.drawString("Challenge: " + the_flash.kpstring, 40, 57); if(first || ++cycle == 100) { if(first) { g.setColor(new Color(85, 85, 85)); g.fillRect(0,0, 440,360); } paint(g); cycle = 0; } } // // newURL() - Force browser to open a new URL // Written: 27-MAR-96 RTC // private void newURL(String location) { URL currentURL = null; try { currentURL = new URL(location); } catch( MalformedURLException e ) { return; } if( currentURL != null ) { getAppletContext().showDocument( currentURL ); } } public void paint(Graphics g) { // this.setBackground(new Color(85, 85, 85)); g.drawImage(reset, 210, 40, this); g.drawImage(submit, 280, 40, this); g.drawImage(picture, 170, 170, this); g.drawImage(wide, 40, 80, this); g.drawImage(speed, 325, 80, this); g.drawImage(logo, 275, 190, this); g.drawImage(triLogo, 24, 190, this); if(threadSuspended) { g.setColor(Color.white); g.drawString("Applet Suspended", 160, 110); g.drawString("Click Here to resume", 150, 130); } first = false; } private void do_reset() { do_i_paint = true; entryallowed = false; period = operiod; message = "Ready"; restart = true; cycle = 90; } private void do_submit() { try { String vdsiArg = validationURL + "?userid=" + tpx.username.getText() + "&response=" + tpx.response.getText() + "&key=" + the_flash.GetRandnum(); //+ "?userid=testuser" //+ "&response=l5uu94" //+ "&key=1532"; URL vdsi = new URL(vdsiArg); DataInputStream dis; String inputLine; dis = new DataInputStream(vdsi.openStream()); inputLine = dis.readLine(); dis.close(); if ("0".equals(inputLine)) { // Access Accepted do_i_paint = false; entryallowed = true; } else { // Access Denied do_i_paint = false; entryallowed = false; } } catch (MalformedURLException me) { System.out.println("MalformedURLException: " + me); } catch (IOException ioe) { System.out.println("IOException: " + ioe); } repaint(); } public boolean mouseDown(java.awt.Event evt, int x, int y) { // showStatus("MouseDown: [" + x + "," + y + "]"); if(x > 325 && x < 400 && y > 80 && y < 110) { period -= 10; if(period < 10) period = 10; } else if(x > 325 && x < 400 && y > 125 && y < 150) { period += 10; } else if(x > 40 && x < 115 && y > 80 && y < 110) { if(++ scale > 20) scale = 20; } else if(x > 40 && x < 115 && y > 110 && y < 150) { scale --; if(scale < 2) scale = 1; } else if(x > 210 && x < 260 && y > 40 && y < 65) { this.do_reset(); } else if(x > 280 && x < 330 && y > 40 && y < 65) { this.do_submit(); return true; } else if(x > 24 && x < 132 && y > 190 && y < 334) { newURL("http://www.trinet.com/"); } else if(x > 295 && x < 420 && y > 190 && y < 330) { newURL("http://www.vdsi.com/"); } else { if (threadSuspended) kicker.resume(); else kicker.suspend(); threadSuspended = !threadSuspended; } first = true; repaint(); return true; } } // ---------------------------------------------------------------------------- // Class: TopPiece // Purpose: // // ---------------------------------------------------------------------------- class TopPiece extends Panel { TextField username, response; public TopPiece() { // setLayout(new BorderLayout()); this.setForeground(Color.white); add(new Label("USERNAME:")); add(username = new TextField("", 8)); username.setForeground(Color.white); add(new Label(" RESPONSE:")); add(response = new TextField("", 8)); response.setForeground(Color.white); this.setBackground(new Color(85, 85, 85)); } } // ---------------------------------------------------------------------------- // Class: // Purpose: // // ---------------------------------------------------------------------------- class BitString extends java.util.Date { int bits[]; int flashbits[]; String kpstring; int length = 0; int randnum = 0; /* Random # generated by Random */ BitString() { int StimLen=18; int Stim[] = new int[41]; /* plain bit string */ int Stim2[] = new int[41]; /* stuffed bit string */ int IStim[] = new int[41]; /* temporary copy if 'Stim' */ int Randnum = 0; int i, k = 0, j = 0; bits = new int[30]; flashbits = new int[30]; for(i=0; i < 40; i++) { Stim[i] = 0; Stim2[i] = 0; } randnum = (int)(2048 * Math.random()); Randnum = randnum; /* Place SYNC pattern into Stimulus vector. */ Stim[0] = 1; Stim[1] = 1; Stim[2] = 0; Stim[3] = 1; Stim[4] = 0; Stim[5] = 0; /* Place operation code into stimulus vector. */ Stim[6] = 1; /* Place random number into stimulus vector. */ for (i = 7 ; i < 17 ; ++i , Randnum >>=1) Stim[i] = Randnum & 1; /* append the CRC to Stim */ /* Initialize IStim vector, and clear checksum field. */ for (i = 0; i < StimLen ; ++i) IStim[i] = Stim[i]; for (i = StimLen; i < StimLen + 6 ; ++i) IStim[i] = 1; /* Compute the checksum. This operation destroys the stimulus. */ for (i = 6 ; i < StimLen ; ++i) { if ( IStim[i] == 1 ) { IStim[i+5] = 1 - IStim[i+5]; IStim[i+6] = 1 - IStim[i+6]; } } /* Copy CRC to parameter. */ for (i = StimLen; i < StimLen + 6; ++i) Stim[i] = IStim[i]; for (i=0;i<24;i++) bits[i] = Stim[i]; //PrintBitStr(bits, 24); /* add stuffing if necessary */ StimLen = 24; for (i = 0 ; i < 6; ++i) Stim2[i] = Stim[i]; for (i = 6 ,j = 6 , k = 0; i < StimLen; ++i) { /* once thru loop for each stimulus bit */ Stim2[j++] = Stim[i]; if ( Stim2[k] != Stim[i] ) k = 2 * Stim[i]; /* bit does not match sync -- reset 'k' */ else /* bit matches sync -- increment 'k' */ { if (++k == 5) { /* insert extra bit */ k = 1; Stim2[j++] = 1; } } } /* once thru loop for each stimulus bit */ for(i=0;i 0; i--) { if ((i%4) == 0) kpstring2[j++] = '-'; Digit = (Stim2[k] * 2 + Stim2[k+1]) * 2 + Stim2[k+2]; kpstring2[j++] = (char)('1' + Digit); k = k + 3; } kpstring2[j] = 0; kpstring = new String(kpstring2); //System.out.println(kpstring2); } int GetRandnum() { return randnum; } void PrintBitStr(int data[], int count) { int i; for (i=0; i