@Override
  public void contextDestroyed(ServletContextEvent sce) {
    TerminalManager terminalManager =
        (TerminalManager) sce.getServletContext().getAttribute(TerminalManager.class.getName());

    terminalManager.shutdown();
  }
Esempio n. 2
0
  /** Force disconnection of this terminal bridge. */
  public void dispatchDisconnect(boolean immediate) {
    // We don't need to do this multiple times.
    synchronized (this) {
      if (disconnected && !immediate) return;

      disconnected = true;
    }

    // Cancel any pending prompts.
    promptHelper.cancelPrompt();

    // disconnection request hangs if we havent really connected to a host yet
    // temporary fix is to just spawn disconnection into a thread
    Thread disconnectThread =
        new Thread(
            new Runnable() {
              public void run() {
                if (transport != null && transport.isConnected()) transport.close();
              }
            });
    disconnectThread.setName("Disconnect");
    disconnectThread.start();

    if (immediate) {
      awaitingClose = true;
      if (disconnectListener != null) disconnectListener.onDisconnected(TerminalBridge.this);
    } else {
      {
        final String line = manager.res.getString(R.string.alert_disconnect_msg);
        ((vt320) buffer).putString("\r\n" + line + "\r\n");
      }
      if (host.getStayConnected()) {
        manager.requestReconnect(this);
        return;
      }
      Thread disconnectPromptThread =
          new Thread(
              new Runnable() {
                public void run() {
                  Boolean result =
                      promptHelper.requestBooleanPrompt(
                          null, manager.res.getString(R.string.prompt_host_disconnected));
                  if (result == null || result.booleanValue()) {
                    awaitingClose = true;

                    // Tell the TerminalManager that we can be destroyed now.
                    if (disconnectListener != null)
                      disconnectListener.onDisconnected(TerminalBridge.this);
                  }
                }
              });
      disconnectPromptThread.setName("DisconnectPrompt");
      disconnectPromptThread.setDaemon(true);
      disconnectPromptThread.start();
    }
  }
