Gitblit Certificate Authority revisions. Eliminate certificate scripts.
5 files added
8 files deleted
11 files modified
| | |
| | | <fileset dir="${basedir}">
|
| | | <include name="LICENSE" />
|
| | | <include name="NOTICE" />
|
| | | <include name="authority*.jar" />
|
| | | </fileset>
|
| | | </fileset> |
| | | </copy>
|
| | | <copy tofile="${project.deploy.dir}/authority.jar" file="${basedir}/authority-${gb.version}.jar" />
|
| | |
|
| | | <!-- Certificate templates -->
|
| | | <mkdir dir="${project.deploy.dir}/certs"/>
|
| | |
| | | <exclude name="com/gitblit/AddIndexedBranch*.class" />
|
| | | <exclude name="com/gitblit/GitBlitServer*.class" />
|
| | | <exclude name="com/gitblit/Launcher*.class" />
|
| | | <exclude name="com/gitblit/MakeCertificate*.class" />
|
| | | <exclude name="com/gitblit/authority/**" />
|
| | | </fileset>
|
| | | </copy>
|
| | |
| | | <exclude name="com/gitblit/AddIndexedBranch*.class" />
|
| | | <exclude name="com/gitblit/GitBlitServer*.class" />
|
| | | <exclude name="com/gitblit/Launcher*.class" />
|
| | | <exclude name="com/gitblit/MakeCertificate*.class" />
|
| | | </fileset>
|
| | | </copy>
|
| | |
|
| | |
| | | <exclude name="com/gitblit/client/**" />
|
| | | <exclude name="com/gitblit/GitBlitServer*.class" />
|
| | | <exclude name="com/gitblit/Launcher*.class" />
|
| | | <exclude name="com/gitblit/MakeCertificate*.class" />
|
| | | <exclude name="com/gitblit/authority/**" />
|
| | | </fileset>
|
| | | </jar>
|
| | |
| | | <resource file="${basedir}/resources/rosette_16x16.png" />
|
| | | <resource file="${basedir}/resources/vcard_16x16.png" />
|
| | | <resource file="${basedir}/resources/settings_16x16.png" />
|
| | | <resource file="${basedir}/resources/settings_32x32.png" />
|
| | | <resource file="${basedir}/resources/search-icon.png" />
|
| | | <resource file="${basedir}/resources/blank.png" />
|
| | | <resource file="${basedir}/resources/bullet_green.png" />
|
| | |
| | | <resource file="${basedir}/resources/bullet_white.png" />
|
| | | <resource file="${basedir}/resources/bullet_delete.png" />
|
| | | <resource file="${basedir}/resources/bullet_key.png" />
|
| | | <resource file="${basedir}/src/log4j.properties" />
|
| | | <resource file="${basedir}/src/com/gitblit/wicket/GitBlitWebApp.properties" />
|
| | | <resource file="${basedir}/src/com/gitblit/wicket/GitBlitWebApp_es.properties" />
|
| | | <resource file="${basedir}/src/com/gitblit/wicket/GitBlitWebApp_ja.properties" />
|
| | |
| | | filename="${manager.zipfile}"
|
| | | targetfilename="manager-${gb.version}.zip"
|
| | | summary="Gitblit Manager v${gb.version} (Swing tool to remotely administer a Gitblit server)"
|
| | | labels="Featured, Type-Package, OpSys-All" />
|
| | |
|
| | | <!-- Upload Gitblit Authority -->
|
| | | <gcupload |
| | | username="${googlecode.user}" |
| | | password="${googlecode.password}" |
| | | projectname="gitblit" |
| | | filename="${authority.zipfile}" |
| | | targetfilename="authority-${gb.version}.zip"
|
| | | summary="Gitblit Authority v${gb.version} (Swing tool to manage client SSL certificates)"
|
| | | labels="Featured, Type-Package, OpSys-All" />
|
| | |
|
| | | <!-- Upload Gitblit API Library -->
|
| | |
| | | package com.gitblit;
|
| | |
|
| | | import java.io.BufferedReader;
|
| | | import java.io.BufferedWriter;
|
| | | import java.io.File;
|
| | | import java.io.FileWriter;
|
| | | import java.io.IOException;
|
| | | import java.io.InputStreamReader;
|
| | | import java.io.OutputStream;
|
| | |
| | | import com.beust.jcommander.Parameter;
|
| | | import com.beust.jcommander.ParameterException;
|
| | | import com.beust.jcommander.Parameters;
|
| | | import com.gitblit.authority.GitblitAuthority;
|
| | | import com.gitblit.authority.NewCertificateConfig;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.utils.TimeUtils;
|
| | | import com.gitblit.utils.X509Utils;
|
| | | import com.gitblit.utils.X509Utils.X509Log;
|
| | | import com.gitblit.utils.X509Utils.X509Metadata;
|
| | | import com.unboundid.ldap.listener.InMemoryDirectoryServer;
|
| | | import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
|
| | |
| | |
|
| | | // conditionally configure the https connector
|
| | | if (params.securePort > 0) {
|
| | | File folder = new File(System.getProperty("user.dir"));
|
| | | final File folder = new File(System.getProperty("user.dir"));
|
| | | File certificatesConf = new File(folder, X509Utils.CA_CONFIG);
|
| | | File serverKeyStore = new File(folder, X509Utils.SERVER_KEY_STORE);
|
| | | File serverTrustStore = new File(folder, X509Utils.SERVER_TRUST_STORE);
|
| | |
| | | }
|
| | |
|
| | | metadata.notAfter = new Date(System.currentTimeMillis() + 10*TimeUtils.ONEYEAR);
|
| | | X509Utils.prepareX509Infrastructure(metadata, folder);
|
| | | X509Utils.prepareX509Infrastructure(metadata, folder, new X509Log() {
|
| | | @Override
|
| | | public void log(String message) {
|
| | | BufferedWriter writer = null;
|
| | | try {
|
| | | writer = new BufferedWriter(new FileWriter(new File(folder, X509Utils.CERTS + File.separator + "log.txt"), true));
|
| | | writer.write(MessageFormat.format("{0,date,yyyy-MM-dd HH:mm}: {1}", new Date(), message));
|
| | | writer.newLine();
|
| | | writer.flush();
|
| | | } catch (Exception e) {
|
| | | LoggerFactory.getLogger(GitblitAuthority.class).error("Failed to append log entry!", e);
|
| | | } finally {
|
| | | if (writer != null) {
|
| | | try {
|
| | | writer.close();
|
| | | } catch (IOException e) {
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | });
|
| | |
|
| | | if (serverKeyStore.exists()) {
|
| | | Connector secureConnector = createSSLConnector(serverKeyStore, serverTrustStore, params.storePassword,
|
New file |
| | |
| | | /* |
| | | * Copyright 2012 gitblit.com. |
| | | * |
| | | * Licensed under the Apache License, Version 2.0 (the "License"); |
| | | * you may not use this file except in compliance with the License. |
| | | * You may obtain a copy of the License at |
| | | * |
| | | * http://www.apache.org/licenses/LICENSE-2.0 |
| | | * |
| | | * Unless required by applicable law or agreed to in writing, software |
| | | * distributed under the License is distributed on an "AS IS" BASIS, |
| | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| | | * See the License for the specific language governing permissions and |
| | | * limitations under the License. |
| | | */ |
| | | package com.gitblit.authority; |
| | | |
| | | import java.awt.GridLayout; |
| | | |
| | | import javax.swing.JPanel; |
| | | import javax.swing.JTextField; |
| | | |
| | | import com.gitblit.client.Translation; |
| | | import com.gitblit.utils.X509Utils.X509Metadata; |
| | | |
| | | public class DefaultOidsPanel extends JPanel { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private JTextField organizationalUnit; |
| | | private JTextField organization; |
| | | private JTextField locality; |
| | | private JTextField stateProvince; |
| | | private JTextField countryCode; |
| | | |
| | | public DefaultOidsPanel(X509Metadata metadata) { |
| | | super(); |
| | | |
| | | organizationalUnit = new JTextField(metadata.getOID("OU", ""), 20); |
| | | organization = new JTextField(metadata.getOID("O", ""), 20); |
| | | locality = new JTextField(metadata.getOID("L", ""), 20); |
| | | stateProvince = new JTextField(metadata.getOID("ST", ""), 20); |
| | | countryCode = new JTextField(metadata.getOID("C", ""), 20); |
| | | |
| | | setLayout(new GridLayout(0, 1, Utils.MARGIN, Utils.MARGIN)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.organizationalUnit") + " (OU)", organizationalUnit)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.organization") + " (O)", organization)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.locality") + " (L)", locality)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.stateProvince") + " (ST)", stateProvince)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.countryCode") + " (C)", countryCode)); |
| | | } |
| | | |
| | | public void update(X509Metadata metadata) { |
| | | metadata.setOID("OU", organizationalUnit.getText()); |
| | | metadata.setOID("O", organization.getText()); |
| | | metadata.setOID("L", locality.getText()); |
| | | metadata.setOID("ST", stateProvince.getText()); |
| | | metadata.setOID("C", countryCode.getText()); |
| | | } |
| | | |
| | | public String getOrganizationalUnit() { |
| | | return organizationalUnit.getText(); |
| | | } |
| | | |
| | | public String getOrganization() { |
| | | return organization.getText(); |
| | | } |
| | | |
| | | public String getLocality() { |
| | | return locality.getText(); |
| | | } |
| | | |
| | | public String getStateProvince() { |
| | | return stateProvince.getText(); |
| | | } |
| | | |
| | | public String getCountryCode() { |
| | | return countryCode.getText(); |
| | | } |
| | | } |
| | |
| | | import java.awt.event.WindowAdapter;
|
| | | import java.awt.event.WindowEvent;
|
| | | import java.io.BufferedInputStream;
|
| | | import java.io.BufferedWriter;
|
| | | import java.io.File;
|
| | | import java.io.FileInputStream;
|
| | | import java.io.FileWriter;
|
| | | import java.io.FilenameFilter;
|
| | | import java.io.IOException;
|
| | | import java.security.PrivateKey;
|
| | | import java.security.cert.CertificateFactory;
|
| | | import java.security.cert.X509Certificate;
|
| | | import java.text.MessageFormat;
|
| | |
| | | import javax.mail.internet.MimeBodyPart;
|
| | | import javax.mail.internet.MimeMultipart;
|
| | | import javax.swing.ImageIcon;
|
| | | import javax.swing.InputVerifier;
|
| | | import javax.swing.JButton;
|
| | | import javax.swing.JComponent;
|
| | | import javax.swing.JFrame;
|
| | | import javax.swing.JLabel;
|
| | | import javax.swing.JOptionPane;
|
| | |
| | | import javax.swing.JTable;
|
| | | import javax.swing.JTextField;
|
| | | import javax.swing.RowFilter;
|
| | | import javax.swing.SwingConstants;
|
| | | import javax.swing.UIManager;
|
| | | import javax.swing.event.ListSelectionEvent;
|
| | | import javax.swing.event.ListSelectionListener;
|
| | |
| | | import org.eclipse.jgit.lib.StoredConfig;
|
| | | import org.eclipse.jgit.storage.file.FileBasedConfig;
|
| | | import org.eclipse.jgit.util.FS;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | | import com.gitblit.ConfigUserService;
|
| | | import com.gitblit.Constants;
|
| | |
| | | import com.gitblit.client.Translation;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.utils.TimeUtils;
|
| | | import com.gitblit.utils.X509Utils;
|
| | | import com.gitblit.utils.X509Utils.RevocationReason;
|
| | | import com.gitblit.utils.X509Utils.X509Log;
|
| | | import com.gitblit.utils.X509Utils.X509Metadata;
|
| | |
|
| | | /**
|
| | |
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class GitblitAuthority extends JFrame {
|
| | | public class GitblitAuthority extends JFrame implements X509Log {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | |
| | | private int defaultDuration;
|
| | |
|
| | | private TableRowSorter<UserCertificateTableModel> defaultSorter;
|
| | | |
| | | private MailExecutor mail;
|
| | |
|
| | | private JButton certificateDefaultsButton;
|
| | |
|
| | | public static void main(String... args) {
|
| | | EventQueue.invokeLater(new Runnable() {
|
| | |
| | |
|
| | | // try to restore saved window size
|
| | | if (StringUtils.isEmpty(sz)) {
|
| | | setSize(850, 500);
|
| | | setSize(900, 600);
|
| | | } else {
|
| | | String[] chunks = sz.split("x");
|
| | | int width = Integer.parseInt(chunks[0]);
|
| | |
| | | return null;
|
| | | }
|
| | | gitblitSettings = new FileSettings(file.getAbsolutePath());
|
| | | mail = new MailExecutor(gitblitSettings);
|
| | | caKeystorePassword = gitblitSettings.getString(Keys.server.storePassword, null);
|
| | | String us = gitblitSettings.getString(Keys.realm.userService, "users.conf");
|
| | | String ext = us.substring(us.lastIndexOf(".") + 1).toLowerCase();
|
| | |
| | | private void load(File folder) {
|
| | | this.folder = folder;
|
| | | this.userService = loadUsers(folder);
|
| | | if (userService != null) {
|
| | | if (userService == null) {
|
| | | JOptionPane.showMessageDialog(this, MessageFormat.format("Sorry, {0} doesn't look like a Gitblit GO installation.", folder));
|
| | | } else {
|
| | | // build empty certificate model for all users
|
| | | Map<String, UserCertificateModel> map = new HashMap<String, UserCertificateModel>();
|
| | | for (String user : userService.getAllUsernames()) {
|
| | |
| | | Collections.sort(tableModel.list);
|
| | | tableModel.fireTableDataChanged();
|
| | | Utils.packColumns(table, Utils.MARGIN);
|
| | | |
| | | File caKeystore = new File(folder, X509Utils.CA_KEY_STORE);
|
| | | if (!caKeystore.exists()) {
|
| | | // show certificate defaults dialog |
| | | certificateDefaultsButton.doClick();
|
| | | }
|
| | | }
|
| | | }
|
| | | |
| | | private void prepareX509Infrastructure() {
|
| | | X509Metadata metadata = new X509Metadata("localhost", caKeystorePassword);
|
| | | X509Utils.prepareX509Infrastructure(metadata, folder, this);
|
| | | }
|
| | |
|
| | | private List<X509Certificate> findCerts(File folder, String username) {
|
| | |
| | | public Insets getInsets() {
|
| | | return Utils.INSETS;
|
| | | }
|
| | | |
| | | @Override
|
| | | public boolean isAllowEmail() {
|
| | | return mail.isReady();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Date getDefaultExpiration() {
|
| | |
| | |
|
| | | @Override
|
| | | public void newCertificate(UserCertificateModel ucm, X509Metadata metadata, boolean sendEmail) {
|
| | | prepareX509Infrastructure();
|
| | | Date notAfter = metadata.notAfter;
|
| | | metadata.serverHostname = gitblitSettings.getString(Keys.web.siteName, "localhost");
|
| | | UserModel user = ucm.user;
|
| | |
| | | }
|
| | |
|
| | | File caKeystoreFile = new File(folder, X509Utils.CA_KEY_STORE);
|
| | | File zip = X509Utils.newClientBundle(metadata, caKeystoreFile, caKeystorePassword);
|
| | | |
| | | File zip = X509Utils.newClientBundle(metadata, caKeystoreFile, caKeystorePassword, GitblitAuthority.this);
|
| | |
|
| | | // save latest expiration date
|
| | | if (ucm.expires == null || metadata.notAfter.after(ucm.expires)) {
|
| | | ucm.expires = metadata.notAfter;
|
| | |
| | | if (sendEmail) {
|
| | | // send email
|
| | | try {
|
| | | MailExecutor mail = new MailExecutor(gitblitSettings);
|
| | | if (mail.isReady()) {
|
| | | Message message = mail.createMessage(user.emailAddress);
|
| | | message.setSubject("Your Gitblit client certificate for " + metadata.serverHostname);
|
| | |
| | | public void revoke(UserCertificateModel ucm, X509Certificate cert, RevocationReason reason) {
|
| | | File caRevocationList = new File(folder, X509Utils.CA_REVOCATION_LIST);
|
| | | File caKeystoreFile = new File(folder, X509Utils.CA_KEY_STORE);
|
| | | if (X509Utils.revoke(cert, reason, caRevocationList, caKeystoreFile, caKeystorePassword)) {
|
| | | if (X509Utils.revoke(cert, reason, caRevocationList, caKeystoreFile, caKeystorePassword, GitblitAuthority.this)) {
|
| | | File certificatesConfigFile = new File(folder, X509Utils.CA_CONFIG);
|
| | | FileBasedConfig config = new FileBasedConfig(certificatesConfigFile, FS.detect());
|
| | | if (certificatesConfigFile.exists()) {
|
| | |
| | | int modelIndex = table.convertRowIndexToModel(table.getSelectedRow());
|
| | | tableModel.fireTableDataChanged();
|
| | | table.getSelectionModel().setSelectionInterval(modelIndex, modelIndex);
|
| | | |
| | | }
|
| | | }
|
| | | };
|
| | |
| | | usersPanel.add(new JScrollPane(table), BorderLayout.CENTER);
|
| | | usersPanel.setMinimumSize(new Dimension(400, 10));
|
| | |
|
| | | final JTextField filterTextfield = new JTextField(20);
|
| | | certificateDefaultsButton = new JButton(new ImageIcon(getClass().getResource("/settings_16x16.png")));
|
| | | certificateDefaultsButton.setFocusable(false);
|
| | | certificateDefaultsButton.setToolTipText(Translation.get("gb.certificateDefaults")); |
| | | certificateDefaultsButton.addActionListener(new ActionListener() {
|
| | | @Override
|
| | | public void actionPerformed(ActionEvent e) {
|
| | | X509Metadata metadata = new X509Metadata("whocares", "whocares");
|
| | | File certificatesConfigFile = new File(folder, X509Utils.CA_CONFIG);
|
| | | FileBasedConfig config = new FileBasedConfig(certificatesConfigFile, FS.detect());
|
| | | NewCertificateConfig certificateConfig = null;
|
| | | if (certificatesConfigFile.exists()) {
|
| | | try {
|
| | | config.load();
|
| | | } catch (Exception x) {
|
| | | Utils.showException(GitblitAuthority.this, x);
|
| | | }
|
| | | certificateConfig = NewCertificateConfig.KEY.parse(config);
|
| | | certificateConfig.update(metadata);
|
| | | }
|
| | | InputVerifier verifier = new InputVerifier() {
|
| | | public boolean verify(JComponent comp) {
|
| | | boolean returnValue;
|
| | | JTextField textField = (JTextField) comp;
|
| | | try {
|
| | | Integer.parseInt(textField.getText());
|
| | | returnValue = true;
|
| | | } catch (NumberFormatException e) {
|
| | | returnValue = false;
|
| | | }
|
| | | return returnValue;
|
| | | }
|
| | | };
|
| | |
|
| | | JTextField durationTF = new JTextField(4);
|
| | | durationTF.setInputVerifier(verifier);
|
| | | durationTF.setVerifyInputWhenFocusTarget(true);
|
| | | durationTF.setText("" + certificateConfig.duration);
|
| | | JPanel durationPanel = Utils.newFieldPanel(Translation.get("gb.duration"), durationTF, Translation.get("gb.duration.days").replace("{0}", "").trim());
|
| | | DefaultOidsPanel oids = new DefaultOidsPanel(metadata);
|
| | |
|
| | | JPanel panel = new JPanel(new BorderLayout());
|
| | | panel.add(durationPanel, BorderLayout.NORTH);
|
| | | panel.add(oids, BorderLayout.CENTER);
|
| | |
|
| | | int result = JOptionPane.showConfirmDialog(GitblitAuthority.this, |
| | | panel, Translation.get("gb.certificateDefaults"), JOptionPane.OK_CANCEL_OPTION,
|
| | | JOptionPane.QUESTION_MESSAGE, new ImageIcon(getClass().getResource("/settings_32x32.png")));
|
| | | if (result == JOptionPane.OK_OPTION) {
|
| | | try {
|
| | | oids.update(metadata);
|
| | | certificateConfig.duration = Integer.parseInt(durationTF.getText());
|
| | | certificateConfig.store(config, metadata);
|
| | | config.save();
|
| | | |
| | | prepareX509Infrastructure();
|
| | | } catch (Exception e1) {
|
| | | Utils.showException(GitblitAuthority.this, e1);
|
| | | }
|
| | | }
|
| | | }
|
| | | });
|
| | | |
| | | JButton newWebCertificate = new JButton(new ImageIcon(getClass().getResource("/rosette_16x16.png")));
|
| | | newWebCertificate.setFocusable(false);
|
| | | newWebCertificate.setToolTipText(Translation.get("gb.newWebCertificate")); |
| | | newWebCertificate.addActionListener(new ActionListener() {
|
| | | @Override
|
| | | public void actionPerformed(ActionEvent e) {
|
| | | Date defaultExpiration = new Date(System.currentTimeMillis() + 10*TimeUtils.ONEYEAR);
|
| | | NewWebCertificateDialog dialog = new NewWebCertificateDialog(GitblitAuthority.this, defaultExpiration);
|
| | | dialog.setModal(true);
|
| | | dialog.setVisible(true);
|
| | | if (dialog.isCanceled()) {
|
| | | return;
|
| | | }
|
| | | prepareX509Infrastructure();
|
| | | Date expires = dialog.getExpiration();
|
| | | String hostname = dialog.getHostname();
|
| | | |
| | | // read CA private key and certificate
|
| | | File caKeystoreFile = new File(folder, X509Utils.CA_KEY_STORE);
|
| | | PrivateKey caPrivateKey = X509Utils.getPrivateKey(X509Utils.CA_ALIAS, caKeystoreFile, caKeystorePassword);
|
| | | X509Certificate caCert = X509Utils.getCertificate(X509Utils.CA_ALIAS, caKeystoreFile, caKeystorePassword);
|
| | | |
| | | // generate new SSL certificate
|
| | | X509Metadata metadata = new X509Metadata(hostname, caKeystorePassword);
|
| | | metadata.notAfter = expires;
|
| | | File serverKeystoreFile = new File(folder, X509Utils.SERVER_KEY_STORE);
|
| | | X509Utils.newSSLCertificate(metadata, caPrivateKey, caCert, serverKeystoreFile, GitblitAuthority.this);
|
| | | }
|
| | | });
|
| | | |
| | | final JTextField filterTextfield = new JTextField(15);
|
| | | filterTextfield.addActionListener(new ActionListener() {
|
| | | public void actionPerformed(ActionEvent e) {
|
| | | filterUsers(filterTextfield.getText());
|
| | |
| | | filterUsers(filterTextfield.getText());
|
| | | }
|
| | | });
|
| | | |
| | | JPanel buttonControls = new JPanel(new FlowLayout(FlowLayout.LEFT, Utils.MARGIN, Utils.MARGIN));
|
| | | buttonControls.add(certificateDefaultsButton);
|
| | | buttonControls.add(newWebCertificate);
|
| | |
|
| | | JPanel userControls = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
|
| | | JPanel userControls = new JPanel(new FlowLayout(FlowLayout.RIGHT, Utils.MARGIN, Utils.MARGIN));
|
| | | userControls.add(new JLabel(Translation.get("gb.filter")));
|
| | | userControls.add(filterTextfield);
|
| | |
|
| | | JPanel topPanel = new JPanel(new BorderLayout(0, 0));
|
| | | topPanel.add(buttonControls, BorderLayout.WEST);
|
| | | topPanel.add(userControls, BorderLayout.EAST);
|
| | | |
| | | JPanel leftPanel = new JPanel(new BorderLayout());
|
| | | leftPanel.add(userControls, BorderLayout.NORTH);
|
| | | leftPanel.add(topPanel, BorderLayout.NORTH);
|
| | | leftPanel.add(usersPanel, BorderLayout.CENTER);
|
| | |
|
| | | userCertificatePanel.setMinimumSize(new Dimension(375, 10));
|
| | | |
| | | JLabel statusLabel = new JLabel();
|
| | | statusLabel.setHorizontalAlignment(SwingConstants.RIGHT);
|
| | | if (X509Utils.unlimitedStrength) {
|
| | | statusLabel.setText("JCE Unlimited Strength Jurisdiction Policy");
|
| | | } else {
|
| | | statusLabel.setText("JCE Standard Encryption Policy");
|
| | | }
|
| | |
|
| | | JPanel root = new JPanel(new BorderLayout()) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
| | | };
|
| | | JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, userCertificatePanel);
|
| | | splitPane.setDividerLocation(1d);
|
| | | root.add(splitPane);
|
| | | root.add(splitPane, BorderLayout.CENTER);
|
| | | root.add(statusLabel, BorderLayout.SOUTH);
|
| | | return root;
|
| | | }
|
| | |
|
| | |
| | | sorter.setRowFilter(containsFilter);
|
| | | table.setRowSorter(sorter);
|
| | | }
|
| | | |
| | | @Override
|
| | | public void log(String message) {
|
| | | BufferedWriter writer = null;
|
| | | try {
|
| | | writer = new BufferedWriter(new FileWriter(new File(folder, X509Utils.CERTS + File.separator + "log.txt"), true));
|
| | | writer.write(MessageFormat.format("{0,date,yyyy-MM-dd HH:mm}: {1}", new Date(), message));
|
| | | writer.newLine();
|
| | | writer.flush();
|
| | | } catch (Exception e) {
|
| | | LoggerFactory.getLogger(GitblitAuthority.class).error("Failed to append log entry!", e);
|
| | | } finally {
|
| | | if (writer != null) {
|
| | | try {
|
| | | writer.close();
|
| | | } catch (IOException e) {
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | | }
|
| | | };
|
| | |
|
| | | public final String OU;
|
| | | public final String O;
|
| | | public final String L;
|
| | | public final String ST;
|
| | | public final String C;
|
| | | public String OU;
|
| | | public String O;
|
| | | public String L;
|
| | | public String ST;
|
| | | public String C;
|
| | |
|
| | | public final int duration;
|
| | | public int duration;
|
| | |
|
| | | private NewCertificateConfig(final Config c) {
|
| | | duration = c.getInt("new", null, "duration", 0);
|
| | |
| | | metadata.oids.put(oid, value);
|
| | | }
|
| | | }
|
| | | |
| | | public void store(Config c, X509Metadata metadata) {
|
| | | store(c, "new", "organizationalUnit", metadata.getOID("OU", null));
|
| | | store(c, "new", "organization", metadata.getOID("O", null));
|
| | | store(c, "new", "locality", metadata.getOID("L", null));
|
| | | store(c, "new", "stateProvince", metadata.getOID("ST", null));
|
| | | store(c, "new", "countryCode", metadata.getOID("C", null));
|
| | | if (duration <= 0) {
|
| | | c.unset("new", null, "duration");
|
| | | } else {
|
| | | c.setInt("new", null, "duration", duration);
|
| | | }
|
| | | }
|
| | | |
| | | private void store(Config c, String section, String name, String value) {
|
| | | if (StringUtils.isEmpty(value)) {
|
| | | c.unset(section, null, name);
|
| | | } else {
|
| | | c.setString(section, null, name, value);
|
| | | }
|
| | | }
|
| | | } |
| | |
| | | JCheckBox sendEmail;
|
| | | boolean isCanceled = true;
|
| | |
|
| | | public NewClientCertificateDialog(Frame owner, String displayname, Date defaultExpiration) {
|
| | | public NewClientCertificateDialog(Frame owner, String displayname, Date defaultExpiration, boolean allowEmail) {
|
| | | super(owner);
|
| | |
|
| | | setTitle(Translation.get("gb.newCertificate"));
|
| | |
|
| | | JPanel content = new JPanel(new BorderLayout(5, 5)) { |
| | | JPanel content = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN)) { |
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | |
| | | hint = new JTextField(20);
|
| | | sendEmail = new JCheckBox(Translation.get("gb.sendEmail"));
|
| | |
|
| | | JPanel panel = new JPanel(new GridLayout(0, 2, 5, 5));
|
| | | JPanel panel = new JPanel(new GridLayout(0, 2, Utils.MARGIN, Utils.MARGIN));
|
| | |
|
| | | panel.add(new JLabel(Translation.get("gb.expires")));
|
| | | panel.add(expirationDate);
|
| | |
| | | panel.add(new JLabel(Translation.get("gb.passwordHint")));
|
| | | panel.add(hint);
|
| | |
|
| | | panel.add(new JLabel(""));
|
| | | panel.add(sendEmail);
|
| | | if (allowEmail) {
|
| | | panel.add(new JLabel(""));
|
| | | panel.add(sendEmail);
|
| | | }
|
| | |
|
| | | content.add(panel, BorderLayout.CENTER);
|
| | |
|
| | |
| | | private boolean validateInputs() {
|
| | | if (getExpiration().getTime() < System.currentTimeMillis()) {
|
| | | // expires before now
|
| | | JOptionPane.showMessageDialog(this, Translation.get("gb.invalidExpiraitonDate"),
|
| | | JOptionPane.showMessageDialog(this, Translation.get("gb.invalidExpirationDate"),
|
| | | Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
|
| | | return false;
|
| | | }
|
New file |
| | |
| | | /*
|
| | | * Copyright 2012 gitblit.com.
|
| | | *
|
| | | * Licensed under the Apache License, Version 2.0 (the "License");
|
| | | * you may not use this file except in compliance with the License.
|
| | | * You may obtain a copy of the License at
|
| | | *
|
| | | * http://www.apache.org/licenses/LICENSE-2.0
|
| | | *
|
| | | * Unless required by applicable law or agreed to in writing, software
|
| | | * distributed under the License is distributed on an "AS IS" BASIS,
|
| | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| | | * See the License for the specific language governing permissions and
|
| | | * limitations under the License.
|
| | | */
|
| | | package com.gitblit.authority;
|
| | |
|
| | | import java.awt.BorderLayout;
|
| | | import java.awt.Frame;
|
| | | import java.awt.GridLayout;
|
| | | import java.awt.Insets;
|
| | | import java.awt.event.ActionEvent;
|
| | | import java.awt.event.ActionListener;
|
| | | import java.util.Date;
|
| | |
|
| | | import javax.swing.JButton;
|
| | | import javax.swing.JDialog;
|
| | | import javax.swing.JLabel;
|
| | | import javax.swing.JOptionPane;
|
| | | import javax.swing.JPanel;
|
| | | import javax.swing.JTextField;
|
| | |
|
| | | import com.gitblit.client.HeaderPanel;
|
| | | import com.gitblit.client.Translation;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.toedter.calendar.JDateChooser;
|
| | |
|
| | | public class NewWebCertificateDialog extends JDialog {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | | |
| | | JDateChooser expirationDate;
|
| | | JTextField hostname;
|
| | | boolean isCanceled = true;
|
| | |
|
| | | public NewWebCertificateDialog(Frame owner, Date defaultExpiration) {
|
| | | super(owner);
|
| | | |
| | | setTitle(Translation.get("gb.newWebCertificate"));
|
| | | |
| | | JPanel content = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN)) { |
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public Insets getInsets() {
|
| | | |
| | | return Utils.INSETS;
|
| | | }
|
| | | };
|
| | | content.add(new HeaderPanel(Translation.get("gb.newWebCertificate"), "rosette_16x16.png"), BorderLayout.NORTH);
|
| | | |
| | | expirationDate = new JDateChooser(defaultExpiration);
|
| | | hostname = new JTextField(20);
|
| | | |
| | | JPanel panel = new JPanel(new GridLayout(0, 2, Utils.MARGIN, Utils.MARGIN));
|
| | | |
| | | panel.add(new JLabel(Translation.get("gb.hostname")));
|
| | | panel.add(hostname);
|
| | |
|
| | | panel.add(new JLabel(Translation.get("gb.expires")));
|
| | | panel.add(expirationDate);
|
| | |
|
| | | content.add(panel, BorderLayout.CENTER);
|
| | | |
| | | JButton ok = new JButton(Translation.get("gb.ok"));
|
| | | ok.addActionListener(new ActionListener() {
|
| | | public void actionPerformed(ActionEvent e) {
|
| | | if (validateInputs()) {
|
| | | isCanceled = false;
|
| | | setVisible(false);
|
| | | }
|
| | | }
|
| | | });
|
| | | JButton cancel = new JButton(Translation.get("gb.cancel"));
|
| | | cancel.addActionListener(new ActionListener() {
|
| | | public void actionPerformed(ActionEvent e) {
|
| | | isCanceled = true;
|
| | | setVisible(false);
|
| | | }
|
| | | });
|
| | | |
| | | JPanel controls = new JPanel();
|
| | | controls.add(ok);
|
| | | controls.add(cancel);
|
| | | |
| | | content.add(controls, BorderLayout.SOUTH);
|
| | | |
| | | getContentPane().add(content, BorderLayout.CENTER);
|
| | | pack();
|
| | | |
| | | setLocationRelativeTo(owner);
|
| | | }
|
| | | |
| | | private boolean validateInputs() {
|
| | | if (getExpiration().getTime() < System.currentTimeMillis()) {
|
| | | // expires before now
|
| | | JOptionPane.showMessageDialog(this, Translation.get("gb.invalidExpirationDate"),
|
| | | Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
|
| | | return false;
|
| | | }
|
| | | if (StringUtils.isEmpty(getHostname())) {
|
| | | // must have hostname
|
| | | JOptionPane.showMessageDialog(this, Translation.get("gb.hostnameRequired"),
|
| | | Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
|
| | | return false;
|
| | | }
|
| | | return true;
|
| | | }
|
| | | |
| | | public String getHostname() {
|
| | | return hostname.getText();
|
| | | }
|
| | | |
| | | public Date getExpiration() {
|
| | | return expirationDate.getDate();
|
| | | }
|
| | | |
| | | public boolean isCanceled() {
|
| | | return isCanceled;
|
| | | }
|
| | | }
|
| | |
| | | package com.gitblit.authority;
|
| | |
|
| | | import java.awt.BorderLayout;
|
| | | import java.awt.Component;
|
| | | import java.awt.Cursor;
|
| | | import java.awt.Dimension;
|
| | | import java.awt.FlowLayout;
|
| | | import java.awt.Frame;
|
| | | import java.awt.GridLayout;
|
| | | import java.awt.event.ActionEvent;
|
| | | import java.awt.event.ActionListener;
|
| | | import java.awt.event.MouseAdapter;
|
| | |
| | |
|
| | | import javax.swing.ImageIcon;
|
| | | import javax.swing.JButton;
|
| | | import javax.swing.JLabel;
|
| | | import javax.swing.JOptionPane;
|
| | | import javax.swing.JPanel;
|
| | | import javax.swing.JScrollPane;
|
| | | import javax.swing.JTable;
|
| | | import javax.swing.JTextField;
|
| | | import javax.swing.event.ListSelectionEvent;
|
| | | import javax.swing.event.ListSelectionListener;
|
| | | import javax.swing.table.TableRowSorter;
|
| | |
| | |
|
| | | private UserCertificateModel ucm;
|
| | |
|
| | | private JTextField displayname;
|
| | | private JTextField username;
|
| | | private JTextField emailAddress;
|
| | | private JTextField organizationalUnit;
|
| | | private JTextField organization;
|
| | | private JTextField locality;
|
| | | private JTextField stateProvince;
|
| | | private JTextField countryCode;
|
| | |
|
| | | private UserOidsPanel oidsPanel;
|
| | | |
| | | private CertificatesTableModel tableModel;
|
| | |
|
| | | private JButton saveUserButton;
|
| | |
| | | super(new BorderLayout());
|
| | |
|
| | | this.owner = owner;
|
| | | oidsPanel = new UserOidsPanel();
|
| | |
|
| | | displayname = new JTextField(20);
|
| | | username = new JTextField(20);
|
| | | username.setEditable(false);
|
| | | emailAddress = new JTextField(20);
|
| | | organizationalUnit = new JTextField(20);
|
| | | organization = new JTextField(20);
|
| | | locality = new JTextField(20);
|
| | | stateProvince = new JTextField(20);
|
| | | countryCode = new JTextField(20);
|
| | | |
| | | JPanel fields = new JPanel(new GridLayout(0, 1, 5, 5));
|
| | | fields.add(newFieldPanel(Translation.get("gb.displayName"), displayname));
|
| | | fields.add(newFieldPanel(Translation.get("gb.username") + " (CN)", username));
|
| | | fields.add(newFieldPanel(Translation.get("gb.emailAddress") + " (E)", emailAddress));
|
| | | fields.add(newFieldPanel(Translation.get("gb.organizationalUnit") + " (OU)", organizationalUnit));
|
| | | fields.add(newFieldPanel(Translation.get("gb.organization") + " (O)", organization));
|
| | | fields.add(newFieldPanel(Translation.get("gb.locality") + " (L)", locality));
|
| | | fields.add(newFieldPanel(Translation.get("gb.stateProvince") + " (ST)", stateProvince));
|
| | | fields.add(newFieldPanel(Translation.get("gb.countryCode") + " (C)", countryCode));
|
| | | |
| | | JPanel fp = new JPanel(new BorderLayout(5, 5));
|
| | | fp.add(fields, BorderLayout.NORTH);
|
| | | JPanel fp = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
|
| | | fp.add(oidsPanel, BorderLayout.NORTH);
|
| | |
|
| | | JPanel fieldsPanel = new JPanel(new BorderLayout());
|
| | | fieldsPanel.add(new HeaderPanel(Translation.get("gb.properties"), "vcard_16x16.png"), BorderLayout.NORTH);
|
| | |
| | | public void actionPerformed(ActionEvent e) {
|
| | | setEditable(false);
|
| | | String username = ucm.user.username;
|
| | | updateUser();
|
| | | oidsPanel.updateUser(ucm);
|
| | | saveUser(username, ucm);
|
| | | }
|
| | | });
|
| | |
| | | // save changes
|
| | | String username = ucm.user.username;
|
| | | setEditable(false);
|
| | | updateUser();
|
| | | oidsPanel.updateUser(ucm);
|
| | | saveUser(username, ucm);
|
| | | }
|
| | |
|
| | | NewClientCertificateDialog dialog = new NewClientCertificateDialog(UserCertificatePanel.this.owner,
|
| | | ucm.user.getDisplayName(), getDefaultExpiration());
|
| | | ucm.user.getDisplayName(), getDefaultExpiration(), isAllowEmail());
|
| | | dialog.setModal(true);
|
| | | dialog.setVisible(true);
|
| | | if (dialog.isCanceled()) {
|
| | |
| | |
|
| | | Object choice = JOptionPane.showInputDialog(UserCertificatePanel.this.owner,
|
| | | Translation.get("gb.revokeCertificateReason"), Translation.get("gb.revokeCertificate"),
|
| | | JOptionPane.PLAIN_MESSAGE, new ImageIcon(getClass().getResource("/rosette_16x16.png")), choices, Translation.get("gb.unspecified"));
|
| | | JOptionPane.PLAIN_MESSAGE, new ImageIcon(getClass().getResource("/rosette_32x32.png")), choices, Translation.get("gb.unspecified"));
|
| | | if (choice == null) {
|
| | | return;
|
| | | }
|
| | |
| | | setEditable(false);
|
| | | }
|
| | |
|
| | | private JPanel newFieldPanel(String label, Component c) {
|
| | | JLabel jlabel = new JLabel(label);
|
| | | jlabel.setPreferredSize(new Dimension(175, 20));
|
| | | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
| | | panel.add(jlabel);
|
| | | panel.add(c);
|
| | | return panel;
|
| | | }
|
| | | |
| | | public void setUserCertificateModel(UserCertificateModel ucm) {
|
| | | this.ucm = ucm;
|
| | | setEditable(false);
|
| | | displayname.setText(ucm.user.getDisplayName());
|
| | | username.setText(ucm.user.username);
|
| | | emailAddress.setText(ucm.user.emailAddress);
|
| | | organizationalUnit.setText(ucm.user.organizationalUnit);
|
| | | organization.setText(ucm.user.organization);
|
| | | locality.setText(ucm.user.locality);
|
| | | stateProvince.setText(ucm.user.stateProvince);
|
| | | countryCode.setText(ucm.user.countryCode);
|
| | | oidsPanel.setUserCertificateModel(ucm);
|
| | |
|
| | | tableModel.setUserCertificateModel(ucm);
|
| | | tableModel.fireTableDataChanged();
|
| | |
| | | }
|
| | |
|
| | | public void setEditable(boolean editable) {
|
| | | displayname.setEditable(editable);
|
| | | // username.setEditable(editable);
|
| | | emailAddress.setEditable(editable);
|
| | | organizationalUnit.setEditable(editable);
|
| | | organization.setEditable(editable);
|
| | | locality.setEditable(editable);
|
| | | stateProvince.setEditable(editable);
|
| | | countryCode.setEditable(editable);
|
| | | oidsPanel.setEditable(editable);
|
| | |
|
| | | editUserButton.setEnabled(!editable && ucm != null);
|
| | | saveUserButton.setEnabled(editable && ucm != null);
|
| | |
| | | revokeCertificateButton.setEnabled(false);
|
| | | }
|
| | |
|
| | | private void updateUser() {
|
| | | ucm.user.displayName = displayname.getText();
|
| | | ucm.user.username = username.getText();
|
| | | ucm.user.emailAddress = emailAddress.getText();
|
| | | ucm.user.organizationalUnit = organizationalUnit.getText();
|
| | | ucm.user.organization = organization.getText();
|
| | | ucm.user.locality = locality.getText();
|
| | | ucm.user.stateProvince = stateProvince.getText();
|
| | | ucm.user.countryCode = countryCode.getText();
|
| | | }
|
| | | |
| | | public abstract Date getDefaultExpiration();
|
| | | public abstract boolean isAllowEmail();
|
| | |
|
| | | public abstract void saveUser(String username, UserCertificateModel ucm);
|
| | | public abstract void newCertificate(UserCertificateModel ucm, X509Metadata metadata, boolean sendEmail);
|
New file |
| | |
| | | /* |
| | | * Copyright 2012 gitblit.com. |
| | | * |
| | | * Licensed under the Apache License, Version 2.0 (the "License"); |
| | | * you may not use this file except in compliance with the License. |
| | | * You may obtain a copy of the License at |
| | | * |
| | | * http://www.apache.org/licenses/LICENSE-2.0 |
| | | * |
| | | * Unless required by applicable law or agreed to in writing, software |
| | | * distributed under the License is distributed on an "AS IS" BASIS, |
| | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| | | * See the License for the specific language governing permissions and |
| | | * limitations under the License. |
| | | */ |
| | | package com.gitblit.authority; |
| | | |
| | | import java.awt.GridLayout; |
| | | |
| | | import javax.swing.JPanel; |
| | | import javax.swing.JTextField; |
| | | |
| | | import com.gitblit.client.Translation; |
| | | |
| | | public class UserOidsPanel extends JPanel { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private JTextField displayname; |
| | | private JTextField username; |
| | | private JTextField emailAddress; |
| | | private JTextField organizationalUnit; |
| | | private JTextField organization; |
| | | private JTextField locality; |
| | | private JTextField stateProvince; |
| | | private JTextField countryCode; |
| | | |
| | | public UserOidsPanel() { |
| | | super(); |
| | | |
| | | displayname = new JTextField(20); |
| | | username = new JTextField(20); |
| | | username.setEditable(false); |
| | | emailAddress = new JTextField(20); |
| | | organizationalUnit = new JTextField(20); |
| | | organization = new JTextField(20); |
| | | locality = new JTextField(20); |
| | | stateProvince = new JTextField(20); |
| | | countryCode = new JTextField(20); |
| | | |
| | | setLayout(new GridLayout(0, 1, Utils.MARGIN, Utils.MARGIN)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.displayName"), displayname)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.username") + " (CN)", username)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.emailAddress") + " (E)", emailAddress)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.organizationalUnit") + " (OU)", organizationalUnit)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.organization") + " (O)", organization)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.locality") + " (L)", locality)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.stateProvince") + " (ST)", stateProvince)); |
| | | add(Utils.newFieldPanel(Translation.get("gb.countryCode") + " (C)", countryCode)); |
| | | } |
| | | |
| | | public void setUserCertificateModel(UserCertificateModel ucm) { |
| | | setEditable(false); |
| | | displayname.setText(ucm.user.getDisplayName()); |
| | | username.setText(ucm.user.username); |
| | | emailAddress.setText(ucm.user.emailAddress); |
| | | organizationalUnit.setText(ucm.user.organizationalUnit); |
| | | organization.setText(ucm.user.organization); |
| | | locality.setText(ucm.user.locality); |
| | | stateProvince.setText(ucm.user.stateProvince); |
| | | countryCode.setText(ucm.user.countryCode); |
| | | } |
| | | |
| | | public void setEditable(boolean editable) { |
| | | displayname.setEditable(editable); |
| | | // username.setEditable(editable); |
| | | emailAddress.setEditable(editable); |
| | | organizationalUnit.setEditable(editable); |
| | | organization.setEditable(editable); |
| | | locality.setEditable(editable); |
| | | stateProvince.setEditable(editable); |
| | | countryCode.setEditable(editable); |
| | | } |
| | | |
| | | protected void updateUser(UserCertificateModel ucm) { |
| | | ucm.user.displayName = displayname.getText(); |
| | | ucm.user.username = username.getText(); |
| | | ucm.user.emailAddress = emailAddress.getText(); |
| | | ucm.user.organizationalUnit = organizationalUnit.getText(); |
| | | ucm.user.organization = organization.getText(); |
| | | ucm.user.locality = locality.getText(); |
| | | ucm.user.stateProvince = stateProvince.getText(); |
| | | ucm.user.countryCode = countryCode.getText(); |
| | | } |
| | | } |
| | |
| | | import java.awt.Color;
|
| | | import java.awt.Component;
|
| | | import java.awt.Dimension;
|
| | | import java.awt.FlowLayout;
|
| | | import java.awt.Font;
|
| | | import java.awt.Insets;
|
| | | import java.io.PrintWriter;
|
| | | import java.io.StringWriter;
|
| | | import java.util.Date;
|
| | |
|
| | | import javax.swing.JLabel;
|
| | | import javax.swing.JOptionPane;
|
| | | import javax.swing.JPanel;
|
| | | import javax.swing.JScrollPane;
|
| | | import javax.swing.JTable;
|
| | | import javax.swing.JTextArea;
|
| | |
| | |
|
| | | import com.gitblit.client.DateCellRenderer;
|
| | | import com.gitblit.client.Translation;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | | public class Utils {
|
| | | |
| | | public final static int LABEL_WIDTH = 175;
|
| | |
|
| | | public final static int MARGIN = 5;
|
| | |
|
| | |
| | | return table;
|
| | | }
|
| | |
|
| | | public static JPanel newFieldPanel(String label, Component c) {
|
| | | return newFieldPanel(label, c, null);
|
| | | }
|
| | | |
| | | public static JPanel newFieldPanel(String label, Component c, String trailingLabel) {
|
| | | JLabel jlabel = new JLabel(label);
|
| | | jlabel.setPreferredSize(new Dimension(Utils.LABEL_WIDTH, 20));
|
| | | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
| | | panel.add(jlabel);
|
| | | panel.add(c);
|
| | | if (!StringUtils.isEmpty(trailingLabel)) {
|
| | | panel.add(new JLabel(trailingLabel)); |
| | | }
|
| | | return panel;
|
| | | }
|
| | | |
| | | public static void showException(Component c, Throwable t) {
|
| | | StringWriter writer = new StringWriter();
|
| | | t.printStackTrace(new PrintWriter(writer));
|
| | |
| | |
|
| | | setTitle(Translation.get("gb.viewCertificate"));
|
| | |
|
| | | JPanel content = new JPanel(new BorderLayout(5, 5)) { |
| | | JPanel content = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN)) { |
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | |
| | | int l1 = 15;
|
| | | int l2 = 25;
|
| | | int l3 = 45;
|
| | | JPanel panel = new JPanel(new GridLayout(0, 1, 0, 10));
|
| | | JPanel panel = new JPanel(new GridLayout(0, 1, 0, 2*Utils.MARGIN));
|
| | | panel.add(newField(Translation.get("gb.version"), "" + cert.getVersion(), 3));
|
| | | panel.add(newField(Translation.get("gb.subject"), cert.getSubjectDN().getName(), l3));
|
| | | panel.add(newField(Translation.get("gb.issuer"), cert.getIssuerDN().getName(), l3));
|
| | |
| | | }
|
| | |
|
| | | private JPanel newField(String label, String value, int cols) {
|
| | | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));
|
| | | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2*Utils.MARGIN, 0));
|
| | | JLabel lbl = new JLabel(label);
|
| | | lbl.setHorizontalAlignment(SwingConstants.RIGHT);
|
| | | lbl.setPreferredSize(new Dimension(125, 20));
|
| | |
| | | */
|
| | | package com.gitblit.utils;
|
| | |
|
| | | import java.io.BufferedWriter;
|
| | | import java.io.File;
|
| | | import java.io.FileInputStream;
|
| | | import java.io.FileOutputStream;
|
| | |
| | |
|
| | | public static final String CA_CN = "Gitblit Certificate Authority";
|
| | |
|
| | | public static final String CA_FN = CA_CN;
|
| | | public static final String CA_ALIAS = CA_CN;
|
| | |
|
| | | private static final String BC = org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;
|
| | |
|
| | |
| | | public String toString() {
|
| | | return name() + " (" + ordinal() + ")";
|
| | | }
|
| | | }
|
| | | |
| | | public interface X509Log {
|
| | | void log(String message);
|
| | | }
|
| | |
|
| | | public static class X509Metadata {
|
| | |
| | | clone.userDisplayname = userDisplayname;
|
| | | return clone;
|
| | | }
|
| | | |
| | | public String getOID(String oid, String defaultValue) {
|
| | | if (oids.containsKey(oid)) {
|
| | | return oids.get(oid);
|
| | | }
|
| | | return defaultValue;
|
| | | }
|
| | | |
| | | public void setOID(String oid, String value) {
|
| | | if (StringUtils.isEmpty(value)) {
|
| | | oids.remove(oid);
|
| | | } else {
|
| | | oids.put(oid, value);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | *
|
| | | * @param metadata
|
| | | * @param folder
|
| | | * @param logger
|
| | | * @param x509log
|
| | | */
|
| | | public static void prepareX509Infrastructure(X509Metadata metadata, File folder) {
|
| | | public static void prepareX509Infrastructure(X509Metadata metadata, File folder, X509Log x509log) {
|
| | | // make the specified folder, if necessary
|
| | | folder.mkdirs();
|
| | |
|
| | |
| | | File caKeyStore = new File(folder, CA_KEY_STORE);
|
| | | if (!caKeyStore.exists()) {
|
| | | logger.info(MessageFormat.format("Generating {0} ({1})", CA_CN, caKeyStore.getAbsolutePath()));
|
| | | X509Certificate caCert = newCertificateAuthority(metadata, caKeyStore);
|
| | | X509Certificate caCert = newCertificateAuthority(metadata, caKeyStore, x509log);
|
| | | saveCertificate(caCert, new File(caKeyStore.getParentFile(), "ca.cer"));
|
| | | }
|
| | |
|
| | |
| | | File caRevocationList = new File(folder, CA_REVOCATION_LIST);
|
| | | if (!caRevocationList.exists()) {
|
| | | logger.info(MessageFormat.format("Generating {0} CRL ({1})", CA_CN, caRevocationList.getAbsolutePath()));
|
| | | newCertificateRevocationList(caRevocationList, caKeyStore, metadata.password); |
| | | newCertificateRevocationList(caRevocationList, caKeyStore, metadata.password);
|
| | | x509log.log("new certificate revocation list created");
|
| | | }
|
| | |
|
| | | // rename the old keystore to the new name
|
| | |
| | | File serverKeyStore = new File(folder, SERVER_KEY_STORE);
|
| | | if (!serverKeyStore.exists()) {
|
| | | logger.info(MessageFormat.format("Generating SSL certificate for {0} signed by {1} ({2})", metadata.commonName, CA_CN, serverKeyStore.getAbsolutePath()));
|
| | | PrivateKey caPrivateKey = getPrivateKey(CA_FN, caKeyStore, metadata.password);
|
| | | X509Certificate caCert = getCertificate(CA_FN, caKeyStore, metadata.password);
|
| | | newSSLCertificate(metadata, caPrivateKey, caCert, serverKeyStore);
|
| | | PrivateKey caPrivateKey = getPrivateKey(CA_ALIAS, caKeyStore, metadata.password);
|
| | | X509Certificate caCert = getCertificate(CA_ALIAS, caKeyStore, metadata.password);
|
| | | newSSLCertificate(metadata, caPrivateKey, caCert, serverKeyStore, x509log); |
| | | }
|
| | |
|
| | | // server certificate trust store holds trusted public certificates
|
| | | File serverTrustStore = new File(folder, X509Utils.SERVER_TRUST_STORE);
|
| | | if (!serverTrustStore.exists()) {
|
| | | logger.info(MessageFormat.format("Importing {0} into trust store ({1})", CA_FN, serverTrustStore.getAbsolutePath()));
|
| | | X509Certificate caCert = getCertificate(CA_FN, caKeyStore, metadata.password);
|
| | | addTrustedCertificate(CA_FN, caCert, serverTrustStore, metadata.password);
|
| | | logger.info(MessageFormat.format("Importing {0} into trust store ({1})", CA_ALIAS, serverTrustStore.getAbsolutePath()));
|
| | | X509Certificate caCert = getCertificate(CA_ALIAS, caKeyStore, metadata.password);
|
| | | addTrustedCertificate(CA_ALIAS, caCert, serverTrustStore, metadata.password);
|
| | | }
|
| | | }
|
| | |
|
| | |
| | | * @param caPrivateKey
|
| | | * @param caCert
|
| | | * @param targetStoreFile
|
| | | * @param x509log
|
| | | */
|
| | | public static X509Certificate newSSLCertificate(X509Metadata sslMetadata, PrivateKey caPrivateKey, X509Certificate caCert, File targetStoreFile) {
|
| | | public static X509Certificate newSSLCertificate(X509Metadata sslMetadata, PrivateKey caPrivateKey, X509Certificate caCert, File targetStoreFile, X509Log x509log) {
|
| | | try {
|
| | | KeyPair pair = newKeyPair();
|
| | |
|
| | |
| | | new Certificate[] { cert, caCert });
|
| | | saveKeyStore(targetStoreFile, serverStore, sslMetadata.password);
|
| | |
|
| | | log(targetStoreFile.getParentFile(), MessageFormat.format("New web certificate {0,number,0} [{1}]", cert.getSerialNumber(), webDN.toString()));
|
| | | |
| | | x509log.log(MessageFormat.format("New web certificate {0,number,0} [{1}]", cert.getSerialNumber(), cert.getSubjectDN().getName()));
|
| | | return cert;
|
| | | } catch (Throwable t) {
|
| | | throw new RuntimeException("Failed to generate SSL certificate!", t);
|
| | |
| | | * @param metadata
|
| | | * @param storeFile
|
| | | * @param keystorePassword
|
| | | * @param x509log
|
| | | * @return
|
| | | */
|
| | | public static X509Certificate newCertificateAuthority(X509Metadata metadata, File storeFile) {
|
| | | public static X509Certificate newCertificateAuthority(X509Metadata metadata, File storeFile, X509Log x509log) {
|
| | | try {
|
| | | KeyPair caPair = newKeyPair();
|
| | |
|
| | |
| | |
|
| | | // Save private key and certificate to new keystore
|
| | | KeyStore store = openKeyStore(storeFile, caMetadata.password);
|
| | | store.setKeyEntry(CA_FN, caPair.getPrivate(), caMetadata.password.toCharArray(),
|
| | | store.setKeyEntry(CA_ALIAS, caPair.getPrivate(), caMetadata.password.toCharArray(),
|
| | | new Certificate[] { cert });
|
| | | saveKeyStore(storeFile, store, caMetadata.password);
|
| | |
|
| | | log(storeFile.getParentFile(), MessageFormat.format("New CA certificate {0,number,0} [{1}]", cert.getSerialNumber(), issuerDN.toString()));
|
| | | x509log.log(MessageFormat.format("New CA certificate {0,number,0} [{1}]", cert.getSerialNumber(), cert.getIssuerDN().getName()));
|
| | |
|
| | | return cert;
|
| | | } catch (Throwable t) {
|
| | | throw new RuntimeException("Failed to generate Gitblit CA certificate!", t);
|
| | |
| | | try {
|
| | | // read the Gitblit CA key and certificate
|
| | | KeyStore store = openKeyStore(caKeystoreFile, caKeystorePassword);
|
| | | PrivateKey caPrivateKey = (PrivateKey) store.getKey(CA_FN, caKeystorePassword.toCharArray());
|
| | | X509Certificate caCert = (X509Certificate) store.getCertificate(CA_FN);
|
| | | PrivateKey caPrivateKey = (PrivateKey) store.getKey(CA_ALIAS, caKeystorePassword.toCharArray());
|
| | | X509Certificate caCert = (X509Certificate) store.getCertificate(CA_ALIAS);
|
| | |
|
| | | X500Name issuerDN = new X500Name(PrincipalUtil.getIssuerX509Principal(caCert).getName());
|
| | | X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(issuerDN, new Date());
|
| | |
| | | caRevocationList.delete();
|
| | | }
|
| | | tmpFile.renameTo(caRevocationList);
|
| | |
|
| | | log(caRevocationList.getParentFile(), "new certificate revocation list created");
|
| | | } finally {
|
| | | if (fos != null) {
|
| | | fos.close();
|
| | |
| | | * @param clientMetadata a container for dynamic parameters needed for generation
|
| | | * @param caKeystoreFile
|
| | | * @param caKeystorePassword
|
| | | * @param x509log
|
| | | * @return a zip file containing the P12, PEM, and personalized README
|
| | | */
|
| | | public static File newClientBundle(X509Metadata clientMetadata, File caKeystoreFile, String caKeystorePassword) {
|
| | | public static File newClientBundle(X509Metadata clientMetadata, File caKeystoreFile, |
| | | String caKeystorePassword, X509Log x509log) {
|
| | | try {
|
| | | // read the Gitblit CA key and certificate
|
| | | KeyStore store = openKeyStore(caKeystoreFile, caKeystorePassword);
|
| | | PrivateKey caPrivateKey = (PrivateKey) store.getKey(CA_FN, caKeystorePassword.toCharArray());
|
| | | X509Certificate caCert = (X509Certificate) store.getCertificate(CA_FN);
|
| | | PrivateKey caPrivateKey = (PrivateKey) store.getKey(CA_ALIAS, caKeystorePassword.toCharArray());
|
| | | X509Certificate caCert = (X509Certificate) store.getCertificate(CA_ALIAS);
|
| | |
|
| | | // generate the P12 and PEM files
|
| | | File targetFolder = new File(caKeystoreFile.getParentFile(), clientMetadata.commonName);
|
| | | newClientCertificate(clientMetadata, caPrivateKey, caCert, targetFolder);
|
| | | |
| | | X509Certificate cert = newClientCertificate(clientMetadata, caPrivateKey, caCert, targetFolder);
|
| | | x509log.log(MessageFormat.format("New client certificate {0,number,0} [{1}]", cert.getSerialNumber(), cert.getSubjectDN().getName()));
|
| | |
|
| | | // process template message
|
| | | String readme = processTemplate(new File(caKeystoreFile.getParentFile(), "instructions.tmpl"), clientMetadata);
|
| | |
|
| | |
| | | // save certificate after successfully creating the key stores
|
| | | saveCertificate(userCert, certFile);
|
| | |
|
| | | log(targetFolder.getParentFile(), MessageFormat.format("New client certificate {0,number,0} [{1}]", userCert.getSerialNumber(), userDN.toString()));
|
| | | |
| | | return userCert;
|
| | | } catch (Throwable t) {
|
| | | throw new RuntimeException("Failed to generate client certificate!", t);
|
| | |
| | | return content;
|
| | | }
|
| | |
|
| | | private static void log(File folder, String message) {
|
| | | BufferedWriter writer = null;
|
| | | try {
|
| | | writer = new BufferedWriter(new FileWriter(new File(folder, "log.txt"), true));
|
| | | writer.write(MessageFormat.format("{0,date,yyyy-MM-dd HH:mm}: {1}", new Date(), message));
|
| | | writer.newLine();
|
| | | writer.flush();
|
| | | } catch (Exception e) {
|
| | | logger.error("Failed to append log entry!", e);
|
| | | } finally {
|
| | | if (writer != null) {
|
| | | try {
|
| | | writer.close();
|
| | | } catch (IOException e) {
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | |
| | | /**
|
| | | * Revoke a certificate.
|
| | | *
|
| | |
| | | * @param caRevocationList
|
| | | * @param caKeystoreFile
|
| | | * @param caKeystorePassword
|
| | | * @param x509log
|
| | | * @return true if the certificate has been revoked
|
| | | */
|
| | | public static boolean revoke(X509Certificate cert, RevocationReason reason,
|
| | | File caRevocationList, File caKeystoreFile, String caKeystorePassword) {
|
| | | File caRevocationList, File caKeystoreFile, String caKeystorePassword,
|
| | | X509Log x509log) {
|
| | | try {
|
| | | // read the Gitblit CA key and certificate
|
| | | KeyStore store = openKeyStore(caKeystoreFile, caKeystorePassword);
|
| | | PrivateKey caPrivateKey = (PrivateKey) store.getKey(CA_FN, caKeystorePassword.toCharArray());
|
| | | return revoke(cert, reason, caRevocationList, caPrivateKey);
|
| | | PrivateKey caPrivateKey = (PrivateKey) store.getKey(CA_ALIAS, caKeystorePassword.toCharArray());
|
| | | return revoke(cert, reason, caRevocationList, caPrivateKey, x509log);
|
| | | } catch (Exception e) {
|
| | | logger.error(MessageFormat.format("Failed to revoke certificate {0,number,0} [{1}] in {2}",
|
| | | cert.getSerialNumber(), cert.getSubjectDN().getName(), caRevocationList));
|
| | |
| | | * @param reason
|
| | | * @param caRevocationList
|
| | | * @param caPrivateKey
|
| | | * @param x509log
|
| | | * @return true if the certificate has been revoked
|
| | | */
|
| | | public static boolean revoke(X509Certificate cert, RevocationReason reason,
|
| | | File caRevocationList, PrivateKey caPrivateKey) {
|
| | | File caRevocationList, PrivateKey caPrivateKey, X509Log x509log) {
|
| | | try {
|
| | | X500Name subjectDN = new X500Name(PrincipalUtil.getSubjectX509Principal(cert).getName());
|
| | | X500Name issuerDN = new X500Name(PrincipalUtil.getIssuerX509Principal(cert).getName());
|
| | | X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(issuerDN, new Date());
|
| | | if (caRevocationList.exists()) {
|
| | |
| | | }
|
| | | tmpFile.renameTo(caRevocationList);
|
| | |
|
| | | log(caRevocationList.getParentFile(), MessageFormat.format("Revoked certificate {0,number,0} reason: {1} [{2}]",
|
| | | cert.getSerialNumber(), reason.toString(), subjectDN.toString()));
|
| | | } finally {
|
| | | if (fos != null) {
|
| | | fos.close();
|
| | |
| | | tmpFile.delete();
|
| | | }
|
| | | }
|
| | | |
| | | x509log.log(MessageFormat.format("Revoked certificate {0,number,0} reason: {1} [{2}]",
|
| | | cert.getSerialNumber(), reason.toString(), cert.getSubjectDN().getName()));
|
| | | return true;
|
| | | } catch (Exception e) {
|
| | | logger.error(MessageFormat.format("Failed to revoke certificate {0,number,0} [{1}] in {2}",
|
| | |
| | | gb.privilegeWithdrawn = privilege withdrawn
|
| | | gb.time.inMinutes = in {0} mins
|
| | | gb.time.inHours = in {0} hours
|
| | | gb.time.inDays = in {0} days |
| | | gb.time.inDays = in {0} days
|
| | | gb.hostname = hostname
|
| | | gb.hostnameRequired = Please enter a hostname
|
| | | gb.newWebCertificate = new server SSL certificate
|
| | | gb.certificateDefaults = certificate defaults
|
| | | gb.duration = duration |
| | |
| | | import com.gitblit.utils.HttpUtils;
|
| | | import com.gitblit.utils.X509Utils;
|
| | | import com.gitblit.utils.X509Utils.RevocationReason;
|
| | | import com.gitblit.utils.X509Utils.X509Log;
|
| | | import com.gitblit.utils.X509Utils.X509Metadata;
|
| | |
|
| | | /**
|
| | |
| | | // based on the JCE policy files
|
| | | String caPassword = "aBcDeFg";
|
| | | File folder = new File(System.getProperty("user.dir"), "x509test");
|
| | | |
| | | X509Log log = new X509Log() {
|
| | | public void log(String message) {
|
| | | System.out.println(message);
|
| | | }
|
| | | };
|
| | |
|
| | | @Before
|
| | | public void prepare() throws Exception {
|
| | | cleanUp();
|
| | | X509Metadata goMetadata = new X509Metadata("localhost", caPassword);
|
| | | X509Utils.prepareX509Infrastructure(goMetadata, folder);
|
| | | X509Utils.prepareX509Infrastructure(goMetadata, folder, log);
|
| | | }
|
| | |
|
| | | @After
|
| | |
| | | @Test
|
| | | public void testNewCA() throws Exception {
|
| | | File storeFile = new File(folder, X509Utils.CA_KEY_STORE);
|
| | | X509Utils.getPrivateKey(X509Utils.CA_FN, storeFile, caPassword);
|
| | | X509Certificate cert = X509Utils.getCertificate(X509Utils.CA_FN, storeFile, caPassword);
|
| | | X509Utils.getPrivateKey(X509Utils.CA_ALIAS, storeFile, caPassword);
|
| | | X509Certificate cert = X509Utils.getCertificate(X509Utils.CA_ALIAS, storeFile, caPassword);
|
| | | assertEquals("O=Gitblit,OU=Gitblit,CN=Gitblit Certificate Authority", cert.getIssuerDN().getName());
|
| | | }
|
| | |
|
| | | @Test
|
| | | public void testCertificateUserMapping() throws Exception {
|
| | | File storeFile = new File(folder, X509Utils.CA_KEY_STORE);
|
| | | PrivateKey caPrivateKey = X509Utils.getPrivateKey(X509Utils.CA_FN, storeFile, caPassword);
|
| | | X509Certificate caCert = X509Utils.getCertificate(X509Utils.CA_FN, storeFile, caPassword);
|
| | | PrivateKey caPrivateKey = X509Utils.getPrivateKey(X509Utils.CA_ALIAS, storeFile, caPassword);
|
| | | X509Certificate caCert = X509Utils.getCertificate(X509Utils.CA_ALIAS, storeFile, caPassword);
|
| | |
|
| | | X509Metadata userMetadata = new X509Metadata("james", "james");
|
| | | userMetadata.serverHostname = "www.myserver.com";
|
| | |
| | | userMetadata.userDisplayname = "James Moger";
|
| | | userMetadata.passwordHint = "your name";
|
| | |
|
| | | File zip = X509Utils.newClientBundle(userMetadata, storeFile, caPassword);
|
| | | File zip = X509Utils.newClientBundle(userMetadata, storeFile, caPassword, log);
|
| | | assertTrue(zip.exists());
|
| | |
|
| | | List<String> expected = Arrays.asList(userMetadata.commonName + ".pem", userMetadata.commonName + ".p12", "README.TXT");
|
| | |
| | | @Test
|
| | | public void testCertificateRevocation() throws Exception {
|
| | | File storeFile = new File(folder, X509Utils.CA_KEY_STORE);
|
| | | PrivateKey caPrivateKey = X509Utils.getPrivateKey(X509Utils.CA_FN, storeFile, caPassword);
|
| | | X509Certificate caCert = X509Utils.getCertificate(X509Utils.CA_FN, storeFile, caPassword);
|
| | | PrivateKey caPrivateKey = X509Utils.getPrivateKey(X509Utils.CA_ALIAS, storeFile, caPassword);
|
| | | X509Certificate caCert = X509Utils.getCertificate(X509Utils.CA_ALIAS, storeFile, caPassword);
|
| | |
|
| | | X509Metadata userMetadata = new X509Metadata("james", "james");
|
| | | userMetadata.serverHostname = "www.myserver.com";
|
| | |
| | | assertFalse(X509Utils.isRevoked(cert1, caRevocationList));
|
| | |
|
| | | // revoke certificate and then confirm it IS revoked
|
| | | X509Utils.revoke(cert1, RevocationReason.ACompromise, caRevocationList, storeFile, caPassword);
|
| | | X509Utils.revoke(cert1, RevocationReason.ACompromise, caRevocationList, storeFile, caPassword, log);
|
| | | assertTrue(X509Utils.isRevoked(cert1, caRevocationList));
|
| | |
|
| | | // generate a second certificate
|
| | |
| | | assertFalse(X509Utils.isRevoked(cert2, caRevocationList));
|
| | |
|
| | | // revoke second certificate and then confirm it IS revoked
|
| | | X509Utils.revoke(cert2, RevocationReason.ACompromise, caRevocationList, caPrivateKey);
|
| | | X509Utils.revoke(cert2, RevocationReason.ACompromise, caRevocationList, caPrivateKey, log);
|
| | | assertTrue(X509Utils.isRevoked(cert1, caRevocationList));
|
| | | assertTrue(X509Utils.isRevoked(cert2, caRevocationList));
|
| | |
|
| | |
| | | assertFalse(X509Utils.isRevoked(cert3, caRevocationList));
|
| | |
|
| | | // revoke third certificate and then confirm it IS revoked
|
| | | X509Utils.revoke(cert3, RevocationReason.ACompromise, caRevocationList, caPrivateKey);
|
| | | X509Utils.revoke(cert3, RevocationReason.ACompromise, caRevocationList, caPrivateKey, log);
|
| | | assertTrue(X509Utils.isRevoked(cert1, caRevocationList));
|
| | | assertTrue(X509Utils.isRevoked(cert2, caRevocationList));
|
| | | assertTrue(X509Utils.isRevoked(cert3, caRevocationList));
|