Made entity resolver visible
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / common / SiteSigner.java
1 /* 
2  * The Shibboleth License, Version 1. 
3  * Copyright (c) 2002 
4  * University Corporation for Advanced Internet Development, Inc. 
5  * All rights reserved
6  * 
7  * 
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions are met:
10  * 
11  * Redistributions of source code must retain the above copyright notice, this 
12  * list of conditions and the following disclaimer.
13  * 
14  * Redistributions in binary form must reproduce the above copyright notice, 
15  * this list of conditions and the following disclaimer in the documentation 
16  * and/or other materials provided with the distribution, if any, must include 
17  * the following acknowledgment: "This product includes software developed by 
18  * the University Corporation for Advanced Internet Development 
19  * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
20  * may appear in the software itself, if and wherever such third-party 
21  * acknowledgments normally appear.
22  * 
23  * Neither the name of Shibboleth nor the names of its contributors, nor 
24  * Internet2, nor the University Corporation for Advanced Internet Development, 
25  * Inc., nor UCAID may be used to endorse or promote products derived from this 
26  * software without specific prior written permission. For written permission, 
27  * please contact shibboleth@shibboleth.org
28  * 
29  * Products derived from this software may not be called Shibboleth, Internet2, 
30  * UCAID, or the University Corporation for Advanced Internet Development, nor 
31  * may Shibboleth appear in their name, without prior written permission of the 
32  * University Corporation for Advanced Internet Development.
33  * 
34  * 
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
36  * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
38  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
39  * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
40  * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
41  * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50 package edu.internet2.middleware.shibboleth.common;
51
52 import java.io.*;
53 import java.security.*;
54 import java.security.cert.*;
55 import org.apache.xml.security.c14n.*;
56 import org.apache.xml.security.signature.*;
57 import org.apache.xml.security.transforms.*;
58 import org.w3c.dom.*;
59
60 /**
61  *  Validates and signs a Shibboleth site file
62  *
63  * @author     Scott Cantor
64  * @created    June 11, 2002
65  */
66 public class SiteSigner
67 {
68     /**
69      *  Validates and signs a Shibboleth site file
70      *
71      * @param  argv           The command line arguments
72      * @exception  Exception  One of about fifty different kinds of possible errors
73      */
74     public static void main(String argv[])
75         throws Exception
76     {
77         if (argv.length == 0)
78             printUsage();
79
80         String keystore = null;
81         String ks_pass = "";
82         String key_alias = null;
83         String key_pass = "";
84         String outfile = null;
85         String arg = null;
86
87         // process arguments
88         for (int i = 0; i < argv.length; i++)
89         {
90             arg = argv[i];
91             if (arg.startsWith("-"))
92             {
93                 String option = arg.substring(1);
94                 if (option.equals("k"))
95                 {
96                     if (++i == argv.length)
97                     {
98                         System.err.println("error: Missing argument to -k option");
99                         System.exit(1);
100                     }
101                     keystore = argv[i];
102                     continue;
103                 }
104                 else if (option.equals("P"))
105                 {
106                     if (++i == argv.length)
107                     {
108                         System.err.println("error: Missing argument to -P option");
109                         System.exit(1);
110                     }
111                     ks_pass = argv[i];
112                     continue;
113                 }
114                 else if (option.equals("a"))
115                 {
116                     if (++i == argv.length)
117                     {
118                         System.err.println("error: Missing argument to -a option");
119                         System.exit(1);
120                     }
121                     key_alias = argv[i];
122                     continue;
123                 }
124                 else if (option.equals("p"))
125                 {
126                     if (++i == argv.length)
127                     {
128                         System.err.println("error: Missing argument to -p option");
129                         System.exit(1);
130                     }
131                     key_pass = argv[i];
132                     continue;
133                 }
134                 else if (option.equals("o"))
135                 {
136                     if (++i == argv.length)
137                     {
138                         System.err.println("error: Missing argument to -o option");
139                         System.exit(1);
140                     }
141                     outfile = argv[i];
142                     continue;
143                 }
144                 else if (option.equals("h"))
145                     printUsage();
146             }
147         }
148
149         if (keystore == null || keystore.length() == 0 ||
150             key_alias == null || key_alias.length() == 0)
151             printUsage();
152             
153         if (key_pass == null)
154             key_pass = ks_pass;
155
156         KeyStore ks = KeyStore.getInstance("JKS");
157         FileInputStream fis = new FileInputStream(keystore);
158         ks.load(fis, ks_pass.toCharArray());
159         PrivateKey privateKey = (PrivateKey)ks.getKey(key_alias, key_pass.toCharArray());
160         X509Certificate cert = (X509Certificate)ks.getCertificate(key_alias);
161         if (privateKey == null || cert == null)
162         {
163             System.err.println("error: couldn't load key or certificate");
164             System.exit(1);
165         }
166
167         Document doc = org.opensaml.XML.parserPool.parse(arg);
168         Element e = doc.getDocumentElement();
169         if (!XML.SHIB_NS.equals(e.getNamespaceURI()) ||
170             (!"SiteGroup".equals(e.getLocalName()) && !"Trust".equals(e.getLocalName())))
171         {
172             System.err.println("error: root element must be shib:SiteGroup or shib:Trust");
173             System.exit(1);
174         }
175
176         NodeList siglist = doc.getElementsByTagNameNS(org.opensaml.XML.XMLSIG_NS, "Signature");
177         if (siglist.getLength() > 0)
178         {
179             System.err.println("error: file already signed");
180             System.exit(1);
181         }
182
183         XMLSignature sig = new XMLSignature(doc, null, XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
184         Transforms transforms = new Transforms(doc);
185         transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
186         sig.addDocument("", transforms, org.apache.xml.security.utils.Constants.ALGO_ID_DIGEST_SHA1);
187         sig.addKeyInfo(cert);
188         e.appendChild(sig.getElement());
189         sig.sign(privateKey);
190
191         OutputStream out = null;
192         if (outfile != null && outfile.length() > 0)
193             out = new FileOutputStream(outfile);
194         else
195             out = System.out;
196
197         Canonicalizer c = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
198         out.write(c.canonicalizeSubtree(doc));
199
200         if (outfile != null && outfile.length() > 0)
201             out.close();
202     }
203
204     private static void printUsage()
205     {
206
207         System.err.println("usage: java edu.internet2.middleware.shibboleth.commmon.SiteSigner (options) uri");
208         System.err.println();
209
210         System.err.println("required options:");
211         System.err.println("  -k keystore   pathname of Java keystore file");
212         System.err.println("  -a key alias  alias of signing key");
213         System.err.println();
214         System.err.println("optional options:");
215         System.err.println("  -P password   keystore password");
216         System.err.println("  -p password   private key password");
217         System.err.println("  -o outfile    write signed copy to this file instead of stdout");
218         System.err.println("  -h            print this message");
219         System.err.println();
220         System.exit(1);
221     }
222
223     static
224     {
225         Init.init();
226     }
227 }
228