Esempio n. 3
0
  @Override
  public void run() {
    while (!requestStopFlag) {
      List<ClientTerminal> list = TerminalManager.getInstance().queueTerminal();
      log.info(" Scan client terminals size: " + list.size());
      for (ClientTerminal ter : list) {
        boolean triggerTimeout = false;
        boolean remove = false;
        synchronized (ter) {
          if (ter.isTimeout()) {
            if ((System.currentTimeMillis() - ter.getTimeout()) / 1000 > 20) {
              triggerTimeout = true;
              remove = true;
            }
          } else {
            if ((System.currentTimeMillis() - ter.lastUpdate) / 1000 > 40) {
              triggerTimeout = true;
              ter.setTimeout(true);
            }
          }
        }

        if (triggerTimeout) {
          ter.postEvent(new TimeoutEvent());
        }
        if (remove) {
          TerminalManager.getInstance().removeTerminal(ter.token);
        }

        log.info(" Terminal " + ter + "   remove:" + remove + "  timeout:" + triggerTimeout + "");
      }

      synchronized (this) {
        try {
          wait(10000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
Esempio n. 4
0
  private static void work(CardTerminal reader, OptionSet args) throws CardException {
    if (!reader.isCardPresent()) {
      System.out.println("No card in " + reader.getName());
      return;
    }

    FileOutputStream o = null;
    if (args.has(OPT_DUMP)) {
      try {
        o = new FileOutputStream((File) args.valueOf(OPT_DUMP));
      } catch (FileNotFoundException e) {
        System.err.println("Can not dump to " + args.valueOf(OPT_DUMP));
      }
    }
    reader = LoggingCardTerminal.getInstance(reader, o);
    // This allows to override the protocol for RemoteTerminal as well.
    final String protocol;
    if (args.has(OPT_T0)) {
      protocol = "T=0";
    } else if (args.has(OPT_T1)) {
      protocol = "T=1";
    } else {
      protocol = "*";
    }
    if (args.has(CMD_APDU)) {

      Card c = null;
      try {
        c = reader.connect(protocol);

        if (args.has(CMD_APDU)) {
          for (Object s : args.valuesOf(CMD_APDU)) {
            CommandAPDU a = new CommandAPDU(HexUtils.stringToBin((String) s));
            ResponseAPDU r = c.getBasicChannel().transmit(a);
            if (args.has(OPT_ERROR) && r.getSW() != 0x9000) {
              System.out.println(
                  "Card returned " + String.format("%04X", r.getSW()) + ", exiting!");
              return;
            }
          }
        }
      } catch (CardException e) {
        if (TerminalManager.getExceptionMessage(e) != null) {
          System.out.println("PC/SC failure: " + TerminalManager.getExceptionMessage(e));
        } else {
          throw e;
        }
      } finally {
        if (c != null) {
          c.disconnect(true);
        }
      }
    } else if (args.has(OPT_CONNECT)) {
      String remote = (String) args.valueOf(OPT_CONNECT);
      JSONMessagePipe transport = null;

      try {
        if (remote.startsWith("http://") || remote.startsWith("https://")) {
          if (args.has(OPT_PINNED)) {
            transport =
                HTTPTransport.open(
                    new URL(remote), certFromPEM(((File) args.valueOf(OPT_PINNED)).getPath()));
          } else {
            transport = HTTPTransport.open(new URL(remote), null);
          }
        } else {
          transport = SocketTransport.connect(string2socket(remote), null);
        }

        // Connect the transport and the terminal
        CmdlineRemoteTerminal c = new CmdlineRemoteTerminal(transport, reader);
        c.forceProtocol(protocol);
        // Run
        c.run();
      } catch (IOException e) {
        System.err.println("Communication error: " + e.getMessage());
      } finally {
        if (transport != null) transport.close();
      }
    }
  }
Esempio n. 5
0
  public static void main(String[] argv) throws Exception {
    OptionSet args = parseOptions(argv);

    if (args.has(OPT_VERBOSE)) {
      verbose = true;
      // Set up slf4j simple in a way that pleases us
      System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug");
      System.setProperty("org.slf4j.simpleLogger.showThreadName", "true");
      System.setProperty("org.slf4j.simpleLogger.showShortLogName", "true");
      System.setProperty("org.slf4j.simpleLogger.levelInBrackets", "true");
    } else {
      System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "warn");
    }

    if (args.has(OPT_VERSION)) {
      String version = "apdu4j " + getVersion(SCTool.class);
      // Append host information
      version += "\nRunning on " + System.getProperty("os.name");
      version += " " + System.getProperty("os.version");
      version += " " + System.getProperty("os.arch");
      version += ", Java " + System.getProperty("java.version");
      version += " by " + System.getProperty("java.vendor");
      System.out.println(version);
    }
    if (args.has(OPT_TEST_SERVER)) {
      // TODO: have the possibility to run SocketServer as well?
      RemoteTerminalServer srv = new RemoteTerminalServer(TestServer.class);
      srv.start(string2socket((String) args.valueOf(OPT_TEST_SERVER)));
      System.console().readLine("Press enter to stop\n");
      srv.stop(1);
      System.exit(0);
    }

    // List TerminalFactory providers
    if (args.has(OPT_PROVIDERS)) {
      Provider providers[] = Security.getProviders("TerminalFactory.PC/SC");
      if (providers != null) {
        System.out.println("Existing TerminalFactory providers:");
        for (Provider p : providers) {
          System.out.println(p.getName());
        }
      }
    }

    // Fix properties on non-windows platforms
    TerminalManager.fixPlatformPaths();

    // Only applies to SunPCSC
    if (args.has(OPT_NO_GET_RESPONSE)) {
      System.setProperty("sun.security.smartcardio.t0GetResponse", "false");
      System.setProperty("sun.security.smartcardio.t1GetResponse", "false");
    }

    // Override PC/SC library path
    if (args.has(OPT_LIB)) {
      System.setProperty("sun.security.smartcardio.library", (String) args.valueOf(OPT_LIB));
    }

    TerminalFactory tf = null;
    CardTerminals terminals = null;

    try {
      // Get a terminal factory
      if (args.has(OPT_PROVIDER)) {
        String pn = (String) args.valueOf(OPT_PROVIDER);
        String pt = (String) args.valueOf(OPT_PROVIDER_TYPE);
        tf = loadFactory(pn, pt);
      } else if (args.has(OPT_SUN)) {
        tf = loadFactory(SUN_CLASS, null);
      } else if (args.has(OPT_JNA)) {
        tf = loadFactory(JNA_CLASS, null);
      } else {
        tf = TerminalFactory.getDefault();
      }

      if (verbose) {
        System.out.println(
            "# Using " + tf.getProvider().getClass().getCanonicalName() + " - " + tf.getProvider());
        if (System.getProperty(TerminalManager.lib_prop) != null) {
          System.out.println(
              "# " + TerminalManager.lib_prop + "=" + System.getProperty(TerminalManager.lib_prop));
        }
      }
      // Get all terminals
      terminals = tf.terminals();
    } catch (Exception e) {
      // XXX: we catch generic Exception here to avoid importing JNA.
      // Try to get a meaningful message
      String msg = TerminalManager.getExceptionMessage(e);
      if (msg == null) msg = e.getMessage();
      System.out.println("No readers: " + msg);
      System.exit(1);
    }

    // Terminals to work on
    List<CardTerminal> do_readers = new ArrayList<CardTerminal>();

    try {
      // List Terminals
      if (args.has(CMD_LIST)) {
        List<CardTerminal> terms = terminals.list();
        if (verbose) {
          System.out.println(
              "# Found " + terms.size() + " terminal" + (terms.size() == 1 ? "" : "s"));
        }
        if (terms.size() == 0) {
          System.err.println("No readers found");
          System.exit(1);
        }
        for (CardTerminal t : terms) {
          String vmd = " ";
          try (PinPadTerminal pp = new PinPadTerminal(t)) {
            pp.probe();
            // Verify, Modify, Display
            if (verbose) {
              vmd += "[";
              vmd += pp.canVerify() ? "V" : " ";
              vmd += pp.canModify() ? "M" : " ";
              vmd += pp.hasDisplay() ? "D" : " ";
              vmd += "] ";
            }
          } catch (CardException e) {
            if (verbose) {
              System.err.println("Could not probe PinPad: " + e.getMessage());
            }
          }

          System.out.println((t.isCardPresent() ? "[*]" : "[ ]") + vmd + t.getName());

          if (args.has(OPT_VERBOSE) && t.isCardPresent()) {
            Card c = t.connect("DIRECT");
            String atr = HexUtils.encodeHexString(c.getATR().getBytes()).toUpperCase();
            c.disconnect(false);
            System.out.println("          " + atr);
            if (args.has(OPT_WEB)) {
              String url = "http://smartcard-atr.appspot.com/parse?ATR=" + atr;
              if (Desktop.isDesktopSupported()) {
                Desktop.getDesktop().browse(new URI(url + "&from=apdu4j"));
              } else {
                System.out.println("          " + url);
              }
            }
          }
        }
      }

      // Select terminals to work on
      if (args.has(OPT_READER)) {
        String reader = (String) args.valueOf(OPT_READER);
        CardTerminal t = terminals.getTerminal(reader);
        if (t == null) {
          System.err.println("Reader \"" + reader + "\" not found.");
          System.exit(1);
        }
        do_readers = Arrays.asList(t);
      } else {
        do_readers = terminals.list(State.CARD_PRESENT);
        if (do_readers.size() > 1 && !args.hasArgument(OPT_ALL)) {
          System.err.println("More than one reader with a card found.");
          System.err.println("Run with --" + OPT_ALL + " to work with all found cards");
          System.exit(1);
        } else if (do_readers.size() == 0 && !args.has(CMD_LIST)) {
          // But if there is a single reader, wait for a card insertion
          List<CardTerminal> empty = terminals.list(State.CARD_ABSENT);
          if (empty.size() == 1 && args.has(OPT_WAIT)) {
            CardTerminal rdr = empty.get(0);
            System.out.println("Please enter a card into " + rdr.getName());
            if (!empty.get(0).waitForCardPresent(30000)) {
              System.out.println("Timeout.");
            } else {
              do_readers = Arrays.asList(rdr);
            }
          } else {
            System.err.println("No reader with a card found!");
            System.exit(1);
          }
        }
      }

    } catch (CardException e) {
      System.out.println("Could not list readers: " + TerminalManager.getExceptionMessage(e));
      e.printStackTrace();
    }

    for (CardTerminal t : do_readers) {
      work(t, args);
    }
  }
Esempio n. 6
0
  /**
   * Something changed in our parent {@link TerminalView}, maybe it's a new parent, or maybe it's an
   * updated font size. We should recalculate terminal size information and request a PTY resize.
   */
  public final synchronized void parentChanged(TerminalView parent) {
    if (manager != null && !manager.isResizeAllowed()) {
      Log.d(TAG, "Resize is not allowed now");
      return;
    }

    this.parent = parent;
    final int width = parent.getWidth();
    final int height = parent.getHeight();

    // Something has gone wrong with our layout; we're 0 width or height!
    if (width <= 0 || height <= 0) return;

    clipboard = (ClipboardManager) parent.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
    keyListener.setClipboardManager(clipboard);

    if (!forcedSize) {
      // recalculate buffer size
      int newColumns, newRows;

      newColumns = width / charWidth;
      newRows = height / charHeight;

      // If nothing has changed in the terminal dimensions and not an intial
      // draw then don't blow away scroll regions and such.
      if (newColumns == columns && newRows == rows) return;

      columns = newColumns;
      rows = newRows;
    }

    // reallocate new bitmap if needed
    boolean newBitmap = (bitmap == null);
    if (bitmap != null) newBitmap = (bitmap.getWidth() != width || bitmap.getHeight() != height);

    if (newBitmap) {
      discardBitmap();
      bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
      canvas.setBitmap(bitmap);
    }

    // clear out any old buffer information
    defaultPaint.setColor(Color.BLACK);
    canvas.drawPaint(defaultPaint);

    // Stroke the border of the terminal if the size is being forced;
    if (forcedSize) {
      int borderX = (columns * charWidth) + 1;
      int borderY = (rows * charHeight) + 1;

      defaultPaint.setColor(Color.GRAY);
      defaultPaint.setStrokeWidth(0.0f);
      if (width >= borderX) canvas.drawLine(borderX, 0, borderX, borderY + 1, defaultPaint);
      if (height >= borderY) canvas.drawLine(0, borderY, borderX + 1, borderY, defaultPaint);
    }

    try {
      // request a terminal pty resize
      synchronized (buffer) {
        buffer.setScreenSize(columns, rows, true);
      }

      if (transport != null) transport.setDimensions(columns, rows, width, height);
    } catch (Exception e) {
      Log.e(TAG, "Problem while trying to resize screen or PTY", e);
    }

    // redraw local output if we don't have a sesson to receive our resize request
    if (transport == null) {
      synchronized (localOutput) {
        ((vt320) buffer).reset();

        for (String line : localOutput) ((vt320) buffer).putString(line);
      }
    }

    // force full redraw with new buffer size
    fullRedraw = true;
    redraw();

    parent.notifyUser(String.format("%d x %d", columns, rows));

    Log.i(TAG, String.format("parentChanged() now width=%d, height=%d", columns, rows));
  }
Esempio n. 7
0
 public synchronized void tryScrollVibrate() {
   manager.tryScrollVibrate();
 }
Esempio n. 8
0
 public synchronized void tryKeyVibrate() {
   manager.tryKeyVibrate();
 }
Esempio n. 9
0
  /**
   * Create new terminal bridge with following parameters. We will immediately launch thread to
   * start SSH connection and handle any hostkey verification and password authentication.
   */
  public TerminalBridge(final TerminalManager manager, final HostBean host) throws IOException {
    Typeface type;

    this.manager = manager;
    this.host = host;

    emulation = manager.getEmulation();
    scrollback = manager.getScrollback();

    // create prompt helper to relay password and hostkey requests up to gui
    promptHelper = new PromptHelper(this);

    // create our default paint
    defaultPaint = new Paint();
    defaultPaint.setAntiAlias(true);
    type = Typeface.createFromAsset(this.manager.res.getAssets(), "UbuntuMono-R.ttf");
    defaultPaint.setTypeface(type);
    defaultPaint.setFakeBoldText(true); // more readable?

    localOutput = new LinkedList<String>();

    fontSizeChangedListeners = new LinkedList<FontSizeChangedListener>();

    int hostFontSize = host.getFontSize();
    if (hostFontSize <= 0) hostFontSize = DEFAULT_FONT_SIZE;
    setFontSize(hostFontSize);

    // create terminal buffer and handle outgoing data
    // this is probably status reply information
    buffer =
        new vt320() {
          @Override
          public void debug(String s) {
            Log.d(TAG, s);
          }

          @Override
          public void write(byte[] b) {
            try {
              if (b != null && transport != null) transport.write(b);
            } catch (IOException e) {
              Log.e(TAG, "Problem writing outgoing data in vt320() thread", e);
            }
          }

          @Override
          public void write(int b) {
            try {
              if (transport != null) transport.write(b);
            } catch (IOException e) {
              Log.e(TAG, "Problem writing outgoing data in vt320() thread", e);
            }
          }

          // We don't use telnet sequences.
          @Override
          public void sendTelnetCommand(byte cmd) {}

          // We don't want remote to resize our window.
          @Override
          public void setWindowSize(int c, int r) {}

          @Override
          public void beep() {
            if (parent.isShown()) manager.playBeep();
            else manager.sendActivityNotification(host);
          }
        };

    // Don't keep any scrollback if a session is not being opened.
    if (host.getWantSession()) buffer.setBufferSize(scrollback);
    else buffer.setBufferSize(0);

    resetColors();
    buffer.setDisplay(this);

    selectionArea = new SelectionArea();

    keyListener = new TerminalKeyListener(manager, this, buffer, host.getEncoding());
  }