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    }