    001    /* Copyright  (c) 2002 Graz University of Technology. All rights reserved.
    002     *
    003     * Redistribution and use in  source and binary forms, with or without
    004     * modification, are permitted  provided that the following conditions are met:
    005     *
    006     * 1. Redistributions of  source code must retain the above copyright notice,
    007     *    this list of conditions and the following disclaimer.
    008     *
    009     * 2. Redistributions in  binary form must reproduce the above copyright notice,
    010     *    this list of conditions and the following disclaimer in the documentation
    011     *    and/or other materials provided with the distribution.
    012     *
    013     * 3. The end-user documentation included with the redistribution, if any, must
    014     *    include the following acknowledgment:
    015     *
    016     *    "This product includes software developed by IAIK of Graz University of
    017     *     Technology."
    018     *
    019     *    Alternately, this acknowledgment may appear in the software itself, if
    020     *    and wherever such third-party acknowledgments normally appear.
    021     *
    022     * 4. The names "Graz University of Technology" and "IAIK of Graz University of
    023     *    Technology" must not be used to endorse or promote products derived from
    024     *    this software without prior written permission.
    025     *
    026     * 5. Products derived from this software may not be called
    027     *    "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
    028     *    written permission of Graz University of Technology.
    029     *
    030     *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
    031     *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    032     *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    033     *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
    034     *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    035     *  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    036     *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    037     *  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
    038     *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    039     *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    040     *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    041     *  POSSIBILITY  OF SUCH DAMAGE.
    042     */
    043
    044    package demo.pkcs.pkcs11;
    045
    046    import java.io.BufferedReader;
    047    import java.io.InputStreamReader;
    048    import java.io.PrintWriter;
    049    import java.util.Hashtable;
    050
    051    import iaik.pkcs.pkcs11.Info;
    052    import iaik.pkcs.pkcs11.Module;
    053    import iaik.pkcs.pkcs11.Session;
    054    import iaik.pkcs.pkcs11.SessionInfo;
    055    import iaik.pkcs.pkcs11.Slot;
    056    import iaik.pkcs.pkcs11.State;
    057    import iaik.pkcs.pkcs11.Token;
    058    import iaik.pkcs.pkcs11.TokenInfo;
    059    import iaik.pkcs.pkcs11.objects.Object;
    060
    061
    062
    063    /**
    064     * This demo program allows to delete certain objects on a certain token. It
    065     * allows the user to select a token. Thereafter, it displays the objects on
    066     * that token and lets the user select one of them to delete it.
    067     *
    068     * @author <a href="mailto:Karl.Scheibelhofer@iaik.at"> Karl Scheibelhofer </a>
    069     * @version 0.1
    070     * @invariants
    071     */
    072    public class DeleteObject {
    073
    074      static PrintWriter output_;
    075
    076      static BufferedReader input_;
    077
    078      static {
    079        try {
    080          //output_ = new PrintWriter(new FileWriter("GetInfo_output.txt"), true);
    081          output_ = new PrintWriter(System.out, true);
    082          input_ = new BufferedReader(new InputStreamReader(System.in));
    083        } catch (Throwable thr) {
    084          thr.printStackTrace();
    085          output_ = new PrintWriter(System.out, true);
    086          input_ = new BufferedReader(new InputStreamReader(System.in));
    087        }
    088      }
    089
    090      public static void main(String[] args) {
    091        if (args.length == 1) {
    092          try {
    093            output_.println("################################################################################");
    094            output_.println("load and initialize module: " + args[0]);
    095            Module pkcs11Module = Module.getInstance(args[0]);
    096            pkcs11Module.initialize(null);
    097
    098            Info info = pkcs11Module.getInfo();
    099            output_.println(info);
    100            output_.println("################################################################################");
    101
    102
    103            output_.println("################################################################################");
    104            output_.println("getting list of all tokens");
    105            Slot[] slotsWithToken = pkcs11Module.getSlotList(Module.SlotRequirement.TOKEN_PRESENT);
    106            Token[] tokens = new Token[slotsWithToken.length];
    107            Hashtable tokenIDtoToken = new Hashtable(tokens.length);
    108
    109            for (int i = 0; i < slotsWithToken.length; i++) {
    110              output_.println("________________________________________________________________________________");
    111              tokens[i] = slotsWithToken[i].getToken();
    112              TokenInfo tokenInfo = tokens[i].getTokenInfo();
    113              long tokenID = tokens[i].getTokenID();
    114              tokenIDtoToken.put(new Long(tokenID), tokens[i]);
    115              output_.println("Token ID: " + tokenID);
    116              output_.println(tokenInfo);
    117              output_.println("________________________________________________________________________________");
    118            }
    119            output_.println("################################################################################");
    120
    121            Token selectedToken = null;
    122            Long selectedTokenID = null;
    123            if (tokens.length == 0) {
    124              output_.println("There is no slot with a present token.");
    125              System.exit(0);
    126            } else if (tokens.length == 1) {
    127              output_.println("Taking token with ID: " + tokens[0].getTokenID());
    128              selectedTokenID = new Long(tokens[0].getTokenID());
    129              selectedToken = tokens[0];
    130            } else {
    131              boolean gotTokenID = false;
    132              while (!gotTokenID) {
    133                output_.print("Enter the ID of the token to use or 'x' to exit: ");
    134                output_.flush();
    135                String tokenIDstring = input_.readLine();
    136                if (tokenIDstring.equalsIgnoreCase("x")) {
    137                  System.exit(0);
    138                }
    139                try {
    140                  selectedTokenID = new Long(tokenIDstring);
    141                  selectedToken = (Token) tokenIDtoToken.get(selectedTokenID);
    142                  if (selectedToken != null) {
    143                    gotTokenID = true;
    144                  } else {
    145                    output_.println("A token with the entered ID \"" + tokenIDstring + "\" does not exist. Try again.");
    146                  }
    147                } catch (NumberFormatException ex) {
    148                  output_.println("The entered ID \"" + tokenIDstring + "\" is invalid. Try again.");
    149                }
    150              }
    151            }
    152
    153            output_.println("################################################################################");
    154            Session session = selectedToken
    155                .openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RW_SESSION, null, null);
    156
    157            TokenInfo tokenInfo = selectedToken.getTokenInfo();
    158            if (tokenInfo.isLoginRequired()) {
    159              if (tokenInfo.isProtectedAuthenticationPath()) {
    160                session.login(Session.UserType.USER, null); // the token prompts the PIN by other means; e.g. PIN-pad
    161              } else {
    162                output_.print("Enter user-PIN or press [return] to list just public objects: ");
    163                output_.flush();
    164                String userPINString = input_.readLine();
    165                output_.println();
    166                output_.print("listing all" + ((userPINString.length() > 0) ? "" : " public") + " objects on token");
    167                if (userPINString.length() > 0) {
    168                  // login user
    169                  session.login(Session.UserType.USER, userPINString.toCharArray());
    170                }
    171              }
    172            }
    173            SessionInfo sessionInfo = session.getSessionInfo();
    174            output_.println("using session:");
    175            output_.println(sessionInfo);
    176
    177            output_.println("listing all" +
    178                              (((sessionInfo.getState() == State.RO_USER_FUNCTIONS) || (sessionInfo.getState() == State.RW_SO_FUNCTIONS))
    179                               ? ""
    180                               : " public")
    181                            + " objects on token with ID " + selectedTokenID);
    182            output_.println("________________________________________________________________________________");
    183
    184            deleteLoop:
    185            while (true) {
    186              session.findObjectsInit(null);
    187              Object[] objects = session.findObjects(1);
    188              Hashtable objectHandleToObject = new Hashtable(10);
    189
    190              while (objects.length > 0) {
    191                output_.println("--------------------------------------------------------------------------------");
    192                long objectHandle = objects[0].getObjectHandle();
    193                objectHandleToObject.put(new Long(objectHandle), objects[0]);
    194                output_.println("Object with handle: " + objectHandle);
    195                output_.println(objects[0]);
    196                output_.println("--------------------------------------------------------------------------------");
    197                objects = session.findObjects(1);
    198              }
    199              session.findObjectsFinal();
    200
    201              output_.println("________________________________________________________________________________");
    202              output_.println("################################################################################");
    203
    204              Object selectedObject = null;
    205              Long selectedObjectHandle;
    206              if (objectHandleToObject.isEmpty()) {
    207                output_.println("There are no objects on the token.");
    208                break deleteLoop;
    209              } else {
    210                boolean gotObjectHandle = false;
    211                while (!gotObjectHandle) {
    212                  output_.print("Enter the handle of the object to delete or 'x' to exit: ");
    213                  output_.flush();
    214                  String objectHandleString = input_.readLine();
    215                  if (objectHandleString.equalsIgnoreCase("x")) {
    216                    break deleteLoop;
    217                  }
    218                  try {
    219                    selectedObjectHandle = new Long(objectHandleString);
    220                    selectedObject = (Object) objectHandleToObject.get(selectedObjectHandle);
    221                    if (selectedObject != null) {
    222                      gotObjectHandle = true;
    223                    } else {
    224                      output_.println("An object with the handle \"" + objectHandleString + "\" does not exist. Try again.");
    225                    }
    226                  } catch (NumberFormatException ex) {
    227                    output_.println("The entered handle \"" + objectHandleString + "\" is invalid. Try again.");
    228                  }
    229                }
    230              }
    231
    232              output_.println("Going to delete this object: ");
    233              output_.println(selectedObject);
    234              output_.println();
    235              output_.print("Are you sure that you want to DELETE this object permanently? [yes/no] ");
    236              output_.flush();
    237              String answer = input_.readLine();
    238              if (answer.equalsIgnoreCase("yes")) {
    239                session.destroyObject(selectedObject);
    240                output_.println("Object deleted.");
    241              }
    242            }
    243
    244            session.closeSession();
    245            pkcs11Module.finalize(null);
    246
    247          } catch (Throwable ex) {
    248            ex.printStackTrace();
    249          }
    250        } else {
    251          printUsage();
    252        }
    253        System.gc(); // to finalize and disconnect the pkcs11Module
    254      }
    255
    256      protected static void printUsage() {
    257        output_.println("DeleteObject <PKCS#11 module name>");
    258        output_.println("e.g.: DeleteObject pk2priv.dll");
    259      }
    260
    261    }